Skip to content
This repository was archived by the owner on Jul 3, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 27 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@ Core-module for related "normalized-db"-libraries providing common models and ut
functions as well as the `Schema` (implemented with `TypeScript`).

- **Author**: Sandro Schmid ([saseb.schmid@gmail.com](<mailto:saseb.schmid@gmail.com>))
- **Version**: 2.4.0
- **Version**: 2.5.0-beta.1

## Notes
## Versioning

- This library is under active development.
- To ease versioning equal major and minor version numbers are used for all modules.
To ease versioning equal major and minor version numbers are used for all modules.

## Installation

Expand Down Expand Up @@ -67,17 +66,37 @@ following options:
- `autoKey` (boolean): If set to `true`, this option tells data stores to automatically generate an unique identifier
for new objects without a key.

- `logging` (`IStoreLogConfig`): By using this option you can enable automatic logging for the store's entities.
The required `mode`-field specifies the mode, whereas `LogMode.Disabled` is used to disable logging at all,
`LogMode.Simple` enables logging but includes only some meta information on the change including store, primary key,
type of change (e.g. `created` or `removed`) and `LogMode.Full` basically does the same as `Simple` but it includes
the changed object. So deciding whether to use `Simple` or `Full` is equal to making a trade-off between loss of
information and a large logging store.
By default, logging is disabled for each store which does not explicitly enable it or does not derive another
preference from one of its parents. This of course can be changed by setting another mode in the `_defaults`-store
(as it can be seen in the example below).
The `eventSelection` can be optionally used to filter the events which should be logged.
`IStoreLogConfig`-instances can be built by using a `StoreLogBuilder`.
Logging is used by the `data-store`-module only.

An example for such a `ISchemaConfig`-object for a simple blog could look like this:

```typescript
const schemaConfig: ISchemaConfig = {
_defaults: {
key: 'id',
autoKey: true
autoKey: true,
logging: {
mode: LogMode.Simple,
}
},
_authored: {
targets: {
author: 'user'
},
logging: {
mode: LogMode.Full,
eventSelection: ['created', 'updated', 'removed', 'cleared']
}
},
role: true,
Expand All @@ -86,6 +105,9 @@ const schemaConfig: ISchemaConfig = {
autoKey: false,
targets: {
role: 'role'
},
logging: {
eventSelection: ['created', 'removed']
}
},
article: {
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@normalized-db/core",
"version": "2.4.0",
"version": "2.5.0-beta.1",
"author": "Sandro Schmid <saseb.schmid@gmail.com>",
"license": "MIT",
"description": "Core-module for related 'normalized-db'-libraries providing common models and utility functions as well as the `Schema` (implemented with `TypeScript`).",
Expand Down Expand Up @@ -28,7 +28,8 @@
"build-prod": "tslint ./src/*.ts ./src/**/*.ts && WEBPACK_ENV=prod webpack",
"build-all": "npm run build && npm run build-prod",
"clean-build": "rm -rf lib/ && npm run build-all",
"test": "npm run build && ./node_modules/karma/bin/karma start ./karma.conf.js",
"test-mocha": "npm run build && ./node_modules/.bin/mocha --compilers ts:ts-node/register ./test/**/*.spec.ts",
"test-karma": "npm run build && ./node_modules/karma/bin/karma start ./karma.conf.js",
"build-and-publish": "npm run clean-build && npm publish"
},
"devDependencies": {
Expand Down
3 changes: 3 additions & 0 deletions src/model/event-selection-type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { EventType } from './index';

export type EventSelection = EventType | EventType[];
1 change: 1 addition & 0 deletions src/model/event-type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type EventType = 'created' | 'updated' | 'removed' | 'cleared';
6 changes: 6 additions & 0 deletions src/model/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { Depth } from './depth';
import { EventSelection } from './event-selection-type';
import { EventType } from './event-type';
import { FetchCallback } from './fetch-callback';
import { KeyMap } from './key-map';
import { LogMode } from './log-mode.enum';
import { NdbDocument } from './ndb-document';
import { NormalizedData } from './normalized-data';
import { ReverseReferences } from './reverse-references';
Expand All @@ -9,8 +12,11 @@ import { ValidKey } from './valid-key';

export {
Depth,
EventSelection,
EventType,
FetchCallback,
KeyMap,
LogMode,
NdbDocument,
NormalizedData,
ReverseReferences,
Expand Down
5 changes: 5 additions & 0 deletions src/model/log-mode.enum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export enum LogMode {
Disabled = 0, // disable logging
Simple = 1, // `LogEntry<?>` except `item`-field
Full = 2 // include `item`-field
}
2 changes: 1 addition & 1 deletion src/model/unique-key-callback.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import { ValidKey } from './valid-key';

export declare type UniqueKeyCallback = (type: string) => ValidKey;
export declare type UniqueKeyCallback = (type: string) => ValidKey | Promise<ValidKey>;
4 changes: 3 additions & 1 deletion src/schema/builder/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { SchemaBuilder } from './schema-builder';
import { StoreBuilder } from './store-builder';
import { StoreLogBuilder } from './store-log-builder';

export {
StoreBuilder,
SchemaBuilder
SchemaBuilder,
StoreLogBuilder
};
15 changes: 13 additions & 2 deletions src/schema/builder/store-builder.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { isNull } from '../../utility/object';
import { IStoreConfig } from '../model/store-config-interface';
import { IStoreLogConfig } from '../model/store-log-config-interface';
import { IStoreTargetConfig } from '../model/store-target-config-interface';
import { IStoreTargetItem } from '../model/store-target-item-interface';

Expand All @@ -8,7 +9,8 @@ export class StoreBuilder {
constructor(private parent?: string,
private key?: string,
private autoKey?: boolean,
private targets?: IStoreTargetConfig) {
private targets?: IStoreTargetConfig,
private logging?: IStoreLogConfig) {
}

public setKey(key: string): StoreBuilder {
Expand Down Expand Up @@ -61,6 +63,11 @@ export class StoreBuilder {
return this;
}

public setLogging(logging: IStoreLogConfig): StoreBuilder {
this.logging = logging;
return this;
}

public get build(): boolean | string | IStoreConfig {
if (this.hasConfiguration) {
const result: IStoreConfig = {};
Expand All @@ -80,6 +87,10 @@ export class StoreBuilder {
result.targets = this.targets;
}

if (this.logging) {
result.logging = this.logging;
}

return result;

} else if (this.parent) {
Expand All @@ -91,7 +102,7 @@ export class StoreBuilder {
}

private get hasConfiguration(): boolean {
return !isNull(this.key) || !isNull(this.autoKey) || this.hasTargets;
return !isNull(this.key) || !isNull(this.autoKey) || this.hasTargets || !isNull(this.logging);
}

private get hasTargets(): boolean {
Expand Down
26 changes: 26 additions & 0 deletions src/schema/builder/store-log-builder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { EventSelection, LogMode } from '../../model';
import { IStoreLogConfig } from '../model';

export class StoreLogBuilder {

constructor(private mode?: LogMode,
private eventSelection?: EventSelection) {
}

public setMode(value: LogMode): StoreLogBuilder {
this.mode = value;
return this;
}

public setEventSelection(value: EventSelection): StoreLogBuilder {
this.eventSelection = value;
return this;
}

public build(): IStoreLogConfig {
return {
mode: this.mode || LogMode.Disabled,
eventSelection: this.eventSelection
};
}
}
10 changes: 7 additions & 3 deletions src/schema/model/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,20 @@ import { ISchemaConfig } from './schema-config-interface';
import { ISchemaExpanded } from './schema-expanded-interface';
import { IStoreConfig } from './store-config-interface';
import { IStore } from './store-interface';
import { IStoreLogConfig } from './store-log-config-interface';
import { IStoreLog } from './store-log-interface';
import { IStoreTargetConfig } from './store-target-config-interface';
import { IStoreTarget } from './store-target-interface';
import { IStoreTargetItem } from './store-target-item-interface';

export {
ISchemaExpanded,
ISchemaConfig,
IStore,
ISchemaExpanded,
IStoreConfig,
IStoreTarget,
IStore,
IStoreLogConfig,
IStoreLog,
IStoreTargetConfig,
IStoreTarget,
IStoreTargetItem
};
2 changes: 2 additions & 0 deletions src/schema/model/store-config-interface.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { IStoreLogConfig } from './store-log-config-interface';
import { IStoreTargetConfig } from './store-target-config-interface';

export interface IStoreConfig {
parent?: string;
key?: string;
autoKey?: boolean;
targets?: IStoreTargetConfig;
logging?: IStoreLogConfig;
}
2 changes: 2 additions & 0 deletions src/schema/model/store-interface.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { IStoreLog } from './store-log-interface';
import { IStoreTarget } from './store-target-interface';

export interface IStore {
type: string;
key?: string;
autoKey?: boolean;
targets?: IStoreTarget;
logging?: IStoreLog;
}
6 changes: 6 additions & 0 deletions src/schema/model/store-log-config-interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { EventSelection, LogMode } from '../../model';

export interface IStoreLogConfig {
mode: LogMode;
eventSelection?: EventSelection;
}
6 changes: 6 additions & 0 deletions src/schema/model/store-log-interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { EventSelection, LogMode } from '../../model';

export interface IStoreLog {
mode: LogMode;
eventSelection?: EventSelection;
}
5 changes: 3 additions & 2 deletions src/schema/schema-interface.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { IStore } from './model/store-interface';
import { IStoreTargetItem } from './model/store-target-item-interface';
import { IStore, IStoreTargetItem } from './model';
import { SchemaLogConfig } from './schema-log-config';

export interface ISchema {
getLogConfig(): SchemaLogConfig;
hasType(type: string): boolean;
getTypes(): string[];
getConfig(type: string): IStore;
Expand Down
49 changes: 49 additions & 0 deletions src/schema/schema-log-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { EventType, LogMode } from '../model';
import { StoreLogBuilder } from './builder/store-log-builder';
import { IStoreLogConfig } from './model/store-log-config-interface';
import { ISchema } from './schema-interface';

export class SchemaLogConfig {

constructor(private readonly _schema: ISchema) {
}

public getConfig(type: string, orDefault?: IStoreLogConfig): IStoreLogConfig {
let config = orDefault || new StoreLogBuilder().build();
if (this._schema.hasType(type)) {
config = Object.assign(config, this._schema.getConfig(type).logging);
}
return config;
}

public getLogMode(type: string, orDefault = LogMode.Disabled): LogMode {
return this._schema.hasType(type)
? this._schema.getConfig(type).logging.mode
: orDefault;
}

public getEventTypes(type: string, orDefault?: EventType[]): EventType[] {
let types: EventType[];
if (this._schema.hasType(type)) {
const eventSelection = this._schema.getConfig(type).logging.eventSelection;
types = Array.isArray(eventSelection) ? eventSelection : [eventSelection];
}
return types && types.length > 0 ? types : orDefault;
}

public isLoggingEnabled(type: string, eventType?: EventType): boolean {
let isEnabled = this._schema.hasType(type);
if (isEnabled) {
const logConfig = this._schema.getConfig(type).logging;
isEnabled = logConfig.mode !== LogMode.Disabled;

if (isEnabled && eventType) {
isEnabled = Array.isArray(logConfig.eventSelection)
? logConfig.eventSelection.indexOf(eventType) >= 0
: logConfig.eventSelection === eventType;
}
}

return isEnabled;
}
}
Loading