tsondb 0.21.1 → 0.21.3
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/src/node/config.d.ts +2 -2
- package/dist/src/node/git.d.ts +4 -4
- package/dist/src/node/git.js +1 -1
- package/dist/src/node/index.d.ts +56 -5
- package/dist/src/node/index.js +140 -12
- package/dist/src/node/renderers/jsonschema/render.js +7 -0
- package/dist/src/node/renderers/ts/render.d.ts +4 -0
- package/dist/src/node/renderers/ts/render.js +7 -1
- package/dist/src/node/schema/dsl/declarations/Decl.d.ts +3 -2
- package/dist/src/node/schema/dsl/declarations/Decl.js +2 -1
- package/dist/src/node/schema/dsl/declarations/SingletonEntityDecl.d.ts +35 -0
- package/dist/src/node/schema/dsl/declarations/SingletonEntityDecl.js +23 -0
- package/dist/src/node/schema/dsl/index.d.ts +1 -0
- package/dist/src/node/schema/dsl/index.js +1 -0
- package/dist/src/node/schema/generatedTypeHelpers.d.ts +18 -0
- package/dist/src/node/schema/guards.d.ts +1 -0
- package/dist/src/node/schema/guards.js +1 -0
- package/dist/src/node/schema/helpers.js +1 -0
- package/dist/src/node/schema/index.d.ts +12 -1
- package/dist/src/node/schema/index.js +51 -0
- package/dist/src/node/schema/treeOperations/customConstraints.d.ts +2 -1
- package/dist/src/node/schema/treeOperations/customConstraints.js +10 -10
- package/dist/src/node/schema/treeOperations/implicitSchema.js +1 -0
- package/dist/src/node/schema/treeOperations/references.js +1 -0
- package/dist/src/node/schema/treeOperations/serialization.d.ts +4 -1
- package/dist/src/node/schema/treeOperations/serialization.js +8 -0
- package/dist/src/node/schema/treeOperations/typeResolution.d.ts +4 -1
- package/dist/src/node/schema/treeOperations/typeResolution.js +6 -0
- package/dist/src/node/schema/treeOperations/validation.js +3 -1
- package/dist/src/node/server/api/declarations.js +209 -23
- package/dist/src/node/server/utils/instanceOperations.js +1 -1
- package/dist/src/node/transaction.d.ts +33 -11
- package/dist/src/node/transaction.js +142 -1
- package/dist/src/node/utils/childInstances.js +1 -1
- package/dist/src/node/utils/customConstraints.d.ts +6 -5
- package/dist/src/node/utils/customConstraints.js +34 -15
- package/dist/src/node/utils/databaseInMemory.d.ts +28 -8
- package/dist/src/node/utils/databaseInMemory.js +126 -9
- package/dist/src/node/utils/databaseOnDisk.js +27 -30
- package/dist/src/node/utils/error.d.ts +0 -8
- package/dist/src/node/utils/error.js +1 -39
- package/dist/src/node/utils/files.d.ts +7 -2
- package/dist/src/node/utils/files.js +9 -0
- package/dist/src/node/utils/references.d.ts +2 -0
- package/dist/src/node/utils/references.js +6 -1
- package/dist/src/node/utils/sortOrder.d.ts +13 -0
- package/dist/src/node/utils/sortOrder.js +12 -0
- package/dist/src/node/utils/unique.d.ts +0 -4
- package/dist/src/node/utils/unique.js +1 -7
- package/dist/src/shared/api.d.ts +59 -2
- package/dist/src/shared/schema/Node.d.ts +5 -1
- package/dist/src/shared/schema/Node.js +6 -0
- package/dist/src/shared/schema/declarations/Declaration.d.ts +3 -2
- package/dist/src/shared/schema/declarations/SingletonEntityDecl.d.ts +18 -0
- package/dist/src/shared/schema/declarations/SingletonEntityDecl.js +8 -0
- package/dist/src/shared/schema/utils/keyPath.d.ts +1 -0
- package/dist/src/shared/schema/utils/keyPath.js +30 -0
- package/dist/src/shared/schema/utils/sortOrder.d.ts +9 -0
- package/dist/src/shared/schema/utils/sortOrder.js +11 -0
- package/dist/src/shared/utils/childInstances.d.ts +4 -0
- package/dist/src/shared/utils/error.d.ts +8 -0
- package/dist/src/shared/utils/error.js +39 -0
- package/dist/src/shared/utils/instances.d.ts +4 -0
- package/dist/src/{node → shared}/utils/render.js +1 -1
- package/dist/src/shared/utils/unique.d.ts +4 -0
- package/dist/src/shared/utils/unique.js +7 -0
- package/dist/src/web/web.js +687 -165
- package/package.json +1 -1
- package/public/css/styles.css +4 -2
- /package/dist/src/{node → shared}/utils/render.d.ts +0 -0
|
@@ -8,6 +8,7 @@ import type { DisplayNameResult } from "../../shared/utils/displayName.ts";
|
|
|
8
8
|
import type { InstanceContainer, InstanceContainerOverview, InstanceContent } from "../../shared/utils/instances.ts";
|
|
9
9
|
import type { DeclarationName, DefaultTSONDBTypes } from "../index.ts";
|
|
10
10
|
import type { EntityDecl } from "./dsl/declarations/EntityDecl.ts";
|
|
11
|
+
import type { SingletonEntityDecl } from "./dsl/declarations/SingletonEntityDecl.ts";
|
|
11
12
|
export interface Register {
|
|
12
13
|
}
|
|
13
14
|
export type AnyEntityMap = Record<string, InstanceContent>;
|
|
@@ -19,6 +20,15 @@ export type RegisteredEntity<Name extends string, T = Register> = T extends {
|
|
|
19
20
|
[K in Name]: InstanceContent;
|
|
20
21
|
};
|
|
21
22
|
} ? T["entityMap"][Name] : InstanceContent;
|
|
23
|
+
export type AnySingletonEntityMap = Record<string, InstanceContent>;
|
|
24
|
+
export type RegisteredSingletonEntityMap<T = Register> = T extends {
|
|
25
|
+
singletonEntityMap: AnySingletonEntityMap;
|
|
26
|
+
} ? T["singletonEntityMap"] : AnySingletonEntityMap;
|
|
27
|
+
export type RegisteredSingletonEntity<Name extends string, T = Register> = T extends {
|
|
28
|
+
singletonEntityMap: {
|
|
29
|
+
[K in Name]: InstanceContent;
|
|
30
|
+
};
|
|
31
|
+
} ? T["singletonEntityMap"][Name] : InstanceContent;
|
|
22
32
|
export type AnyChildEntityMap = Record<string, [
|
|
23
33
|
content: InstanceContent,
|
|
24
34
|
parentKey: string,
|
|
@@ -133,6 +143,14 @@ export type GetDisplayNameAndId<T extends AnyEntityMap = RegisteredEntityMap> =
|
|
|
133
143
|
* A function that retrieves an entity declaration by its name.
|
|
134
144
|
*/
|
|
135
145
|
export type GetEntityByName<T extends AnyEntityMap = RegisteredEntityMap> = <E extends Extract<keyof T, string> = Extract<keyof T, string>>(name: E) => EntityDecl<E> | undefined;
|
|
146
|
+
/**
|
|
147
|
+
* A function that retrieves an entity declaration by its name.
|
|
148
|
+
*/
|
|
149
|
+
export type GetSingletonEntityByName<T extends AnySingletonEntityMap = RegisteredSingletonEntityMap> = <E extends Extract<keyof T, string> = Extract<keyof T, string>>(name: E) => SingletonEntityDecl<E> | undefined;
|
|
150
|
+
/**
|
|
151
|
+
* A function that retrieves the singleton instance by its entity if available.
|
|
152
|
+
*/
|
|
153
|
+
export type GetSingletonInstance<T extends AnySingletonEntityMap = RegisteredSingletonEntityMap> = <E extends Extract<keyof T, string> = Extract<keyof T, string>>(entity: E) => T[E] | undefined;
|
|
136
154
|
/**
|
|
137
155
|
* A type guard function that checks if a given string is a valid declaration name.
|
|
138
156
|
*/
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { isDecl, isDeclWithoutTypeParameters } from "./dsl/declarations/Decl.ts";
|
|
2
2
|
export { isEntityDecl, isEntityDeclWithParentReference } from "./dsl/declarations/EntityDecl.ts";
|
|
3
3
|
export { isEnumDecl } from "./dsl/declarations/EnumDecl.ts";
|
|
4
|
+
export { isSingletonEntityDecl } from "./dsl/declarations/SingletonEntityDecl.ts";
|
|
4
5
|
export { isTypeAliasDecl } from "./dsl/declarations/TypeAliasDecl.ts";
|
|
5
6
|
export { isArrayType } from "./dsl/types/ArrayType.ts";
|
|
6
7
|
export { isBooleanType } from "./dsl/types/BooleanType.ts";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { isDecl, isDeclWithoutTypeParameters } from "./dsl/declarations/Decl.js";
|
|
2
2
|
export { isEntityDecl, isEntityDeclWithParentReference } from "./dsl/declarations/EntityDecl.js";
|
|
3
3
|
export { isEnumDecl } from "./dsl/declarations/EnumDecl.js";
|
|
4
|
+
export { isSingletonEntityDecl } from "./dsl/declarations/SingletonEntityDecl.js";
|
|
4
5
|
export { isTypeAliasDecl } from "./dsl/declarations/TypeAliasDecl.js";
|
|
5
6
|
export { isArrayType } from "./dsl/types/ArrayType.js";
|
|
6
7
|
export { isBooleanType } from "./dsl/types/BooleanType.js";
|
|
@@ -12,6 +12,7 @@ export const reduceNodes = (reducer, nodes, options = {}) => {
|
|
|
12
12
|
const reduceNodeTree = (parentNodes, node, collectedResults, reducedDecls) => {
|
|
13
13
|
switch (node.kind) {
|
|
14
14
|
case NodeKind.EntityDecl:
|
|
15
|
+
case NodeKind.SingletonEntityDecl:
|
|
15
16
|
case NodeKind.EnumDecl:
|
|
16
17
|
case NodeKind.TypeAliasDecl:
|
|
17
18
|
return reduceNodeTree([node], node.type.value, reducer(parentNodes, node, collectedResults), [...reducedDecls, node]);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type { DeclarationName, DefaultTSONDBTypes, EntityName } from "../index.ts";
|
|
1
|
+
import type { DeclarationName, DefaultTSONDBTypes, EntityName, SingletonEntityName } from "../index.ts";
|
|
2
2
|
import type { Decl } from "./dsl/declarations/Decl.ts";
|
|
3
3
|
import type { EntityDecl } from "./dsl/declarations/EntityDecl.ts";
|
|
4
|
+
import type { SingletonEntityDecl } from "./dsl/index.ts";
|
|
4
5
|
export declare class Schema<T extends DefaultTSONDBTypes = DefaultTSONDBTypes> {
|
|
5
6
|
#private;
|
|
6
7
|
constructor(declarations: Decl[], localeEntity?: EntityDecl);
|
|
@@ -8,6 +9,10 @@ export declare class Schema<T extends DefaultTSONDBTypes = DefaultTSONDBTypes> {
|
|
|
8
9
|
get resolvedEntities(): EntityDecl<EntityName<T>>[];
|
|
9
10
|
getEntity<E extends EntityName<T>>(name: E): EntityDecl<E> | undefined;
|
|
10
11
|
getResolvedEntity<E extends EntityName<T>>(name: E): EntityDecl<E> | undefined;
|
|
12
|
+
get singletonEntities(): SingletonEntityDecl<SingletonEntityName<T>>[];
|
|
13
|
+
get resolvedSingletonEntities(): SingletonEntityDecl<SingletonEntityName<T>>[];
|
|
14
|
+
getSingletonEntity<E extends SingletonEntityName<T>>(name: E): SingletonEntityDecl<E> | undefined;
|
|
15
|
+
getResolvedSingletonEntity<E extends SingletonEntityName<T>>(name: E): SingletonEntityDecl<E> | undefined;
|
|
11
16
|
get declarations(): Decl[];
|
|
12
17
|
get resolvedDeclarations(): Decl[];
|
|
13
18
|
getDeclaration<E extends DeclarationName<T>>(name: E): Decl<E> | undefined;
|
|
@@ -19,6 +24,12 @@ export declare class Schema<T extends DefaultTSONDBTypes = DefaultTSONDBTypes> {
|
|
|
19
24
|
* This includes all entity declarations, but not nested entity declarations, as they cannot be referenced directly by their name.
|
|
20
25
|
*/
|
|
21
26
|
isEntityName(name: string): name is EntityName<T>;
|
|
27
|
+
/**
|
|
28
|
+
* Checks if the given name is a valid singleton entity name in the schema.
|
|
29
|
+
*
|
|
30
|
+
* This includes all entity declarations, but not nested entity declarations, as they cannot be referenced directly by their name.
|
|
31
|
+
*/
|
|
32
|
+
isSingletonEntityName(name: string): name is SingletonEntityName<T>;
|
|
22
33
|
/**
|
|
23
34
|
* Checks if the given name is a valid declaration name in the schema. This includes entity declarations, enum declarations and type alias declarations.
|
|
24
35
|
*
|
|
@@ -8,6 +8,7 @@ import { renderKeyPath } from "../../shared/schema/utils/keyPath.js";
|
|
|
8
8
|
import { getParameterNames, resolveTypeArgumentsInDecls, walkNodeTree, } from "./dsl/declarations/Decl.js";
|
|
9
9
|
import { isEntityDecl } from "./dsl/declarations/EntityDecl.js";
|
|
10
10
|
import { cases, isEnumDecl } from "./dsl/declarations/EnumDecl.js";
|
|
11
|
+
import { isSingletonEntityDecl } from "./dsl/declarations/SingletonEntityDecl.js";
|
|
11
12
|
import { isChildEntitiesType } from "./dsl/types/ChildEntitiesType.js";
|
|
12
13
|
import { isFloatType } from "./dsl/types/FloatType.js";
|
|
13
14
|
import { isIncludeIdentifierType } from "./dsl/types/IncludeIdentifierType.js";
|
|
@@ -23,8 +24,10 @@ const debug = Debug("tsondb:schema");
|
|
|
23
24
|
export class Schema {
|
|
24
25
|
#declarations;
|
|
25
26
|
#entities;
|
|
27
|
+
#singletonEntities;
|
|
26
28
|
#resolvedDeclarations;
|
|
27
29
|
#resolvedEntities;
|
|
30
|
+
#resolvedSingletonEntities;
|
|
28
31
|
#localeEntity;
|
|
29
32
|
#declarationMap;
|
|
30
33
|
#resolvedDeclarationMap;
|
|
@@ -58,6 +61,8 @@ export class Schema {
|
|
|
58
61
|
this.#resolvedDeclarations = resolveTypeArgumentsInDecls(allDeclsWithoutNestedEntities);
|
|
59
62
|
this.#entities = allDeclsWithoutNestedEntities.filter(isEntityDecl);
|
|
60
63
|
this.#resolvedEntities = this.#resolvedDeclarations.filter(isEntityDecl);
|
|
64
|
+
this.#singletonEntities = allDeclsWithoutNestedEntities.filter(isSingletonEntityDecl);
|
|
65
|
+
this.#resolvedSingletonEntities = this.#resolvedDeclarations.filter(isSingletonEntityDecl);
|
|
61
66
|
this.#declarationMap = Dictionary.fromEntries(allDeclsWithoutNestedEntities.map(decl => [decl.name, decl]));
|
|
62
67
|
this.#resolvedDeclarationMap = Dictionary.fromEntries(this.#resolvedDeclarations.map(decl => [decl.name, decl]));
|
|
63
68
|
debug("created schema, no integrity violations found");
|
|
@@ -76,6 +81,20 @@ export class Schema {
|
|
|
76
81
|
const decl = this.#resolvedDeclarationMap.get(name);
|
|
77
82
|
return decl && isEntityDecl(decl) ? decl : undefined;
|
|
78
83
|
}
|
|
84
|
+
get singletonEntities() {
|
|
85
|
+
return this.#singletonEntities;
|
|
86
|
+
}
|
|
87
|
+
get resolvedSingletonEntities() {
|
|
88
|
+
return this.#resolvedSingletonEntities;
|
|
89
|
+
}
|
|
90
|
+
getSingletonEntity(name) {
|
|
91
|
+
const decl = this.#declarationMap.get(name);
|
|
92
|
+
return decl && isSingletonEntityDecl(decl) ? decl : undefined;
|
|
93
|
+
}
|
|
94
|
+
getResolvedSingletonEntity(name) {
|
|
95
|
+
const decl = this.#resolvedDeclarationMap.get(name);
|
|
96
|
+
return decl && isSingletonEntityDecl(decl) ? decl : undefined;
|
|
97
|
+
}
|
|
79
98
|
get declarations() {
|
|
80
99
|
return this.#declarations;
|
|
81
100
|
}
|
|
@@ -99,6 +118,14 @@ export class Schema {
|
|
|
99
118
|
isEntityName(name) {
|
|
100
119
|
return this.#entities.some(entity => entity.name === name);
|
|
101
120
|
}
|
|
121
|
+
/**
|
|
122
|
+
* Checks if the given name is a valid singleton entity name in the schema.
|
|
123
|
+
*
|
|
124
|
+
* This includes all entity declarations, but not nested entity declarations, as they cannot be referenced directly by their name.
|
|
125
|
+
*/
|
|
126
|
+
isSingletonEntityName(name) {
|
|
127
|
+
return this.#singletonEntities.some(entity => entity.name === name);
|
|
128
|
+
}
|
|
102
129
|
/**
|
|
103
130
|
* Checks if the given name is a valid declaration name in the schema. This includes entity declarations, enum declarations and type alias declarations.
|
|
104
131
|
*
|
|
@@ -234,6 +261,19 @@ const checkChildEntityTypeInEntityDecl = (checkedDecls, entityDecl, decl) => {
|
|
|
234
261
|
}, decl);
|
|
235
262
|
}
|
|
236
263
|
};
|
|
264
|
+
const checkChildEntityTypeInSingletonEntityDecl = (checkedDecls, entityDecl, decl) => {
|
|
265
|
+
if (!checkedDecls.has(decl)) {
|
|
266
|
+
checkedDecls.add(decl);
|
|
267
|
+
walkNodeTree(node => {
|
|
268
|
+
if (isIncludeIdentifierType(node)) {
|
|
269
|
+
checkChildEntityTypeInSingletonEntityDecl(checkedDecls, entityDecl, node.reference);
|
|
270
|
+
}
|
|
271
|
+
else if (isChildEntitiesType(node)) {
|
|
272
|
+
throw new Error(`Child entities type for entity "${node.entity.name}" in entity declaration "${entityDecl.name}" is not allowed in a singleton entity. Use a regular entity instead.`);
|
|
273
|
+
}
|
|
274
|
+
}, decl);
|
|
275
|
+
}
|
|
276
|
+
};
|
|
237
277
|
const checkChildEntityTypes = (localeEntity, decls) => {
|
|
238
278
|
if (localeEntity && localeEntity.parentReferenceKey !== undefined) {
|
|
239
279
|
throw new TypeError(`The locale entity "${localeEntity.name}" cannot be used as a child entity to other entities.`);
|
|
@@ -246,6 +286,9 @@ const checkChildEntityTypes = (localeEntity, decls) => {
|
|
|
246
286
|
if (isEntityDecl(decl)) {
|
|
247
287
|
checkChildEntityTypeInEntityDecl(new Set(), decl, decl);
|
|
248
288
|
}
|
|
289
|
+
if (isSingletonEntityDecl(decl)) {
|
|
290
|
+
checkChildEntityTypeInSingletonEntityDecl(new Set(), decl, decl);
|
|
291
|
+
}
|
|
249
292
|
}
|
|
250
293
|
};
|
|
251
294
|
const checkChildEntitiesProvideCorrectPathToParentReferenceIdentifierType = (decls) => {
|
|
@@ -269,6 +312,7 @@ const isDeclarationRecursive = (declToCheck) => {
|
|
|
269
312
|
const isDeclarationIncludedInNode = (visitedDecls, node) => {
|
|
270
313
|
switch (node.kind) {
|
|
271
314
|
case NodeKind.EntityDecl:
|
|
315
|
+
case NodeKind.SingletonEntityDecl:
|
|
272
316
|
case NodeKind.EnumDecl:
|
|
273
317
|
case NodeKind.TypeAliasDecl:
|
|
274
318
|
return visitedDecls.includes(node)
|
|
@@ -396,6 +440,13 @@ const checkSortOrders = (declarations) => {
|
|
|
396
440
|
if (!isValidSortOrderType(type)) {
|
|
397
441
|
throw TypeError(`type at key path "${renderKeyPath(sortOrder.keyPath)}" is not a valid sort order type (string, integer, or float) in entity "${decl.name}"`);
|
|
398
442
|
}
|
|
443
|
+
if (sortOrder.isIndex &&
|
|
444
|
+
(!isIntegerType(type) ||
|
|
445
|
+
type.maximum !== undefined ||
|
|
446
|
+
(typeof type.minimum === "object" && type.minimum.isExclusive) ||
|
|
447
|
+
type.multipleOf !== undefined)) {
|
|
448
|
+
throw TypeError(`type at key path ${renderKeyPath(sortOrder.keyPath)} is not a valid index sort order type (integer, optional inclusive minimum, no other constraints) in entity "${decl.name}"`);
|
|
449
|
+
}
|
|
399
450
|
}
|
|
400
451
|
else {
|
|
401
452
|
// const entityMapType = getType(decl.type.value, sortOrder.entityMapKeyPath)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { InstanceContent } from "../../../shared/utils/instances.ts";
|
|
2
2
|
import type { CustomConstraintHelpers } from "../../utils/customConstraints.ts";
|
|
3
3
|
import type { EntityDecl } from "../dsl/declarations/EntityDecl.ts";
|
|
4
|
+
import type { SingletonEntityDecl } from "../dsl/index.ts";
|
|
4
5
|
export declare const checkCustomConstraintsInEntityDecl: (node: EntityDecl, value: [id: string, content: InstanceContent], helpers: CustomConstraintHelpers) => string[];
|
|
5
|
-
export
|
|
6
|
+
export declare const checkCustomConstraintsInSingletonEntityDecl: (node: SingletonEntityDecl, value: InstanceContent, helpers: CustomConstraintHelpers) => string[];
|
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
import { assertExhaustive } from "@elyukai/utils/typeSafety";
|
|
2
2
|
import { ENUM_DISCRIMINATOR_KEY } from "../../../shared/schema/declarations/EnumDecl.js";
|
|
3
3
|
import { NodeKind } from "../../../shared/schema/Node.js";
|
|
4
|
-
export const checkCustomConstraintsInEntityDecl = (node, value, helpers) => (node.customConstraints?.({ ...helpers, instanceId: value[0], instanceContent: value[1] }) ?? []).concat(
|
|
5
|
-
export {
|
|
6
|
-
const
|
|
4
|
+
export const checkCustomConstraintsInEntityDecl = (node, value, helpers) => (node.customConstraints?.({ ...helpers, instanceId: value[0], instanceContent: value[1] }) ?? []).concat(checkNestedCustomConstraints(node.type.value, value, helpers));
|
|
5
|
+
export const checkCustomConstraintsInSingletonEntityDecl = (node, value, helpers) => (node.customConstraints?.({ ...helpers, instanceId: node.name, instanceContent: value }) ?? []).concat(checkNestedCustomConstraints(node.type.value, value, helpers));
|
|
6
|
+
const checkNestedCustomConstraints = (node, value, helpers) => {
|
|
7
7
|
switch (node.kind) {
|
|
8
8
|
case NodeKind.EnumDecl:
|
|
9
|
-
return (node.customConstraints?.({ ...helpers, value }) ?? []).concat(
|
|
9
|
+
return (node.customConstraints?.({ ...helpers, value }) ?? []).concat(checkNestedCustomConstraints(node.type.value, value, helpers));
|
|
10
10
|
case NodeKind.TypeAliasDecl:
|
|
11
|
-
return (node.customConstraints?.({ ...helpers, value }) ?? []).concat(
|
|
11
|
+
return (node.customConstraints?.({ ...helpers, value }) ?? []).concat(checkNestedCustomConstraints(node.type.value, value, helpers));
|
|
12
12
|
case NodeKind.ArrayType:
|
|
13
13
|
return Array.isArray(value)
|
|
14
|
-
? value.flatMap(item =>
|
|
14
|
+
? value.flatMap(item => checkNestedCustomConstraints(node.items, item, helpers))
|
|
15
15
|
: [];
|
|
16
16
|
case NodeKind.ObjectType:
|
|
17
17
|
return typeof value === "object" && value !== null
|
|
18
18
|
? Object.entries(value).flatMap(([key, propValue]) => node.properties[key]
|
|
19
|
-
?
|
|
19
|
+
? checkNestedCustomConstraints(node.properties[key].type, propValue, helpers)
|
|
20
20
|
: [])
|
|
21
21
|
: [];
|
|
22
22
|
case NodeKind.TypeArgumentType: {
|
|
23
23
|
throw new TypeError(`type argument "${node.argument.name}" is unresolved. Make sure to resolve all type arguments before checking for nested custom constraints.`);
|
|
24
24
|
}
|
|
25
25
|
case NodeKind.IncludeIdentifierType:
|
|
26
|
-
return
|
|
26
|
+
return checkNestedCustomConstraints(node.reference, value, helpers);
|
|
27
27
|
case NodeKind.NestedEntityMapType:
|
|
28
|
-
return
|
|
28
|
+
return checkNestedCustomConstraints(node.type.value, value, helpers);
|
|
29
29
|
case NodeKind.EnumType: {
|
|
30
30
|
if (typeof value !== "object" ||
|
|
31
31
|
value === null ||
|
|
@@ -39,7 +39,7 @@ const checkCustomConstraints = (node, value, helpers) => {
|
|
|
39
39
|
node.values[enumCase] !== undefined &&
|
|
40
40
|
node.values[enumCase].type !== null &&
|
|
41
41
|
enumCase in value
|
|
42
|
-
?
|
|
42
|
+
? checkNestedCustomConstraints(node.values[enumCase].type, value[enumCase], helpers)
|
|
43
43
|
: [];
|
|
44
44
|
}
|
|
45
45
|
case NodeKind.BooleanType:
|
|
@@ -3,6 +3,7 @@ import { NodeKind } from "../../../shared/schema/Node.js";
|
|
|
3
3
|
export const getNestedDeclarations = (addedDecls, node, parentDecl) => {
|
|
4
4
|
switch (node.kind) {
|
|
5
5
|
case NodeKind.EntityDecl:
|
|
6
|
+
case NodeKind.SingletonEntityDecl:
|
|
6
7
|
case NodeKind.EnumDecl:
|
|
7
8
|
case NodeKind.TypeAliasDecl:
|
|
8
9
|
return addedDecls.includes(node)
|
|
@@ -6,6 +6,7 @@ import { resolveTypeArguments } from "./typeResolution.js";
|
|
|
6
6
|
export const getReferences = (node, value, inDecl) => {
|
|
7
7
|
switch (node.kind) {
|
|
8
8
|
case NodeKind.EntityDecl:
|
|
9
|
+
case NodeKind.SingletonEntityDecl:
|
|
9
10
|
case NodeKind.EnumDecl:
|
|
10
11
|
case NodeKind.TypeAliasDecl:
|
|
11
12
|
return getReferences(node.type.value, value, [...inDecl, node]);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { SerializedEntityDecl } from "../../../shared/schema/declarations/EntityDecl.ts";
|
|
2
2
|
import type { SerializedEnumDecl } from "../../../shared/schema/declarations/EnumDecl.ts";
|
|
3
|
+
import type { SerializedSingletonEntityDecl } from "../../../shared/schema/declarations/SingletonEntityDecl.ts";
|
|
3
4
|
import type { SerializedTypeAliasDecl } from "../../../shared/schema/declarations/TypeAliasDecl.ts";
|
|
4
5
|
import { NodeKind } from "../../../shared/schema/Node.js";
|
|
5
6
|
import type { SerializedTypeParameter } from "../../../shared/schema/TypeParameter.ts";
|
|
@@ -19,6 +20,7 @@ import type { SerializedTranslationObjectType } from "../../../shared/schema/typ
|
|
|
19
20
|
import type { SerializedTypeArgumentType } from "../../../shared/schema/types/TypeArgumentType.ts";
|
|
20
21
|
import { type EntityDecl } from "../dsl/declarations/EntityDecl.ts";
|
|
21
22
|
import { type EnumDecl } from "../dsl/declarations/EnumDecl.ts";
|
|
23
|
+
import type { SingletonEntityDecl } from "../dsl/declarations/SingletonEntityDecl.ts";
|
|
22
24
|
import { type TypeAliasDecl } from "../dsl/declarations/TypeAliasDecl.ts";
|
|
23
25
|
import type { Node, Type } from "../dsl/index.ts";
|
|
24
26
|
import { type TypeParameter } from "../dsl/TypeParameter.ts";
|
|
@@ -38,6 +40,7 @@ import { type TranslationObjectType } from "../dsl/types/TranslationObjectType.t
|
|
|
38
40
|
import { type TypeArgumentType } from "../dsl/types/TypeArgumentType.ts";
|
|
39
41
|
export type SerializedNodeMap = {
|
|
40
42
|
[NodeKind.EntityDecl]: [EntityDecl, SerializedEntityDecl];
|
|
43
|
+
[NodeKind.SingletonEntityDecl]: [EntityDecl, SerializedSingletonEntityDecl];
|
|
41
44
|
[NodeKind.EnumDecl]: [EnumDecl, SerializedEnumDecl];
|
|
42
45
|
[NodeKind.TypeAliasDecl]: [TypeAliasDecl, SerializedTypeAliasDecl];
|
|
43
46
|
[NodeKind.ArrayType]: [ArrayType, SerializedArrayType];
|
|
@@ -65,7 +68,7 @@ export type SerializedMemberDeclObject<T extends Record<string, MemberDecl>> = {
|
|
|
65
68
|
export type SerializedEnumCaseDeclObject<T extends Record<string, EnumCaseDecl>> = {
|
|
66
69
|
[K in keyof T]: T[K] extends EnumCaseDecl<infer CT> ? SerializedEnumCaseDecl<CT extends Type ? Serialized<CT> : null> : never;
|
|
67
70
|
};
|
|
68
|
-
export type Serialized<T extends Node> = T extends EntityDecl<infer Name, infer T, infer FK> ? SerializedEntityDecl<Name, SerializedMemberDeclObject<T>, FK> : T extends EnumDecl<infer Name, infer T, infer Params> ? SerializedEnumDecl<Name, SerializedEnumCaseDeclObject<T>, SerializedTypeParameters<Params>> : T extends TypeAliasDecl<infer Name, infer T, infer Params> ? SerializedTypeAliasDecl<Name, Serialized<T>, SerializedTypeParameters<Params>> : T extends ArrayType<infer T> ? SerializedArrayType<Serialized<T>> : T extends ObjectType<infer T> ? SerializedObjectType<SerializedMemberDeclObject<T>> : T extends BooleanType ? SerializedBooleanType : T extends DateType ? SerializedDateType : T extends FloatType ? SerializedFloatType : T extends IntegerType ? SerializedIntegerType : T extends StringType ? SerializedStringType : T extends TypeArgumentType<infer T> ? SerializedTypeArgumentType<Serialized<T>> : T extends ReferenceIdentifierType ? SerializedReferenceIdentifierType : T extends IncludeIdentifierType<infer Params> ? SerializedIncludeIdentifierType<SerializedTypeParameters<Params>> : T extends NestedEntityMapType<infer Name, infer T> ? SerializedNestedEntityMapType<Name, SerializedMemberDeclObject<T>> : T extends EnumType<infer T> ? SerializedEnumType<SerializedEnumCaseDeclObject<T>> : T extends TypeParameter<infer N, infer C> ? SerializedTypeParameter<N, C extends Type ? Serialized<C> : undefined> : T extends ChildEntitiesType ? SerializedChildEntitiesType : T extends TranslationObjectType<infer E> ? SerializedTranslationObjectType<E> : never;
|
|
71
|
+
export type Serialized<T extends Node> = T extends EntityDecl<infer Name, infer T, infer FK> ? SerializedEntityDecl<Name, SerializedMemberDeclObject<T>, FK> : T extends SingletonEntityDecl<infer Name, infer T> ? SerializedSingletonEntityDecl<Name, SerializedMemberDeclObject<T>> : T extends EnumDecl<infer Name, infer T, infer Params> ? SerializedEnumDecl<Name, SerializedEnumCaseDeclObject<T>, SerializedTypeParameters<Params>> : T extends TypeAliasDecl<infer Name, infer T, infer Params> ? SerializedTypeAliasDecl<Name, Serialized<T>, SerializedTypeParameters<Params>> : T extends ArrayType<infer T> ? SerializedArrayType<Serialized<T>> : T extends ObjectType<infer T> ? SerializedObjectType<SerializedMemberDeclObject<T>> : T extends BooleanType ? SerializedBooleanType : T extends DateType ? SerializedDateType : T extends FloatType ? SerializedFloatType : T extends IntegerType ? SerializedIntegerType : T extends StringType ? SerializedStringType : T extends TypeArgumentType<infer T> ? SerializedTypeArgumentType<Serialized<T>> : T extends ReferenceIdentifierType ? SerializedReferenceIdentifierType : T extends IncludeIdentifierType<infer Params> ? SerializedIncludeIdentifierType<SerializedTypeParameters<Params>> : T extends NestedEntityMapType<infer Name, infer T> ? SerializedNestedEntityMapType<Name, SerializedMemberDeclObject<T>> : T extends EnumType<infer T> ? SerializedEnumType<SerializedEnumCaseDeclObject<T>> : T extends TypeParameter<infer N, infer C> ? SerializedTypeParameter<N, C extends Type ? Serialized<C> : undefined> : T extends ChildEntitiesType ? SerializedChildEntitiesType : T extends TranslationObjectType<infer E> ? SerializedTranslationObjectType<E> : never;
|
|
69
72
|
export type SerializedOf<T extends Node> = SerializedNodeMap[T["kind"]][1];
|
|
70
73
|
export type Serializer<T extends Node = Node> = (node: T) => Serialized<T>;
|
|
71
74
|
export declare const serializeNode: <T extends Node>(node: T) => Serialized<T>;
|
|
@@ -30,6 +30,14 @@ export const serializeNode = (node) => {
|
|
|
30
30
|
};
|
|
31
31
|
return serializedNode;
|
|
32
32
|
}
|
|
33
|
+
case NodeKind.SingletonEntityDecl: {
|
|
34
|
+
const serializedNode = {
|
|
35
|
+
...node,
|
|
36
|
+
type: serializeNode(node.type.value),
|
|
37
|
+
customConstraints: node.customConstraints !== undefined,
|
|
38
|
+
};
|
|
39
|
+
return serializedNode;
|
|
40
|
+
}
|
|
33
41
|
case NodeKind.EnumDecl: {
|
|
34
42
|
const serializedNode = {
|
|
35
43
|
...node,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type Decl, type IncludableDeclP } from "../dsl/declarations/Decl.ts";
|
|
2
2
|
import { EntityDecl } from "../dsl/declarations/EntityDecl.ts";
|
|
3
3
|
import { EnumDecl } from "../dsl/declarations/EnumDecl.ts";
|
|
4
|
+
import { SingletonEntityDecl } from "../dsl/declarations/SingletonEntityDecl.ts";
|
|
4
5
|
import { TypeAliasDecl } from "../dsl/declarations/TypeAliasDecl.ts";
|
|
5
6
|
import type { Node, Type } from "../dsl/index.ts";
|
|
6
7
|
import type { TypeParameter } from "../dsl/TypeParameter.ts";
|
|
@@ -22,7 +23,9 @@ import type { TranslationObjectType } from "../dsl/types/TranslationObjectType.t
|
|
|
22
23
|
import { type TypeArgumentType } from "../dsl/types/TypeArgumentType.ts";
|
|
23
24
|
export type NodeWithResolvedTypeArguments<T extends Node | null> = T extends BooleanType | DateType | FloatType | IntegerType | StringType | ReferenceIdentifierType | ChildEntitiesType | TranslationObjectType ? T : T extends EntityDecl<infer N, infer P, infer FK> ? EntityDecl<N, {
|
|
24
25
|
[K in keyof P]: P[K] extends MemberDecl<infer PT, infer R> ? MemberDecl<NodeWithResolvedTypeArguments<PT>, R> : never;
|
|
25
|
-
}, FK> : T extends
|
|
26
|
+
}, FK> : T extends SingletonEntityDecl<infer N, infer P> ? SingletonEntityDecl<N, {
|
|
27
|
+
[K in keyof P]: P[K] extends MemberDecl<infer PT, infer R> ? MemberDecl<NodeWithResolvedTypeArguments<PT>, R> : never;
|
|
28
|
+
}> : T extends EnumDecl<infer N, infer V, TypeParameter[]> ? EnumDecl<N, {
|
|
26
29
|
[K in keyof V]: V[K] extends EnumCaseDecl<infer CT> ? EnumCaseDecl<NodeWithResolvedTypeArguments<CT>> : never;
|
|
27
30
|
}, [
|
|
28
31
|
]> : T extends TypeAliasDecl<infer N, infer U, TypeParameter[]> ? TypeAliasDecl<N, NodeWithResolvedTypeArguments<U>, []> : T extends ArrayType<infer I> ? ArrayType<NodeWithResolvedTypeArguments<I>> : T extends EnumType<infer V> ? EnumType<{
|
|
@@ -3,6 +3,7 @@ import { NodeKind } from "../../../shared/schema/Node.js";
|
|
|
3
3
|
import { getTypeArgumentsRecord, isDeclWithoutTypeParameters, } from "../dsl/declarations/Decl.js";
|
|
4
4
|
import { EntityDecl } from "../dsl/declarations/EntityDecl.js";
|
|
5
5
|
import { EnumDecl } from "../dsl/declarations/EnumDecl.js";
|
|
6
|
+
import { SingletonEntityDecl } from "../dsl/declarations/SingletonEntityDecl.js";
|
|
6
7
|
import { isTypeAliasDecl, TypeAliasDecl } from "../dsl/declarations/TypeAliasDecl.js";
|
|
7
8
|
import { ArrayType } from "../dsl/types/ArrayType.js";
|
|
8
9
|
import {} from "../dsl/types/BooleanType.js";
|
|
@@ -24,6 +25,11 @@ export const resolveTypeArguments = (args, node, inDecl) => {
|
|
|
24
25
|
...node,
|
|
25
26
|
type: () => resolveTypeArguments({}, node.type.value, [...inDecl, node]),
|
|
26
27
|
});
|
|
28
|
+
case NodeKind.SingletonEntityDecl:
|
|
29
|
+
return SingletonEntityDecl(node.sourceUrl, {
|
|
30
|
+
...node,
|
|
31
|
+
type: () => resolveTypeArguments({}, node.type.value, [...inDecl, node]),
|
|
32
|
+
});
|
|
27
33
|
case NodeKind.EnumDecl:
|
|
28
34
|
return EnumDecl(node.sourceUrl, {
|
|
29
35
|
name: node.name,
|
|
@@ -4,6 +4,7 @@ import { assertExhaustive } from "@elyukai/utils/typeSafety";
|
|
|
4
4
|
import { MessageError, parseMessage, validate } from "messageformat";
|
|
5
5
|
import { ENUM_DISCRIMINATOR_KEY } from "../../../shared/schema/declarations/EnumDecl.js";
|
|
6
6
|
import { NodeKind } from "../../../shared/schema/Node.js";
|
|
7
|
+
import { wrapErrorsIfAny } from "../../../shared/utils/error.js";
|
|
7
8
|
import { extendsParameterTypes, extractParameterTypeNamesFromMessage, } from "../../../shared/utils/translation.js";
|
|
8
9
|
import { parallelizeErrors } from "../../../shared/utils/validation.js";
|
|
9
10
|
import { validateArrayConstraints } from "../../../shared/validation/array.js";
|
|
@@ -12,7 +13,6 @@ import { validateNumberConstraints } from "../../../shared/validation/number.js"
|
|
|
12
13
|
import { validateObjectConstraints, validateObjectRangeConstraints, validateUnknownKeys, } from "../../../shared/validation/object.js";
|
|
13
14
|
import { validateStringConstraints } from "../../../shared/validation/string.js";
|
|
14
15
|
import {} from "../../utils/databaseInMemory.js";
|
|
15
|
-
import { wrapErrorsIfAny } from "../../utils/error.js";
|
|
16
16
|
import { entity, json, key } from "../../utils/errorFormatting.js";
|
|
17
17
|
import { getTypeArgumentsRecord } from "../dsl/declarations/Decl.js";
|
|
18
18
|
import { createEntityIdentifierType } from "../dsl/declarations/EntityDecl.js";
|
|
@@ -34,6 +34,7 @@ export const createReferenceValidator = (isEntityName, databaseInMemory, useStyl
|
|
|
34
34
|
export const validateDeclStructuralIntegrity = (helpers, inDecls, decl, typeArgs, value) => {
|
|
35
35
|
switch (decl.kind) {
|
|
36
36
|
case NodeKind.EntityDecl:
|
|
37
|
+
case NodeKind.SingletonEntityDecl:
|
|
37
38
|
return validateTypeStructuralIntegrity(helpers, inDecls, decl.type.value, value);
|
|
38
39
|
case NodeKind.EnumDecl:
|
|
39
40
|
case NodeKind.TypeAliasDecl:
|
|
@@ -286,6 +287,7 @@ export const validateTypeStructuralIntegrity = (helpers, inDecls, type, value) =
|
|
|
286
287
|
export const validateDeclReferentialIntegrity = (helpers, checkEntityName, checkReferentialIntegrity, inDecls, decl, typeArgs, value) => {
|
|
287
288
|
switch (decl.kind) {
|
|
288
289
|
case NodeKind.EntityDecl:
|
|
290
|
+
case NodeKind.SingletonEntityDecl:
|
|
289
291
|
return validateTypeReferentialIntegrity(helpers, checkEntityName, checkReferentialIntegrity, inDecls, decl.type.value, value);
|
|
290
292
|
case NodeKind.EnumDecl:
|
|
291
293
|
case NodeKind.TypeAliasDecl:
|