@mayhem93/nexxus-core-lib 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-cjs/common/BuiltinSchemas.js +24 -5
- package/dist-cjs/common/BuiltinSchemas.js.map +1 -1
- package/dist-cjs/common/FilterQuery.js +4 -15
- package/dist-cjs/common/FilterQuery.js.map +1 -1
- package/dist-cjs/common/InferModel.js +3 -0
- package/dist-cjs/common/InferModel.js.map +1 -0
- package/dist-cjs/common/JsonPatch.js +42 -225
- package/dist-cjs/common/JsonPatch.js.map +1 -1
- package/dist-cjs/common/SchemaValidator.js +100 -29
- package/dist-cjs/common/SchemaValidator.js.map +1 -1
- package/dist-cjs/index.js +3 -0
- package/dist-cjs/index.js.map +1 -1
- package/dist-cjs/lib/BaseService.js +6 -6
- package/dist-cjs/lib/BaseService.js.map +1 -1
- package/dist-cjs/lib/ConfigManager.js +18 -21
- package/dist-cjs/lib/ConfigManager.js.map +1 -1
- package/dist-cjs/lib/Exceptions.js +8 -1
- package/dist-cjs/lib/Exceptions.js.map +1 -1
- package/dist-cjs/lib/Logger.js +138 -65
- package/dist-cjs/lib/Logger.js.map +1 -1
- package/dist-cjs/models/AppModel.js +17 -3
- package/dist-cjs/models/AppModel.js.map +1 -1
- package/dist-cjs/models/Application.js +51 -12
- package/dist-cjs/models/Application.js.map +1 -1
- package/dist-cjs/models/BaseModel.js.map +1 -1
- package/dist-cjs/models/BuiltinModel.js +8 -0
- package/dist-cjs/models/BuiltinModel.js.map +1 -0
- package/dist-cjs/models/User.js +12 -3
- package/dist-cjs/models/User.js.map +1 -1
- package/dist-esm/common/BuiltinSchemas.js +23 -4
- package/dist-esm/common/BuiltinSchemas.js.map +1 -1
- package/dist-esm/common/FilterQuery.js +5 -16
- package/dist-esm/common/FilterQuery.js.map +1 -1
- package/dist-esm/common/InferModel.js +2 -0
- package/dist-esm/common/InferModel.js.map +1 -0
- package/dist-esm/common/JsonPatch.js +44 -227
- package/dist-esm/common/JsonPatch.js.map +1 -1
- package/dist-esm/common/SchemaValidator.js +100 -29
- package/dist-esm/common/SchemaValidator.js.map +1 -1
- package/dist-esm/index.js +3 -0
- package/dist-esm/index.js.map +1 -1
- package/dist-esm/lib/BaseService.js +8 -8
- package/dist-esm/lib/BaseService.js.map +1 -1
- package/dist-esm/lib/ConfigManager.js +18 -21
- package/dist-esm/lib/ConfigManager.js.map +1 -1
- package/dist-esm/lib/Exceptions.js +6 -0
- package/dist-esm/lib/Exceptions.js.map +1 -1
- package/dist-esm/lib/Logger.js +139 -66
- package/dist-esm/lib/Logger.js.map +1 -1
- package/dist-esm/models/AppModel.js +17 -3
- package/dist-esm/models/AppModel.js.map +1 -1
- package/dist-esm/models/Application.js +52 -13
- package/dist-esm/models/Application.js.map +1 -1
- package/dist-esm/models/BaseModel.js.map +1 -1
- package/dist-esm/models/BuiltinModel.js +4 -0
- package/dist-esm/models/BuiltinModel.js.map +1 -0
- package/dist-esm/models/User.js +11 -2
- package/dist-esm/models/User.js.map +1 -1
- package/dist-types/common/BuiltinSchemas.d.ts +59 -5
- package/dist-types/common/FilterQuery.d.ts +3 -11
- package/dist-types/common/InferModel.d.ts +29 -0
- package/dist-types/common/JsonPatch.d.ts +4 -45
- package/dist-types/common/ModelTypes.d.ts +1 -0
- package/dist-types/common/QueuePayloads.d.ts +48 -26
- package/dist-types/common/SchemaValidator.d.ts +42 -2
- package/dist-types/index.d.ts +3 -0
- package/dist-types/lib/BaseService.d.ts +8 -1
- package/dist-types/lib/ConfigManager.d.ts +6 -12
- package/dist-types/lib/Exceptions.d.ts +4 -0
- package/dist-types/lib/Logger.d.ts +84 -14
- package/dist-types/models/AppModel.d.ts +31 -5
- package/dist-types/models/Application.d.ts +36 -8
- package/dist-types/models/BaseModel.d.ts +14 -12
- package/dist-types/models/BuiltinModel.d.ts +3 -0
- package/dist-types/models/User.d.ts +15 -13
- package/package.json +4 -4
- package/src/schemas/winston-logger.schema.json +51 -6
package/dist-esm/models/User.js
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { MODEL_REGISTRY } from "./BaseModel";
|
|
2
|
+
import { NexxusBuiltinModel } from "./BuiltinModel";
|
|
3
|
+
import { NEXXUS_BUILTIN_MODEL_SCHEMAS } from "../common/BuiltinSchemas";
|
|
2
4
|
import { InvalidUserModelException } from "../lib/Exceptions";
|
|
3
|
-
export class
|
|
5
|
+
export class NexxusUser extends NexxusBuiltinModel {
|
|
6
|
+
static getModelSchema(userDetails) {
|
|
7
|
+
const base = { ...NEXXUS_BUILTIN_MODEL_SCHEMAS.user };
|
|
8
|
+
if (userDetails) {
|
|
9
|
+
base.details = { type: 'object', required: false, properties: userDetails };
|
|
10
|
+
}
|
|
11
|
+
return base;
|
|
12
|
+
}
|
|
4
13
|
constructor(data) {
|
|
5
14
|
super({ ...data, type: MODEL_REGISTRY.user });
|
|
6
15
|
if (this.data.appId === undefined || typeof this.data.appId !== 'string') {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"User.js","sourceRoot":"","sources":["../../src/models/User.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"User.js","sourceRoot":"","sources":["../../src/models/User.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,cAAc,EACf,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAGpD,OAAO,EAAE,4BAA4B,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAW9D,MAAM,OAAO,UAAW,SAAQ,kBAA+B;IAKtD,MAAM,CAAC,cAAc,CAAC,WAA2C;QACtE,MAAM,IAAI,GAAmB,EAAE,GAAG,4BAA4B,CAAC,IAAI,EAAE,CAAC;QAEtE,IAAI,WAAW,EAAE,CAAC;YAChB,IAAI,CAAC,OAAO,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC;QAC9E,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED,YAAY,IAAiB;QAC3B,KAAK,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC;QAE9C,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YACzE,MAAM,IAAI,yBAAyB,CAAC,+CAA+C,CAAC,CAAC;QACvF,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,KAAK,SAAS,IAAI,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC/E,MAAM,IAAI,yBAAyB,CAAC,kDAAkD,CAAC,CAAC;QAC1F,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAChH,MAAM,IAAI,yBAAyB,CAAC,8CAA8C,CAAC,CAAC;QACtF,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,CAAC,aAAa,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,QAAQ,CAAC,EAAE,CAAC;YACnJ,MAAM,IAAI,yBAAyB,CAAC,kEAAkE,CAAC,CAAC;QAC1G,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YACzE,MAAM,IAAI,yBAAyB,CAAC,4CAA4C,CAAC,CAAC;QACpF,CAAC;aAAM,CAAC;YACN,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC;YAExF,IAAI,CAAC,aAAa,EAAE,CAAC;gBACnB,MAAM,IAAI,yBAAyB,CAAC,4CAA4C,CAAC,CAAC;YACpF,CAAC;QACH,CAAC;QAED,IAAI,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC3C,MAAM,IAAI,yBAAyB,CAAC,kCAAkC,CAAC,CAAC;QAC1E,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC7E,MAAM,IAAI,yBAAyB,CAAC,8CAA8C,CAAC,CAAC;QACtF,CAAC;IACH,CAAC;CACF"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Universal fields present in all models
|
|
3
|
-
*
|
|
2
|
+
* Universal fields present in all models (auto-managed by NexxusBaseModel).
|
|
3
|
+
* 'type' and 'appId' are excluded as they are handled separately in queries.
|
|
4
4
|
*/
|
|
5
5
|
export declare const NEXXUS_UNIVERSAL_FIELDS: {
|
|
6
6
|
readonly id: {
|
|
@@ -17,13 +17,31 @@ export declare const NEXXUS_UNIVERSAL_FIELDS: {
|
|
|
17
17
|
};
|
|
18
18
|
};
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
20
|
+
* Field names reserved by Nexxus across ALL app models. App developers cannot
|
|
21
|
+
* declare a field of these names in their application schemas — the
|
|
22
|
+
* `NexxusApplication` constructor enforces this on schema registration.
|
|
23
|
+
*
|
|
24
|
+
* Most of these are caller-settable at model construction time (e.g. `appId`,
|
|
25
|
+
* `userId`, `type` — set by the API/Worker). `version` is the sole exception:
|
|
26
|
+
* it's set exclusively by the database adapter and rejected from user input
|
|
27
|
+
* (see the inline check in `NexxusSchemaValidator.validateAgainstSchema`).
|
|
28
|
+
*/
|
|
29
|
+
export declare const NEXXUS_RESERVED_FIELD_NAMES: ReadonlySet<string>;
|
|
30
|
+
/**
|
|
31
|
+
* Schema definitions for built-in (reserved) models. These are the runtime
|
|
32
|
+
* source of truth for built-in model field shapes; the corresponding TS
|
|
33
|
+
* interfaces (INexxusUser, INexxusApplication) are derived from these.
|
|
21
34
|
*/
|
|
22
35
|
export declare const NEXXUS_BUILTIN_MODEL_SCHEMAS: {
|
|
23
36
|
readonly user: {
|
|
37
|
+
readonly appId: {
|
|
38
|
+
readonly type: "string";
|
|
39
|
+
readonly required: true;
|
|
40
|
+
readonly filterable: true;
|
|
41
|
+
};
|
|
24
42
|
readonly userType: {
|
|
25
43
|
readonly type: "string";
|
|
26
|
-
readonly required:
|
|
44
|
+
readonly required: true;
|
|
27
45
|
readonly filterable: true;
|
|
28
46
|
};
|
|
29
47
|
readonly username: {
|
|
@@ -33,7 +51,8 @@ export declare const NEXXUS_BUILTIN_MODEL_SCHEMAS: {
|
|
|
33
51
|
};
|
|
34
52
|
readonly password: {
|
|
35
53
|
readonly type: "string";
|
|
36
|
-
readonly required:
|
|
54
|
+
readonly required: true;
|
|
55
|
+
readonly nullable: true;
|
|
37
56
|
};
|
|
38
57
|
readonly authProviders: {
|
|
39
58
|
readonly type: "array";
|
|
@@ -57,6 +76,41 @@ export declare const NEXXUS_BUILTIN_MODEL_SCHEMAS: {
|
|
|
57
76
|
readonly required: true;
|
|
58
77
|
readonly filterable: true;
|
|
59
78
|
};
|
|
79
|
+
readonly description: {
|
|
80
|
+
readonly type: "string";
|
|
81
|
+
readonly required: false;
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Per-application auth block. When `authEnabled` is true this must be
|
|
85
|
+
* present and contain a non-empty `strategies` map; when false it should
|
|
86
|
+
* be absent or have an empty `strategies`. The conditional rule isn't
|
|
87
|
+
* expressible in the static schema — it's enforced imperatively in the
|
|
88
|
+
* `NexxusApplication` constructor.
|
|
89
|
+
*
|
|
90
|
+
* `strategies` is a free-form map keyed by strategy name (e.g. 'local',
|
|
91
|
+
* 'google'). The shape of each value is validated by that strategy's
|
|
92
|
+
* own JSON Schema, loaded by the `NexxusAuthStrategy` base class.
|
|
93
|
+
*/
|
|
94
|
+
readonly auth: {
|
|
95
|
+
readonly type: "object";
|
|
96
|
+
readonly required: false;
|
|
97
|
+
readonly nullable: true;
|
|
98
|
+
readonly properties: {
|
|
99
|
+
readonly jwtSecret: {
|
|
100
|
+
readonly type: "string";
|
|
101
|
+
readonly required: true;
|
|
102
|
+
};
|
|
103
|
+
readonly jwtExpiresIn: {
|
|
104
|
+
readonly type: "string";
|
|
105
|
+
readonly required: false;
|
|
106
|
+
};
|
|
107
|
+
readonly strategies: {
|
|
108
|
+
readonly type: "object";
|
|
109
|
+
readonly required: true;
|
|
110
|
+
readonly properties: {};
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
};
|
|
60
114
|
};
|
|
61
115
|
};
|
|
62
116
|
/**
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import type { NexxusModelDef } from '../common/ModelTypes';
|
|
2
|
-
import {
|
|
3
|
-
import type { NexxusAppModelType } from '../models/AppModel';
|
|
4
|
-
import type { NexxusUserDetailSchema } from '../models/User';
|
|
2
|
+
import type { INexxusAppModel } from '../models/AppModel';
|
|
5
3
|
export type NexxusComparisonOperator = 'gte' | 'lte' | 'gt' | 'lt' | 'ne' | 'in';
|
|
6
4
|
export type NexxusLogicalOperator = '$and' | '$or';
|
|
7
5
|
export type NexxusFieldValue = string | number | boolean;
|
|
@@ -30,21 +28,15 @@ type FilterNodeWithContext = FilterNode & {
|
|
|
30
28
|
depth: number;
|
|
31
29
|
parentOperator?: NexxusLogicalOperator;
|
|
32
30
|
};
|
|
33
|
-
export type NexxusFilterQueryConfig = {
|
|
34
|
-
appModelDef: NexxusModelDef;
|
|
35
|
-
} | {
|
|
36
|
-
modelType: NexxusBuiltinModelType;
|
|
37
|
-
userDetailsSchema?: NexxusUserDetailSchema;
|
|
38
|
-
};
|
|
39
31
|
export declare class NexxusFilterQuery {
|
|
40
32
|
private query;
|
|
41
33
|
private nodes;
|
|
42
34
|
private modelDef;
|
|
43
|
-
constructor(query: NexxusFilterQueryType,
|
|
35
|
+
constructor(query: NexxusFilterQueryType, schema: NexxusModelDef);
|
|
44
36
|
getNodes(): FilterNode[];
|
|
45
37
|
getNormalizedQuery(): NexxusFilterQueryType;
|
|
46
38
|
[Symbol.iterator](): Generator<FilterNodeWithContext>;
|
|
47
|
-
test(object: Partial<
|
|
39
|
+
test(object: Partial<INexxusAppModel>): boolean;
|
|
48
40
|
private testNode;
|
|
49
41
|
private validateAndParse;
|
|
50
42
|
private parseQuery;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export type InferFieldDef<D> = D extends {
|
|
2
|
+
type: 'string';
|
|
3
|
+
} ? string : D extends {
|
|
4
|
+
type: 'number';
|
|
5
|
+
} ? number : D extends {
|
|
6
|
+
type: 'boolean';
|
|
7
|
+
} ? boolean : D extends {
|
|
8
|
+
type: 'date';
|
|
9
|
+
} ? number : D extends {
|
|
10
|
+
type: 'array';
|
|
11
|
+
arrayType: infer AT;
|
|
12
|
+
properties?: infer P;
|
|
13
|
+
} ? AT extends 'object' ? P extends Record<string, any> ? Array<InferModel<P>> : never : AT extends 'string' ? string[] : AT extends 'number' ? number[] : AT extends 'boolean' ? boolean[] : AT extends 'date' ? number[] : never : D extends {
|
|
14
|
+
type: 'object';
|
|
15
|
+
properties: infer P;
|
|
16
|
+
} ? P extends Record<string, any> ? InferModel<P> : never : never;
|
|
17
|
+
type ApplyNullable<D, T> = D extends {
|
|
18
|
+
nullable: true;
|
|
19
|
+
} ? T | null : T;
|
|
20
|
+
export type InferModel<S> = {
|
|
21
|
+
-readonly [K in keyof S as S[K] extends {
|
|
22
|
+
required: true;
|
|
23
|
+
} ? K : never]: ApplyNullable<S[K], InferFieldDef<S[K]>>;
|
|
24
|
+
} & {
|
|
25
|
+
-readonly [K in keyof S as S[K] extends {
|
|
26
|
+
required: true;
|
|
27
|
+
} ? never : K]?: ApplyNullable<S[K], InferFieldDef<S[K]>>;
|
|
28
|
+
};
|
|
29
|
+
export {};
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import { NexxusAppModelType } from '../models/AppModel';
|
|
4
|
-
import { NexxusBuiltinModelType } from './BuiltinSchemas';
|
|
5
|
-
import type { NexxusUserDetailSchema } from '../models/User';
|
|
1
|
+
import type { NexxusModelDef, NexxusModelFieldType } from '../common/ModelTypes';
|
|
2
|
+
import { INexxusAppModel } from '../models/AppModel';
|
|
6
3
|
declare const JSON_OPS: readonly ["replace", "append", "prepend", "incr", "decr"];
|
|
7
4
|
export type NexxusJsonPatchConstructor = {
|
|
8
5
|
op: typeof JSON_OPS[number];
|
|
@@ -26,12 +23,6 @@ type NexxusJsonPatchMetadataInternal = NexxusJsonPatchMetadata & {
|
|
|
26
23
|
pathFieldTypes?: NexxusModelFieldType[];
|
|
27
24
|
};
|
|
28
25
|
export type NexxusJsonPatchMetadataConstructor = Omit<NexxusJsonPatchMetadata, 'pathFieldTypes'>;
|
|
29
|
-
export type NexxusJsonPatchValidationConfig = {
|
|
30
|
-
appSchema: NexxusApplicationSchema;
|
|
31
|
-
} | {
|
|
32
|
-
modelType: NexxusBuiltinModelType;
|
|
33
|
-
userDetailsSchema?: NexxusUserDetailSchema;
|
|
34
|
-
};
|
|
35
26
|
export declare class NexxusJsonPatch {
|
|
36
27
|
private valid;
|
|
37
28
|
private fullPatch;
|
|
@@ -39,40 +30,8 @@ export declare class NexxusJsonPatch {
|
|
|
39
30
|
constructor(fullPatch: NexxusJsonPatchConstructor | NexxusJsonPatchInternal);
|
|
40
31
|
get(): NexxusJsonPatchInternal;
|
|
41
32
|
isValid(): boolean;
|
|
42
|
-
getPartialModel(): Partial<
|
|
43
|
-
validate(
|
|
44
|
-
private static validateAgainstType;
|
|
33
|
+
getPartialModel(): Partial<INexxusAppModel>;
|
|
34
|
+
validate(schema: NexxusModelDef): void;
|
|
45
35
|
private static traverseSchema;
|
|
46
|
-
private static validateValueType;
|
|
47
|
-
/**
|
|
48
|
-
* Validate string type
|
|
49
|
-
*/
|
|
50
|
-
private static validateString;
|
|
51
|
-
/**
|
|
52
|
-
* Validate number type
|
|
53
|
-
*/
|
|
54
|
-
private static validateNumber;
|
|
55
|
-
/**
|
|
56
|
-
* Validate boolean type
|
|
57
|
-
*/
|
|
58
|
-
private static validateBoolean;
|
|
59
|
-
/**
|
|
60
|
-
* Validate date type
|
|
61
|
-
*/
|
|
62
|
-
private static validateDate;
|
|
63
|
-
/**
|
|
64
|
-
* Validate object type (recursively validates properties)
|
|
65
|
-
*/
|
|
66
|
-
private static validateObject;
|
|
67
|
-
/**
|
|
68
|
-
* Validate array type (recursively validates elements)
|
|
69
|
-
*/
|
|
70
|
-
private static validateArray;
|
|
71
|
-
/**
|
|
72
|
-
* Helper to validate primitive types (reusable for arrays)
|
|
73
|
-
*/
|
|
74
|
-
private static validatePrimitiveType;
|
|
75
|
-
private static isObjectFieldDef;
|
|
76
|
-
private static isArrayFieldDef;
|
|
77
36
|
}
|
|
78
37
|
export {};
|
|
@@ -3,6 +3,7 @@ export type NexxusModelFieldType = NexxusModelPrimitiveType | 'array' | 'object'
|
|
|
3
3
|
interface BaseFieldDef {
|
|
4
4
|
type: NexxusModelFieldType;
|
|
5
5
|
required?: boolean;
|
|
6
|
+
nullable?: boolean;
|
|
6
7
|
}
|
|
7
8
|
export interface PrimitiveFieldDef extends BaseFieldDef {
|
|
8
9
|
type: NexxusModelPrimitiveType;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { INexxusAppModel } from '../models/AppModel';
|
|
2
2
|
import { NexxusJsonPatchInternal, NexxusJsonPatchMetadata } from '../common/JsonPatch';
|
|
3
3
|
export interface NexxusBaseQueuePayload {
|
|
4
4
|
event: string;
|
|
@@ -6,65 +6,87 @@ export interface NexxusBaseQueuePayload {
|
|
|
6
6
|
}
|
|
7
7
|
export type NexxusModelCreatedPayload = {
|
|
8
8
|
event: 'model_created';
|
|
9
|
-
data:
|
|
9
|
+
data: INexxusAppModel;
|
|
10
10
|
};
|
|
11
11
|
export type NexxusModelUpdatedPayload = {
|
|
12
12
|
event: 'model_updated';
|
|
13
13
|
data: Array<NexxusJsonPatchInternal>;
|
|
14
14
|
};
|
|
15
|
-
export type NexxusModelDeletedData = Pick<
|
|
15
|
+
export type NexxusModelDeletedData = Pick<INexxusAppModel, 'id' | 'type' | 'appId' | 'userId'>;
|
|
16
16
|
export type NexxusModelDeletedPayload = {
|
|
17
17
|
event: 'model_deleted';
|
|
18
18
|
data: NexxusModelDeletedData;
|
|
19
19
|
};
|
|
20
20
|
export type NexxusWriterPayload = NexxusModelCreatedPayload | NexxusModelUpdatedPayload | NexxusModelDeletedPayload;
|
|
21
|
-
export type
|
|
21
|
+
export type NexxusTransportManagerJsonPatch = Omit<NexxusJsonPatchInternal, 'metadata'> & {
|
|
22
22
|
metadata: NexxusJsonPatchMetadata & {
|
|
23
|
-
partialModel: Partial<
|
|
23
|
+
partialModel: Partial<INexxusAppModel>;
|
|
24
24
|
};
|
|
25
25
|
};
|
|
26
26
|
export type NexxusTransportManagerModelUpdatedPayload = {
|
|
27
27
|
event: 'model_updated';
|
|
28
|
-
data: Array<
|
|
28
|
+
data: Array<NexxusTransportManagerJsonPatch>;
|
|
29
29
|
};
|
|
30
30
|
export type NexxusTransportManagerPayload = NexxusModelCreatedPayload | NexxusTransportManagerModelUpdatedPayload | NexxusModelDeletedPayload;
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Metadata for transport-bound model events (create/update/delete alike).
|
|
33
|
+
* Carries the channels that matched the subscription router for this device,
|
|
34
|
+
* so the client can correlate the event with its local subscription containers.
|
|
35
|
+
*/
|
|
36
|
+
export interface NexxusTransportMetadata {
|
|
33
37
|
channels: Array<string>;
|
|
34
38
|
}
|
|
35
39
|
/**
|
|
36
|
-
*
|
|
40
|
+
* Payload for any transport worker - model created
|
|
41
|
+
*/
|
|
42
|
+
export type NexxusTransportModelCreatedPayload = {
|
|
43
|
+
event: 'model_created';
|
|
44
|
+
model: INexxusAppModel;
|
|
45
|
+
metadata: NexxusTransportMetadata;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Payload for any transport worker - model deleted
|
|
37
49
|
*/
|
|
38
|
-
export type
|
|
39
|
-
|
|
50
|
+
export type NexxusTransportModelDeletedPayload = {
|
|
51
|
+
event: 'model_deleted';
|
|
52
|
+
model: NexxusModelDeletedData;
|
|
53
|
+
metadata: NexxusTransportMetadata;
|
|
40
54
|
};
|
|
41
55
|
/**
|
|
42
|
-
* Payload for
|
|
56
|
+
* Payload for any transport worker - model updated.
|
|
57
|
+
* All patches in a single event target the same model — its identity is hoisted
|
|
58
|
+
* into `model`, and the matched channels into top-level `metadata`. Per-patch
|
|
59
|
+
* metadata is intentionally absent (it was redundant across patches of the same
|
|
60
|
+
* update event under the previous shape).
|
|
43
61
|
*/
|
|
44
|
-
export type
|
|
62
|
+
export type NexxusTransportModelUpdatedPayload = {
|
|
45
63
|
event: 'model_updated';
|
|
46
|
-
|
|
64
|
+
/**
|
|
65
|
+
* Includes `version` — the post-update version stamp assigned by the adapter.
|
|
66
|
+
* Clients use it for gap detection: apply if `model.version === local.version + 1`,
|
|
67
|
+
* request a fresh GET if there's a gap, ignore if it's already been applied.
|
|
68
|
+
*/
|
|
69
|
+
model: Pick<INexxusAppModel, 'id' | 'type' | 'appId' | 'userId' | 'version'>;
|
|
70
|
+
patches: Array<Omit<NexxusJsonPatchInternal, 'metadata'>>;
|
|
71
|
+
metadata: NexxusTransportMetadata;
|
|
47
72
|
};
|
|
48
|
-
|
|
73
|
+
/**
|
|
74
|
+
* Canonical payload consumed by ALL transport workers (volatile and persistent alike).
|
|
75
|
+
* The shape is identical across transports; each transport translates the inner `data`
|
|
76
|
+
* into its own wire format inside its `sendToDevice` implementation.
|
|
77
|
+
*/
|
|
78
|
+
export type NexxusTransportWorkerPayload = {
|
|
49
79
|
event: 'device_message';
|
|
50
80
|
deviceIds: Array<string>;
|
|
51
|
-
data:
|
|
52
|
-
};
|
|
53
|
-
export type NexxusMqttPayload = {
|
|
54
|
-
event: 'mqtt_publish';
|
|
55
|
-
topic: string;
|
|
56
|
-
payload: Buffer;
|
|
57
|
-
} | {
|
|
58
|
-
event: 'mqtt_subscribe';
|
|
59
|
-
topic: string;
|
|
81
|
+
data: NexxusTransportModelCreatedPayload | NexxusTransportModelUpdatedPayload | NexxusTransportModelDeletedPayload;
|
|
60
82
|
};
|
|
61
83
|
export interface NexxusBuiltInQueuePayloadMap {
|
|
62
84
|
'writer': NexxusWriterPayload;
|
|
63
85
|
'transport-manager': NexxusTransportManagerPayload;
|
|
64
86
|
}
|
|
65
87
|
export interface NexxusDynamicQueuePayloadMap {
|
|
66
|
-
'websockets-transport':
|
|
67
|
-
'mqtt-transport':
|
|
88
|
+
'websockets-transport': NexxusTransportWorkerPayload;
|
|
89
|
+
'mqtt-transport': NexxusTransportWorkerPayload;
|
|
68
90
|
}
|
|
69
91
|
export type NexxusBuiltInQueueName = keyof NexxusBuiltInQueuePayloadMap;
|
|
70
92
|
export type NexxusDynamicQueueType = keyof NexxusDynamicQueuePayloadMap;
|
|
@@ -1,4 +1,44 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { NexxusFieldDef, NexxusModelDef } from './ModelTypes';
|
|
2
|
+
/**
|
|
3
|
+
* Pure schema-aware validation + normalization for a single value against a
|
|
4
|
+
* field definition, or for whole-model data against a model definition.
|
|
5
|
+
*
|
|
6
|
+
* Returns a normalized copy of the input value (e.g. date strings become
|
|
7
|
+
* integer timestamps). Throws InvalidSchemaDataException on the first violation.
|
|
8
|
+
*
|
|
9
|
+
* Used by:
|
|
10
|
+
* - NexxusJsonPatch (per-path validation on patch operations)
|
|
11
|
+
* - NexxusAppModel (whole-model validation on construction)
|
|
12
|
+
*
|
|
13
|
+
* Required-field checking is intentionally NOT performed here yet; only fields
|
|
14
|
+
* present in the input are validated.
|
|
15
|
+
*/
|
|
2
16
|
export declare class NexxusSchemaValidator {
|
|
3
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Validate every present field of `data` against the model definition.
|
|
19
|
+
* Returns a shallow-merged copy of `data` with each value normalized.
|
|
20
|
+
* Unknown fields (present in data but not declared in modelDef) are passed
|
|
21
|
+
* through unchanged.
|
|
22
|
+
*/
|
|
23
|
+
static validateAgainstSchema(data: Record<string, unknown>, modelDef: NexxusModelDef): Record<string, unknown>;
|
|
24
|
+
/**
|
|
25
|
+
* Validate a single value against a field definition. Returns the normalized
|
|
26
|
+
* value. Throws InvalidSchemaDataException on failure.
|
|
27
|
+
*
|
|
28
|
+
* `path` is used only for error messages.
|
|
29
|
+
*/
|
|
30
|
+
static validateValue(value: unknown, fieldDef: NexxusFieldDef, path: string): unknown;
|
|
31
|
+
private static validateString;
|
|
32
|
+
private static validateNumber;
|
|
33
|
+
private static validateBoolean;
|
|
34
|
+
/**
|
|
35
|
+
* Accepts: number (ms timestamp), ISO date string, or numeric string.
|
|
36
|
+
* Returns: integer ms timestamp.
|
|
37
|
+
*
|
|
38
|
+
* This is the single canonical date parser for the system; the previous
|
|
39
|
+
* inconsistency between `Date.parse()` and `new Date(s).getTime()` is gone.
|
|
40
|
+
*/
|
|
41
|
+
private static validateDate;
|
|
42
|
+
private static validateObject;
|
|
43
|
+
private static validateArray;
|
|
4
44
|
}
|
package/dist-types/index.d.ts
CHANGED
|
@@ -6,7 +6,10 @@ export * from "./lib/Logger";
|
|
|
6
6
|
export * from "./common/QueuePayloads";
|
|
7
7
|
export * from "./common/JsonPatch";
|
|
8
8
|
export * from "./common/FilterQuery";
|
|
9
|
+
export * from "./common/InferModel";
|
|
10
|
+
export * from "./common/SchemaValidator";
|
|
9
11
|
export * from "./models/BaseModel";
|
|
12
|
+
export * from "./models/BuiltinModel";
|
|
10
13
|
export * from './common/BuiltinSchemas';
|
|
11
14
|
export * from "./models/AppModel";
|
|
12
15
|
export * from "./models/Application";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ConfigEnvVars, ConfigCliArgs, AddJsonSchemaDefFuncArg, NexxusConfigManager } from './ConfigManager';
|
|
2
|
-
import type { NexxusBaseLogger } from
|
|
2
|
+
import type { NexxusBaseLogger } from './Logger';
|
|
3
3
|
import { NexxusConfig } from './ConfigProvider';
|
|
4
4
|
export type EventMap = Record<string | symbol, any[]>;
|
|
5
5
|
export interface INexxusBaseServices {
|
|
@@ -18,6 +18,13 @@ export declare abstract class NexxusBaseService<T extends NexxusConfig, Ev exten
|
|
|
18
18
|
protected config: Readonly<T>;
|
|
19
19
|
protected static envVars: ConfigEnvVars;
|
|
20
20
|
protected static cliArgs: ConfigCliArgs;
|
|
21
|
+
/**
|
|
22
|
+
* The top-level key under which this service's configuration sits in the merged
|
|
23
|
+
* root config (e.g. "logger", "database", "redis", "app"). Required for every
|
|
24
|
+
* concrete service — ConfigManager uses it as the property name when grafting
|
|
25
|
+
* the service's schema definition into the root JSON Schema.
|
|
26
|
+
*/
|
|
27
|
+
protected static configRootKey: string;
|
|
21
28
|
protected static schemaPath: string;
|
|
22
29
|
private static schemaContents;
|
|
23
30
|
constructor(config: Readonly<T>);
|
|
@@ -9,21 +9,17 @@ export type AddJsonSchemaDefFuncArg = {
|
|
|
9
9
|
};
|
|
10
10
|
type EnvVarsSpec = {
|
|
11
11
|
name: string;
|
|
12
|
+
/** Dot-notation path relative to the service's configRootKey (e.g. "host", "auth.jwtSecret"). */
|
|
12
13
|
location: string;
|
|
13
14
|
};
|
|
14
|
-
export type ConfigEnvVars =
|
|
15
|
-
source: string;
|
|
16
|
-
specs: Array<EnvVarsSpec>;
|
|
17
|
-
};
|
|
15
|
+
export type ConfigEnvVars = Array<EnvVarsSpec>;
|
|
18
16
|
type CliArgsSpec = {
|
|
19
17
|
name: string;
|
|
18
|
+
/** Dot-notation path relative to the service's configRootKey. */
|
|
20
19
|
location: string;
|
|
21
20
|
type: CliArgType;
|
|
22
21
|
};
|
|
23
|
-
export type ConfigCliArgs =
|
|
24
|
-
source: string;
|
|
25
|
-
specs: Array<CliArgsSpec>;
|
|
26
|
-
};
|
|
22
|
+
export type ConfigCliArgs = Array<CliArgsSpec>;
|
|
27
23
|
export declare class NexxusConfigManager {
|
|
28
24
|
private static CONF_FILE_NAME;
|
|
29
25
|
private jsonSchema;
|
|
@@ -32,12 +28,10 @@ export declare class NexxusConfigManager {
|
|
|
32
28
|
private data;
|
|
33
29
|
private configProviders;
|
|
34
30
|
private customProviders;
|
|
35
|
-
constructor(
|
|
31
|
+
constructor(configFileName?: string);
|
|
36
32
|
addCustomProvider(provider: INexxusConfigProvider): void;
|
|
37
33
|
private addJsonSchemaDef;
|
|
38
|
-
validateServices(svcs: Array<typeof NexxusBaseService>): void
|
|
39
|
-
private addCliArgsToSpec;
|
|
40
|
-
private addEnvVarsToSpec;
|
|
34
|
+
validateServices(svcs: Array<typeof NexxusBaseService>): Promise<void>;
|
|
41
35
|
private populateFromCliArgs;
|
|
42
36
|
private populateFromEnvVars;
|
|
43
37
|
private populateFromCustomProviders;
|
|
@@ -5,6 +5,7 @@ export declare enum NexxusExceptions {
|
|
|
5
5
|
INVALID_CONFIG = "InvalidConfigException",
|
|
6
6
|
INVALID_JSON_PATCH = "InvalidJsonPatchException",
|
|
7
7
|
INVALID_QUERY_FILTER = "InvalidQueryFilterException",
|
|
8
|
+
INVALID_SCHEMA_DATA = "InvalidSchemaDataException",
|
|
8
9
|
INVALID_USER_MODEL = "InvalidUserModelException"
|
|
9
10
|
}
|
|
10
11
|
export declare class NexxusException extends Error {
|
|
@@ -28,6 +29,9 @@ export declare class InvalidJsonPatchException extends NexxusException {
|
|
|
28
29
|
export declare class InvalidQueryFilterException extends NexxusException {
|
|
29
30
|
constructor(message: string);
|
|
30
31
|
}
|
|
32
|
+
export declare class InvalidSchemaDataException extends NexxusException {
|
|
33
|
+
constructor(message: string);
|
|
34
|
+
}
|
|
31
35
|
export declare class InvalidUserModelException extends NexxusException {
|
|
32
36
|
constructor(message: string);
|
|
33
37
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ConfigEnvVars, ConfigCliArgs } from './ConfigManager';
|
|
2
2
|
import { NexxusBaseService, INexxusBaseServices } from './BaseService';
|
|
3
3
|
import { NexxusConfig } from './ConfigProvider';
|
|
4
|
-
type
|
|
4
|
+
export type LogAttributes = Record<string, unknown>;
|
|
5
5
|
export declare const enum NexxusLoggerLevels {
|
|
6
6
|
EMERGENCY = "emerg",
|
|
7
7
|
ALERT = "alert",
|
|
@@ -12,37 +12,107 @@ export declare const enum NexxusLoggerLevels {
|
|
|
12
12
|
INFO = "info",
|
|
13
13
|
DEBUG = "debug"
|
|
14
14
|
}
|
|
15
|
+
export type StdoutTransportConfig = {
|
|
16
|
+
type: 'stdout';
|
|
17
|
+
};
|
|
18
|
+
export type FileTransportConfig = {
|
|
19
|
+
type: 'file';
|
|
20
|
+
filename: string;
|
|
21
|
+
maxSize?: number;
|
|
22
|
+
maxFiles?: number;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Catch-all for transports loaded dynamically from npm packages. The `type`
|
|
26
|
+
* field is the package name (e.g. "winston-papertrail"); `export` optionally
|
|
27
|
+
* names the class export within the package; `options` is the passthrough
|
|
28
|
+
* config object handed to the transport's constructor.
|
|
29
|
+
*
|
|
30
|
+
* The schema's `oneOf` discriminator excludes built-in type strings from this
|
|
31
|
+
* variant, so the TS-side `type: string` doesn't cause ambiguity at runtime.
|
|
32
|
+
*/
|
|
33
|
+
export type CustomTransportConfig = {
|
|
34
|
+
type: string;
|
|
35
|
+
export?: string;
|
|
36
|
+
options?: Record<string, unknown>;
|
|
37
|
+
};
|
|
38
|
+
export type WinstonNexxusTransportConfig = StdoutTransportConfig | FileTransportConfig | CustomTransportConfig;
|
|
15
39
|
type WinstonNexxusLoggerConfig = {
|
|
16
40
|
level: NexxusLoggerLevels;
|
|
17
41
|
logType: "json" | "text";
|
|
18
42
|
timestamps: boolean;
|
|
19
43
|
colors: boolean;
|
|
44
|
+
transports?: Array<WinstonNexxusTransportConfig>;
|
|
20
45
|
} & NexxusConfig;
|
|
21
46
|
export interface INexxusLogger {
|
|
22
|
-
log(level: NexxusLoggerLevels, message:
|
|
47
|
+
log(level: NexxusLoggerLevels, message: string, attributes?: LogAttributes, label?: string): void;
|
|
23
48
|
}
|
|
24
|
-
export interface INexxusAsyncLogger
|
|
25
|
-
log(level: NexxusLoggerLevels, message:
|
|
49
|
+
export interface INexxusAsyncLogger {
|
|
50
|
+
log(level: NexxusLoggerLevels, message: string, attributes?: LogAttributes, label?: string): Promise<void>;
|
|
26
51
|
}
|
|
27
52
|
interface NexxusLoggerServices extends Omit<INexxusBaseServices, 'logger'> {
|
|
28
53
|
}
|
|
29
54
|
export declare abstract class NexxusBaseLogger<T extends NexxusConfig> extends NexxusBaseService<T> implements INexxusLogger {
|
|
55
|
+
protected static configRootKey: string;
|
|
30
56
|
constructor(services: NexxusLoggerServices);
|
|
31
|
-
abstract log(level: NexxusLoggerLevels, message:
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
57
|
+
abstract log(level: NexxusLoggerLevels, message: string, attributes?: LogAttributes, label?: string): void;
|
|
58
|
+
protected static serializeError(err: Error): Record<string, unknown>;
|
|
59
|
+
protected static makeSafeReplacer(): (key: string, value: unknown) => unknown;
|
|
60
|
+
protected static safeStringify(value: unknown): string;
|
|
61
|
+
debug(message: string, label?: string): void;
|
|
62
|
+
debug(message: string, attributes: LogAttributes, label?: string): void;
|
|
63
|
+
info(message: string, label?: string): void;
|
|
64
|
+
info(message: string, attributes: LogAttributes, label?: string): void;
|
|
65
|
+
warn(message: string, label?: string): void;
|
|
66
|
+
warn(message: string, attributes: LogAttributes, label?: string): void;
|
|
67
|
+
error(message: string, label?: string): void;
|
|
68
|
+
error(message: string, attributes: LogAttributes, label?: string): void;
|
|
69
|
+
critical(message: string, label?: string): void;
|
|
70
|
+
critical(message: string, attributes: LogAttributes, label?: string): void;
|
|
71
|
+
alert(message: string, label?: string): void;
|
|
72
|
+
alert(message: string, attributes: LogAttributes, label?: string): void;
|
|
73
|
+
emerg(message: string, label?: string): void;
|
|
74
|
+
emerg(message: string, attributes: LogAttributes, label?: string): void;
|
|
75
|
+
private dispatch;
|
|
39
76
|
}
|
|
40
77
|
export declare class WinstonNexxusLogger extends NexxusBaseLogger<WinstonNexxusLoggerConfig> {
|
|
41
78
|
private winston;
|
|
42
79
|
protected static schemaPath: string;
|
|
43
80
|
protected static envVars: ConfigEnvVars;
|
|
44
81
|
protected static cliArgs: ConfigCliArgs;
|
|
45
|
-
|
|
46
|
-
|
|
82
|
+
/**
|
|
83
|
+
* Private — use `WinstonNexxusLogger.create(...)` instead. Transport instances
|
|
84
|
+
* must be resolved (async, since custom ones are dynamically imported) before
|
|
85
|
+
* the Winston logger can be constructed; the factory owns that step.
|
|
86
|
+
*/
|
|
87
|
+
private constructor();
|
|
88
|
+
/**
|
|
89
|
+
* Async factory. Custom transports are loaded via dynamic `import()` so
|
|
90
|
+
* initialization is unavoidably async. API/Worker bootstrap code should
|
|
91
|
+
* `await WinstonNexxusLogger.create(...)` in place of `new WinstonNexxusLogger(...)`.
|
|
92
|
+
*/
|
|
93
|
+
static create(services: NexxusLoggerServices): Promise<WinstonNexxusLogger>;
|
|
94
|
+
/**
|
|
95
|
+
* Maps each transport config entry to a constructed Winston transport.
|
|
96
|
+
* Built-in types are instantiated synchronously; everything else falls
|
|
97
|
+
* through to `loadCustomTransport`, which dynamically imports the npm
|
|
98
|
+
* package named by `type`.
|
|
99
|
+
*
|
|
100
|
+
* If the config has no transports (undefined or empty array), defaults to
|
|
101
|
+
* a single Console transport so the logger is never silent.
|
|
102
|
+
*/
|
|
103
|
+
private static resolveTransports;
|
|
104
|
+
/**
|
|
105
|
+
* Dynamically imports the npm package named by `transport.type` and instantiates
|
|
106
|
+
* its transport class. The class is resolved in priority order:
|
|
107
|
+
* 1. `mod[transport.export]` if `transport.export` is set in config
|
|
108
|
+
* 2. `mod.default` if it's a function/class (ESM default export)
|
|
109
|
+
* 3. The module itself if it's a function/class (CJS `module.exports = Cls`)
|
|
110
|
+
*
|
|
111
|
+
* On any failure (package missing, no resolvable class, constructor throws)
|
|
112
|
+
* we re-wrap as `InvalidConfigException` so the operator sees an actionable
|
|
113
|
+
* message rather than a raw module-resolution stack trace.
|
|
114
|
+
*/
|
|
115
|
+
private static loadCustomTransport;
|
|
116
|
+
log(level: NexxusLoggerLevels, message: string, attributes?: LogAttributes, label?: string): void;
|
|
47
117
|
}
|
|
48
118
|
export {};
|