tsondb 0.7.6 → 0.7.7
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/schema/Node.d.ts +8 -1
- package/dist/src/node/schema/Node.js +34 -18
- package/dist/src/node/schema/Schema.js +14 -10
- package/dist/src/node/schema/TypeParameter.js +1 -1
- package/dist/src/node/schema/declarations/EntityDecl.js +1 -1
- package/dist/src/node/schema/declarations/EnumDecl.js +1 -1
- package/dist/src/node/schema/declarations/TypeAliasDecl.js +1 -1
- package/dist/src/node/schema/types/generic/ArrayType.js +1 -1
- package/dist/src/node/schema/types/generic/EnumType.js +1 -1
- package/dist/src/node/schema/types/generic/ObjectType.js +1 -1
- package/dist/src/node/schema/types/references/ChildEntitiesType.js +1 -1
- package/dist/src/node/schema/types/references/IncludeIdentifierType.js +2 -2
- package/dist/src/node/schema/types/references/NestedEntityMapType.d.ts +12 -2
- package/dist/src/node/schema/types/references/NestedEntityMapType.js +2 -2
- package/dist/src/node/schema/types/references/ReferenceIdentifierType.js +2 -2
- package/dist/src/shared/schema/declarations/EntityDecl.d.ts +2 -0
- package/dist/src/shared/schema/declarations/EntityDecl.js +2 -0
- package/dist/src/shared/schema/declarations/EnumDecl.d.ts +2 -1
- package/dist/src/shared/schema/declarations/EnumDecl.js +2 -0
- package/dist/src/shared/schema/declarations/TypeAliasDecl.d.ts +2 -1
- package/dist/src/shared/schema/declarations/TypeAliasDecl.js +2 -1
- package/dist/src/web/components/InstanceRouteSkeleton.d.ts +5 -0
- package/dist/src/web/components/InstanceRouteSkeleton.js +4 -4
- package/dist/src/web/components/typeInputs/utils/MismatchingTypeError.js +2 -2
- package/dist/src/web/hooks/useSecondaryDeclarations.js +6 -3
- package/dist/src/web/hooks/useSettings.js +0 -1
- package/dist/src/web/routes/CreateInstance.js +27 -22
- package/dist/src/web/routes/Instance.js +20 -8
- package/dist/src/web/utils/typeSkeleton.js +1 -1
- package/package.json +1 -1
|
@@ -39,6 +39,13 @@ import type { Type } from "./types/Type.ts";
|
|
|
39
39
|
export type { BaseNode } from "../../shared/schema/Node.ts";
|
|
40
40
|
export { NodeKind };
|
|
41
41
|
export type Node = Decl | Type | TypeParameter;
|
|
42
|
+
export type NestedDecl = Decl | NestedEntity;
|
|
43
|
+
export type NestedEntity = {
|
|
44
|
+
kind: "NestedEntity";
|
|
45
|
+
sourceUrl: string;
|
|
46
|
+
name: string;
|
|
47
|
+
type: NestedEntityMapType;
|
|
48
|
+
};
|
|
42
49
|
export declare const reduceNodes: <R>(reducer: (parentNodes: Node[], node: Node, collectedResults: R[]) => R[], nodes: readonly Node[], options?: {
|
|
43
50
|
initialResults?: R[];
|
|
44
51
|
followIncludes?: boolean;
|
|
@@ -55,7 +62,7 @@ export interface Validators {
|
|
|
55
62
|
}
|
|
56
63
|
export declare const createValidators: (instancesByEntityName: InstancesByEntityName, useStyling: boolean, checkReferentialIntegrity?: boolean) => Validators;
|
|
57
64
|
export type Predicate<T extends Node> = (node: Node) => node is T;
|
|
58
|
-
export type GetNestedDeclarations<T extends Node = Node> = (addedDecls:
|
|
65
|
+
export type GetNestedDeclarations<T extends Node = Node> = (addedDecls: NestedDecl[], node: T, parentDecl: Decl | undefined) => NestedDecl[];
|
|
59
66
|
export declare const getNestedDeclarations: GetNestedDeclarations;
|
|
60
67
|
export type Validator<T extends Node = Node> = (helpers: Validators, node: T, value: unknown) => Error[];
|
|
61
68
|
export type ValidatorOfParamDecl<T extends Node = Node> = (helpers: Validators, node: T, typeArgs: Type[], value: unknown) => Error[];
|
|
@@ -91,42 +91,58 @@ export const createValidators = (instancesByEntityName, useStyling, checkReferen
|
|
|
91
91
|
]
|
|
92
92
|
: () => [],
|
|
93
93
|
});
|
|
94
|
-
export const getNestedDeclarations = (addedDecls, node) => {
|
|
94
|
+
export const getNestedDeclarations = (addedDecls, node, parentDecl) => {
|
|
95
95
|
switch (node.kind) {
|
|
96
96
|
case NodeKind.EntityDecl:
|
|
97
|
-
return
|
|
97
|
+
return addedDecls.includes(node)
|
|
98
|
+
? addedDecls
|
|
99
|
+
: getNestedDeclarationsInEntityDecl([...addedDecls, node], node, parentDecl);
|
|
98
100
|
case NodeKind.EnumDecl:
|
|
99
|
-
return
|
|
101
|
+
return addedDecls.includes(node)
|
|
102
|
+
? addedDecls
|
|
103
|
+
: getNestedDeclarationsInEnumDecl([...addedDecls, node], node, parentDecl);
|
|
100
104
|
case NodeKind.TypeAliasDecl:
|
|
101
|
-
return
|
|
105
|
+
return addedDecls.includes(node)
|
|
106
|
+
? addedDecls
|
|
107
|
+
: getNestedDeclarationsInTypeAliasDecl([...addedDecls, node], node, parentDecl);
|
|
102
108
|
case NodeKind.ArrayType:
|
|
103
|
-
return getNestedDeclarationsInArrayType(addedDecls, node);
|
|
109
|
+
return getNestedDeclarationsInArrayType(addedDecls, node, parentDecl);
|
|
104
110
|
case NodeKind.ObjectType:
|
|
105
|
-
return getNestedDeclarationsInObjectType(addedDecls, node);
|
|
111
|
+
return getNestedDeclarationsInObjectType(addedDecls, node, parentDecl);
|
|
106
112
|
case NodeKind.BooleanType:
|
|
107
|
-
return getNestedDeclarationsInBooleanType(addedDecls, node);
|
|
113
|
+
return getNestedDeclarationsInBooleanType(addedDecls, node, parentDecl);
|
|
108
114
|
case NodeKind.DateType:
|
|
109
|
-
return getNestedDeclarationsInDateType(addedDecls, node);
|
|
115
|
+
return getNestedDeclarationsInDateType(addedDecls, node, parentDecl);
|
|
110
116
|
case NodeKind.FloatType:
|
|
111
|
-
return getNestedDeclarationsInFloatType(addedDecls, node);
|
|
117
|
+
return getNestedDeclarationsInFloatType(addedDecls, node, parentDecl);
|
|
112
118
|
case NodeKind.IntegerType:
|
|
113
|
-
return getNestedDeclarationsInIntegerType(addedDecls, node);
|
|
119
|
+
return getNestedDeclarationsInIntegerType(addedDecls, node, parentDecl);
|
|
114
120
|
case NodeKind.StringType:
|
|
115
|
-
return getNestedDeclarationsInStringType(addedDecls, node);
|
|
121
|
+
return getNestedDeclarationsInStringType(addedDecls, node, parentDecl);
|
|
116
122
|
case NodeKind.TypeArgumentType:
|
|
117
|
-
return getNestedDeclarationsInTypeArgumentType(addedDecls, node);
|
|
123
|
+
return getNestedDeclarationsInTypeArgumentType(addedDecls, node, parentDecl);
|
|
118
124
|
case NodeKind.ReferenceIdentifierType:
|
|
119
|
-
return getNestedDeclarationsInReferenceIdentifierType(addedDecls, node);
|
|
125
|
+
return getNestedDeclarationsInReferenceIdentifierType(addedDecls, node, parentDecl);
|
|
120
126
|
case NodeKind.IncludeIdentifierType:
|
|
121
|
-
return getNestedDeclarationsInIncludeIdentifierType(addedDecls, node);
|
|
127
|
+
return getNestedDeclarationsInIncludeIdentifierType(addedDecls, node, parentDecl);
|
|
122
128
|
case NodeKind.NestedEntityMapType:
|
|
123
|
-
return
|
|
129
|
+
return addedDecls.some(addedDecl => addedDecl.kind === "NestedEntity" && addedDecl.type === node)
|
|
130
|
+
? addedDecls
|
|
131
|
+
: getNestedDeclarationsInNestedEntityMapType([
|
|
132
|
+
...addedDecls,
|
|
133
|
+
{
|
|
134
|
+
kind: "NestedEntity",
|
|
135
|
+
sourceUrl: parentDecl?.sourceUrl ?? "",
|
|
136
|
+
name: node.name,
|
|
137
|
+
type: node,
|
|
138
|
+
},
|
|
139
|
+
], node, parentDecl);
|
|
124
140
|
case NodeKind.EnumType:
|
|
125
|
-
return getNestedDeclarationsInEnumType(addedDecls, node);
|
|
141
|
+
return getNestedDeclarationsInEnumType(addedDecls, node, parentDecl);
|
|
126
142
|
case NodeKind.TypeParameter:
|
|
127
|
-
return getNestedDeclarationsInTypeParameter(addedDecls, node);
|
|
143
|
+
return getNestedDeclarationsInTypeParameter(addedDecls, node, parentDecl);
|
|
128
144
|
case NodeKind.ChildEntitiesType:
|
|
129
|
-
return getNestedDeclarationsInChildEntitiesType(addedDecls, node);
|
|
145
|
+
return getNestedDeclarationsInChildEntitiesType(addedDecls, node, parentDecl);
|
|
130
146
|
default:
|
|
131
147
|
return assertExhaustive(node);
|
|
132
148
|
}
|
|
@@ -152,29 +152,33 @@ const checkChildEntitiesProvideCorrectPathToParentReferenceIdentifierType = (dec
|
|
|
152
152
|
}
|
|
153
153
|
}
|
|
154
154
|
};
|
|
155
|
-
const addDeclarations = (existingDecls, declsToAdd
|
|
155
|
+
const addDeclarations = (existingDecls, declsToAdd) => declsToAdd.reduce((accDecls, decl) => {
|
|
156
156
|
if (!accDecls.includes(decl)) {
|
|
157
|
-
|
|
158
|
-
const nestedDecls = nested ? getNestedDeclarations(accDecls, decl) : [];
|
|
159
|
-
return addDeclarations([...accDecls, decl], nestedDecls, false);
|
|
157
|
+
return getNestedDeclarations(accDecls, decl.kind === "NestedEntity" ? decl.type : decl, undefined);
|
|
160
158
|
}
|
|
161
159
|
return accDecls;
|
|
162
160
|
}, existingDecls);
|
|
163
161
|
export const Schema = (declarations, localeEntity) => {
|
|
164
162
|
debug("creating schema from %d declarations", declarations.length);
|
|
165
163
|
debug("collecting nested declarations ...");
|
|
166
|
-
const allDecls = addDeclarations([], localeEntity ? declarations.concat(localeEntity) : declarations
|
|
164
|
+
const allDecls = addDeclarations([], localeEntity ? declarations.concat(localeEntity) : declarations);
|
|
165
|
+
debug("found %d nested declarations", allDecls.length);
|
|
166
|
+
debug("checking for duplicate identifiers ...");
|
|
167
|
+
allDecls.forEach((decl, declIndex) => {
|
|
168
|
+
checkDuplicateIdentifier(allDecls.slice(0, declIndex), decl);
|
|
169
|
+
});
|
|
170
|
+
const allDeclsWithoutNestedEntities = allDecls.filter(decl => decl.kind !== "NestedEntity");
|
|
167
171
|
debug("checking name shadowing ...");
|
|
168
|
-
checkParameterNamesShadowing(
|
|
172
|
+
checkParameterNamesShadowing(allDeclsWithoutNestedEntities);
|
|
169
173
|
debug("checking entity display name paths ...");
|
|
170
|
-
checkEntityDisplayNamePaths(
|
|
174
|
+
checkEntityDisplayNamePaths(allDeclsWithoutNestedEntities, localeEntity);
|
|
171
175
|
debug("checking child entities ...");
|
|
172
|
-
checkChildEntitiesProvideCorrectPathToParentReferenceIdentifierType(
|
|
176
|
+
checkChildEntitiesProvideCorrectPathToParentReferenceIdentifierType(allDeclsWithoutNestedEntities);
|
|
173
177
|
debug("checking child entity types ...");
|
|
174
|
-
checkChildEntityTypes(localeEntity,
|
|
178
|
+
checkChildEntityTypes(localeEntity, allDeclsWithoutNestedEntities);
|
|
175
179
|
debug("created schema, no integrity violations found");
|
|
176
180
|
return {
|
|
177
|
-
declarations:
|
|
181
|
+
declarations: allDeclsWithoutNestedEntities,
|
|
178
182
|
localeEntity,
|
|
179
183
|
};
|
|
180
184
|
};
|
|
@@ -4,7 +4,7 @@ export const Param = (name, constraint) => ({
|
|
|
4
4
|
name,
|
|
5
5
|
constraint,
|
|
6
6
|
});
|
|
7
|
-
export const getNestedDeclarationsInTypeParameter = (addedDecls, param) =>
|
|
7
|
+
export const getNestedDeclarationsInTypeParameter = (addedDecls, param, parentDecl) => param.constraint ? getNestedDeclarations(addedDecls, param.constraint, parentDecl) : addedDecls;
|
|
8
8
|
export const resolveTypeArgumentsInTypeParameter = (_args, param) => param;
|
|
9
9
|
export const serializeTypeParameter = type => ({
|
|
10
10
|
...type,
|
|
@@ -26,7 +26,7 @@ export const EntityDecl = (sourceUrl, options) => {
|
|
|
26
26
|
export { EntityDecl as Entity };
|
|
27
27
|
export const isEntityDecl = node => node.kind === NodeKind.EntityDecl;
|
|
28
28
|
export const isEntityDeclWithParentReference = (decl) => decl.parentReferenceKey !== undefined;
|
|
29
|
-
export const getNestedDeclarationsInEntityDecl = (isDeclAdded, decl) => getNestedDeclarationsInObjectType(isDeclAdded, decl.type.value);
|
|
29
|
+
export const getNestedDeclarationsInEntityDecl = (isDeclAdded, decl) => getNestedDeclarationsInObjectType(isDeclAdded, decl.type.value, decl);
|
|
30
30
|
export const validateEntityDecl = (helpers, decl, value) => validateType(helpers, decl.type.value, value);
|
|
31
31
|
export const resolveTypeArgumentsInEntityDecl = (_args, decl) => EntityDecl(decl.sourceUrl, {
|
|
32
32
|
...decl,
|
|
@@ -28,7 +28,7 @@ export const EnumDecl = (sourceUrl, options) => {
|
|
|
28
28
|
};
|
|
29
29
|
export { EnumDecl as Enum };
|
|
30
30
|
export const isEnumDecl = node => node.kind === NodeKind.EnumDecl;
|
|
31
|
-
export const getNestedDeclarationsInEnumDecl = (addedDecls, decl) => getNestedDeclarationsInEnumType(addedDecls, decl.type.value);
|
|
31
|
+
export const getNestedDeclarationsInEnumDecl = (addedDecls, decl) => getNestedDeclarationsInEnumType(addedDecls, decl.type.value, decl);
|
|
32
32
|
export const validateEnumDecl = (helpers, decl, args, value) => validateEnumType(helpers, resolveTypeArgumentsInEnumType(getTypeArgumentsRecord(decl, args), decl.type.value), value);
|
|
33
33
|
export const resolveTypeArgumentsInEnumDecl = (args, decl) => EnumDecl(decl.sourceUrl, {
|
|
34
34
|
name: decl.name,
|
|
@@ -26,7 +26,7 @@ export const TypeAliasDecl = (sourceUrl, options) => {
|
|
|
26
26
|
};
|
|
27
27
|
export { TypeAliasDecl as TypeAlias };
|
|
28
28
|
export const isTypeAliasDecl = node => node.kind === NodeKind.TypeAliasDecl;
|
|
29
|
-
export const getNestedDeclarationsInTypeAliasDecl = (addedDecls, decl) => getNestedDeclarations(addedDecls, decl.type.value);
|
|
29
|
+
export const getNestedDeclarationsInTypeAliasDecl = (addedDecls, decl) => getNestedDeclarations(addedDecls, decl.type.value, decl);
|
|
30
30
|
export const validateTypeAliasDecl = ((helpers, decl, args, value) => validateType(helpers, resolveTypeArguments(getTypeArgumentsRecord(decl, args), decl.type.value), value));
|
|
31
31
|
export const resolveTypeArgumentsInTypeAliasDecl = (args, decl) => TypeAliasDecl(decl.sourceUrl, {
|
|
32
32
|
...decl,
|
|
@@ -14,7 +14,7 @@ export const ArrayType = (items, options = {}) => ({
|
|
|
14
14
|
});
|
|
15
15
|
export { ArrayType as Array };
|
|
16
16
|
export const isArrayType = node => node.kind === NodeKind.ArrayType;
|
|
17
|
-
export const getNestedDeclarationsInArrayType = (addedDecls, type) => getNestedDeclarations(addedDecls, type.items);
|
|
17
|
+
export const getNestedDeclarationsInArrayType = (addedDecls, type, parentDecl) => getNestedDeclarations(addedDecls, type.items, parentDecl);
|
|
18
18
|
export const validateArrayType = (helpers, type, value) => {
|
|
19
19
|
if (!Array.isArray(value)) {
|
|
20
20
|
return [TypeError(`expected an array, but got ${json(value, helpers.useStyling)}`)];
|
|
@@ -9,7 +9,7 @@ export const EnumType = (values) => ({
|
|
|
9
9
|
values,
|
|
10
10
|
});
|
|
11
11
|
export const isEnumType = node => node.kind === NodeKind.EnumType;
|
|
12
|
-
export const getNestedDeclarationsInEnumType = (addedDecls, type) => Object.values(type.values).reduce((acc, caseMember) => caseMember.type === null ? acc : getNestedDeclarations(acc, caseMember.type), addedDecls);
|
|
12
|
+
export const getNestedDeclarationsInEnumType = (addedDecls, type, parentDecl) => Object.values(type.values).reduce((acc, caseMember) => caseMember.type === null ? acc : getNestedDeclarations(acc, caseMember.type, parentDecl), addedDecls);
|
|
13
13
|
export const validateEnumType = (helpers, type, value) => {
|
|
14
14
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
15
15
|
return [TypeError(`expected an object, but got ${json(value, helpers.useStyling)}`)];
|
|
@@ -25,7 +25,7 @@ export const ObjectType = (properties, options = {}) => {
|
|
|
25
25
|
};
|
|
26
26
|
export { ObjectType as Object };
|
|
27
27
|
export const isObjectType = node => node.kind === NodeKind.ObjectType;
|
|
28
|
-
export const getNestedDeclarationsInObjectType = (addedDecls, type) => Object.values(type.properties).reduce((acc, prop) => getNestedDeclarations(acc, prop.type), addedDecls);
|
|
28
|
+
export const getNestedDeclarationsInObjectType = (addedDecls, type, parentDecl) => Object.values(type.properties).reduce((acc, prop) => getNestedDeclarations(acc, prop.type, parentDecl), addedDecls);
|
|
29
29
|
export const validateObjectType = (helpers, type, value) => {
|
|
30
30
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
31
31
|
return [TypeError(`expected an object, but got ${json(value, helpers.useStyling)}`)];
|
|
@@ -7,7 +7,7 @@ export const ChildEntitiesType = (entity) => ({
|
|
|
7
7
|
});
|
|
8
8
|
export { ChildEntitiesType as ChildEntities };
|
|
9
9
|
export const isChildEntitiesType = node => node.kind === NodeKind.ChildEntitiesType;
|
|
10
|
-
export const getNestedDeclarationsInChildEntitiesType = (addedDecls, type) => getNestedDeclarations(
|
|
10
|
+
export const getNestedDeclarationsInChildEntitiesType = (addedDecls, type, parentDecl) => getNestedDeclarations(addedDecls, type.entity, parentDecl);
|
|
11
11
|
export const validateChildEntitiesType = () => [];
|
|
12
12
|
export const resolveTypeArgumentsInChildEntitiesType = (_args, type) => type;
|
|
13
13
|
export const serializeChildEntitiesType = type => ({
|
|
@@ -16,9 +16,9 @@ export const IncludeIdentifierType = (reference) => ({
|
|
|
16
16
|
export { IncludeIdentifierType as IncludeIdentifier };
|
|
17
17
|
export const isIncludeIdentifierType = node => node.kind === NodeKind.IncludeIdentifierType;
|
|
18
18
|
const isNoGenericIncludeIdentifierType = (node) => node.args.length === 0 && node.reference.parameters.length === 0;
|
|
19
|
-
export const getNestedDeclarationsInIncludeIdentifierType = (addedDecls, type) => type.args.reduce((accAddedDecls, arg) => getNestedDeclarations(accAddedDecls, arg), addedDecls.includes(type.reference)
|
|
19
|
+
export const getNestedDeclarationsInIncludeIdentifierType = (addedDecls, type, parentDecl) => type.args.reduce((accAddedDecls, arg) => getNestedDeclarations(accAddedDecls, arg, parentDecl), addedDecls.includes(type.reference)
|
|
20
20
|
? addedDecls
|
|
21
|
-
: getNestedDeclarations(
|
|
21
|
+
: getNestedDeclarations(addedDecls, type.reference, parentDecl));
|
|
22
22
|
export const validateIncludeIdentifierType = (helpers, type, value) => validateDecl(helpers, type.reference, type.args, value);
|
|
23
23
|
export const resolveTypeArgumentsInIncludeIdentifierType = ((args, type) => (isNoGenericIncludeIdentifierType(type)
|
|
24
24
|
? type
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { Lazy } from "../../../../shared/utils/lazy.ts";
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
2
|
+
import type { DisplayNameCustomizer } from "../../../utils/displayName.ts";
|
|
3
|
+
import type { EntityDecl } from "../../declarations/EntityDecl.js";
|
|
4
|
+
import { type EntityDisplayName } from "../../declarations/EntityDecl.js";
|
|
5
|
+
import type { TypeAliasDecl } from "../../declarations/TypeAliasDecl.js";
|
|
4
6
|
import type { GetNestedDeclarations, GetReferences, Predicate, Serializer, TypeArgumentsResolver, Validator } from "../../Node.ts";
|
|
5
7
|
import { NodeKind } from "../../Node.ts";
|
|
6
8
|
import type { MemberDecl, ObjectType } from "../generic/ObjectType.ts";
|
|
@@ -11,15 +13,23 @@ type PossibleType<T extends TConstraint> = ObjectType<T> | IncludeIdentifier<[],
|
|
|
11
13
|
export interface NestedEntityMapType<Name extends string = string, T extends TConstraint = TConstraint> extends BaseType {
|
|
12
14
|
kind: NodeKind["NestedEntityMapType"];
|
|
13
15
|
name: Name;
|
|
16
|
+
namePlural: string;
|
|
14
17
|
comment?: string;
|
|
15
18
|
secondaryEntity: EntityDecl;
|
|
16
19
|
type: Lazy<PossibleType<T>>;
|
|
17
20
|
}
|
|
18
21
|
export declare const NestedEntityMapType: <Name extends string, T extends TConstraint>(options: {
|
|
19
22
|
name: Name;
|
|
23
|
+
namePlural: string;
|
|
20
24
|
comment?: string;
|
|
21
25
|
secondaryEntity: EntityDecl;
|
|
22
26
|
type: PossibleType<T>;
|
|
27
|
+
/**
|
|
28
|
+
* @default "name"
|
|
29
|
+
*/
|
|
30
|
+
displayName?: EntityDisplayName<T>;
|
|
31
|
+
displayNameCustomizer?: DisplayNameCustomizer<ObjectType<T>>;
|
|
32
|
+
isDeprecated?: boolean;
|
|
23
33
|
}) => NestedEntityMapType<Name, T>;
|
|
24
34
|
export { NestedEntityMapType as NestedEntityMap };
|
|
25
35
|
export declare const isNestedEntityMapType: Predicate<NestedEntityMapType>;
|
|
@@ -3,7 +3,7 @@ import { sortObjectKeysAlphabetically } from "../../../../shared/utils/object.js
|
|
|
3
3
|
import { parallelizeErrors } from "../../../../shared/utils/validation.js";
|
|
4
4
|
import { wrapErrorsIfAny } from "../../../utils/error.js";
|
|
5
5
|
import { entity, json, key as keyColor } from "../../../utils/errorFormatting.js";
|
|
6
|
-
import {} from "../../declarations/
|
|
6
|
+
import {} from "../../declarations/EntityDecl.js";
|
|
7
7
|
import { getNestedDeclarations, NodeKind, resolveTypeArguments, validateType } from "../../Node.js";
|
|
8
8
|
import { getReferencesForObjectType, isObjectType, serializeObjectType, } from "../generic/ObjectType.js";
|
|
9
9
|
import { formatValue } from "../Type.js";
|
|
@@ -26,7 +26,7 @@ const _NestedEntityMapType = (options) => {
|
|
|
26
26
|
return nestedEntityMapType;
|
|
27
27
|
};
|
|
28
28
|
export const isNestedEntityMapType = node => node.kind === NodeKind.NestedEntityMapType;
|
|
29
|
-
export const getNestedDeclarationsInNestedEntityMapType = (addedDecls, type) => getNestedDeclarations(
|
|
29
|
+
export const getNestedDeclarationsInNestedEntityMapType = (addedDecls, type, parentDecl) => getNestedDeclarations(getNestedDeclarations(addedDecls, type.secondaryEntity, parentDecl), type.type.value, parentDecl);
|
|
30
30
|
export const validateNestedEntityMapType = (helpers, type, value) => {
|
|
31
31
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
32
32
|
return [TypeError(`expected an object, but got ${json(value, helpers.useStyling)}`)];
|
|
@@ -6,9 +6,9 @@ export const ReferenceIdentifierType = (entity) => ({
|
|
|
6
6
|
});
|
|
7
7
|
export { ReferenceIdentifierType as ReferenceIdentifier };
|
|
8
8
|
export const isReferenceIdentifierType = (node) => node.kind === NodeKind.ReferenceIdentifierType;
|
|
9
|
-
export const getNestedDeclarationsInReferenceIdentifierType = (addedDecls, type) => addedDecls.includes(type.entity)
|
|
9
|
+
export const getNestedDeclarationsInReferenceIdentifierType = (addedDecls, type, parentDecl) => addedDecls.includes(type.entity)
|
|
10
10
|
? addedDecls
|
|
11
|
-
: getNestedDeclarations(
|
|
11
|
+
: getNestedDeclarations(addedDecls, type.entity, parentDecl);
|
|
12
12
|
export const validateReferenceIdentifierType = (helpers, type, value) => validateType(helpers, createEntityIdentifierType(), value).concat(helpers.checkReferentialIntegrity({
|
|
13
13
|
name: type.entity.name,
|
|
14
14
|
value: value,
|
|
@@ -27,6 +27,8 @@ export interface SerializedEntityDecl<Name extends string = string, T extends TC
|
|
|
27
27
|
isDeprecated?: boolean;
|
|
28
28
|
}
|
|
29
29
|
export declare const isSerializedEntityDecl: (node: SerializedNode) => node is SerializedEntityDecl;
|
|
30
|
+
export declare const isSerializedEntityDeclWithParentReference: <Name extends string, T extends TConstraint, FK extends (keyof T & string) | undefined>(decl: SerializedEntityDecl<Name, T, FK>) => decl is SerializedEntityDecl<Name, T, NonNullable<FK>>;
|
|
31
|
+
export declare const isSerializedEntityDeclWithoutParentReference: <Name extends string, T extends TConstraint>(decl: SerializedEntityDecl<Name, T>) => decl is SerializedEntityDecl<Name, T, undefined>;
|
|
30
32
|
export declare const resolveTypeArgumentsInSerializedEntityDecl: SerializedTypeArgumentsResolver<SerializedEntityDecl>;
|
|
31
33
|
export declare const getReferencesForSerializedEntityDecl: GetReferencesSerialized<SerializedEntityDecl>;
|
|
32
34
|
export {};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { NodeKind, resolveSerializedTypeArguments, } from "../Node.js";
|
|
2
2
|
import { getReferencesForSerializedObjectType, } from "../types/ObjectType.js";
|
|
3
3
|
export const isSerializedEntityDecl = (node) => node.kind === NodeKind.EntityDecl;
|
|
4
|
+
export const isSerializedEntityDeclWithParentReference = (decl) => decl.parentReferenceKey !== undefined;
|
|
5
|
+
export const isSerializedEntityDeclWithoutParentReference = (decl) => decl.parentReferenceKey === undefined;
|
|
4
6
|
export const resolveTypeArgumentsInSerializedEntityDecl = (decls, _args, decl) => ({
|
|
5
7
|
...decl,
|
|
6
8
|
type: resolveSerializedTypeArguments(decls, {}, decl.type),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { NodeKind, type GetReferencesSerialized, type SerializedNode, type SerializedTypeArgumentsResolver } from "../Node.js";
|
|
2
2
|
import type { SerializedTypeParameter } from "../TypeParameter.ts";
|
|
3
3
|
import { type SerializedEnumCaseDecl, type SerializedEnumType } from "../types/EnumType.ts";
|
|
4
4
|
import type { SerializedBaseDecl } from "./Declaration.ts";
|
|
@@ -7,5 +7,6 @@ export interface SerializedEnumDecl<Name extends string = string, T extends Reco
|
|
|
7
7
|
type: SerializedEnumType<T>;
|
|
8
8
|
isDeprecated?: boolean;
|
|
9
9
|
}
|
|
10
|
+
export declare const isSerializedEnumDecl: (node: SerializedNode) => node is SerializedEnumDecl;
|
|
10
11
|
export declare const resolveTypeArgumentsInSerializedEnumDecl: SerializedTypeArgumentsResolver<SerializedEnumDecl>;
|
|
11
12
|
export declare const getReferencesForSerializedEnumDecl: GetReferencesSerialized<SerializedEnumDecl>;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { NodeKind, } from "../Node.js";
|
|
1
2
|
import { getReferencesForSerializedEnumType, resolveTypeArgumentsInSerializedEnumType, } from "../types/EnumType.js";
|
|
3
|
+
export const isSerializedEnumDecl = (node) => node.kind === NodeKind.EnumDecl;
|
|
2
4
|
export const resolveTypeArgumentsInSerializedEnumDecl = (decls, args, decl) => {
|
|
3
5
|
return {
|
|
4
6
|
...decl,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type GetReferencesSerialized, type
|
|
1
|
+
import { NodeKind, type GetReferencesSerialized, type SerializedNode, type SerializedTypeArgumentsResolver } from "../Node.ts";
|
|
2
2
|
import type { SerializedTypeParameter } from "../TypeParameter.ts";
|
|
3
3
|
import type { SerializedType } from "../types/Type.ts";
|
|
4
4
|
import type { SerializedBaseDecl } from "./Declaration.ts";
|
|
@@ -7,5 +7,6 @@ export interface SerializedTypeAliasDecl<Name extends string = string, T extends
|
|
|
7
7
|
type: T;
|
|
8
8
|
isDeprecated?: boolean;
|
|
9
9
|
}
|
|
10
|
+
export declare const isSerializedTypeAliasDecl: (node: SerializedNode) => node is SerializedTypeAliasDecl;
|
|
10
11
|
export declare const resolveTypeArgumentsInSerializedTypeAliasDecl: SerializedTypeArgumentsResolver<SerializedTypeAliasDecl>;
|
|
11
12
|
export declare const getReferencesForSerializedTypeAliasDecl: GetReferencesSerialized<SerializedTypeAliasDecl>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { getReferencesSerialized, resolveSerializedTypeArguments, } from "../Node.js";
|
|
1
|
+
import { getReferencesSerialized, NodeKind, resolveSerializedTypeArguments, } from "../Node.js";
|
|
2
|
+
export const isSerializedTypeAliasDecl = (node) => node.kind === NodeKind.TypeAliasDecl;
|
|
2
3
|
export const resolveTypeArgumentsInSerializedTypeAliasDecl = (decls, args, decl) => ({
|
|
3
4
|
...decl,
|
|
4
5
|
parameters: [],
|
|
@@ -34,6 +34,11 @@ export type InstanceRouteSkeletonTitleBuilder = (values: {
|
|
|
34
34
|
}) => string | undefined;
|
|
35
35
|
type Props = {
|
|
36
36
|
mode: "create" | "edit";
|
|
37
|
+
buttons: {
|
|
38
|
+
label: string;
|
|
39
|
+
name: string;
|
|
40
|
+
primary?: boolean;
|
|
41
|
+
}[];
|
|
37
42
|
init: InstanceRouteSkeletonInitializer;
|
|
38
43
|
titleBuilder: InstanceRouteSkeletonTitleBuilder;
|
|
39
44
|
onSubmit: InstanceRouteSkeletonOnSubmitHandler;
|
|
@@ -15,7 +15,7 @@ import { NotFound } from "../routes/NotFound.js";
|
|
|
15
15
|
import { Layout } from "./Layout.js";
|
|
16
16
|
import { TypeInput } from "./typeInputs/TypeInput.js";
|
|
17
17
|
import { ValidationErrors } from "./typeInputs/utils/ValidationErrors.js";
|
|
18
|
-
export const InstanceRouteSkeleton = ({ mode, init, titleBuilder, onSubmit, }) => {
|
|
18
|
+
export const InstanceRouteSkeleton = ({ mode, buttons, init, titleBuilder, onSubmit, }) => {
|
|
19
19
|
const { params: { name, id }, } = useRoute();
|
|
20
20
|
const [locales] = useSetting("displayedLocales");
|
|
21
21
|
const [getDeclFromDeclName, declsLoaded] = useGetDeclFromDeclName();
|
|
@@ -31,7 +31,7 @@ export const InstanceRouteSkeleton = ({ mode, init, titleBuilder, onSubmit, }) =
|
|
|
31
31
|
"Not found — TSONDB";
|
|
32
32
|
}, [entity, id, instanceContent, locales, titleBuilder]);
|
|
33
33
|
useEffect(() => {
|
|
34
|
-
if (entity && instanceContent === undefined) {
|
|
34
|
+
if (entity && instanceContent === undefined && declsLoaded) {
|
|
35
35
|
init({ locales, entity, instanceId: id, setInstanceContent, getDeclFromDeclName })
|
|
36
36
|
.then(() => id
|
|
37
37
|
? getChildInstancesForInstanceByEntityName(locales, entity.name, id).then(result => {
|
|
@@ -42,7 +42,7 @@ export const InstanceRouteSkeleton = ({ mode, init, titleBuilder, onSubmit, }) =
|
|
|
42
42
|
console.error("Error initializing instance route skeleton:", error);
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
|
-
}, [entity, getDeclFromDeclName, id, init, instanceContent, locales, name]);
|
|
45
|
+
}, [entity, declsLoaded, getDeclFromDeclName, id, init, instanceContent, locales, name]);
|
|
46
46
|
const handleSubmit = (event) => {
|
|
47
47
|
event.preventDefault();
|
|
48
48
|
if (entity && instanceContent !== undefined) {
|
|
@@ -110,5 +110,5 @@ export const InstanceRouteSkeleton = ({ mode, init, titleBuilder, onSubmit, }) =
|
|
|
110
110
|
}
|
|
111
111
|
}, children: "Delete" }))] }), !id && isLocaleEntity && (_jsxs("div", { class: "field field--id", children: [_jsx("label", { htmlFor: "id", children: "ID" }), _jsx("p", { className: "comment", children: "The instance\u2019s identifier. An IETF language tag (BCP47)." }), _jsx("input", { type: "text", id: "id", value: customId, required: true, pattern: "[a-z]{2,3}(-[A-Z]{2,3})?", placeholder: "en-US, de-DE, \u2026", onInput: event => {
|
|
112
112
|
setCustomId(event.currentTarget.value);
|
|
113
|
-
}, "aria-invalid": idErrors.length > 0 }), _jsx(ValidationErrors, { errors: idErrors })] })), _jsxs("form", { onSubmit: handleSubmit, children: [_jsx(TypeInput, { type: entity.type, value: instanceContent, path: undefined, instanceNamesByEntity: instanceNamesByEntity, childInstances: childInstances, getDeclFromDeclName: getDeclFromDeclName, onChange: setInstanceContent, onChildChange: handleOnChildChange, onChildAdd: handleOnChildAdd, onChildRemove: handleOnChildRemove }), _jsx("div", { class: "form-footer btns", children: _jsx("button", { type: "submit", name:
|
|
113
|
+
}, "aria-invalid": idErrors.length > 0 }), _jsx(ValidationErrors, { errors: idErrors })] })), _jsxs("form", { onSubmit: handleSubmit, children: [_jsx(TypeInput, { type: entity.type, value: instanceContent, path: undefined, instanceNamesByEntity: instanceNamesByEntity, childInstances: childInstances, getDeclFromDeclName: getDeclFromDeclName, onChange: setInstanceContent, onChildChange: handleOnChildChange, onChildAdd: handleOnChildAdd, onChildRemove: handleOnChildRemove }), _jsx("div", { class: "form-footer btns", children: buttons.map(button => (_jsx("button", { type: "submit", name: button.name, class: button.primary ? "primary" : undefined, children: button.label }, button.name))) })] })] }));
|
|
114
114
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsxs as _jsxs } from "preact/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
|
|
2
2
|
export const MismatchingTypeError = ({ expected, actual }) => {
|
|
3
|
-
return (_jsxs("div", { role: "alert", children: ["Expected value of type ", expected, ", but got ", JSON.stringify(actual)] }));
|
|
3
|
+
return (_jsxs("div", { role: "alert", children: ["Expected value of type ", expected, ", but got", " ", _jsx("code", { children: actual === undefined ? "undefined" : JSON.stringify(actual) })] }));
|
|
4
4
|
};
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { useCallback, useEffect, useState } from "preact/hooks";
|
|
2
|
+
import { isSerializedEntityDeclWithParentReference } from "../../shared/schema/declarations/EntityDecl.js";
|
|
3
|
+
import { isSerializedEnumDecl } from "../../shared/schema/declarations/EnumDecl.js";
|
|
4
|
+
import { isSerializedTypeAliasDecl } from "../../shared/schema/declarations/TypeAliasDecl.js";
|
|
2
5
|
import { getAllDeclarations } from "../api/declarations.js";
|
|
3
6
|
import { useSetting } from "./useSettings.js";
|
|
4
7
|
export const useGetDeclFromDeclName = () => {
|
|
@@ -9,9 +12,9 @@ export const useGetDeclFromDeclName = () => {
|
|
|
9
12
|
.then(data => {
|
|
10
13
|
setSecondaryDeclarations(data.declarations
|
|
11
14
|
.map(decl => decl.declaration)
|
|
12
|
-
.filter(
|
|
13
|
-
decl
|
|
14
|
-
decl
|
|
15
|
+
.filter(decl => isSerializedEnumDecl(decl) ||
|
|
16
|
+
isSerializedTypeAliasDecl(decl) ||
|
|
17
|
+
isSerializedEntityDeclWithParentReference(decl)));
|
|
15
18
|
})
|
|
16
19
|
.catch((error) => {
|
|
17
20
|
if (error instanceof Error) {
|
|
@@ -9,7 +9,6 @@ const defaultSettingsFromConfig = (config) => ({
|
|
|
9
9
|
displayedLocales: config.defaultLocales.length > 0 ? config.defaultLocales : defaultSettings.displayedLocales,
|
|
10
10
|
});
|
|
11
11
|
export const useSettings = (config) => {
|
|
12
|
-
console.log("useSettings");
|
|
13
12
|
const [settings, setSettings] = useState(() => Object.fromEntries(Object.entries(defaultSettingsFromConfig(config)).map(([key, initialValue]) => {
|
|
14
13
|
const item = localStorage.getItem(key);
|
|
15
14
|
if (item) {
|
|
@@ -13,27 +13,28 @@ const titleBuilder = ({ entity }) => {
|
|
|
13
13
|
};
|
|
14
14
|
const onSubmit = async ({ locales, entity, buttonName, instanceContent, isLocaleEntity, customId, childInstances, setInstanceContent, setCustomId, route, getDeclFromDeclName, }) => {
|
|
15
15
|
try {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
16
|
+
if (buttonName) {
|
|
17
|
+
const createdInstance = await createInstanceByEntityNameAndId(locales, entity.name, {
|
|
18
|
+
childInstances,
|
|
19
|
+
entityName: entity.name,
|
|
20
|
+
content: instanceContent,
|
|
21
|
+
id: undefined,
|
|
22
|
+
}, isLocaleEntity ? customId : undefined);
|
|
23
|
+
switch (buttonName) {
|
|
24
|
+
case "saveandcontinue": {
|
|
25
|
+
route(`/entities/${entity.name}/instances/${createdInstance.instance.id}`);
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
case "saveandaddanother": {
|
|
29
|
+
setInstanceContent(createTypeSkeleton(getDeclFromDeclName, entity.type));
|
|
30
|
+
setCustomId("");
|
|
31
|
+
alert(`Instance of entity ${entity.name} created successfully with identifier ${createdInstance.instance.id}. You can add another instance now.`);
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
case "save": {
|
|
35
|
+
route(`/entities/${entity.name}?created=${encodeURIComponent(createdInstance.instance.id)}`);
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
37
38
|
}
|
|
38
39
|
}
|
|
39
40
|
}
|
|
@@ -43,4 +44,8 @@ const onSubmit = async ({ locales, entity, buttonName, instanceContent, isLocale
|
|
|
43
44
|
}
|
|
44
45
|
}
|
|
45
46
|
};
|
|
46
|
-
export const CreateInstance = () => (_jsx(InstanceRouteSkeleton, { mode: "create",
|
|
47
|
+
export const CreateInstance = () => (_jsx(InstanceRouteSkeleton, { mode: "create", buttons: [
|
|
48
|
+
{ label: "Save", name: "save", primary: true },
|
|
49
|
+
{ label: "Save and continue", name: "saveandcontinue" },
|
|
50
|
+
{ label: "Save and add another", name: "saveandaddanother" },
|
|
51
|
+
], init: init, titleBuilder: titleBuilder, onSubmit: onSubmit }));
|
|
@@ -21,23 +21,35 @@ const titleBuilder = ({ locales, entity, instanceId, instanceContent, }) => {
|
|
|
21
21
|
}
|
|
22
22
|
return undefined;
|
|
23
23
|
};
|
|
24
|
-
const onSubmit = async ({ locales, entity, instanceId, instanceContent, buttonName, childInstances, }) => {
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
const onSubmit = async ({ locales, entity, instanceId, instanceContent, buttonName, childInstances, route, }) => {
|
|
25
|
+
try {
|
|
26
|
+
if (instanceId && buttonName) {
|
|
27
27
|
await updateInstanceByEntityNameAndId(locales, entity.name, instanceId, {
|
|
28
28
|
childInstances,
|
|
29
29
|
entityName: entity.name,
|
|
30
30
|
content: instanceContent,
|
|
31
31
|
id: instanceId,
|
|
32
32
|
});
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
switch (buttonName) {
|
|
34
|
+
case "saveandcontinue": {
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
case "save": {
|
|
38
|
+
route(`/entities/${entity.name}`);
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
37
41
|
}
|
|
38
42
|
}
|
|
39
43
|
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
if (error instanceof Error) {
|
|
46
|
+
alert(`Error updating instance:\n\n${error}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
40
49
|
};
|
|
41
50
|
export const Instance = () => {
|
|
42
|
-
return (_jsx(InstanceRouteSkeleton, { mode: "edit",
|
|
51
|
+
return (_jsx(InstanceRouteSkeleton, { mode: "edit", buttons: [
|
|
52
|
+
{ label: "Save", name: "save", primary: true },
|
|
53
|
+
{ label: "Save and continue", name: "saveandcontinue" },
|
|
54
|
+
], init: init, titleBuilder: titleBuilder, onSubmit: onSubmit }));
|
|
43
55
|
};
|