diff --git a/e2e/protractor.conf.js b/e2e/protractor.conf.js deleted file mode 100644 index 98f33e8..0000000 --- a/e2e/protractor.conf.js +++ /dev/null @@ -1,12 +0,0 @@ -// Protractor configuration file, see link for more information -// https://github.com/angular/protractor/blob/master/lib/config.ts - -exports.config = { - allScriptsTimeout: 11000, - specs: ['./src/**/*.e2e-spec.ts'], - capabilities: { - browserName: 'chrome' - }, - directConnect: true, - baseUrl: 'http://localhost:4200/' -}; diff --git a/e2e/src/app.e2e-spec.ts b/e2e/src/app.e2e-spec.ts deleted file mode 100644 index 53e277f..0000000 --- a/e2e/src/app.e2e-spec.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { AppPage } from './app.po'; - -describe('workspace-project App', () => { - let page: AppPage; - - beforeEach(() => { - page = new AppPage(); - }); - - it('should display welcome message', () => { - page.navigateTo(); - expect(page.getParagraphText()).toEqual('Welcome to ngrx-auto-entity-app!'); - }); -}); diff --git a/e2e/src/app.po.ts b/e2e/src/app.po.ts deleted file mode 100644 index 82ea75b..0000000 --- a/e2e/src/app.po.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { browser, by, element } from 'protractor'; - -export class AppPage { - navigateTo() { - return browser.get('/'); - } - - getParagraphText() { - return element(by.css('app-root h1')).getText(); - } -} diff --git a/e2e/tsconfig.e2e.json b/e2e/tsconfig.e2e.json deleted file mode 100644 index d02c341..0000000 --- a/e2e/tsconfig.e2e.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../tsconfig.json", - "compilerOptions": { - "outDir": "../out-tsc/app", - "module": "commonjs", - "target": "es5", - "types": ["jest", "node"] - } -} diff --git a/projects/ngrx-auto-entity/src/index.ts b/projects/ngrx-auto-entity/src/index.ts index 4887f32..2cad7b3 100644 --- a/projects/ngrx-auto-entity/src/index.ts +++ b/projects/ngrx-auto-entity/src/index.ts @@ -1,200 +1,200 @@ -/* - * Public API Surface of ngrx-auto-entity - */ - -/* - * Modules - */ -export { - NgrxAutoEntityModule, - NgRxAutoEntityRootModuleWithEffects, - NgRxAutoEntityRootModuleNoEntityEffects, - NgRxAutoEntityRootModuleNoEffects, - NgRxAutoEntityFeatureModule, - NgRxAutoEntityModuleConfig, - getNgRxAutoEntityMetaReducer -} from './lib/module'; - -/* - * Common models referenced throughout Auto-Entity - */ -export { - IPage, - Page, - IFirstLastRange, - IRangeInfo, - ISkipTakeRange, - IStartEndRange, - Range, - RangeValue, - IPageInfo -} from './lib/models'; - -export { IEntityDictionary, IEntityState, EntityIdentity } from './lib/util/entity-state'; -export { IModelState, IModelClass } from './lib/util/model-state'; -export { IEntityFacade } from './lib/util/facade'; -export { ISelectorMap } from './lib/util/selector-map'; - -/* - * Builders - */ -export { buildFacade } from './lib/util/facade-builder'; -export { buildSelectorMap } from './lib/util/selector-map-builder'; -export { buildFeatureState, buildState } from './lib/util/state-builder'; - -/* - * Action Support - */ -export { EntityActionTypes } from './lib/actions/action-types'; -export { IEntityInfo } from './lib/actions/entity-info'; -export { EntityAction } from './lib/actions/entity-action'; -export { ICorrelatedAction } from './lib/actions/entity-action'; -export { fromEntityActions } from './lib/actions/action-operators'; -export { ofEntityType } from './lib/actions/action-operators'; -export { ofEntityAction } from './lib/actions/action-operators'; -export { isEntityActionInstance, EntityActions } from './lib/actions/entity-actions-union'; - -/* - * Actions - */ -export { Load, LoadFailure, LoadSuccess } from './lib/actions/load-actions'; -export { LoadMany, LoadManyFailure, LoadManySuccess } from './lib/actions/load-many-actions'; -export { LoadAll, LoadAllFailure, LoadAllSuccess } from './lib/actions/load-all-actions'; -export { LoadPage, LoadPageFailure, LoadPageSuccess } from './lib/actions/load-page-actions'; -export { LoadRange, LoadRangeFailure, LoadRangeSuccess } from './lib/actions/load-range-actions'; - -export { CreateMany, CreateManyFailure, CreateManySuccess } from './lib/actions/create-actions'; -export { Create, CreateFailure, CreateSuccess } from './lib/actions/create-actions'; -export { UpdateMany, UpdateManyFailure, UpdateManySuccess } from './lib/actions/update-actions'; -export { Update, UpdateFailure, UpdateSuccess } from './lib/actions/update-actions'; -export { UpsertMany, UpsertManyFailure, UpsertManySuccess } from './lib/actions/upsert-actions'; -export { Upsert, UpsertFailure, UpsertSuccess } from './lib/actions/upsert-actions'; -export { ReplaceMany, ReplaceManyFailure, ReplaceManySuccess } from './lib/actions/replace-actions'; -export { Replace, ReplaceFailure, ReplaceSuccess } from './lib/actions/replace-actions'; -export { DeleteMany, DeleteManyFailure, DeleteManySuccess } from './lib/actions/delete-actions'; -export { Delete, DeleteFailure, DeleteSuccess } from './lib/actions/delete-actions'; -export { - DeleteManyByKeys, - DeleteManyByKeysFailure, - DeleteManyByKeysSuccess, - DeleteByKeyFailure, - DeleteByKeySuccess, - DeleteByKey -} from './lib/actions/delete-by-key-actions'; - -export { - Select, - SelectByKey, - Selected, - SelectedMany, - SelectMany, - SelectManyByKeys, - SelectMore, - SelectMoreByKeys -} from './lib/actions/selection-actions'; -export { Deselected, DeselectAll, DeselectManyByKeys, DeselectMany, Deselect } from './lib/actions/deselection-actions'; -export { EditEnded, EndEdit, Changed, Change, EditedByKey, Edited, EditByKey, Edit } from './lib/actions/edit-actions'; -export { Clear } from './lib/actions/actions'; - -/* - * Decorators - */ -export { Entity } from './lib/decorators/entity'; -export { Key } from './lib/decorators/key'; - -/* - * Entity Metadata and Management - */ -export { ENTITY_OPTS_PROP } from './lib/decorators/entity-tokens'; -export { IEffectExcept, IEntityOptions, IEntityTransformer } from './lib/decorators/entity'; -export { IEffectExclusions } from './lib/decorators/effect-exclusions'; -export { curd, loads, extra, all, matching, except } from './lib/decorators/effect-exclusion-utils'; - -/* - * Entity Metadata Utilities - */ -export { makeEntity } from './lib/util/make-entity'; -export { - nameOfEntity, - pluralNameOfEntity, - uriNameOfEntity, - entityComparer, - entityTransforms -} from './lib/decorators/entity-util'; -export { - getKey, - getKeyFromModel, - getKeyFromEntity, - getKeyNames, - getKeyNamesFromModel, - getKeyNamesFromEntity, - checkKeyName -} from './lib/decorators/key'; - -/* - * Reducer - */ -export { autoEntityReducer, autoEntityMetaReducer, stateNameFromAction } from './lib/reducer/reducer'; - -/* - * Entity Service - */ -export { NgrxAutoEntityService } from './lib/service/service'; -export { IAutoEntityService } from './lib/service/interface'; - -export { - IEntityRangeRef, - IEntityPageRef, - IEntityRef, - IEntityIdentityRef, - IEntityIdentitiesRef -} from './lib/service/refs'; -export { IEntityWithRangeInfo, IEntityWithPageInfo, IEntityError } from './lib/service/wrapper-models'; - -/* - * Transformation utilities - */ -export { - transformEntityFromServer, - transformEntitiesFromServer, - transformEntityToServer, - transformEntitiesToServer -} from './lib/service/transformation'; - -/* - * Operators - */ -export { EntityOperators } from './lib/effects/operators'; - -/* - * Effect Groups - */ -export { EntityEffects } from './lib/effects/effects-all'; -export { LoadEffects } from './lib/effects/effects-loads'; -export { CUDEffects } from './lib/effects/effects-cud'; -export { ExtraEffects } from './lib/effects/effects-extra'; - -/* - * Effects - */ -export { - LoadEffect, - LoadAllEffect, - LoadManyEffect, - LoadPageEffect, - LoadRangeEffect -} from './lib/effects/effects-loads-discrete'; -export { - CreateEffect, - CreateManyEffect, - DeleteEffect, - DeleteManyEffect, - DeleteByKeyEffect, - DeleteManyByKeysEffect, - ReplaceEffect, - ReplaceManyEffect, - UpdateEffect, - UpdateManyEffect, - UpsertEffect, - UpsertManyEffect -} from './lib/effects/effects-cud-discrete'; +// /* +// * Public API Surface of ngrx-auto-entity +// */ +// +// /* +// * Modules +// */ +// export { +// NgrxAutoEntityModule, +// NgRxAutoEntityRootModuleWithEffects, +// NgRxAutoEntityRootModuleNoEntityEffects, +// NgRxAutoEntityRootModuleNoEffects, +// NgRxAutoEntityFeatureModule, +// NgRxAutoEntityModuleConfig, +// getNgRxAutoEntityMetaReducer +// } from './lib/module'; +// +// /* +// * Common models and types referenced throughout Auto-Entity +// */ +// export { +// IPage, +// Page, +// IFirstLastRange, +// IRangeInfo, +// ISkipTakeRange, +// IStartEndRange, +// Range, +// RangeValue, +// IPageInfo +// } from './lib/models'; +// export { EntityIdentity } from './lib/types/entity-identity'; +// export { IEntityDictionary, IEntityState } from './lib/util/entity-state'; +// export { IModelState, IModelClass } from './lib/util/model-state'; +// export { IEntityFacade } from './lib/util/facade'; +// export { ISelectorMap } from './lib/util/selector-map'; +// +// /* +// * Builders +// */ +// export { buildFacade } from './lib/util/facade-builder'; +// export { buildSelectorMap } from './lib/util/selector-map-builder'; +// export { buildFeatureState, buildState } from './lib/util/state-builder'; +// +// /* +// * Action Support +// */ +// export { EntityActionTypes } from './lib/actions/action-types'; +// export { IEntityInfo } from './lib/actions/entity-info'; +// export { EntityAction } from './lib/actions/entity-action'; +// export { ICorrelatedAction } from './lib/actions/entity-action'; +// export { fromEntityActions } from './lib/actions/action-operators'; +// export { ofEntityType } from './lib/actions/action-operators'; +// export { ofEntityAction } from './lib/actions/action-operators'; +// export { isEntityActionInstance, EntityActions } from './lib/actions/entity-actions-union'; +// +// /* +// * Actions +// */ +// export { Load, LoadFailure, LoadSuccess } from './lib/actions/load-actions'; +// export { LoadMany, LoadManyFailure, LoadManySuccess } from './lib/actions/load-many-actions'; +// export { LoadAll, LoadAllFailure, LoadAllSuccess } from './lib/actions/load-all-actions'; +// export { LoadPage, LoadPageFailure, LoadPageSuccess } from './lib/actions/load-page-actions'; +// export { LoadRange, LoadRangeFailure, LoadRangeSuccess } from './lib/actions/load-range-actions'; +// +// export { CreateMany, CreateManyFailure, CreateManySuccess } from './lib/actions/create-actions'; +// export { Create, CreateFailure, CreateSuccess } from './lib/actions/create-actions'; +// export { UpdateMany, UpdateManyFailure, UpdateManySuccess } from './lib/actions/update-actions'; +// export { Update, UpdateFailure, UpdateSuccess } from './lib/actions/update-actions'; +// export { UpsertMany, UpsertManyFailure, UpsertManySuccess } from './lib/actions/upsert-actions'; +// export { Upsert, UpsertFailure, UpsertSuccess } from './lib/actions/upsert-actions'; +// export { ReplaceMany, ReplaceManyFailure, ReplaceManySuccess } from './lib/actions/replace-actions'; +// export { Replace, ReplaceFailure, ReplaceSuccess } from './lib/actions/replace-actions'; +// export { DeleteMany, DeleteManyFailure, DeleteManySuccess } from './lib/actions/delete-actions'; +// export { Delete, DeleteFailure, DeleteSuccess } from './lib/actions/delete-actions'; +// export { +// DeleteManyByKeys, +// DeleteManyByKeysFailure, +// DeleteManyByKeysSuccess, +// DeleteByKeyFailure, +// DeleteByKeySuccess, +// DeleteByKey +// } from './lib/actions/delete-by-key-actions'; +// +// export { +// Select, +// SelectByKey, +// Selected, +// SelectedMany, +// SelectMany, +// SelectManyByKeys, +// SelectMore, +// SelectMoreByKeys +// } from './lib/actions/selection-actions'; +// export { Deselected, DeselectAll, DeselectManyByKeys, DeselectMany, Deselect } from './lib/actions/deselection-actions'; +// export { EditEnded, EndEdit, Changed, Change, EditedByKey, Edited, EditByKey, Edit } from './lib/actions/edit-actions'; +// export { Clear } from './lib/actions/actions'; +// +// /* +// * Decorators +// */ +// export { Entity } from './lib/decorators/entity-decorator'; +// export { Key } from './lib/decorators/key-decorator'; +// +// /* +// * Entity Metadata and Management +// */ +// export { ENTITY_OPTS_PROP } from './lib/decorators/entity-tokens'; +// export { IEffectExcept, IEntityOptions, IEntityTransformer, EntityAge } from './lib/decorators/entity-options'; +// export { IEffectExclusions } from './lib/decorators/effect-exclusions'; +// export { curd, loads, extra, all, matching, except } from './lib/decorators/effect-exclusion-utils'; +// +// /* +// * Entity Metadata Utilities +// */ +// export { makeEntity } from './lib/util/make-entity'; +// export { +// nameOfEntity, +// pluralNameOfEntity, +// uriNameOfEntity, +// entityComparer, +// entityTransforms +// } from './lib/decorators/entity-util'; +// export { +// getKey, +// getKeyFromModel, +// getKeyFromEntity, +// getKeyNames, +// getKeyNamesFromModel, +// getKeyNamesFromEntity, +// checkKeyName +// } from './lib/decorators/key-util'; +// +// /* +// * Reducer +// */ +// export { autoEntityReducer, autoEntityMetaReducer, stateNameFromAction } from './lib/reducer/reducer'; +// +// /* +// * Entity Service +// */ +// export { NgrxAutoEntityService } from './lib/service/service'; +// export { IAutoEntityService } from './lib/service/interface'; +// +// export { +// IEntityRangeRef, +// IEntityPageRef, +// IEntityRef, +// IEntityIdentityRef, +// IEntityIdentitiesRef +// } from './lib/service/refs'; +// export { IEntityWithRangeInfo, IEntityWithPageInfo, IEntityError } from './lib/service/wrapper-models'; +// +// /* +// * Transformation utilities +// */ +// export { +// transformEntityFromServer, +// transformEntitiesFromServer, +// transformEntityToServer, +// transformEntitiesToServer +// } from './lib/service/transformation'; +// +// /* +// * Operators +// */ +// export { EntityOperators } from './lib/effects/operators'; +// +// /* +// * Effect Groups +// */ +// export { EntityEffects } from './lib/effects/effects-all'; +// export { LoadEffects } from './lib/effects/effects-loads'; +// export { CUDEffects } from './lib/effects/effects-cud'; +// export { ExtraEffects } from './lib/effects/effects-extra'; +// +// /* +// * Effects +// */ +// export { +// LoadEffect, +// LoadAllEffect, +// LoadManyEffect, +// LoadPageEffect, +// LoadRangeEffect +// } from './lib/effects/effects-loads-discrete'; +// export { +// CreateEffect, +// CreateManyEffect, +// DeleteEffect, +// DeleteManyEffect, +// DeleteByKeyEffect, +// DeleteManyByKeysEffect, +// ReplaceEffect, +// ReplaceManyEffect, +// UpdateEffect, +// UpdateManyEffect, +// UpsertEffect, +// UpsertManyEffect +// } from './lib/effects/effects-cud-discrete'; diff --git a/projects/ngrx-auto-entity/src/lib/actions/actions.spec.ts b/projects/ngrx-auto-entity/src/lib/actions/actions.spec.ts index 59c283c..d33d86c 100644 --- a/projects/ngrx-auto-entity/src/lib/actions/actions.spec.ts +++ b/projects/ngrx-auto-entity/src/lib/actions/actions.spec.ts @@ -3,14 +3,12 @@ import { provideMockActions } from '@ngrx/effects/testing'; import { hot } from 'jasmine-marbles'; import { Observable } from 'rxjs'; -import { Entity } from '../decorators/entity'; -import { Key } from '../decorators/key'; +import { Entity } from '../decorators/entity-decorator'; +import { Key } from '../decorators/key-decorator'; import { IEntityError } from '../service/wrapper-models'; import { fromEntityActions, ofEntityAction, ofEntityType } from './action-operators'; import { EntityActionTypes } from './action-types'; -import { - Clear -} from './actions'; +import { Clear } from './actions'; import { Create, CreateFailure, diff --git a/projects/ngrx-auto-entity/src/lib/actions/delete-by-key-actions.ts b/projects/ngrx-auto-entity/src/lib/actions/delete-by-key-actions.ts index edf54a5..76ab0f9 100644 --- a/projects/ngrx-auto-entity/src/lib/actions/delete-by-key-actions.ts +++ b/projects/ngrx-auto-entity/src/lib/actions/delete-by-key-actions.ts @@ -1,4 +1,4 @@ -import { EntityIdentity } from '../util/entity-state'; +import { EntityIdentity } from '../types/entity-identity'; import { EntityActionTypes } from './action-types'; import { EntityAction } from './entity-action'; diff --git a/projects/ngrx-auto-entity/src/lib/actions/deselection-actions.ts b/projects/ngrx-auto-entity/src/lib/actions/deselection-actions.ts index 55be8b8..a71e72a 100644 --- a/projects/ngrx-auto-entity/src/lib/actions/deselection-actions.ts +++ b/projects/ngrx-auto-entity/src/lib/actions/deselection-actions.ts @@ -1,4 +1,4 @@ -import { EntityIdentity } from '../util/entity-state'; +import { EntityIdentity } from '../types/entity-identity'; import { EntityActionTypes } from './action-types'; import { EntityAction } from './entity-action'; diff --git a/projects/ngrx-auto-entity/src/lib/actions/edit-actions.ts b/projects/ngrx-auto-entity/src/lib/actions/edit-actions.ts index 7ffbc3a..95ead86 100644 --- a/projects/ngrx-auto-entity/src/lib/actions/edit-actions.ts +++ b/projects/ngrx-auto-entity/src/lib/actions/edit-actions.ts @@ -1,4 +1,4 @@ -import { EntityIdentity } from '../util/entity-state'; +import { EntityIdentity } from '../types/entity-identity'; import { EntityActionTypes } from './action-types'; import { EntityAction } from './entity-action'; diff --git a/projects/ngrx-auto-entity/src/lib/actions/entity-actions-union.ts b/projects/ngrx-auto-entity/src/lib/actions/entity-actions-union.ts index 1546241..a4bc35e 100644 --- a/projects/ngrx-auto-entity/src/lib/actions/entity-actions-union.ts +++ b/projects/ngrx-auto-entity/src/lib/actions/entity-actions-union.ts @@ -1,6 +1,4 @@ -import { - Clear -} from './actions'; +import { Clear } from './actions'; import { Create, CreateFailure, @@ -19,7 +17,8 @@ import { } from './delete-actions'; import { DeleteByKey, - DeleteByKeyFailure, DeleteByKeySuccess, + DeleteByKeyFailure, + DeleteByKeySuccess, DeleteManyByKeys, DeleteManyByKeysFailure, DeleteManyByKeysSuccess diff --git a/projects/ngrx-auto-entity/src/lib/actions/entity-info.ts b/projects/ngrx-auto-entity/src/lib/actions/entity-info.ts index b022d8d..b1c8ee1 100644 --- a/projects/ngrx-auto-entity/src/lib/actions/entity-info.ts +++ b/projects/ngrx-auto-entity/src/lib/actions/entity-info.ts @@ -1,4 +1,4 @@ -import { IEntityNames, IEntityTransformer } from '../decorators/entity'; +import { IEntityNames, IEntityTransformer } from '../decorators/entity-options'; /** * Descriptor of an Entity model and related metadata. diff --git a/projects/ngrx-auto-entity/src/lib/actions/selection-actions.ts b/projects/ngrx-auto-entity/src/lib/actions/selection-actions.ts index a2f8e04..909f5a0 100644 --- a/projects/ngrx-auto-entity/src/lib/actions/selection-actions.ts +++ b/projects/ngrx-auto-entity/src/lib/actions/selection-actions.ts @@ -1,4 +1,4 @@ -import { EntityIdentity } from '../util/entity-state'; +import { EntityIdentity } from '../types/entity-identity'; import { EntityActionTypes } from './action-types'; import { EntityAction } from './entity-action'; diff --git a/projects/ngrx-auto-entity/src/lib/actions/util.ts b/projects/ngrx-auto-entity/src/lib/actions/util.ts index 455adde..c3a917d 100644 --- a/projects/ngrx-auto-entity/src/lib/actions/util.ts +++ b/projects/ngrx-auto-entity/src/lib/actions/util.ts @@ -1,7 +1,7 @@ import { pascalCase } from '../../util/case'; -import { IEntityOptions } from '../decorators/entity'; +import { IEntityOptions } from '../decorators/entity-options'; import { ENTITY_OPTS_PROP } from '../decorators/entity-tokens'; -import { checkKeyName } from '../decorators/key'; +import { checkKeyName } from '../decorators/key-util'; import { IEntityInfo } from './entity-info'; /** diff --git a/projects/ngrx-auto-entity/src/lib/decorators/entiti-decorator.spec.ts b/projects/ngrx-auto-entity/src/lib/decorators/entiti-decorator.spec.ts new file mode 100644 index 0000000..f88000d --- /dev/null +++ b/projects/ngrx-auto-entity/src/lib/decorators/entiti-decorator.spec.ts @@ -0,0 +1,166 @@ +import { EntityActionTypes } from '../actions/action-types'; +import { all, curd, extra, loads, matching } from './effect-exclusion-utils'; +import { Entity } from './entity-decorator'; +import { EntityAge } from './entity-options'; +import { ENTITY_OPTS_PROP } from './entity-tokens'; + +describe('Decorator: @Entity', () => { + test('should decorate model type with un-editable "__nae_entity_opts" property', () => { + @Entity({ modelName: 'Model' }) + class Model {} + + expect(Model[ENTITY_OPTS_PROP]).toBeTruthy(); + expect(() => { + Model[ENTITY_OPTS_PROP] = ''; + }).toThrow(); + }); + + test('should add required modelName property to entity options from options object', () => { + @Entity({ modelName: 'Model' }) + class Model {} + + expect(Model[ENTITY_OPTS_PROP].modelName).toBe('Model'); + }); + + test('should add required modelName property to entity options from string name', () => { + @Entity('Model') + class Model {} + + expect(Model[ENTITY_OPTS_PROP].modelName).toBe('Model'); + }); + + test('should add required modelName and additional options properties to entity options from string name and additional options object', () => { + @Entity('Model', { + pluralName: 'Models', + uriName: 'models' + }) + class Model {} + + expect(Model[ENTITY_OPTS_PROP].modelName).toBe('Model'); + expect(Model[ENTITY_OPTS_PROP]).toMatchObject({ + modelName: 'Model', + pluralName: 'Models', + uriName: 'models' + }); + }); + + test('should add custom pluralized name to entity options', () => { + @Entity({ modelName: 'Model', pluralName: 'Models' }) + class Model {} + + expect(Model[ENTITY_OPTS_PROP].modelName).toBe('Model'); + expect(Model[ENTITY_OPTS_PROP].pluralName).toBe('Models'); + }); + + test('should add custom uri name to entity options', () => { + @Entity({ modelName: 'Model', uriName: 'modeling' }) + class Model {} + + expect(Model[ENTITY_OPTS_PROP].modelName).toBe('Model'); + expect(Model[ENTITY_OPTS_PROP].uriName).toBe('modeling'); + }); + + test('should add defaultMaxAge to entity options', () => { + @Entity({ modelName: 'Model', defaultMaxAge: EntityAge.Day }) + class Model {} + + expect(Model[ENTITY_OPTS_PROP].modelName).toBe('Model'); + expect(Model[ENTITY_OPTS_PROP].defaultMaxAge).toBe(86400); + }); + + test('should add all effects as exclusions', () => { + @Entity({ modelName: 'Model', excludeEffects: all }) + class Model {} + + expect(Model[ENTITY_OPTS_PROP].modelName).toBe('Model'); + expect(Model[ENTITY_OPTS_PROP].excludeEffects).toBe(all); + }); + + test('should add all effects except Clear as exclusions', () => { + @Entity({ modelName: 'Model', excludeEffects: all.except(EntityActionTypes.Clear) }) + class Model {} + + expect(Model[ENTITY_OPTS_PROP].modelName).toBe('Model'); + expect(Model[ENTITY_OPTS_PROP].excludeEffects).toEqual(all.except(EntityActionTypes.Clear)); + }); + + test('should add loads effects as exclusions', () => { + @Entity({ modelName: 'Model', excludeEffects: loads }) + class Model {} + + expect(Model[ENTITY_OPTS_PROP].modelName).toBe('Model'); + expect(Model[ENTITY_OPTS_PROP].excludeEffects).toBe(loads); + }); + + test('should add loads effects except Load as exclusions', () => { + @Entity({ modelName: 'Model', excludeEffects: loads.except(EntityActionTypes.Load) }) + class Model {} + + expect(Model[ENTITY_OPTS_PROP].modelName).toBe('Model'); + expect(Model[ENTITY_OPTS_PROP].excludeEffects).toEqual(loads.except(EntityActionTypes.Load)); + }); + + test('should add curd effects as exclusions', () => { + @Entity({ modelName: 'Model', excludeEffects: curd }) + class Model {} + + expect(Model[ENTITY_OPTS_PROP].modelName).toBe('Model'); + expect(Model[ENTITY_OPTS_PROP].excludeEffects).toBe(curd); + }); + + test('should add curd effects except Create as exclusions', () => { + @Entity({ modelName: 'Model', excludeEffects: curd.except(EntityActionTypes.Create) }) + class Model {} + + expect(Model[ENTITY_OPTS_PROP].modelName).toBe('Model'); + expect(Model[ENTITY_OPTS_PROP].excludeEffects).toEqual(curd.except(EntityActionTypes.Create)); + }); + + test('should add extra effects as exclusions', () => { + @Entity({ modelName: 'Model', excludeEffects: extra }) + class Model {} + + expect(Model[ENTITY_OPTS_PROP].modelName).toBe('Model'); + expect(Model[ENTITY_OPTS_PROP].excludeEffects).toBe(extra); + }); + + test('should add extra effects except Select as exclusions', () => { + @Entity({ modelName: 'Model', excludeEffects: extra.except(EntityActionTypes.Select) }) + class Model {} + + expect(Model[ENTITY_OPTS_PROP].modelName).toBe('Model'); + expect(Model[ENTITY_OPTS_PROP].excludeEffects).toEqual(extra.except(EntityActionTypes.Select)); + }); + + test('should add matching effects as exclusions', () => { + @Entity({ + modelName: 'Model', + excludeEffects: matching(EntityActionTypes.Select, EntityActionTypes.Clear, EntityActionTypes.Load) + }) + class Model {} + + expect(Model[ENTITY_OPTS_PROP].modelName).toBe('Model'); + expect(Model[ENTITY_OPTS_PROP].excludeEffects).toEqual( + matching(EntityActionTypes.Select, EntityActionTypes.Clear, EntityActionTypes.Load) + ); + }); + + test('should include transformations listed in decorator', () => { + const xform1 = { fromServer: data => data, toServer: data => data }; + const xform2 = { + fromServer: data => ((data.prop = +data.prop), data), + toServer: data => ((data.prop = data.prop.toString()), data) + }; + + @Entity({ + modelName: 'Model', + transform: [xform1, xform2] + }) + class Model { + prop: number; + } + + expect(Model[ENTITY_OPTS_PROP].modelName).toBe('Model'); + expect(Model[ENTITY_OPTS_PROP].transform).toEqual([xform1, xform2]); + }); +}); diff --git a/projects/ngrx-auto-entity/src/lib/decorators/entity-decorator.ts b/projects/ngrx-auto-entity/src/lib/decorators/entity-decorator.ts new file mode 100644 index 0000000..6bc3ded --- /dev/null +++ b/projects/ngrx-auto-entity/src/lib/decorators/entity-decorator.ts @@ -0,0 +1,39 @@ +import { IEntityOptions } from './entity-options'; +import { ENTITY_OPTS_PROP } from './entity-tokens'; + +/** + * Entity decorator for configuring each entity model. + * + * @param options - The configuration options to apply + */ +export function Entity(options: IEntityOptions); + +/** + * Entity decorator for configuring each entity model. + * + * @param modelName - The model name option to apply + * @param options - Additional configuration options to apply + */ +export function Entity(modelName?: string, options?: Partial); + +/** + * Entity decorator for configuring each entity model. + * + * @param nameOrOptions - The model name or configuration options to apply + * @param maybeOptions - Additional options to apply if a model name is passed as the first param + */ +export function Entity(nameOrOptions: string | IEntityOptions, maybeOptions?: Partial) { + return function entityDecorator(constructor: any) { + const initialOptions = typeof nameOrOptions === 'object' ? nameOrOptions : { modelName: nameOrOptions }; + const options = maybeOptions ? { ...maybeOptions, ...initialOptions } : initialOptions; + + const descriptor = Object.create(null); + descriptor.configurable = false; + descriptor.enumerable = false; + descriptor.writable = false; + descriptor.value = options; + Object.defineProperty(constructor, ENTITY_OPTS_PROP, descriptor); + + return constructor; + }; +} diff --git a/projects/ngrx-auto-entity/src/lib/decorators/entity-operators.spec.ts b/projects/ngrx-auto-entity/src/lib/decorators/entity-operators.spec.ts new file mode 100644 index 0000000..44264d4 --- /dev/null +++ b/projects/ngrx-auto-entity/src/lib/decorators/entity-operators.spec.ts @@ -0,0 +1,56 @@ +import { hot } from 'jasmine-marbles'; +import { EntityActionTypes } from '../actions/action-types'; +import { Clear } from '../actions/actions'; +import { matching } from './effect-exclusion-utils'; +import { Entity } from './entity-decorator'; +import { shouldApplyEffect } from './entity-operators'; +import { ENTITY_OPTS_PROP } from './entity-tokens'; +import { Key } from './key-decorator'; + +describe('Operator: shouldApplyEffect', () => { + test('should not filter out model without @entity decorator', () => { + class Model { + @Key id: number; + } + + const action = new Clear(Model); + + const actions = hot('-a-|', { a: action }); + const expected = hot('-a-|', { a: action }); + const result = actions.pipe(shouldApplyEffect()); + + expect(result).toBeObservable(expected); + }); + + test('should not filter out model without exclusion', () => { + @Entity({ modelName: 'Model' }) + class Model { + @Key id: number; + } + + const action = new Clear(Model); + + const actions = hot('-a-|', { a: action }); + const expected = hot('-a-|', { a: action }); + const result = actions.pipe(shouldApplyEffect()); + + expect(Model[ENTITY_OPTS_PROP].modelName).toBe('Model'); + expect(result).toBeObservable(expected); + }); + + test('should filter out model with exclusion', () => { + @Entity({ modelName: 'Model', excludeEffects: matching(EntityActionTypes.Clear) }) + class Model { + @Key id: number; + } + + const action = new Clear(Model); + + const actions = hot('-a-|)', { a: action }); + const expected = hot('---|', { a: action }); + const result = actions.pipe(shouldApplyEffect()); + + expect(Model[ENTITY_OPTS_PROP].modelName).toBe('Model'); + expect(result).toBeObservable(expected); + }); +}); diff --git a/projects/ngrx-auto-entity/src/lib/decorators/entity.ts b/projects/ngrx-auto-entity/src/lib/decorators/entity-options.ts similarity index 57% rename from projects/ngrx-auto-entity/src/lib/decorators/entity.ts rename to projects/ngrx-auto-entity/src/lib/decorators/entity-options.ts index 5fff0c1..ae3dcfa 100644 --- a/projects/ngrx-auto-entity/src/lib/decorators/entity.ts +++ b/projects/ngrx-auto-entity/src/lib/decorators/entity-options.ts @@ -1,6 +1,5 @@ import { EntityActionTypes } from '../actions/action-types'; import { IEffectExclusions } from './effect-exclusions'; -import { ENTITY_OPTS_PROP } from './entity-tokens'; /** * Defines effect exceptions for the decorated model. @@ -18,6 +17,7 @@ export interface IEntityTransformer { } export type EntityComparer = (a, b) => number; + export interface IEntityComparerMap { [key: string]: EntityComparer | string; } @@ -28,27 +28,29 @@ export interface IEntityNames { uriName?: string; } +export enum EntityAge { + Minute = 60, + Hour = EntityAge.Minute * 60, + QuarterDay = EntityAge.Hour * 6, + HalfDay = EntityAge.Hour * 12, + Day = EntityAge.Hour * 24, + Week = EntityAge.Day * 7 +} + /** * The options that may be configured for a decorated entity model. + * + * @property comparer - (optional) A default comparer for sorting entities on selection + * @property comparers - (optional) A set of comparer functions or named comparer references for sorting entities + * @property transform - (optional) A set of entity transform objects that may be composed, in order, to transform the entity + * @property excludeEffects - (optional) The effect exclusion config + * @see IEffectExclusions + * @property defaultMaxAge - (optional) A default maximum age, in seconds, after which load*IfNecessary actions will always load */ export interface IEntityOptions extends IEntityNames { comparer?: EntityComparer; comparers?: IEntityComparerMap; transform?: IEntityTransformer[]; excludeEffects?: IEffectExclusions | IEffectExcept; -} - -/** - * Entity decorator for configuring each entity model. - * - * @param options The configuration options to apply. - */ -export function Entity(options: IEntityOptions) { - return function entityDecorator(constructor: any) { - const descriptor = Object.create(null); - descriptor.value = options; - Object.defineProperty(constructor, ENTITY_OPTS_PROP, descriptor); - - return constructor; - }; + defaultMaxAge?: number | EntityAge; } diff --git a/projects/ngrx-auto-entity/src/lib/decorators/entity-tokens.spec.ts b/projects/ngrx-auto-entity/src/lib/decorators/entity-tokens.spec.ts new file mode 100644 index 0000000..c3e8e36 --- /dev/null +++ b/projects/ngrx-auto-entity/src/lib/decorators/entity-tokens.spec.ts @@ -0,0 +1,19 @@ +import { ENTITY_OPTS_PROP, NAE_KEY_NAMES, NAE_KEYS } from './entity-tokens'; + +describe('Constant: ENTITY_OPTS_PROP', () => { + test('should equal "__nae_entity_opts"', () => { + expect(ENTITY_OPTS_PROP).toBe('__nae_entity_opts'); + }); +}); + +describe('Constant: NAE_KEYS', () => { + test('should equal "__nae_keys"', () => { + expect(NAE_KEYS).toBe('__nae_keys'); + }); +}); + +describe('Constant: NAE_KEY_NAMES', () => { + test('should equal "__nae_key_names"', () => { + expect(NAE_KEY_NAMES).toBe('__nae_key_names'); + }); +}); diff --git a/projects/ngrx-auto-entity/src/lib/decorators/entity-tokens.ts b/projects/ngrx-auto-entity/src/lib/decorators/entity-tokens.ts index bf3c51e..d3c2d2b 100644 --- a/projects/ngrx-auto-entity/src/lib/decorators/entity-tokens.ts +++ b/projects/ngrx-auto-entity/src/lib/decorators/entity-tokens.ts @@ -1 +1,7 @@ +// NOTE: The following constants should be Symbol() to avoid any potential conflict with +// any user-defined properties on the entity models. However, use of Symbol() here causes +// problems with the Jest test runner at the current time + export const ENTITY_OPTS_PROP = '__nae_entity_opts'; +export const NAE_KEYS = '__nae_keys'; +export const NAE_KEY_NAMES = '__nae_key_names'; diff --git a/projects/ngrx-auto-entity/src/lib/decorators/entity-util.spec.ts b/projects/ngrx-auto-entity/src/lib/decorators/entity-util.spec.ts index d6133d4..ab00ae9 100644 --- a/projects/ngrx-auto-entity/src/lib/decorators/entity-util.spec.ts +++ b/projects/ngrx-auto-entity/src/lib/decorators/entity-util.spec.ts @@ -1,11 +1,19 @@ -import { Entity } from './entity'; -import { entityComparer, entityTransforms, nameOfEntity, pluralNameOfEntity, uriNameOfEntity } from './entity-util'; -import { Key } from './key'; +import { Entity } from './entity-decorator'; +import { + entityComparer, + entityMaxAge, + entityTransforms, + nameOfEntity, + pluralNameOfEntity, + uriNameOfEntity +} from './entity-util'; +import { Key } from './key-decorator'; @Entity({ modelName: 'TestEntity', pluralName: 'TestEntities', uriName: 'test-entities', + defaultMaxAge: 600, comparer: (a: any, b: any) => a.id - b.id, comparers: { default: 'id', @@ -39,7 +47,7 @@ describe('nameOfEntity()', () => { it('should return nullish if entity null', () => { const name = nameOfEntity(null); - expect(name).toBeNull(); + expect(name).toBeUndefined(); }); it('should return nullish if entity undefined', () => { @@ -66,7 +74,7 @@ describe('uriNameOfEntity()', () => { it('should return nullish if entity null', () => { const name = uriNameOfEntity(null); - expect(name).toBeNull(); + expect(name).toBeUndefined(); }); it('should return nullish if entity undefined', () => { @@ -93,7 +101,7 @@ describe('pluralNameOfEntity()', () => { it('should return nullish if entity null', () => { const name = pluralNameOfEntity(null); - expect(name).toBeNull(); + expect(name).toBeUndefined(); }); it('should return nullish if entity undefined', () => { @@ -134,7 +142,7 @@ describe('entityComparer()', () => { it('should return nullish if entity null', () => { const name = entityComparer(null); - expect(name).toBeNull(); + expect(name).toBeUndefined(); }); it('should return nullish if entity undefined', () => { @@ -165,7 +173,7 @@ describe('entityTransforms()', () => { it('should return nullish if entity null', () => { const transforms = entityTransforms(null); - expect(transforms).toBeNull(); + expect(transforms).toBeUndefined(); }); it('should return nullish if entity undefined', () => { @@ -178,3 +186,30 @@ describe('entityTransforms()', () => { expect(transforms).toBeUndefined(); }); }); + +describe('entityMaxAge()', () => { + it('should return max age of entity type if decorated', () => { + const maxAge = entityMaxAge(TestEntity); + expect(maxAge).toBe(600); + }); + + it('should return max age of entity instance if decorated', () => { + const maxAge = entityMaxAge(new TestEntity()); + expect(maxAge).toBe(600); + }); + + it('should return nullish if entity null', () => { + const transforms = entityMaxAge(null); + expect(transforms).toBeUndefined(); + }); + + it('should return nullish if entity undefined', () => { + const transforms = entityMaxAge(undefined); + expect(transforms).toBeUndefined(); + }); + + it('should return nullish if entity is not decorated', () => { + const transforms = entityMaxAge(new NotAnEntity()); + expect(transforms).toBeUndefined(); + }); +}); diff --git a/projects/ngrx-auto-entity/src/lib/decorators/entity-util.ts b/projects/ngrx-auto-entity/src/lib/decorators/entity-util.ts index 2002aaf..52dd0a8 100644 --- a/projects/ngrx-auto-entity/src/lib/decorators/entity-util.ts +++ b/projects/ngrx-auto-entity/src/lib/decorators/entity-util.ts @@ -1,24 +1,35 @@ +import { pipe } from '../../util/func'; import { TNew } from '../actions/model-constructor'; -import { EntityComparer, IEntityOptions, IEntityTransformer } from './entity'; +import { EntityComparer, IEntityOptions, IEntityTransformer } from './entity-options'; import { ENTITY_OPTS_PROP } from './entity-tokens'; -export const nameOfEntity = (entityOrType: TNew | TModel): string | null | undefined => - entityOrType && - ((entityOrType[ENTITY_OPTS_PROP] || - (entityOrType.constructor ? entityOrType.constructor[ENTITY_OPTS_PROP] : {}) || - {}) as IEntityOptions).modelName; +export const EMPTY_OBJECT = {}; + +export const getEntity = (entityOrType: TNew | TModel | TModel[]): TNew | TModel => + Array.isArray(entityOrType) ? entityOrType[0] : entityOrType; + +export const ensureObject = value => value || EMPTY_OBJECT; + +export const getEntityOptions = (entityOrType: TNew | TModel | TModel[]): IEntityOptions => + (entityOrType[ENTITY_OPTS_PROP] || + (entityOrType.constructor ? entityOrType.constructor[ENTITY_OPTS_PROP] : EMPTY_OBJECT) || + EMPTY_OBJECT) as IEntityOptions; + +export const entityOptions = (entityOrType: TNew | TModel | TModel[]): IEntityOptions => + pipe( + getEntity, + ensureObject, + getEntityOptions + )(entityOrType); + +export const nameOfEntity = (entityOrType: TNew | TModel): string | undefined => + entityOptions(entityOrType).modelName; export const uriNameOfEntity = (entityOrType: TNew | TModel): string | null | undefined => - entityOrType && - ((entityOrType[ENTITY_OPTS_PROP] || - (entityOrType.constructor ? entityOrType.constructor[ENTITY_OPTS_PROP] : {}) || - {}) as IEntityOptions).uriName; + entityOptions(entityOrType).uriName; export const pluralNameOfEntity = (entityOrType: TNew | TModel): string | null | undefined => - entityOrType && - ((entityOrType[ENTITY_OPTS_PROP] || - (entityOrType.constructor ? entityOrType.constructor[ENTITY_OPTS_PROP] : {}) || - {}) as IEntityOptions).pluralName; + entityOptions(entityOrType).pluralName; export const mapComparer = (options: IEntityOptions, name: string): EntityComparer => !!options.comparers @@ -40,26 +51,14 @@ export const namedComparer = (options: IEntityOptions, name: string): EntityComp export const getComparer = (options: IEntityOptions, name?: string): EntityComparer => !!options ? (!!name ? namedComparer(options, name) : defaultComparer(options)) : undefined; -export const getEntity = (entityOrType: TNew | TModel | TModel[]): TNew | TModel => - Array.isArray(entityOrType) ? entityOrType[0] : entityOrType; - export const entityComparer = ( entityOrType: TNew | TModel | TModel[], name?: string -): EntityComparer | null | undefined => - (entityOrType = getEntity(entityOrType)) && - entityOrType && - getComparer( - (entityOrType[ENTITY_OPTS_PROP] || - (entityOrType.constructor ? entityOrType.constructor[ENTITY_OPTS_PROP] : {}) || - {}) as IEntityOptions, - name - ); +): EntityComparer | null | undefined => getComparer(entityOptions(entityOrType), name); export const entityTransforms = ( entityOrType: TNew | TModel -): IEntityTransformer[] | null | undefined => - entityOrType && - ((entityOrType[ENTITY_OPTS_PROP] || - (entityOrType.constructor ? entityOrType.constructor[ENTITY_OPTS_PROP] : {}) || - {}) as IEntityOptions).transform; +): IEntityTransformer[] | null | undefined => entityOptions(entityOrType).transform; + +export const entityMaxAge = (entityOrType: TNew | TModel | TModel[]): number => + entityOptions(entityOrType).defaultMaxAge; diff --git a/projects/ngrx-auto-entity/src/lib/decorators/entity.spec.ts b/projects/ngrx-auto-entity/src/lib/decorators/entity.spec.ts index d01c799..671a93d 100644 --- a/projects/ngrx-auto-entity/src/lib/decorators/entity.spec.ts +++ b/projects/ngrx-auto-entity/src/lib/decorators/entity.spec.ts @@ -1,12 +1,6 @@ -import { hot } from 'jasmine-marbles'; - import { EntityActionTypes } from '../actions/action-types'; -import { Clear } from '../actions/actions'; import { all, curd, except, extra, loads, matching } from './effect-exclusion-utils'; -import { Entity } from './entity'; -import { shouldApplyEffect } from './entity-operators'; import { ENTITY_OPTS_PROP } from './entity-tokens'; -import { Key } from './key'; describe('Function: except', () => { test('should return function if called partially', () => { @@ -232,181 +226,3 @@ describe('Utility: curd', () => { expect(curd.except(EntityActionTypes.Create, EntityActionTypes.Delete)).toEqual(EXCEPTED); }); }); - -describe('Constant: ENTITY_OPTS_PROP', () => { - test('should equal "__nae_entity_opts"', () => { - expect(ENTITY_OPTS_PROP).toBe('__nae_entity_opts'); - }); -}); - -describe('Decorator: @Entity', () => { - test('should decorate model type with uneditable "__nae_entity_opts" property', () => { - @Entity({ modelName: 'Model' }) - class Model {} - - expect(Model[ENTITY_OPTS_PROP]).toBeTruthy(); - expect(() => { - Model[ENTITY_OPTS_PROP] = ''; - }).toThrow(); - }); - - test('should add custom pluralized name to entity options', () => { - @Entity({ modelName: 'Model', pluralName: 'Models' }) - class Model {} - - expect(Model[ENTITY_OPTS_PROP].modelName).toBe('Model'); - expect(Model[ENTITY_OPTS_PROP].pluralName).toBe('Models'); - }); - - test('should add custom uri name to entity options', () => { - @Entity({ modelName: 'Model', uriName: 'modeling' }) - class Model {} - - expect(Model[ENTITY_OPTS_PROP].modelName).toBe('Model'); - expect(Model[ENTITY_OPTS_PROP].uriName).toBe('modeling'); - }); - - test('should add all effects as exclusions', () => { - @Entity({ modelName: 'Model', excludeEffects: all }) - class Model {} - - expect(Model[ENTITY_OPTS_PROP].modelName).toBe('Model'); - expect(Model[ENTITY_OPTS_PROP].excludeEffects).toBe(all); - }); - - test('should add all effects except Clear as exclusions', () => { - @Entity({ modelName: 'Model', excludeEffects: all.except(EntityActionTypes.Clear) }) - class Model {} - - expect(Model[ENTITY_OPTS_PROP].modelName).toBe('Model'); - expect(Model[ENTITY_OPTS_PROP].excludeEffects).toEqual(all.except(EntityActionTypes.Clear)); - }); - - test('should add loads effects as exclusions', () => { - @Entity({ modelName: 'Model', excludeEffects: loads }) - class Model {} - - expect(Model[ENTITY_OPTS_PROP].modelName).toBe('Model'); - expect(Model[ENTITY_OPTS_PROP].excludeEffects).toBe(loads); - }); - - test('should add loads effects except Load as exclusions', () => { - @Entity({ modelName: 'Model', excludeEffects: loads.except(EntityActionTypes.Load) }) - class Model {} - - expect(Model[ENTITY_OPTS_PROP].modelName).toBe('Model'); - expect(Model[ENTITY_OPTS_PROP].excludeEffects).toEqual(loads.except(EntityActionTypes.Load)); - }); - - test('should add curd effects as exclusions', () => { - @Entity({ modelName: 'Model', excludeEffects: curd }) - class Model {} - - expect(Model[ENTITY_OPTS_PROP].modelName).toBe('Model'); - expect(Model[ENTITY_OPTS_PROP].excludeEffects).toBe(curd); - }); - - test('should add curd effects except Create as exclusions', () => { - @Entity({ modelName: 'Model', excludeEffects: curd.except(EntityActionTypes.Create) }) - class Model {} - - expect(Model[ENTITY_OPTS_PROP].modelName).toBe('Model'); - expect(Model[ENTITY_OPTS_PROP].excludeEffects).toEqual(curd.except(EntityActionTypes.Create)); - }); - - test('should add extra effects as exclusions', () => { - @Entity({ modelName: 'Model', excludeEffects: extra }) - class Model {} - - expect(Model[ENTITY_OPTS_PROP].modelName).toBe('Model'); - expect(Model[ENTITY_OPTS_PROP].excludeEffects).toBe(extra); - }); - - test('should add extra effects except Select as exclusions', () => { - @Entity({ modelName: 'Model', excludeEffects: extra.except(EntityActionTypes.Select) }) - class Model {} - - expect(Model[ENTITY_OPTS_PROP].modelName).toBe('Model'); - expect(Model[ENTITY_OPTS_PROP].excludeEffects).toEqual(extra.except(EntityActionTypes.Select)); - }); - - test('should add matching effects as exclusions', () => { - @Entity({ - modelName: 'Model', - excludeEffects: matching(EntityActionTypes.Select, EntityActionTypes.Clear, EntityActionTypes.Load) - }) - class Model {} - - expect(Model[ENTITY_OPTS_PROP].modelName).toBe('Model'); - expect(Model[ENTITY_OPTS_PROP].excludeEffects).toEqual( - matching(EntityActionTypes.Select, EntityActionTypes.Clear, EntityActionTypes.Load) - ); - }); - - test('should include transformations listed in decorator', () => { - const xform1 = { fromServer: data => data, toServer: data => data }; - const xform2 = { - fromServer: data => ((data.prop = +data.prop), data), - toServer: data => ((data.prop = data.prop.toString()), data) - }; - - @Entity({ - modelName: 'Model', - transform: [xform1, xform2] - }) - class Model { - prop: number; - } - - expect(Model[ENTITY_OPTS_PROP].modelName).toBe('Model'); - expect(Model[ENTITY_OPTS_PROP].transform).toEqual([xform1, xform2]); - }); -}); - -describe('Operator: shouldApplyEffect', () => { - test('should not filter out model without @entity decorator', () => { - class Model { - @Key id: number; - } - - const action = new Clear(Model); - - const actions = hot('-a-|', { a: action }); - const expected = hot('-a-|', { a: action }); - const result = actions.pipe(shouldApplyEffect()); - - expect(result).toBeObservable(expected); - }); - - test('should not filter out model without exclusion', () => { - @Entity({ modelName: 'Model' }) - class Model { - @Key id: number; - } - - const action = new Clear(Model); - - const actions = hot('-a-|', { a: action }); - const expected = hot('-a-|', { a: action }); - const result = actions.pipe(shouldApplyEffect()); - - expect(Model[ENTITY_OPTS_PROP].modelName).toBe('Model'); - expect(result).toBeObservable(expected); - }); - - test('should filter out model with exclusion', () => { - @Entity({ modelName: 'Model', excludeEffects: matching(EntityActionTypes.Clear) }) - class Model { - @Key id: number; - } - - const action = new Clear(Model); - - const actions = hot('-a-|)', { a: action }); - const expected = hot('---|', { a: action }); - const result = actions.pipe(shouldApplyEffect()); - - expect(Model[ENTITY_OPTS_PROP].modelName).toBe('Model'); - expect(result).toBeObservable(expected); - }); -}); diff --git a/projects/ngrx-auto-entity/src/lib/decorators/key-decorator.spec.ts b/projects/ngrx-auto-entity/src/lib/decorators/key-decorator.spec.ts new file mode 100644 index 0000000..48a88ca --- /dev/null +++ b/projects/ngrx-auto-entity/src/lib/decorators/key-decorator.spec.ts @@ -0,0 +1,28 @@ +import { NAE_KEYS } from './entity-tokens'; +import { Key } from './key-decorator'; + +class TestEntity { + @Key id: number; +} + +describe('Function: Key', () => { + test(`should attach ${NAE_KEYS} property to target`, () => { + const myEntity = {}; + Key(myEntity, 'test'); + expect(myEntity[NAE_KEYS]).toBeDefined(); + }); +}); + +describe('Decorator: @Key', () => { + test(`should attach ${NAE_KEYS} property to target`, () => { + const myEntity = new TestEntity(); + expect(myEntity[NAE_KEYS]).toBeDefined(); + }); + + test(`should return name key property`, () => { + const myEntity = new TestEntity(); + const keyNames = myEntity[NAE_KEYS]; + expect(keyNames.length).toBe(1); + expect(keyNames[0]).toBe('id'); + }); +}); diff --git a/projects/ngrx-auto-entity/src/lib/decorators/key-decorator.ts b/projects/ngrx-auto-entity/src/lib/decorators/key-decorator.ts new file mode 100644 index 0000000..4c5f3e3 --- /dev/null +++ b/projects/ngrx-auto-entity/src/lib/decorators/key-decorator.ts @@ -0,0 +1,12 @@ +import { NAE_KEY_NAMES, NAE_KEYS } from './entity-tokens'; + +/** + * Used to designate the key property for the entity + * + * @param target the entity's class + * @param keyName the key's name + */ +export function Key(target, keyName: string | symbol): void { + target[NAE_KEY_NAMES] = target[NAE_KEY_NAMES] ? [...target[NAE_KEY_NAMES], keyName] : [keyName]; + Object.defineProperty(target, NAE_KEYS, { get: () => target[NAE_KEY_NAMES] }); +} diff --git a/projects/ngrx-auto-entity/src/lib/decorators/key.ts b/projects/ngrx-auto-entity/src/lib/decorators/key-util.ts similarity index 77% rename from projects/ngrx-auto-entity/src/lib/decorators/key.ts rename to projects/ngrx-auto-entity/src/lib/decorators/key-util.ts index 6a41ffc..e20b1a1 100644 --- a/projects/ngrx-auto-entity/src/lib/decorators/key.ts +++ b/projects/ngrx-auto-entity/src/lib/decorators/key-util.ts @@ -1,22 +1,6 @@ import { IEntityAction } from '../actions/entity-action'; -import { EntityIdentity } from '../util/entity-state'; - -// NOTE: The following two constants should be Symbol() to avoid any potential conflict with -// any user-defined properties on the entity models. However, use of Symbol() here causes -// problems with the Jest test runner at the current time -export const NAE_KEYS = '__nae_keys'; -export const NAE_KEY_NAMES = '__nae_key_names'; - -/** - * Used to designate the key property for the entity - * - * @param target the entity's class - * @param keyName the key's name - */ -export function Key(target, keyName: string | symbol): void { - target[NAE_KEY_NAMES] = target[NAE_KEY_NAMES] ? [...target[NAE_KEY_NAMES], keyName] : [keyName]; - Object.defineProperty(target, NAE_KEYS, { get: () => target[NAE_KEY_NAMES] }); -} +import { EntityIdentity } from '../types/entity-identity'; +import { NAE_KEYS } from './entity-tokens'; export function checkKeyName(type: any, modelName: string): boolean { const keys = type.prototype[NAE_KEYS]; diff --git a/projects/ngrx-auto-entity/src/lib/decorators/key.spec.ts b/projects/ngrx-auto-entity/src/lib/decorators/key.spec.ts index 5ff1b99..9a3b23d 100644 --- a/projects/ngrx-auto-entity/src/lib/decorators/key.spec.ts +++ b/projects/ngrx-auto-entity/src/lib/decorators/key.spec.ts @@ -1,14 +1,15 @@ -import { getKey, getKeyFromModel, Load, LoadAll } from '../..'; +import { Load } from '../actions/load-actions'; +import { LoadAll } from '../actions/load-all-actions'; import { makeEntity } from '../util/make-entity'; +import { Key } from './key-decorator'; import { + getKey, getKeyFromEntity, + getKeyFromModel, getKeyNames, getKeyNamesFromEntity, - getKeyNamesFromModel, - Key, - NAE_KEY_NAMES, - NAE_KEYS -} from './key'; + getKeyNamesFromModel +} from './key-util'; class TestEntity { @Key id: number; @@ -22,40 +23,6 @@ class CompositeEntity { const makeTestEntity = makeEntity(TestEntity); const makeCompositeEntity = makeEntity(CompositeEntity); -describe('Function: Key', () => { - test(`should attach ${NAE_KEYS} property to target`, () => { - const myEntity = {}; - Key(myEntity, 'test'); - expect(myEntity[NAE_KEYS]).toBeDefined(); - }); -}); - -describe('Decorator: @Key', () => { - test(`should attach ${NAE_KEYS} property to target`, () => { - const myEntity = new TestEntity(); - expect(myEntity[NAE_KEYS]).toBeDefined(); - }); - - test(`should return name key property`, () => { - const myEntity = new TestEntity(); - const keyNames = myEntity[NAE_KEYS]; - expect(keyNames.length).toBe(1); - expect(keyNames[0]).toBe('id'); - }); -}); - -describe('Constant: NAE_KEYS', () => { - test('should equal "__nae_keys"', () => { - expect(NAE_KEYS).toBe('__nae_keys'); - }); -}); - -describe('Constant: NAE_KEY_NAMES', () => { - test('should equal "__nae_key_names"', () => { - expect(NAE_KEY_NAMES).toBe('__nae_key_names'); - }); -}); - describe('Function: getKeyNames()', () => { it('should log a console error and return empty array if action is falsy', () => { const errorSpy = jest.spyOn(console, 'error'); diff --git a/projects/ngrx-auto-entity/src/lib/effects/operators.ts b/projects/ngrx-auto-entity/src/lib/effects/operators.ts index de4f192..52a2cee 100644 --- a/projects/ngrx-auto-entity/src/lib/effects/operators.ts +++ b/projects/ngrx-auto-entity/src/lib/effects/operators.ts @@ -21,7 +21,8 @@ import { } from '../actions/delete-actions'; import { DeleteByKey, - DeleteByKeyFailure, DeleteByKeySuccess, + DeleteByKeyFailure, + DeleteByKeySuccess, DeleteManyByKeys, DeleteManyByKeysFailure, DeleteManyByKeysSuccess @@ -53,7 +54,8 @@ import { SelectByKey, Selected, SelectedMany, - SelectedMore, SelectMany, + SelectedMore, + SelectMany, SelectManyByKeys, SelectMore, SelectMoreByKeys diff --git a/projects/ngrx-auto-entity/src/lib/reducer/reducer.spec.ts b/projects/ngrx-auto-entity/src/lib/reducer/reducer.spec.ts index cc52036..a6abe77 100644 --- a/projects/ngrx-auto-entity/src/lib/reducer/reducer.spec.ts +++ b/projects/ngrx-auto-entity/src/lib/reducer/reducer.spec.ts @@ -1,31 +1,28 @@ import 'jest-extended'; -import { - CreateManySuccess, - CreateSuccess, - DeleteByKeySuccess, - DeleteManyByKeysSuccess, - DeleteManySuccess, - DeleteSuccess, DeselectAll, DeselectMany, DeselectManyByKeys, EditByKey, - LoadAllSuccess, - LoadManySuccess, - LoadPageSuccess, - LoadRangeSuccess, - ReplaceManySuccess, - ReplaceSuccess, Select, SelectByKey, SelectMany, SelectManyByKeys, SelectMore, - SelectMoreByKeys, - UpdateSuccess, - UpsertManySuccess, - UpsertSuccess -} from '../..'; -import { - Clear -} from '../actions/actions'; -import { Deselect } from '../actions/deselection-actions'; -import { Edit } from '../actions/edit-actions'; +import { Clear } from '../actions/actions'; +import { CreateManySuccess, CreateSuccess } from '../actions/create-actions'; +import { DeleteManySuccess, DeleteSuccess } from '../actions/delete-actions'; +import { DeleteByKeySuccess, DeleteManyByKeysSuccess } from '../actions/delete-by-key-actions'; +import { Deselect, DeselectAll, DeselectMany, DeselectManyByKeys } from '../actions/deselection-actions'; +import { Edit, EditByKey } from '../actions/edit-actions'; import { Load, LoadSuccess } from '../actions/load-actions'; -import { UpdateManySuccess } from '../actions/update-actions'; -import { Key } from '../decorators/key'; +import { LoadAllSuccess } from '../actions/load-all-actions'; +import { LoadManySuccess } from '../actions/load-many-actions'; +import { LoadPageSuccess } from '../actions/load-page-actions'; +import { LoadRangeSuccess } from '../actions/load-range-actions'; +import { ReplaceManySuccess, ReplaceSuccess } from '../actions/replace-actions'; +import { + Select, + SelectByKey, + SelectMany, + SelectManyByKeys, + SelectMore, + SelectMoreByKeys +} from '../actions/selection-actions'; +import { UpdateManySuccess, UpdateSuccess } from '../actions/update-actions'; +import { UpsertManySuccess, UpsertSuccess } from '../actions/upsert-actions'; +import { Key } from '../decorators/key-decorator'; import { autoEntityMetaReducer, autoEntityReducer, stateNameFromAction } from './reducer'; class TestEntity { @@ -180,7 +177,7 @@ describe('NgRX Auto-Entity: Reducer', () => { new LoadAllSuccess(TestEntity, [{ identity: 1 }, { identity: 2 }, { identity: 3 }]) ); - expect(newState).toEqual({ + expect(newState).toMatchObject({ testEntity: { currentPage: 1, entities: { @@ -243,19 +240,17 @@ describe('NgRX Auto-Entity: Reducer', () => { const metaReducer = autoEntityMetaReducer(rootReducer); const newState = metaReducer( state, - new LoadAllSuccess(TestEntity, [{ identity: 1 }, { identity: 2 }, { identity: 3 }]) + new LoadManySuccess(TestEntity, [{ identity: 1 }, { identity: 2 }, { identity: 3 }]) ); expect(newState).toEqual({ testEntity: { - currentPage: 1, entities: { 1: { identity: 1 }, 2: { identity: 2 }, 3: { identity: 3 } }, ids: [1, 2, 3], - totalPageableCount: 3, isLoading: false, loadedAt: expect.toBeNumber() } diff --git a/projects/ngrx-auto-entity/src/lib/reducer/reducer.ts b/projects/ngrx-auto-entity/src/lib/reducer/reducer.ts index 8638f6a..46b6e24 100644 --- a/projects/ngrx-auto-entity/src/lib/reducer/reducer.ts +++ b/projects/ngrx-auto-entity/src/lib/reducer/reducer.ts @@ -1,35 +1,31 @@ import { ActionReducer } from '@ngrx/store'; -import { - Change, - CreateManySuccess, - CreateSuccess, - DeleteByKeySuccess, - DeleteManyByKeysSuccess, - DeleteManySuccess, - DeleteSuccess, DeselectMany, DeselectManyByKeys, Edit, EditByKey, - LoadPageSuccess, - LoadRangeSuccess, - ReplaceManySuccess, - ReplaceSuccess, Select, - SelectByKey, - SelectMany, - SelectManyByKeys, - SelectMore, - SelectMoreByKeys, - UpdateSuccess, - UpsertManySuccess -} from '../..'; import { camelCase } from '../../util/case'; import { iif, isUndefined, map, noop, pipe, throwError } from '../../util/func'; import { EntityActionTypes } from '../actions/action-types'; +import { CreateManySuccess, CreateSuccess } from '../actions/create-actions'; +import { DeleteManySuccess, DeleteSuccess } from '../actions/delete-actions'; +import { DeleteByKeySuccess, DeleteManyByKeysSuccess } from '../actions/delete-by-key-actions'; +import { DeselectMany, DeselectManyByKeys } from '../actions/deselection-actions'; +import { Change, Edit, EditByKey } from '../actions/edit-actions'; import { IEntityAction } from '../actions/entity-action'; import { EntityActions } from '../actions/entity-actions-union'; import { LoadSuccess } from '../actions/load-actions'; -import { UpdateManySuccess } from '../actions/update-actions'; -import { UpsertSuccess } from '../actions/upsert-actions'; -import { getKey } from '../decorators/key'; -import { EntityIdentity } from '../util/entity-state'; +import { LoadPageSuccess } from '../actions/load-page-actions'; +import { LoadRangeSuccess } from '../actions/load-range-actions'; +import { ReplaceManySuccess, ReplaceSuccess } from '../actions/replace-actions'; +import { + Select, + SelectByKey, + SelectMany, + SelectManyByKeys, + SelectMore, + SelectMoreByKeys +} from '../actions/selection-actions'; +import { UpdateManySuccess, UpdateSuccess } from '../actions/update-actions'; +import { UpsertManySuccess, UpsertSuccess } from '../actions/upsert-actions'; +import { getKey } from '../decorators/key-util'; +import { EntityIdentity } from '../types/entity-identity'; import { FEATURE_AFFINITY } from '../util/util-tokens'; export function stateNameFromAction(action: IEntityAction): string { diff --git a/projects/ngrx-auto-entity/src/lib/service/interface.ts b/projects/ngrx-auto-entity/src/lib/service/interface.ts index 9c94203..44c7f97 100644 --- a/projects/ngrx-auto-entity/src/lib/service/interface.ts +++ b/projects/ngrx-auto-entity/src/lib/service/interface.ts @@ -1,8 +1,8 @@ import { Observable } from 'rxjs'; +import { EntityIdentity } from '../types/entity-identity'; import { IEntityInfo } from '../actions/entity-info'; import { Page, Range } from '../models'; -import { EntityIdentity } from '../util/entity-state'; import { IEntityWithPageInfo, IEntityWithRangeInfo } from './wrapper-models'; // prettier-ignore diff --git a/projects/ngrx-auto-entity/src/lib/service/refs.ts b/projects/ngrx-auto-entity/src/lib/service/refs.ts index 0070b06..1992884 100644 --- a/projects/ngrx-auto-entity/src/lib/service/refs.ts +++ b/projects/ngrx-auto-entity/src/lib/service/refs.ts @@ -1,6 +1,6 @@ import { IEntityInfo } from '../actions/entity-info'; import { IPageInfo, IRangeInfo } from '../models'; -import { EntityIdentity } from '../util/entity-state'; +import { EntityIdentity } from '../types/entity-identity'; export interface IEntityRef { info: IEntityInfo; diff --git a/projects/ngrx-auto-entity/src/lib/service/service.spec.ts b/projects/ngrx-auto-entity/src/lib/service/service.spec.ts index 40edeae..87e8dd5 100644 --- a/projects/ngrx-auto-entity/src/lib/service/service.spec.ts +++ b/projects/ngrx-auto-entity/src/lib/service/service.spec.ts @@ -4,10 +4,10 @@ import { Injectable, Injector } from '@angular/core'; import { TestBed } from '@angular/core/testing'; import { Observable, of, throwError } from 'rxjs'; import { catchError } from 'rxjs/operators'; +import { EntityIdentity } from '../types/entity-identity'; import { IEntityInfo } from '../actions/entity-info'; import { Page, Range } from '../models'; -import { EntityIdentity } from '../util/entity-state'; import { logAndThrow, logErrorDetails, logServiceLocateFailure, notAFunction, notImplemented } from './error-handling'; import { IAutoEntityService } from './interface'; import { NgrxAutoEntityService } from './service'; diff --git a/projects/ngrx-auto-entity/src/lib/service/service.ts b/projects/ngrx-auto-entity/src/lib/service/service.ts index 8dbe94a..b6973a1 100644 --- a/projects/ngrx-auto-entity/src/lib/service/service.ts +++ b/projects/ngrx-auto-entity/src/lib/service/service.ts @@ -3,7 +3,7 @@ import { Observable } from 'rxjs'; import { IEntityInfo } from '../actions/entity-info'; import { Page, Range } from '../models'; -import { EntityIdentity } from '../util/entity-state'; +import { EntityIdentity } from '../types/entity-identity'; import { IEntityIdentitiesRef, IEntityIdentityRef, IEntityPageRef, IEntityRangeRef, IEntityRef } from './refs'; import { callService } from './service-invocation'; import { diff --git a/projects/ngrx-auto-entity/src/lib/service/transformation.ts b/projects/ngrx-auto-entity/src/lib/service/transformation.ts index a887a64..f9e791a 100644 --- a/projects/ngrx-auto-entity/src/lib/service/transformation.ts +++ b/projects/ngrx-auto-entity/src/lib/service/transformation.ts @@ -1,5 +1,5 @@ import { IEntityInfo } from '../actions/entity-info'; -import { IEntityTransformer } from '../decorators/entity'; +import { IEntityTransformer } from '../decorators/entity-options'; const FROM = 'fromServer'; const TO = 'toServer'; diff --git a/projects/ngrx-auto-entity/src/lib/types/entity-identity.ts b/projects/ngrx-auto-entity/src/lib/types/entity-identity.ts new file mode 100644 index 0000000..2523a18 --- /dev/null +++ b/projects/ngrx-auto-entity/src/lib/types/entity-identity.ts @@ -0,0 +1,11 @@ +/* + * Represents an entity identity + * + * @remarks + * At the current time, entity identities must be either number + * or string. These two types should allow the vast majority + * of potential identities to be represented effectively in + * entity state, including composite keys (which auto-entity + * automatically creates as strings.) + */ +export type EntityIdentity = string | number; diff --git a/projects/ngrx-auto-entity/src/lib/util/entity-state.ts b/projects/ngrx-auto-entity/src/lib/util/entity-state.ts index 4a99d0f..8273c2f 100644 --- a/projects/ngrx-auto-entity/src/lib/util/entity-state.ts +++ b/projects/ngrx-auto-entity/src/lib/util/entity-state.ts @@ -1,4 +1,5 @@ import { Page, Range } from '../models'; +import { EntityIdentity } from '../types/entity-identity'; /** * Structure for how entities are stored within the `entities` state property: @@ -8,8 +9,6 @@ export interface IEntityDictionary { [key: string]: TModel; } -export type EntityIdentity = string | number; - /** * Structure for how entities are stored, including useful computed properties * such as an array of their keys, status flags, timestamps, etc. diff --git a/projects/ngrx-auto-entity/src/lib/util/facade-builder.ts b/projects/ngrx-auto-entity/src/lib/util/facade-builder.ts index c369647..602991c 100644 --- a/projects/ngrx-auto-entity/src/lib/util/facade-builder.ts +++ b/projects/ngrx-auto-entity/src/lib/util/facade-builder.ts @@ -1,33 +1,31 @@ import { Store } from '@ngrx/store'; import { Observable } from 'rxjs'; -import { - Change, - Create, - Delete, - DeleteByKey, DeselectManyByKeys, EditByKey, EndEdit, - Load, - LoadMany, - LoadPage, - Replace, - ReplaceMany, Select, SelectMany, - SelectMore, - Upsert, - UpsertMany -} from '../..'; -import { - Clear -} from '../actions/actions'; -import { CreateMany } from '../actions/create-actions'; -import { DeleteMany } from '../actions/delete-actions'; -import { DeleteManyByKeys } from '../actions/delete-by-key-actions'; -import { Deselect, DeselectAll, DeselectMany } from '../actions/deselection-actions'; -import { Edit } from '../actions/edit-actions'; + +import { Clear } from '../actions/actions'; +import { Create, CreateMany } from '../actions/create-actions'; +import { Delete, DeleteMany } from '../actions/delete-actions'; +import { DeleteByKey, DeleteManyByKeys } from '../actions/delete-by-key-actions'; +import { Deselect, DeselectAll, DeselectMany, DeselectManyByKeys } from '../actions/deselection-actions'; +import { Change, Edit, EditByKey, EndEdit } from '../actions/edit-actions'; +import { Load } from '../actions/load-actions'; import { LoadAll } from '../actions/load-all-actions'; +import { LoadMany } from '../actions/load-many-actions'; +import { LoadPage } from '../actions/load-page-actions'; import { LoadRange } from '../actions/load-range-actions'; -import { SelectByKey, SelectManyByKeys, SelectMoreByKeys } from '../actions/selection-actions'; +import { Replace, ReplaceMany } from '../actions/replace-actions'; +import { + Select, + SelectByKey, + SelectMany, + SelectManyByKeys, + SelectMore, + SelectMoreByKeys +} from '../actions/selection-actions'; import { Update, UpdateMany } from '../actions/update-actions'; +import { Upsert, UpsertMany } from '../actions/upsert-actions'; import { Page, Range } from '../models'; -import { EntityIdentity, IEntityDictionary } from './entity-state'; +import { EntityIdentity } from '../types/entity-identity'; +import { IEntityDictionary } from './entity-state'; import { IEntityFacade } from './facade'; import { ISelectorMap } from './selector-map'; @@ -133,6 +131,7 @@ export const buildFacade = (selectors: ISelectorMap { return this.store.select(selectors.selectCustomSorted, { name }); } + // endregion // region Dispatches diff --git a/projects/ngrx-auto-entity/src/lib/util/facade.ts b/projects/ngrx-auto-entity/src/lib/util/facade.ts index 410876e..774c063 100644 --- a/projects/ngrx-auto-entity/src/lib/util/facade.ts +++ b/projects/ngrx-auto-entity/src/lib/util/facade.ts @@ -1,7 +1,8 @@ import { Observable } from 'rxjs'; +import { EntityIdentity } from '../types/entity-identity'; import { Page, Range } from '../models'; -import { EntityIdentity, IEntityDictionary } from './entity-state'; +import { IEntityDictionary } from './entity-state'; /** * The definition of an Auto-Entity facade class diff --git a/projects/ngrx-auto-entity/src/lib/util/make-entity.spec.ts b/projects/ngrx-auto-entity/src/lib/util/make-entity.spec.ts index 84d6831..a07c908 100644 --- a/projects/ngrx-auto-entity/src/lib/util/make-entity.spec.ts +++ b/projects/ngrx-auto-entity/src/lib/util/make-entity.spec.ts @@ -1,5 +1,6 @@ -import { Entity, ENTITY_OPTS_PROP, Key } from '../..'; -import { NAE_KEY_NAMES, NAE_KEYS } from '../decorators/key'; +import { Entity } from '../decorators/entity-decorator'; +import { ENTITY_OPTS_PROP, NAE_KEY_NAMES, NAE_KEYS } from '../decorators/entity-tokens'; +import { Key } from '../decorators/key-decorator'; import { makeEntity } from './make-entity'; @Entity({ diff --git a/projects/ngrx-auto-entity/src/lib/util/selector-map-builder.spec.ts b/projects/ngrx-auto-entity/src/lib/util/selector-map-builder.spec.ts index d7e462c..4967394 100644 --- a/projects/ngrx-auto-entity/src/lib/util/selector-map-builder.spec.ts +++ b/projects/ngrx-auto-entity/src/lib/util/selector-map-builder.spec.ts @@ -2,7 +2,9 @@ import { TestBed } from '@angular/core/testing'; import { Store } from '@ngrx/store'; import { MockStore, provideMockStore } from '@ngrx/store/testing'; import { hot } from 'jasmine-marbles'; -import { Entity, ISelectorMap, Key } from '../..'; +import { Entity } from '../decorators/entity-decorator'; +import { Key } from '../decorators/key-decorator'; +import { ISelectorMap } from '../util/selector-map'; import { IEntityState } from './entity-state'; import { makeEntity } from './make-entity'; import { diff --git a/projects/ngrx-auto-entity/src/lib/util/selector-map-builder.ts b/projects/ngrx-auto-entity/src/lib/util/selector-map-builder.ts index 4492a3f..62d8fca 100644 --- a/projects/ngrx-auto-entity/src/lib/util/selector-map-builder.ts +++ b/projects/ngrx-auto-entity/src/lib/util/selector-map-builder.ts @@ -1,7 +1,8 @@ import { createSelector, MemoizedSelector, Selector } from '@ngrx/store'; import { entityComparer } from '../decorators/entity-util'; import { Page, Range } from '../models'; -import { EntityIdentity, IEntityDictionary, IEntityState } from './entity-state'; +import { EntityIdentity } from '../types/entity-identity'; +import { IEntityDictionary, IEntityState } from './entity-state'; import { ISelectorMap } from './selector-map'; // prettier-ignore diff --git a/projects/ngrx-auto-entity/src/lib/util/selector-map.ts b/projects/ngrx-auto-entity/src/lib/util/selector-map.ts index fc49709..3a7082c 100644 --- a/projects/ngrx-auto-entity/src/lib/util/selector-map.ts +++ b/projects/ngrx-auto-entity/src/lib/util/selector-map.ts @@ -1,6 +1,7 @@ import { MemoizedSelector } from '@ngrx/store'; import { Page, Range } from '../models'; -import { EntityIdentity, IEntityDictionary } from './entity-state'; +import { EntityIdentity } from '../types/entity-identity'; +import { IEntityDictionary } from './entity-state'; /** * Structure of a Selector Map defining all the selectors that may diff --git a/projects/ngrx-auto-entity/src/lib/util/state-builder.spec.ts b/projects/ngrx-auto-entity/src/lib/util/state-builder.spec.ts index b122744..28192eb 100644 --- a/projects/ngrx-auto-entity/src/lib/util/state-builder.spec.ts +++ b/projects/ngrx-auto-entity/src/lib/util/state-builder.spec.ts @@ -1,5 +1,5 @@ -import { Entity } from '../decorators/entity'; -import { Key } from '../decorators/key'; +import { Entity } from '../decorators/entity-decorator'; +import { Key } from '../decorators/key-decorator'; import { buildState, NO_ENTITY_DECORATOR_MSG, NO_ENTITY_KEY_MSG, NO_MODEL_NAME_MSG } from './state-builder'; @Entity({ modelName: 'Test' }) diff --git a/projects/ngrx-auto-entity/src/lib/util/state-builder.ts b/projects/ngrx-auto-entity/src/lib/util/state-builder.ts index 6ca5e79..ba4697f 100644 --- a/projects/ngrx-auto-entity/src/lib/util/state-builder.ts +++ b/projects/ngrx-auto-entity/src/lib/util/state-builder.ts @@ -1,10 +1,10 @@ import { createSelector, MemoizedSelector } from '@ngrx/store'; import { camelCase } from '../../util/case'; -import { IEntityOptions } from '../decorators/entity'; -import { ENTITY_OPTS_PROP } from '../decorators/entity-tokens'; -import { NAE_KEY_NAMES, NAE_KEYS } from '../decorators/key'; -import { EntityIdentity, IEntityState } from './entity-state'; +import { IEntityOptions } from '../decorators/entity-options'; +import { ENTITY_OPTS_PROP, NAE_KEY_NAMES, NAE_KEYS } from '../decorators/entity-tokens'; +import { EntityIdentity } from '../types/entity-identity'; +import { IEntityState } from './entity-state'; import { buildFacade } from './facade-builder'; import { makeEntity } from './make-entity'; import { IModelClass, IModelState } from './model-state'; diff --git a/projects/ngrx-auto-entity/src/lib/util/util.spec.ts b/projects/ngrx-auto-entity/src/lib/util/util.spec.ts index cb94e97..89f48c4 100644 --- a/projects/ngrx-auto-entity/src/lib/util/util.spec.ts +++ b/projects/ngrx-auto-entity/src/lib/util/util.spec.ts @@ -2,8 +2,8 @@ import { TestBed } from '@angular/core/testing'; import { createFeatureSelector, Store } from '@ngrx/store'; import { provideMockStore } from '@ngrx/store/testing'; -import { Entity } from '../decorators/entity'; -import { Key } from '../decorators/key'; +import { Entity } from '../decorators/entity-decorator'; +import { Key } from '../decorators/key-decorator'; import { IEntityState } from './entity-state'; import { buildFacade } from './facade-builder'; import { ISelectorMap } from './selector-map'; diff --git a/projects/ngrx-auto-entity/src/util/func.ts b/projects/ngrx-auto-entity/src/util/func.ts index 933521e..57ef071 100644 --- a/projects/ngrx-auto-entity/src/util/func.ts +++ b/projects/ngrx-auto-entity/src/util/func.ts @@ -10,6 +10,8 @@ export const tap = (fn: (x) => void) => data => { export const noop = () => void 0; +export const not = (fn: (...args: any[]) => any) => value => fn(!value); + export const isUndefined = value => value === undefined; export const throwError = (message: string) => () => {