ing
This commit is contained in:
parent
bc3f80b726
commit
769594fb9f
40
angular.json
40
angular.json
|
@ -235,6 +235,46 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"@loafer/ng-entity": {
|
||||||
|
"root": "projects/loafer/ng-entity",
|
||||||
|
"sourceRoot": "projects/loafer/ng-entity/src",
|
||||||
|
"projectType": "library",
|
||||||
|
"prefix": "lib",
|
||||||
|
"architect": {
|
||||||
|
"build": {
|
||||||
|
"builder": "@angular-devkit/build-ng-packagr:build",
|
||||||
|
"options": {
|
||||||
|
"tsConfig": "projects/loafer/ng-entity/tsconfig.lib.json",
|
||||||
|
"project": "projects/loafer/ng-entity/ng-package.json"
|
||||||
|
},
|
||||||
|
"configurations": {
|
||||||
|
"production": {
|
||||||
|
"project": "projects/loafer/ng-entity/ng-package.prod.json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"builder": "@angular-devkit/build-angular:karma",
|
||||||
|
"options": {
|
||||||
|
"main": "projects/loafer/ng-entity/src/test.ts",
|
||||||
|
"tsConfig": "projects/loafer/ng-entity/tsconfig.spec.json",
|
||||||
|
"karmaConfig": "projects/loafer/ng-entity/karma.conf.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lint": {
|
||||||
|
"builder": "@angular-devkit/build-angular:tslint",
|
||||||
|
"options": {
|
||||||
|
"tsConfig": [
|
||||||
|
"projects/loafer/ng-entity/tsconfig.lib.json",
|
||||||
|
"projects/loafer/ng-entity/tsconfig.spec.json"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"**/node_modules/**"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"defaultProject": "example"
|
"defaultProject": "example"
|
||||||
|
|
|
@ -53,4 +53,4 @@
|
||||||
"ts-node": "~5.0.1",
|
"ts-node": "~5.0.1",
|
||||||
"tslint": "~5.9.1"
|
"tslint": "~5.9.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
31
projects/loafer/ng-entity/karma.conf.js
Normal file
31
projects/loafer/ng-entity/karma.conf.js
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// Karma configuration file, see link for more information
|
||||||
|
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
||||||
|
|
||||||
|
module.exports = function (config) {
|
||||||
|
config.set({
|
||||||
|
basePath: '',
|
||||||
|
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
||||||
|
plugins: [
|
||||||
|
require('karma-jasmine'),
|
||||||
|
require('karma-chrome-launcher'),
|
||||||
|
require('karma-jasmine-html-reporter'),
|
||||||
|
require('karma-coverage-istanbul-reporter'),
|
||||||
|
require('@angular-devkit/build-angular/plugins/karma')
|
||||||
|
],
|
||||||
|
client: {
|
||||||
|
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||||
|
},
|
||||||
|
coverageIstanbulReporter: {
|
||||||
|
dir: require('path').join(__dirname, '../../../coverage'),
|
||||||
|
reports: ['html', 'lcovonly'],
|
||||||
|
fixWebpackSourcePaths: true
|
||||||
|
},
|
||||||
|
reporters: ['progress', 'kjhtml'],
|
||||||
|
port: 9876,
|
||||||
|
colors: true,
|
||||||
|
logLevel: config.LOG_INFO,
|
||||||
|
autoWatch: true,
|
||||||
|
browsers: ['Chrome'],
|
||||||
|
singleRun: false
|
||||||
|
});
|
||||||
|
};
|
8
projects/loafer/ng-entity/ng-package.json
Normal file
8
projects/loafer/ng-entity/ng-package.json
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
|
||||||
|
"dest": "../../../dist/loafer/ng-entity",
|
||||||
|
"deleteDestPath": true,
|
||||||
|
"lib": {
|
||||||
|
"entryFile": "src/public_api.ts"
|
||||||
|
}
|
||||||
|
}
|
7
projects/loafer/ng-entity/ng-package.prod.json
Normal file
7
projects/loafer/ng-entity/ng-package.prod.json
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
|
||||||
|
"dest": "../../../dist/loafer/ng-entity",
|
||||||
|
"lib": {
|
||||||
|
"entryFile": "src/public_api.ts"
|
||||||
|
}
|
||||||
|
}
|
15
projects/loafer/ng-entity/package.json
Normal file
15
projects/loafer/ng-entity/package.json
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"name": "@loafer/ng-entity",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.loafle.net/loafer/ng.git"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"registry": "https://nexus.loafle.net/repository/npm-loafle/"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@angular/common": "^6.0.0-rc.0 || ^6.0.0",
|
||||||
|
"@angular/core": "^6.0.0-rc.0 || ^6.0.0"
|
||||||
|
}
|
||||||
|
}
|
22
projects/loafer/ng-entity/src/lib/adapter.ts
Normal file
22
projects/loafer/ng-entity/src/lib/adapter.ts
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import { IDSelector, EntityAdapter } from './type';
|
||||||
|
import { createInitialStateFactory } from './state';
|
||||||
|
import { createSelectorsFactory } from './selectors';
|
||||||
|
import { createUnsortedStateAdapter } from './unsorted_state_adapter';
|
||||||
|
|
||||||
|
export function createEntityAdapter<T, E>(selectId?: IDSelector<T>): EntityAdapter<T, E>;
|
||||||
|
export function createEntityAdapter<T, E>(selectId: IDSelector<T>): EntityAdapter<T, E> {
|
||||||
|
if (undefined === selectId) {
|
||||||
|
selectId = (e: any) => e.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
const stateFactory = createInitialStateFactory<T, E>();
|
||||||
|
const selectorsFactory = createSelectorsFactory<T, E>();
|
||||||
|
const stateAdapter = createUnsortedStateAdapter<T, E>(selectId);
|
||||||
|
|
||||||
|
return {
|
||||||
|
selectId,
|
||||||
|
...stateFactory,
|
||||||
|
...selectorsFactory,
|
||||||
|
...stateAdapter,
|
||||||
|
};
|
||||||
|
}
|
62
projects/loafer/ng-entity/src/lib/selectors.ts
Normal file
62
projects/loafer/ng-entity/src/lib/selectors.ts
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
import { EntityState, EntitySelectors, Dictionary } from './type';
|
||||||
|
import { createSelector } from '@ngrx/store';
|
||||||
|
|
||||||
|
|
||||||
|
export function createSelectorsFactory<T, E>() {
|
||||||
|
function getSelectors(): EntitySelectors<T, E, EntityState<T, E>>;
|
||||||
|
function getSelectors<S>(selectState: (state: S) => EntityState<T, E>): EntitySelectors<T, E, S>;
|
||||||
|
function getSelectors(selectState?: (state: any) => EntityState<T, E>): EntitySelectors<T, E, any> {
|
||||||
|
const selectIds = (state: any) => state.ids;
|
||||||
|
const selectEntities = (state: EntityState<T, E>) => state.entities;
|
||||||
|
const selectAll = createSelector(
|
||||||
|
selectIds,
|
||||||
|
selectEntities,
|
||||||
|
(ids: T[], entities: Dictionary<T>): any => ids.map((id: any) => (entities as any)[id])
|
||||||
|
);
|
||||||
|
const selectTotal = createSelector(selectIds, ids => ids.length);
|
||||||
|
const selectError = (state: any) => state.error;
|
||||||
|
|
||||||
|
if (!selectState) {
|
||||||
|
return {
|
||||||
|
selectIds,
|
||||||
|
selectEntities,
|
||||||
|
selectOne: (id: string | number) => createSelector(
|
||||||
|
selectEntities,
|
||||||
|
(entities: Dictionary<T>): T => {
|
||||||
|
if (null !== entities) {
|
||||||
|
return (entities as any)[id];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
),
|
||||||
|
selectAll,
|
||||||
|
selectTotal,
|
||||||
|
selectError,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
selectIds: createSelector(selectState, selectIds),
|
||||||
|
selectEntities: createSelector(selectState, selectEntities),
|
||||||
|
selectOne: (id: string | number) => createSelector(
|
||||||
|
selectState,
|
||||||
|
createSelector(
|
||||||
|
selectEntities,
|
||||||
|
(entities: Dictionary<T>): T => {
|
||||||
|
if (null !== entities) {
|
||||||
|
return (entities as any)[id];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
),
|
||||||
|
selectAll: createSelector(selectState, selectAll),
|
||||||
|
selectTotal: createSelector(selectState, selectTotal),
|
||||||
|
selectError: createSelector(selectState, selectError),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
getSelectors
|
||||||
|
};
|
||||||
|
}
|
21
projects/loafer/ng-entity/src/lib/state.ts
Normal file
21
projects/loafer/ng-entity/src/lib/state.ts
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import { EntityState } from './type';
|
||||||
|
|
||||||
|
export function getInitialEntityState<T, E>(): EntityState<T, E> {
|
||||||
|
return {
|
||||||
|
ids: [],
|
||||||
|
entities: {},
|
||||||
|
error: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createInitialStateFactory<T, E>() {
|
||||||
|
function getInitialState(): EntityState<T, E>;
|
||||||
|
function getInitialState<S extends object>(additionalState: S): EntityState<T, E> & S;
|
||||||
|
function getInitialState(additionalState: any = {}): any {
|
||||||
|
return Object.assign(getInitialEntityState(), additionalState);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
getInitialState
|
||||||
|
};
|
||||||
|
}
|
45
projects/loafer/ng-entity/src/lib/state_adapter.ts
Normal file
45
projects/loafer/ng-entity/src/lib/state_adapter.ts
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
import { EntityState } from './type';
|
||||||
|
|
||||||
|
export enum DidMutate {
|
||||||
|
EntitiesOnly,
|
||||||
|
Both,
|
||||||
|
Error,
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createStateOperator<T, E, R>(mutator: (arg: R, state: EntityState<T, E>) => DidMutate): EntityState<T, E>;
|
||||||
|
export function createStateOperator<T, E, R>(mutator: (arg: any, state: any) => DidMutate): any {
|
||||||
|
return function operation<S extends EntityState<T, E>>(arg: R, state: any): S {
|
||||||
|
const clonedEntityState: EntityState<T, E> = {
|
||||||
|
ids: [...state.ids],
|
||||||
|
entities: { ...state.entities },
|
||||||
|
error: state.error,
|
||||||
|
};
|
||||||
|
|
||||||
|
const didMutate = mutator(arg, clonedEntityState);
|
||||||
|
|
||||||
|
if (didMutate === DidMutate.Both) {
|
||||||
|
clonedEntityState.error = null;
|
||||||
|
return Object.assign({}, state, clonedEntityState);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (didMutate === DidMutate.EntitiesOnly) {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
entities: clonedEntityState.entities,
|
||||||
|
error: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (didMutate === DidMutate.Error) {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
ids: null,
|
||||||
|
entities: null,
|
||||||
|
error: clonedEntityState.error,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
};
|
||||||
|
}
|
67
projects/loafer/ng-entity/src/lib/type.ts
Normal file
67
projects/loafer/ng-entity/src/lib/type.ts
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
export type IDSelectorStr<T> = (model: T) => string;
|
||||||
|
export type IDSelectorNum<T> = (model: T) => number;
|
||||||
|
export type IDSelector<T> = IDSelectorStr<T> | IDSelectorNum<T>;
|
||||||
|
|
||||||
|
export interface DictionaryNum<T> {
|
||||||
|
[id: number]: T;
|
||||||
|
}
|
||||||
|
export abstract class Dictionary<T> implements DictionaryNum<T> {
|
||||||
|
[id: string]: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdateStr<T> {
|
||||||
|
id: string;
|
||||||
|
changes: Partial<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdateNum<T> {
|
||||||
|
id: number;
|
||||||
|
changes: Partial<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Update<T> = UpdateStr<T> | UpdateNum<T>;
|
||||||
|
|
||||||
|
export interface EntityState<T, E> {
|
||||||
|
ids: string[] | number[];
|
||||||
|
entities: Dictionary<T>;
|
||||||
|
error: E | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EntityStateAdapter<T, E> {
|
||||||
|
setOne<S extends EntityState<T, E>>(entity: T, state: S): S;
|
||||||
|
setAll<S extends EntityState<T, E>>(entities: T[], state: S): S;
|
||||||
|
|
||||||
|
addOne<S extends EntityState<T, E>>(entity: T, state: S): S;
|
||||||
|
addMany<S extends EntityState<T, E>>(entities: T[], state: S): S;
|
||||||
|
|
||||||
|
updateOne<S extends EntityState<T, E>>(entity: T, state: S): S;
|
||||||
|
updateMany<S extends EntityState<T, E>>(entities: T[], state: S): S;
|
||||||
|
|
||||||
|
upsertOne<S extends EntityState<T, E>>(entity: T, state: S): S;
|
||||||
|
upsertMany<S extends EntityState<T, E>>(entities: T[], state: S): S;
|
||||||
|
|
||||||
|
removeOne<S extends EntityState<T, E>>(entity: T, state: S): S;
|
||||||
|
removeMany<S extends EntityState<T, E>>(entities: T[], state: S): S;
|
||||||
|
removeAll<S extends EntityState<T, E>>(state: S): S;
|
||||||
|
|
||||||
|
setError<S extends EntityState<T, E>>(error: E, state: S): S;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EntitySelectors<T, E, S> {
|
||||||
|
selectIds: (state: S) => string[] | number[];
|
||||||
|
selectEntities: (state: S) => Dictionary<T>;
|
||||||
|
selectOne: (id: string | number) => (state: S) => T;
|
||||||
|
selectAll: (state: S) => T[];
|
||||||
|
selectTotal: (state: S) => number;
|
||||||
|
selectError: (state: S) => E;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EntityAdapter<T, E> extends EntityStateAdapter<T, E> {
|
||||||
|
selectId: IDSelector<T>;
|
||||||
|
getInitialState(): EntityState<T, E>;
|
||||||
|
getInitialState<S extends object>(state: S): EntityState<T, E> & S;
|
||||||
|
getSelectors(): EntitySelectors<T, E, EntityState<T, E>>;
|
||||||
|
getSelectors<S>(
|
||||||
|
selectState: (state: S) => EntityState<T, E>
|
||||||
|
): EntitySelectors<T, E, S>;
|
||||||
|
}
|
189
projects/loafer/ng-entity/src/lib/unsorted_state_adapter.ts
Normal file
189
projects/loafer/ng-entity/src/lib/unsorted_state_adapter.ts
Normal file
|
@ -0,0 +1,189 @@
|
||||||
|
import { IDSelector, EntityStateAdapter, EntityState, Update } from './type';
|
||||||
|
import { DidMutate, createStateOperator } from './state_adapter';
|
||||||
|
|
||||||
|
export function createUnsortedStateAdapter<T, E>(selectId: IDSelector<T>): EntityStateAdapter<T, E>;
|
||||||
|
export function createUnsortedStateAdapter<T, E>(selectId: IDSelector<T>): any {
|
||||||
|
type R = EntityState<T, E>;
|
||||||
|
|
||||||
|
function addOneMutably(entity: T, state: R): DidMutate;
|
||||||
|
function addOneMutably(entity: any, state: any): DidMutate {
|
||||||
|
const id = selectId(entity);
|
||||||
|
|
||||||
|
if (id in state.entities) {
|
||||||
|
return DidMutate.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.ids.push(id);
|
||||||
|
state.entities[id] = entity;
|
||||||
|
|
||||||
|
return DidMutate.Both;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addManyMutably(entities: T[], state: R): DidMutate;
|
||||||
|
function addManyMutably(entities: any[], state: any): DidMutate {
|
||||||
|
let didMutate = false;
|
||||||
|
|
||||||
|
for (const entity of entities) {
|
||||||
|
didMutate = addOneMutably(entity, state) !== DidMutate.None || didMutate;
|
||||||
|
}
|
||||||
|
|
||||||
|
return didMutate ? DidMutate.Both : DidMutate.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setOneMutably(entity: T, state: R): DidMutate;
|
||||||
|
function setOneMutably(entity: any, state: any): DidMutate {
|
||||||
|
state.ids = [];
|
||||||
|
state.entities = {};
|
||||||
|
|
||||||
|
addManyMutably([entity], state);
|
||||||
|
|
||||||
|
return DidMutate.Both;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function setAllMutably(entities: T[], state: R): DidMutate;
|
||||||
|
function setAllMutably(entities: any[], state: any): DidMutate {
|
||||||
|
state.ids = [];
|
||||||
|
state.entities = {};
|
||||||
|
|
||||||
|
addManyMutably(entities, state);
|
||||||
|
|
||||||
|
return DidMutate.Both;
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeOneMutably(id: string | number, state: R): DidMutate;
|
||||||
|
function removeOneMutably(id: any, state: any): DidMutate {
|
||||||
|
return removeManyMutably([id], state);
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeManyMutably(ids: string[] | number[], state: R): DidMutate;
|
||||||
|
function removeManyMutably(ids: any[], state: any): DidMutate {
|
||||||
|
const didMutate =
|
||||||
|
ids
|
||||||
|
.filter(id => id in state.entities)
|
||||||
|
.map(id => delete state.entities[id]).length > 0;
|
||||||
|
|
||||||
|
if (didMutate) {
|
||||||
|
state.ids = state.ids.filter((_id: any) => _id in state.entities);
|
||||||
|
}
|
||||||
|
|
||||||
|
return didMutate ? DidMutate.Both : DidMutate.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeAllMutably<S extends R>(state: S): DidMutate;
|
||||||
|
function removeAllMutably<S extends R>(state: any): DidMutate {
|
||||||
|
state.ids = [];
|
||||||
|
state.entities = {};
|
||||||
|
|
||||||
|
return DidMutate.Both;
|
||||||
|
}
|
||||||
|
|
||||||
|
function takeNewKey(
|
||||||
|
keys: { [id: string]: string },
|
||||||
|
update: Update<T>,
|
||||||
|
state: R
|
||||||
|
): void;
|
||||||
|
function takeNewKey(
|
||||||
|
keys: { [id: string]: any },
|
||||||
|
update: Update<T>,
|
||||||
|
state: any
|
||||||
|
): boolean {
|
||||||
|
const original = state.entities[update.id];
|
||||||
|
const updated: T = Object.assign({}, original, update.changes);
|
||||||
|
const newKey = selectId(updated);
|
||||||
|
const hasNewKey = newKey !== update.id;
|
||||||
|
|
||||||
|
if (hasNewKey) {
|
||||||
|
keys[update.id] = newKey;
|
||||||
|
delete state.entities[update.id];
|
||||||
|
}
|
||||||
|
|
||||||
|
state.entities[newKey] = updated;
|
||||||
|
|
||||||
|
return hasNewKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateOneMutably(update: Update<T>, state: R): DidMutate;
|
||||||
|
function updateOneMutably(update: any, state: any): DidMutate {
|
||||||
|
return updateManyMutably([update], state);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateManyMutably(updates: Update<T>[], state: R): DidMutate;
|
||||||
|
function updateManyMutably(updates: any[], state: any): DidMutate {
|
||||||
|
const newKeys: { [id: string]: string } = {};
|
||||||
|
|
||||||
|
updates = updates.filter(update => update.id in state.entities);
|
||||||
|
|
||||||
|
const didMutateEntities = updates.length > 0;
|
||||||
|
|
||||||
|
if (didMutateEntities) {
|
||||||
|
const didMutateIds =
|
||||||
|
updates.filter(update => takeNewKey(newKeys, update, state)).length > 0;
|
||||||
|
|
||||||
|
if (didMutateIds) {
|
||||||
|
state.ids = state.ids.map((id: any) => newKeys[id] || id);
|
||||||
|
return DidMutate.Both;
|
||||||
|
} else {
|
||||||
|
return DidMutate.EntitiesOnly;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return DidMutate.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
function upsertOneMutably(entity: T, state: R): DidMutate;
|
||||||
|
function upsertOneMutably(entity: any, state: any): DidMutate {
|
||||||
|
return upsertManyMutably([entity], state);
|
||||||
|
}
|
||||||
|
|
||||||
|
function upsertManyMutably(entities: T[], state: R): DidMutate;
|
||||||
|
function upsertManyMutably(entities: any[], state: any): DidMutate {
|
||||||
|
const added: any[] = [];
|
||||||
|
const updated: any[] = [];
|
||||||
|
|
||||||
|
for (const entity of entities) {
|
||||||
|
const id = selectId(entity);
|
||||||
|
if (id in state.entities) {
|
||||||
|
updated.push({ id, changes: entity });
|
||||||
|
} else {
|
||||||
|
added.push(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const didMutateByUpdated = updateManyMutably(updated, state);
|
||||||
|
const didMutateByAdded = addManyMutably(added, state);
|
||||||
|
|
||||||
|
switch (true) {
|
||||||
|
case didMutateByAdded === DidMutate.None &&
|
||||||
|
didMutateByUpdated === DidMutate.None:
|
||||||
|
return DidMutate.None;
|
||||||
|
case didMutateByAdded === DidMutate.Both ||
|
||||||
|
didMutateByUpdated === DidMutate.Both:
|
||||||
|
return DidMutate.Both;
|
||||||
|
default:
|
||||||
|
return DidMutate.EntitiesOnly;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setErrorMutably<S extends R>(error: E, state: S): DidMutate;
|
||||||
|
function setErrorMutably<S extends R>(error: any, state: any): DidMutate {
|
||||||
|
state.error = error;
|
||||||
|
|
||||||
|
return DidMutate.Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
setOne: createStateOperator(setOneMutably),
|
||||||
|
setAll: createStateOperator(setAllMutably),
|
||||||
|
addOne: createStateOperator(addOneMutably),
|
||||||
|
addMany: createStateOperator(addManyMutably),
|
||||||
|
updateOne: createStateOperator(updateOneMutably),
|
||||||
|
updateMany: createStateOperator(updateManyMutably),
|
||||||
|
upsertOne: createStateOperator(upsertOneMutably),
|
||||||
|
upsertMany: createStateOperator(upsertManyMutably),
|
||||||
|
removeOne: createStateOperator(removeOneMutably),
|
||||||
|
removeMany: createStateOperator(removeManyMutably),
|
||||||
|
removeAll: createStateOperator(removeAllMutably),
|
||||||
|
setError: createStateOperator(setErrorMutably),
|
||||||
|
};
|
||||||
|
}
|
6
projects/loafer/ng-entity/src/public_api.ts
Normal file
6
projects/loafer/ng-entity/src/public_api.ts
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
/*
|
||||||
|
* Public API Surface of ng-entity
|
||||||
|
*/
|
||||||
|
|
||||||
|
export { createEntityAdapter } from './lib/adapter';
|
||||||
|
export { EntityState, EntityAdapter } from './lib/type';
|
22
projects/loafer/ng-entity/src/test.ts
Normal file
22
projects/loafer/ng-entity/src/test.ts
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
|
||||||
|
|
||||||
|
import 'core-js/es7/reflect';
|
||||||
|
import 'zone.js/dist/zone';
|
||||||
|
import 'zone.js/dist/zone-testing';
|
||||||
|
import { getTestBed } from '@angular/core/testing';
|
||||||
|
import {
|
||||||
|
BrowserDynamicTestingModule,
|
||||||
|
platformBrowserDynamicTesting
|
||||||
|
} from '@angular/platform-browser-dynamic/testing';
|
||||||
|
|
||||||
|
declare const require: any;
|
||||||
|
|
||||||
|
// First, initialize the Angular testing environment.
|
||||||
|
getTestBed().initTestEnvironment(
|
||||||
|
BrowserDynamicTestingModule,
|
||||||
|
platformBrowserDynamicTesting()
|
||||||
|
);
|
||||||
|
// Then we find all the tests.
|
||||||
|
const context = require.context('./', true, /\.spec\.ts$/);
|
||||||
|
// And load the modules.
|
||||||
|
context.keys().map(context);
|
33
projects/loafer/ng-entity/tsconfig.lib.json
Normal file
33
projects/loafer/ng-entity/tsconfig.lib.json
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
{
|
||||||
|
"extends": "../../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../../out-tsc/lib",
|
||||||
|
"target": "es2015",
|
||||||
|
"module": "es2015",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"declaration": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"inlineSources": true,
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"importHelpers": true,
|
||||||
|
"types": [],
|
||||||
|
"lib": [
|
||||||
|
"dom",
|
||||||
|
"es2015"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"angularCompilerOptions": {
|
||||||
|
"annotateForClosureCompiler": true,
|
||||||
|
"skipTemplateCodegen": true,
|
||||||
|
"strictMetadataEmit": true,
|
||||||
|
"fullTemplateTypeCheck": true,
|
||||||
|
"strictInjectionParameters": true,
|
||||||
|
"flatModuleId": "AUTOGENERATED",
|
||||||
|
"flatModuleOutFile": "AUTOGENERATED"
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"src/test.ts",
|
||||||
|
"**/*.spec.ts"
|
||||||
|
]
|
||||||
|
}
|
17
projects/loafer/ng-entity/tsconfig.spec.json
Normal file
17
projects/loafer/ng-entity/tsconfig.spec.json
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"extends": "../../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../../out-tsc/spec",
|
||||||
|
"types": [
|
||||||
|
"jasmine",
|
||||||
|
"node"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"src/test.ts"
|
||||||
|
],
|
||||||
|
"include": [
|
||||||
|
"**/*.spec.ts",
|
||||||
|
"**/*.d.ts"
|
||||||
|
]
|
||||||
|
}
|
17
projects/loafer/ng-entity/tslint.json
Normal file
17
projects/loafer/ng-entity/tslint.json
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"extends": "../../../tslint.json",
|
||||||
|
"rules": {
|
||||||
|
"directive-selector": [
|
||||||
|
true,
|
||||||
|
"attribute",
|
||||||
|
"lib",
|
||||||
|
"camelCase"
|
||||||
|
],
|
||||||
|
"component-selector": [
|
||||||
|
true,
|
||||||
|
"element",
|
||||||
|
"lib",
|
||||||
|
"kebab-case"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@loafer/ng-rpc",
|
"name": "@loafer/ng-rpc",
|
||||||
"version": "0.0.6",
|
"version": "0.0.1",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://git.loafle.net/loafer/ng.git"
|
"url": "https://git.loafle.net/loafer/ng.git"
|
||||||
|
|
|
@ -25,6 +25,9 @@
|
||||||
],
|
],
|
||||||
"@loafer/ng-rpc": [
|
"@loafer/ng-rpc": [
|
||||||
"dist/loafer/ng-rpc"
|
"dist/loafer/ng-rpc"
|
||||||
|
],
|
||||||
|
"@loafer/ng-entity": [
|
||||||
|
"dist/loafer/ng-entity"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user