tsondb 0.7.6 → 0.7.8
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/node/server/api/git.js +156 -24
- package/dist/src/node/server/index.js +4 -0
- package/dist/src/node/utils/instanceOperations.d.ts +1 -1
- package/dist/src/node/utils/instanceOperations.js +2 -2
- package/dist/src/shared/api.d.ts +17 -1
- 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/shared/utils/git.d.ts +4 -0
- package/dist/src/shared/utils/git.js +6 -1
- package/dist/src/shared/utils/markdown.d.ts +36 -17
- package/dist/src/shared/utils/markdown.js +79 -23
- package/dist/src/shared/utils/object.d.ts +1 -0
- package/dist/src/shared/utils/object.js +1 -0
- package/dist/src/web/api/git.d.ts +5 -1
- package/dist/src/web/api/git.js +6 -2
- package/dist/src/web/components/ContextProviderWrapper.d.ts +7 -0
- package/dist/src/web/components/ContextProviderWrapper.js +5 -0
- package/dist/src/web/components/InstanceRouteSkeleton.d.ts +6 -0
- package/dist/src/web/components/InstanceRouteSkeleton.js +12 -8
- package/dist/src/web/components/LoadingOverlay.d.ts +1 -0
- package/dist/src/web/components/LoadingOverlay.js +3 -0
- package/dist/src/web/components/ModalDialog.js +4 -3
- package/dist/src/web/components/git/Git.js +47 -0
- package/dist/src/web/components/git/GitBranchManager.d.ts +7 -0
- package/dist/src/web/components/git/GitBranchManager.js +17 -0
- package/dist/src/web/components/git/GitFileList.d.ts +17 -0
- package/dist/src/web/components/git/GitFileList.js +11 -0
- package/dist/src/web/components/git/GitFileManager.d.ts +8 -0
- package/dist/src/web/components/git/GitFileManager.js +34 -0
- package/dist/src/web/components/git/GitStatusIndicator.d.ts +7 -0
- package/dist/src/web/components/git/GitStatusIndicator.js +6 -0
- package/dist/src/web/components/typeInputs/StringTypeInput.js +1 -1
- package/dist/src/web/components/typeInputs/utils/MismatchingTypeError.js +2 -2
- package/dist/src/web/context/entities.d.ts +6 -5
- package/dist/src/web/context/git.d.ts +2 -1
- package/dist/src/web/context/gitClient.d.ts +2 -0
- package/dist/src/web/context/gitClient.js +2 -0
- package/dist/src/web/hooks/useGitClient.d.ts +37 -0
- package/dist/src/web/hooks/useGitClient.js +313 -0
- package/dist/src/web/hooks/useSecondaryDeclarations.js +6 -3
- package/dist/src/web/hooks/useSettings.js +0 -1
- package/dist/src/web/index.js +6 -2
- package/dist/src/web/routes/CreateInstance.js +29 -23
- package/dist/src/web/routes/Entity.js +10 -4
- package/dist/src/web/routes/Instance.js +21 -8
- package/dist/src/web/signals/loading.d.ts +2 -0
- package/dist/src/web/signals/loading.js +11 -0
- package/dist/src/web/utils/BlockMarkdown.js +1 -1
- package/dist/src/web/utils/debug.d.ts +1 -0
- package/dist/src/web/utils/debug.js +4 -0
- package/dist/src/web/utils/typeSkeleton.js +1 -1
- package/package.json +3 -3
- package/public/css/styles.css +132 -70
- package/dist/src/web/components/Git.js +0 -164
- /package/dist/src/web/components/{Git.d.ts → git/Git.d.ts} +0 -0
|
@@ -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,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Debug from "debug";
|
|
2
2
|
import express, {} from "express";
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
-
import { hasFileChanges } from "../../../shared/utils/git.js";
|
|
4
|
+
import { hasFileChanges, splitBranchName } from "../../../shared/utils/git.js";
|
|
5
5
|
import { getInstanceContainerOverview } from "../../../shared/utils/instances.js";
|
|
6
6
|
import { attachGitStatusToInstancesByEntityName } from "../../utils/instances.js";
|
|
7
7
|
import { reinit } from "../init.js";
|
|
@@ -10,12 +10,18 @@ const debug = Debug("tsondb:server:api:git");
|
|
|
10
10
|
export const gitApi = express.Router();
|
|
11
11
|
gitApi.use((req, res, next) => {
|
|
12
12
|
debug(req.path);
|
|
13
|
-
if (req.gitRoot === undefined) {
|
|
14
|
-
res.status(
|
|
13
|
+
if (req.path !== "/" && req.gitRoot === undefined) {
|
|
14
|
+
res.status(400).send("Git repository not found");
|
|
15
15
|
return;
|
|
16
16
|
}
|
|
17
17
|
next();
|
|
18
18
|
});
|
|
19
|
+
gitApi.get("/", (req, res) => {
|
|
20
|
+
const body = {
|
|
21
|
+
isRepo: req.gitRoot !== undefined,
|
|
22
|
+
};
|
|
23
|
+
res.json(body);
|
|
24
|
+
});
|
|
19
25
|
gitApi.get("/status", async (req, res) => {
|
|
20
26
|
const status = await req.git.status();
|
|
21
27
|
attachGitStatusToInstancesByEntityName(req.instancesByEntityName, req.dataRoot,
|
|
@@ -23,6 +29,8 @@ gitApi.get("/status", async (req, res) => {
|
|
|
23
29
|
req.gitRoot, status);
|
|
24
30
|
const getChildInstancesForInstanceId = createChildInstancesForInstanceIdGetter(req);
|
|
25
31
|
const body = {
|
|
32
|
+
currentBranch: status.current,
|
|
33
|
+
trackingBranch: status.tracking,
|
|
26
34
|
commitsAhead: status.ahead,
|
|
27
35
|
commitsBehind: status.behind,
|
|
28
36
|
instances: Object.fromEntries(Object.entries(req.instancesByEntityName).map(([entityName, instances]) => [
|
|
@@ -36,62 +44,94 @@ gitApi.get("/status", async (req, res) => {
|
|
|
36
44
|
};
|
|
37
45
|
res.json(body);
|
|
38
46
|
});
|
|
47
|
+
gitApi.post("/fetch", async (req, res) => {
|
|
48
|
+
try {
|
|
49
|
+
await req.git.fetch(["--all", "-p"]);
|
|
50
|
+
res.set("Content-Type", "text/plain");
|
|
51
|
+
res.status(200).send("Fetched all remotes");
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
debug(`${req.path}: ${error.message}`);
|
|
55
|
+
res.set("Content-Type", "text/plain");
|
|
56
|
+
res.status(500).send(error instanceof Error ? error.message : "Fetching all remotes failed");
|
|
57
|
+
}
|
|
58
|
+
});
|
|
39
59
|
gitApi.post("/stage", async (req, res) => {
|
|
40
60
|
try {
|
|
41
61
|
await req.git.add(req.dataRoot);
|
|
62
|
+
res.set("Content-Type", "text/plain");
|
|
42
63
|
res.status(200).send("Added all database files to index");
|
|
43
64
|
}
|
|
44
65
|
catch (error) {
|
|
45
66
|
debug(`${req.path}: ${error.message}`);
|
|
46
|
-
res.
|
|
67
|
+
res.set("Content-Type", "text/plain");
|
|
68
|
+
res
|
|
69
|
+
.status(500)
|
|
70
|
+
.send(error instanceof Error ? error.message : "Adding all database files to index failed");
|
|
47
71
|
}
|
|
48
72
|
});
|
|
49
73
|
gitApi.post("/stage/:entityName", async (req, res) => {
|
|
50
74
|
try {
|
|
51
75
|
await req.git.add(join(req.dataRoot, req.params.entityName));
|
|
76
|
+
res.set("Content-Type", "text/plain");
|
|
52
77
|
res.status(200).send(`Added all database files for entity ${req.params.entityName} to index`);
|
|
53
78
|
}
|
|
54
79
|
catch (error) {
|
|
55
80
|
debug(`${req.path}: ${error.message}`);
|
|
81
|
+
res.set("Content-Type", "text/plain");
|
|
56
82
|
res
|
|
57
83
|
.status(500)
|
|
58
|
-
.send(
|
|
84
|
+
.send(error instanceof Error
|
|
85
|
+
? error.message
|
|
86
|
+
: `Adding all database files for entity ${req.params.entityName} to index failed`);
|
|
59
87
|
}
|
|
60
88
|
});
|
|
61
89
|
gitApi.post("/stage/:entityName/:instanceId", async (req, res) => {
|
|
62
90
|
try {
|
|
63
91
|
await req.git.add(join(req.dataRoot, req.params.entityName, `${req.params.instanceId}.json`));
|
|
92
|
+
res.set("Content-Type", "text/plain");
|
|
64
93
|
res
|
|
65
94
|
.status(200)
|
|
66
95
|
.send(`Added database file ${req.params.instanceId} for entity ${req.params.entityName} to index`);
|
|
67
96
|
}
|
|
68
97
|
catch (error) {
|
|
69
98
|
debug(`${req.path}: ${error.message}`);
|
|
99
|
+
res.set("Content-Type", "text/plain");
|
|
70
100
|
res
|
|
71
101
|
.status(500)
|
|
72
|
-
.send(
|
|
102
|
+
.send(error instanceof Error
|
|
103
|
+
? error.message
|
|
104
|
+
: `Adding database file ${req.params.instanceId} for entity ${req.params.entityName} to index failed`);
|
|
73
105
|
}
|
|
74
106
|
});
|
|
75
107
|
gitApi.post("/unstage", async (req, res) => {
|
|
76
108
|
try {
|
|
77
109
|
await req.git.reset(["HEAD", "--", req.dataRoot]);
|
|
110
|
+
res.set("Content-Type", "text/plain");
|
|
78
111
|
res.status(200).send("Removed all database files to index");
|
|
79
112
|
}
|
|
80
113
|
catch (error) {
|
|
81
114
|
debug(`${req.path}: ${error.message}`);
|
|
82
|
-
res.
|
|
115
|
+
res.set("Content-Type", "text/plain");
|
|
116
|
+
res
|
|
117
|
+
.status(500)
|
|
118
|
+
.send(error instanceof Error ? error.message : "Removing all database files to index failed");
|
|
83
119
|
}
|
|
84
120
|
});
|
|
85
121
|
gitApi.post("/unstage/:entityName", async (req, res) => {
|
|
86
122
|
try {
|
|
87
123
|
await req.git.reset(["HEAD", "--", join(req.dataRoot, req.params.entityName)]);
|
|
124
|
+
res.set("Content-Type", "text/plain");
|
|
88
125
|
res.status(200).send(`Removed all database files for entity ${req.params.entityName} to index`);
|
|
89
126
|
}
|
|
90
127
|
catch (error) {
|
|
91
128
|
debug(`${req.path}: ${error.message}`);
|
|
129
|
+
res.set("Content-Type", "text/plain");
|
|
92
130
|
res
|
|
93
131
|
.status(500)
|
|
94
|
-
.send(
|
|
132
|
+
.send(error instanceof Error
|
|
133
|
+
? error.message
|
|
134
|
+
: `Removing all database files for entity ${req.params.entityName} to index failed`);
|
|
95
135
|
}
|
|
96
136
|
});
|
|
97
137
|
gitApi.post("/unstage/:entityName/:instanceId", async (req, res) => {
|
|
@@ -101,78 +141,170 @@ gitApi.post("/unstage/:entityName/:instanceId", async (req, res) => {
|
|
|
101
141
|
"--",
|
|
102
142
|
join(req.dataRoot, req.params.entityName, `${req.params.instanceId}.json`),
|
|
103
143
|
]);
|
|
144
|
+
res.set("Content-Type", "text/plain");
|
|
104
145
|
res
|
|
105
146
|
.status(200)
|
|
106
147
|
.send(`Removed database file ${req.params.instanceId} for entity ${req.params.entityName} to index`);
|
|
107
148
|
}
|
|
108
149
|
catch (error) {
|
|
109
150
|
debug(`${req.path}: ${error.message}`);
|
|
151
|
+
res.set("Content-Type", "text/plain");
|
|
110
152
|
res
|
|
111
153
|
.status(500)
|
|
112
|
-
.send(
|
|
154
|
+
.send(error instanceof Error
|
|
155
|
+
? error.message
|
|
156
|
+
: `Removing database file ${req.params.instanceId} for entity ${req.params.entityName} to index failed`);
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
gitApi.post("/reset", async (req, res) => {
|
|
160
|
+
try {
|
|
161
|
+
await req.git.raw(["restore", "--", req.dataRoot]);
|
|
162
|
+
res.set("Content-Type", "text/plain");
|
|
163
|
+
res.status(200).send("Removed all database files to index");
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
debug(`${req.path}: ${error.message}`);
|
|
167
|
+
res.set("Content-Type", "text/plain");
|
|
168
|
+
res
|
|
169
|
+
.status(500)
|
|
170
|
+
.send(error instanceof Error ? error.message : "Removing all database files to index failed");
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
gitApi.post("/reset/:entityName/:instanceId", async (req, res) => {
|
|
174
|
+
try {
|
|
175
|
+
await req.git.raw([
|
|
176
|
+
"restore",
|
|
177
|
+
"--",
|
|
178
|
+
join(req.dataRoot, req.params.entityName, `${req.params.instanceId}.json`),
|
|
179
|
+
]);
|
|
180
|
+
await reinit(req);
|
|
181
|
+
res.set("Content-Type", "text/plain");
|
|
182
|
+
res
|
|
183
|
+
.status(200)
|
|
184
|
+
.send(`Removed database file ${req.params.instanceId} for entity ${req.params.entityName} to index`);
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
debug(`${req.path}: ${error.message}`);
|
|
188
|
+
res.set("Content-Type", "text/plain");
|
|
189
|
+
res
|
|
190
|
+
.status(500)
|
|
191
|
+
.send(error instanceof Error
|
|
192
|
+
? error.message
|
|
193
|
+
: `Removing database file ${req.params.instanceId} for entity ${req.params.entityName} to index failed`);
|
|
113
194
|
}
|
|
114
195
|
});
|
|
115
196
|
gitApi.post("/commit", async (req, res) => {
|
|
116
197
|
const message = req.body.message;
|
|
117
198
|
if (typeof message !== "string" || message.length === 0) {
|
|
199
|
+
res.set("Content-Type", "text/plain");
|
|
118
200
|
res.status(400).send("Invalid commit message");
|
|
119
201
|
return;
|
|
120
202
|
}
|
|
121
203
|
try {
|
|
122
204
|
await req.git.commit(message);
|
|
205
|
+
res.set("Content-Type", "text/plain");
|
|
123
206
|
res.status(200).send("Commit successful");
|
|
124
207
|
}
|
|
125
|
-
catch {
|
|
126
|
-
res.
|
|
208
|
+
catch (error) {
|
|
209
|
+
res.set("Content-Type", "text/plain");
|
|
210
|
+
res.status(500).send(error instanceof Error ? error.message : "Commit failed");
|
|
127
211
|
}
|
|
128
212
|
});
|
|
129
213
|
gitApi.post("/push", async (req, res) => {
|
|
130
214
|
try {
|
|
131
|
-
await req.git.
|
|
215
|
+
const status = await req.git.status();
|
|
216
|
+
const remotes = await req.git.getRemotes();
|
|
217
|
+
await req.git.push(remotes[0]?.name, status.current ?? undefined);
|
|
218
|
+
res.set("Content-Type", "text/plain");
|
|
132
219
|
res.status(200).send("Push successful");
|
|
133
220
|
}
|
|
134
|
-
catch {
|
|
135
|
-
res.
|
|
221
|
+
catch (error) {
|
|
222
|
+
res.set("Content-Type", "text/plain");
|
|
223
|
+
res.status(500).send(error instanceof Error ? error.message : "Push failed");
|
|
136
224
|
}
|
|
137
225
|
});
|
|
138
226
|
gitApi.post("/pull", async (req, res) => {
|
|
139
227
|
try {
|
|
140
|
-
await req.git.
|
|
228
|
+
const status = await req.git.status();
|
|
229
|
+
const remotes = await req.git.getRemotes();
|
|
230
|
+
await req.git.pull(remotes[0]?.name, status.current ?? undefined);
|
|
231
|
+
res.set("Content-Type", "text/plain");
|
|
141
232
|
res.status(200).send("Pull successful");
|
|
142
233
|
}
|
|
143
|
-
catch {
|
|
144
|
-
res.
|
|
234
|
+
catch (error) {
|
|
235
|
+
res.set("Content-Type", "text/plain");
|
|
236
|
+
res.status(500).send(error instanceof Error ? error.message : "Pull failed");
|
|
145
237
|
}
|
|
146
238
|
});
|
|
147
239
|
gitApi.get("/branch", async (req, res) => {
|
|
148
|
-
const branchSummary = await req.git.
|
|
240
|
+
const branchSummary = await req.git.branch();
|
|
149
241
|
const body = {
|
|
150
242
|
allBranches: branchSummary.all,
|
|
151
243
|
currentBranch: branchSummary.current,
|
|
244
|
+
isDetached: branchSummary.detached,
|
|
245
|
+
branches: branchSummary.branches,
|
|
152
246
|
};
|
|
153
247
|
res.json(body);
|
|
154
248
|
});
|
|
155
249
|
gitApi.post("/branch", async (req, res) => {
|
|
156
250
|
const branchName = req.body.branchName;
|
|
157
251
|
if (typeof branchName !== "string" || branchName.length === 0) {
|
|
252
|
+
res.set("Content-Type", "text/plain");
|
|
158
253
|
res.status(400).send("Invalid branch name");
|
|
159
254
|
return;
|
|
160
255
|
}
|
|
161
256
|
try {
|
|
162
257
|
await req.git.checkoutLocalBranch(branchName);
|
|
163
258
|
await reinit(req);
|
|
259
|
+
res.set("Content-Type", "text/plain");
|
|
164
260
|
res.status(200).send(`Creation of branch "${branchName}" successful`);
|
|
165
261
|
}
|
|
166
|
-
catch {
|
|
167
|
-
res.
|
|
262
|
+
catch (error) {
|
|
263
|
+
res.set("Content-Type", "text/plain");
|
|
264
|
+
res
|
|
265
|
+
.status(500)
|
|
266
|
+
.send(error instanceof Error ? error.message : `Creation of branch "${branchName}" failed`);
|
|
168
267
|
}
|
|
169
268
|
});
|
|
170
269
|
gitApi.post("/branch/:branchName", async (req, res) => {
|
|
270
|
+
const branchName = decodeURIComponent(req.params.branchName);
|
|
171
271
|
try {
|
|
172
|
-
|
|
173
|
-
|
|
272
|
+
const { remote, name: actualBranch } = splitBranchName(branchName);
|
|
273
|
+
if (remote) {
|
|
274
|
+
debug(`Switch to remote branch "${remote}/${actualBranch}"`);
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
debug(`Switch to local branch "${actualBranch}"`);
|
|
278
|
+
}
|
|
279
|
+
await req.git.raw("switch", actualBranch);
|
|
280
|
+
await reinit(req);
|
|
281
|
+
res.set("Content-Type", "text/plain");
|
|
282
|
+
res.status(200).send(`Switch to branch "${branchName}" successful`);
|
|
283
|
+
}
|
|
284
|
+
catch (error) {
|
|
285
|
+
res.set("Content-Type", "text/plain");
|
|
286
|
+
res
|
|
287
|
+
.status(500)
|
|
288
|
+
.send(error instanceof Error ? error.message : `Switch to branch "${branchName}" failed`);
|
|
174
289
|
}
|
|
175
|
-
|
|
176
|
-
|
|
290
|
+
});
|
|
291
|
+
gitApi.delete("/branch/:branchName", async (req, res) => {
|
|
292
|
+
const branchName = decodeURIComponent(req.params.branchName);
|
|
293
|
+
try {
|
|
294
|
+
const branchSummary = await req.git.branchLocal();
|
|
295
|
+
if (branchSummary.current === branchName) {
|
|
296
|
+
res.set("Content-Type", "text/plain");
|
|
297
|
+
res.status(400).send("Cannot delete the branch currently checked out");
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
await req.git.deleteLocalBranch(branchName, true);
|
|
301
|
+
res.set("Content-Type", "text/plain");
|
|
302
|
+
res.status(200).send(`Deletion of branch "${branchName}" successful`);
|
|
303
|
+
}
|
|
304
|
+
catch (error) {
|
|
305
|
+
res.set("Content-Type", "text/plain");
|
|
306
|
+
res
|
|
307
|
+
.status(500)
|
|
308
|
+
.send(error instanceof Error ? error.message : `Deletion of branch "${branchName}" failed`);
|
|
177
309
|
}
|
|
178
310
|
});
|