tsondb 0.10.1 → 0.11.0

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.
Files changed (29) hide show
  1. package/dist/src/node/index.js +1 -1
  2. package/dist/src/node/schema/Node.d.ts +5 -5
  3. package/dist/src/node/schema/Node.js +53 -53
  4. package/dist/src/node/schema/Schema.js +58 -1
  5. package/dist/src/node/schema/declarations/Declaration.js +1 -1
  6. package/dist/src/node/schema/declarations/EntityDecl.js +4 -4
  7. package/dist/src/node/schema/declarations/EnumDecl.js +7 -4
  8. package/dist/src/node/schema/declarations/TypeAliasDecl.d.ts +2 -2
  9. package/dist/src/node/schema/declarations/TypeAliasDecl.js +4 -4
  10. package/dist/src/node/schema/types/generic/ArrayType.js +4 -4
  11. package/dist/src/node/schema/types/generic/EnumType.js +6 -6
  12. package/dist/src/node/schema/types/generic/ObjectType.js +5 -5
  13. package/dist/src/node/schema/types/primitives/BooleanType.js +1 -1
  14. package/dist/src/node/schema/types/primitives/DateType.js +1 -1
  15. package/dist/src/node/schema/types/primitives/FloatType.js +1 -1
  16. package/dist/src/node/schema/types/primitives/IntegerType.js +1 -1
  17. package/dist/src/node/schema/types/primitives/StringType.js +1 -1
  18. package/dist/src/node/schema/types/references/IncludeIdentifierType.d.ts +3 -3
  19. package/dist/src/node/schema/types/references/IncludeIdentifierType.js +30 -6
  20. package/dist/src/node/schema/types/references/NestedEntityMapType.js +7 -7
  21. package/dist/src/node/schema/types/references/ReferenceIdentifierType.js +1 -1
  22. package/dist/src/node/schema/types/references/TypeArgumentType.js +1 -1
  23. package/dist/src/node/utils/instanceOperations.js +1 -1
  24. package/dist/src/node/utils/references.js +4 -4
  25. package/dist/src/shared/utils/markdown.d.ts +7 -1
  26. package/dist/src/shared/utils/markdown.js +34 -15
  27. package/dist/src/web/routes/Entity.js +4 -4
  28. package/dist/src/web/utils/InlineMarkdown.js +2 -0
  29. package/package.json +6 -6
@@ -34,7 +34,7 @@ const _validate = (dataRootPath, entities, instancesByEntityName, options = {})
34
34
  const errors = (checkOnlyEntities.length > 0
35
35
  ? entities.filter(entity => checkOnlyEntities.includes(entity.name))
36
36
  : entities)
37
- .flatMap(entity => parallelizeErrors(instancesByEntityName[entity.name]?.map(instance => wrapErrorsIfAny(`in file ${styleText("white", `"${dataRootPath}${sep}${styleText("bold", join(entity.name, getFileNameForId(instance.id)))}"`)}`, validateEntityDecl(validationHelpers, entity, instance.content))) ?? []))
37
+ .flatMap(entity => parallelizeErrors(instancesByEntityName[entity.name]?.map(instance => wrapErrorsIfAny(`in file ${styleText("white", `"${dataRootPath}${sep}${styleText("bold", join(entity.name, getFileNameForId(instance.id)))}"`)}`, validateEntityDecl(validationHelpers, [], entity, instance.content))) ?? []))
38
38
  .toSorted((a, b) => a.message.localeCompare(b.message));
39
39
  if (errors.length === 0) {
40
40
  debug("All entities are valid");
@@ -64,8 +64,8 @@ export declare const createValidators: (instancesByEntityName: InstancesByEntity
64
64
  export type Predicate<T extends Node> = (node: Node) => node is T;
65
65
  export type GetNestedDeclarations<T extends Node = Node> = (addedDecls: NestedDecl[], node: T, parentDecl: Decl | undefined) => NestedDecl[];
66
66
  export declare const getNestedDeclarations: GetNestedDeclarations;
67
- export type Validator<T extends Node = Node> = (helpers: Validators, node: T, value: unknown) => Error[];
68
- export type ValidatorOfParamDecl<T extends Node = Node> = (helpers: Validators, node: T, typeArgs: Type[], value: unknown) => Error[];
67
+ export type Validator<T extends Node = Node> = (helpers: Validators, inDecls: Decl[], node: T, value: unknown) => Error[];
68
+ export type ValidatorOfParamDecl<T extends Node = Node> = (helpers: Validators, inDecls: Decl[], node: T, typeArgs: Type[], value: unknown) => Error[];
69
69
  export declare const validateDecl: ValidatorOfParamDecl<Decl>;
70
70
  export declare const validateType: Validator<Type>;
71
71
  export type NodeWithResolvedTypeArguments<T extends Node | null> = T extends BooleanType | DateType | FloatType | IntegerType | StringType | ReferenceIdentifierType ? T : T extends EntityDecl<infer N, infer P, infer FK> ? EntityDecl<N, {
@@ -80,8 +80,8 @@ export type NodeWithResolvedTypeArguments<T extends Node | null> = T extends Boo
80
80
  }> : T extends TypeArgumentType ? Type : T extends IncludeIdentifierType<[], IncludableDeclP<[]>> ? T : T extends IncludeIdentifierType ? Type : T extends NestedEntityMapType<infer N, infer P> ? NestedEntityMapType<N, {
81
81
  [K in keyof P]: P[K] extends MemberDecl<infer PT, infer R> ? MemberDecl<NodeWithResolvedTypeArguments<PT>, R> : never;
82
82
  }> : T extends TypeParameter<infer N, infer C> ? TypeParameter<N, NodeWithResolvedTypeArguments<C>> : T extends ChildEntitiesType<infer E> ? ChildEntitiesType<E> : T extends null ? null : never;
83
- export type TypeArgumentsResolver<T extends Node = Node> = (args: Record<string, Type>, node: T) => NodeWithResolvedTypeArguments<T>;
84
- export declare const resolveTypeArguments: <T extends Node = Node>(args: Record<string, Type>, node: T) => NodeWithResolvedTypeArguments<T>;
83
+ export type TypeArgumentsResolver<T extends Node = Node> = (args: Record<string, Type>, node: T, inDecl: Decl[]) => NodeWithResolvedTypeArguments<T>;
84
+ export declare const resolveTypeArguments: <T extends Node = Node>(args: Record<string, Type>, node: T, inDecl: Decl[]) => NodeWithResolvedTypeArguments<T>;
85
85
  export type SerializedNodeMap = {
86
86
  [NodeKind.EntityDecl]: [EntityDecl, SerializedEntityDecl];
87
87
  [NodeKind.EnumDecl]: [EnumDecl, SerializedEnumDecl];
@@ -114,5 +114,5 @@ export type Serialized<T extends Node> = T extends EntityDecl<infer Name, infer
114
114
  export type SerializedOf<T extends Node> = SerializedNodeMap[T["kind"]][1];
115
115
  export type Serializer<T extends Node = Node> = (node: T) => Serialized<T>;
116
116
  export declare const serializeNode: <T extends Node>(node: T) => Serialized<T>;
117
- export type GetReferences<T extends Node = Node> = (node: T, value: unknown) => string[];
117
+ export type GetReferences<T extends Node = Node> = (node: T, value: unknown, inDecl: Decl[]) => string[];
118
118
  export declare const getReferences: GetReferences;
@@ -147,86 +147,86 @@ export const getNestedDeclarations = (addedDecls, node, parentDecl) => {
147
147
  return assertExhaustive(node);
148
148
  }
149
149
  };
150
- export const validateDecl = (helpers, decl, typeArgs, value) => {
150
+ export const validateDecl = (helpers, inDecls, decl, typeArgs, value) => {
151
151
  switch (decl.kind) {
152
152
  case NodeKind.EntityDecl:
153
- return validateEntityDecl(helpers, decl, value);
153
+ return validateEntityDecl(helpers, inDecls, decl, value);
154
154
  case NodeKind.EnumDecl:
155
- return validateEnumDecl(helpers, decl, typeArgs, value);
155
+ return validateEnumDecl(helpers, inDecls, decl, typeArgs, value);
156
156
  case NodeKind.TypeAliasDecl:
157
- return validateTypeAliasDecl(helpers, decl, typeArgs, value);
157
+ return validateTypeAliasDecl(helpers, inDecls, decl, typeArgs, value);
158
158
  default:
159
159
  return assertExhaustive(decl);
160
160
  }
161
161
  };
162
- export const validateType = (helpers, type, value) => {
162
+ export const validateType = (helpers, inDecls, type, value) => {
163
163
  switch (type.kind) {
164
164
  case NodeKind.ArrayType:
165
- return validateArrayType(helpers, type, value);
165
+ return validateArrayType(helpers, inDecls, type, value);
166
166
  case NodeKind.ObjectType:
167
- return validateObjectType(helpers, type, value);
167
+ return validateObjectType(helpers, inDecls, type, value);
168
168
  case NodeKind.BooleanType:
169
- return validateBooleanType(helpers, type, value);
169
+ return validateBooleanType(helpers, inDecls, type, value);
170
170
  case NodeKind.DateType:
171
- return validateDateType(helpers, type, value);
171
+ return validateDateType(helpers, inDecls, type, value);
172
172
  case NodeKind.FloatType:
173
- return validateFloatType(helpers, type, value);
173
+ return validateFloatType(helpers, inDecls, type, value);
174
174
  case NodeKind.IntegerType:
175
- return validateIntegerType(helpers, type, value);
175
+ return validateIntegerType(helpers, inDecls, type, value);
176
176
  case NodeKind.StringType:
177
- return validateStringType(helpers, type, value);
177
+ return validateStringType(helpers, inDecls, type, value);
178
178
  case NodeKind.TypeArgumentType:
179
- return validateTypeArgumentType(helpers, type, value);
179
+ return validateTypeArgumentType(helpers, inDecls, type, value);
180
180
  case NodeKind.ReferenceIdentifierType:
181
- return validateReferenceIdentifierType(helpers, type, value);
181
+ return validateReferenceIdentifierType(helpers, inDecls, type, value);
182
182
  case NodeKind.IncludeIdentifierType:
183
- return validateIncludeIdentifierType(helpers, type, value);
183
+ return validateIncludeIdentifierType(helpers, inDecls, type, value);
184
184
  case NodeKind.NestedEntityMapType:
185
- return validateNestedEntityMapType(helpers, type, value);
185
+ return validateNestedEntityMapType(helpers, inDecls, type, value);
186
186
  case NodeKind.EnumType:
187
- return validateEnumType(helpers, type, value);
187
+ return validateEnumType(helpers, inDecls, type, value);
188
188
  case NodeKind.ChildEntitiesType:
189
- return validateChildEntitiesType(helpers, type, value);
189
+ return validateChildEntitiesType(helpers, inDecls, type, value);
190
190
  default:
191
191
  return assertExhaustive(type);
192
192
  }
193
193
  };
194
- export const resolveTypeArguments = (args, node) => {
194
+ export const resolveTypeArguments = (args, node, inDecl) => {
195
195
  switch (node.kind) {
196
196
  case NodeKind.EntityDecl:
197
- return resolveTypeArgumentsInEntityDecl(args, node);
197
+ return resolveTypeArgumentsInEntityDecl(args, node, inDecl);
198
198
  case NodeKind.EnumDecl:
199
- return resolveTypeArgumentsInEnumDecl(args, node);
199
+ return resolveTypeArgumentsInEnumDecl(args, node, inDecl);
200
200
  case NodeKind.TypeAliasDecl:
201
- return resolveTypeArgumentsInTypeAliasDecl(args, node);
201
+ return resolveTypeArgumentsInTypeAliasDecl(args, node, inDecl);
202
202
  case NodeKind.ArrayType:
203
- return resolveTypeArgumentsInArrayType(args, node);
203
+ return resolveTypeArgumentsInArrayType(args, node, inDecl);
204
204
  case NodeKind.ObjectType:
205
- return resolveTypeArgumentsInObjectType(args, node);
205
+ return resolveTypeArgumentsInObjectType(args, node, inDecl);
206
206
  case NodeKind.BooleanType:
207
- return resolveTypeArgumentsInBooleanType(args, node);
207
+ return resolveTypeArgumentsInBooleanType(args, node, inDecl);
208
208
  case NodeKind.DateType:
209
- return resolveTypeArgumentsInDateType(args, node);
209
+ return resolveTypeArgumentsInDateType(args, node, inDecl);
210
210
  case NodeKind.FloatType:
211
- return resolveTypeArgumentsInFloatType(args, node);
211
+ return resolveTypeArgumentsInFloatType(args, node, inDecl);
212
212
  case NodeKind.IntegerType:
213
- return resolveTypeArgumentsInIntegerType(args, node);
213
+ return resolveTypeArgumentsInIntegerType(args, node, inDecl);
214
214
  case NodeKind.StringType:
215
- return resolveTypeArgumentsInStringType(args, node);
215
+ return resolveTypeArgumentsInStringType(args, node, inDecl);
216
216
  case NodeKind.TypeArgumentType:
217
217
  return resolveTypeArgumentsInTypeArgumentType(args, node);
218
218
  case NodeKind.ReferenceIdentifierType:
219
- return resolveTypeArgumentsInReferenceIdentifierType(args, node);
219
+ return resolveTypeArgumentsInReferenceIdentifierType(args, node, inDecl);
220
220
  case NodeKind.IncludeIdentifierType:
221
- return resolveTypeArgumentsInIncludeIdentifierType(args, node);
221
+ return resolveTypeArgumentsInIncludeIdentifierType(args, node, inDecl);
222
222
  case NodeKind.NestedEntityMapType:
223
- return resolveTypeArgumentsInNestedEntityMapType(args, node);
223
+ return resolveTypeArgumentsInNestedEntityMapType(args, node, inDecl);
224
224
  case NodeKind.EnumType:
225
- return resolveTypeArgumentsInEnumType(args, node);
225
+ return resolveTypeArgumentsInEnumType(args, node, inDecl);
226
226
  case NodeKind.TypeParameter:
227
- return resolveTypeArgumentsInTypeParameter(args, node);
227
+ return resolveTypeArgumentsInTypeParameter(args, node, inDecl);
228
228
  case NodeKind.ChildEntitiesType:
229
- return resolveTypeArgumentsInChildEntitiesType(args, node);
229
+ return resolveTypeArgumentsInChildEntitiesType(args, node, inDecl);
230
230
  default:
231
231
  return assertExhaustive(node);
232
232
  }
@@ -271,42 +271,42 @@ export const serializeNode = (node) => {
271
271
  return assertExhaustive(node);
272
272
  }
273
273
  };
274
- export const getReferences = (node, value) => {
274
+ export const getReferences = (node, value, inDecl) => {
275
275
  switch (node.kind) {
276
276
  case NodeKind.EntityDecl:
277
- return getReferencesForEntityDecl(node, value);
277
+ return getReferencesForEntityDecl(node, value, inDecl);
278
278
  case NodeKind.EnumDecl:
279
- return getReferencesForEnumDecl(node, value);
279
+ return getReferencesForEnumDecl(node, value, inDecl);
280
280
  case NodeKind.TypeAliasDecl:
281
- return getReferencesForTypeAliasDecl(node, value);
281
+ return getReferencesForTypeAliasDecl(node, value, inDecl);
282
282
  case NodeKind.ArrayType:
283
- return getReferencesForArrayType(node, value);
283
+ return getReferencesForArrayType(node, value, inDecl);
284
284
  case NodeKind.ObjectType:
285
- return getReferencesForObjectType(node, value);
285
+ return getReferencesForObjectType(node, value, inDecl);
286
286
  case NodeKind.BooleanType:
287
- return getReferencesForBooleanType(node, value);
287
+ return getReferencesForBooleanType(node, value, inDecl);
288
288
  case NodeKind.DateType:
289
- return getReferencesForDateType(node, value);
289
+ return getReferencesForDateType(node, value, inDecl);
290
290
  case NodeKind.FloatType:
291
- return getReferencesForFloatType(node, value);
291
+ return getReferencesForFloatType(node, value, inDecl);
292
292
  case NodeKind.IntegerType:
293
- return getReferencesForIntegerType(node, value);
293
+ return getReferencesForIntegerType(node, value, inDecl);
294
294
  case NodeKind.StringType:
295
- return getReferencesForStringType(node, value);
295
+ return getReferencesForStringType(node, value, inDecl);
296
296
  case NodeKind.TypeArgumentType:
297
- return getReferencesForTypeArgumentType(node, value);
297
+ return getReferencesForTypeArgumentType(node, value, inDecl);
298
298
  case NodeKind.ReferenceIdentifierType:
299
- return getReferencesForReferenceIdentifierType(node, value);
299
+ return getReferencesForReferenceIdentifierType(node, value, inDecl);
300
300
  case NodeKind.IncludeIdentifierType:
301
- return getReferencesForIncludeIdentifierType(node, value);
301
+ return getReferencesForIncludeIdentifierType(node, value, inDecl);
302
302
  case NodeKind.NestedEntityMapType:
303
- return getReferencesForNestedEntityMapType(node, value);
303
+ return getReferencesForNestedEntityMapType(node, value, inDecl);
304
304
  case NodeKind.EnumType:
305
- return getReferencesForEnumType(node, value);
305
+ return getReferencesForEnumType(node, value, inDecl);
306
306
  case NodeKind.TypeParameter:
307
- return getReferencesForTypeParameter(node, value);
307
+ return getReferencesForTypeParameter(node, value, inDecl);
308
308
  case NodeKind.ChildEntitiesType:
309
- return getReferencesForChildEntitiesType(node, value);
309
+ return getReferencesForChildEntitiesType(node, value, inDecl);
310
310
  default:
311
311
  return assertExhaustive(node);
312
312
  }
@@ -1,8 +1,9 @@
1
1
  import Debug from "debug";
2
+ import { assertExhaustive } from "../../shared/utils/typeSafety.js";
2
3
  import { getParameterNames, walkNodeTree } from "./declarations/Declaration.js";
3
4
  import { isEntityDecl } from "./declarations/EntityDecl.js";
4
5
  import { cases, isEnumDecl } from "./declarations/EnumDecl.js";
5
- import { getNestedDeclarations } from "./Node.js";
6
+ import { getNestedDeclarations, NodeKind } from "./Node.js";
6
7
  import { isObjectType } from "./types/generic/ObjectType.js";
7
8
  import { isStringType } from "./types/primitives/StringType.js";
8
9
  import { isChildEntitiesType } from "./types/references/ChildEntitiesType.js";
@@ -152,6 +153,60 @@ const checkChildEntitiesProvideCorrectPathToParentReferenceIdentifierType = (dec
152
153
  }
153
154
  }
154
155
  };
156
+ const isDeclarationRecursive = (declToCheck) => {
157
+ const isDeclarationIncludedInNode = (visitedDecls, node) => {
158
+ switch (node.kind) {
159
+ case NodeKind.EntityDecl:
160
+ case NodeKind.EnumDecl:
161
+ case NodeKind.TypeAliasDecl:
162
+ return visitedDecls.includes(node)
163
+ ? false
164
+ : declToCheck === node ||
165
+ isDeclarationIncludedInNode([...visitedDecls, node], node.type.value);
166
+ case NodeKind.BooleanType:
167
+ case NodeKind.DateType:
168
+ case NodeKind.FloatType:
169
+ case NodeKind.IntegerType:
170
+ case NodeKind.StringType:
171
+ case NodeKind.TypeArgumentType:
172
+ case NodeKind.ReferenceIdentifierType:
173
+ case NodeKind.TypeParameter:
174
+ case NodeKind.ChildEntitiesType:
175
+ return false;
176
+ case NodeKind.ArrayType:
177
+ return isDeclarationIncludedInNode(visitedDecls, node.items);
178
+ case NodeKind.ObjectType:
179
+ return Object.entries(node.properties).some(([_, memberDecl]) => isDeclarationIncludedInNode(visitedDecls, memberDecl.type));
180
+ case NodeKind.IncludeIdentifierType:
181
+ return (declToCheck === node.reference ||
182
+ isDeclarationIncludedInNode(visitedDecls, node.reference));
183
+ case NodeKind.NestedEntityMapType:
184
+ return isDeclarationIncludedInNode(visitedDecls, node.type.value);
185
+ case NodeKind.EnumType:
186
+ return Object.entries(node.values).some(([_, caseDecl]) => caseDecl.type !== null && isDeclarationIncludedInNode(visitedDecls, caseDecl.type));
187
+ default:
188
+ return assertExhaustive(node);
189
+ }
190
+ };
191
+ return isDeclarationIncludedInNode([declToCheck], declToCheck.type.value);
192
+ };
193
+ const checkRecursiveGenericTypeAliasesAndEnumerationsAreOnlyParameterizedDirectlyInTypeAliases = (declarations) => {
194
+ const genericRecursiveDeclarations = declarations.filter(decl => isDeclarationRecursive(decl) && decl.parameters.length > 0);
195
+ for (const decl of declarations) {
196
+ walkNodeTree((node, parentTypes) => {
197
+ if (isIncludeIdentifierType(node) &&
198
+ genericRecursiveDeclarations.includes(node.reference) &&
199
+ decl !== node.reference) {
200
+ if (parentTypes.length > 0) {
201
+ throw TypeError(`generic recursive type "${node.reference.name}", referenced in declaration "${decl.name}", may only be included as a direct descendant of a type alias. This is required for resolving generics for outputs without support for generics, as well as internal type validation.`);
202
+ }
203
+ if (decl.parameters.length > 0) {
204
+ throw TypeError(`generic recursive type "${node.reference.name}", referenced in declaration "${decl.name}", may only be included in a non-generic type alias. This is required for resolving generics for outputs without support for generics, as well as internal type validation.`);
205
+ }
206
+ }
207
+ }, decl);
208
+ }
209
+ };
155
210
  const addDeclarations = (existingDecls, declsToAdd) => declsToAdd.reduce((accDecls, decl) => {
156
211
  if (!accDecls.includes(decl)) {
157
212
  return getNestedDeclarations(accDecls, decl.kind === "NestedEntity" ? decl.type : decl, undefined);
@@ -176,6 +231,8 @@ export const Schema = (declarations, localeEntity) => {
176
231
  checkChildEntitiesProvideCorrectPathToParentReferenceIdentifierType(allDeclsWithoutNestedEntities);
177
232
  debug("checking child entity types ...");
178
233
  checkChildEntityTypes(localeEntity, allDeclsWithoutNestedEntities);
234
+ debug("checking generic recursive types ...");
235
+ checkRecursiveGenericTypeAliasesAndEnumerationsAreOnlyParameterizedDirectlyInTypeAliases(allDeclsWithoutNestedEntities);
179
236
  debug("created schema, no integrity violations found");
180
237
  return {
181
238
  declarations: allDeclsWithoutNestedEntities,
@@ -16,7 +16,7 @@ export const validateDeclName = (name) => {
16
16
  }
17
17
  };
18
18
  export const isDeclWithoutTypeParameters = (decl) => decl.parameters.length === 0;
19
- export const resolveTypeArgumentsInDecls = (decls) => decls.filter(isDeclWithoutTypeParameters).map(decl => resolveTypeArguments({}, decl));
19
+ export const resolveTypeArgumentsInDecls = (decls) => decls.filter(isDeclWithoutTypeParameters).map(decl => resolveTypeArguments({}, decl, []));
20
20
  export function walkNodeTree(callbackFn, decl) {
21
21
  callbackFn(decl, [], decl);
22
22
  walkTypeNodeTree(callbackFn, decl.type.value, [], decl);
@@ -27,10 +27,10 @@ export { EntityDecl as Entity };
27
27
  export const isEntityDecl = node => node.kind === NodeKind.EntityDecl;
28
28
  export const isEntityDeclWithParentReference = (decl) => decl.parentReferenceKey !== undefined;
29
29
  export const getNestedDeclarationsInEntityDecl = (isDeclAdded, decl) => getNestedDeclarationsInObjectType(isDeclAdded, decl.type.value, decl);
30
- export const validateEntityDecl = (helpers, decl, value) => validateType(helpers, decl.type.value, value);
31
- export const resolveTypeArgumentsInEntityDecl = (_args, decl) => EntityDecl(decl.sourceUrl, {
30
+ export const validateEntityDecl = (helpers, inDecls, decl, value) => validateType(helpers, inDecls, decl.type.value, value);
31
+ export const resolveTypeArgumentsInEntityDecl = (_args, decl, inDecl) => EntityDecl(decl.sourceUrl, {
32
32
  ...decl,
33
- type: () => resolveTypeArguments({}, decl.type.value),
33
+ type: () => resolveTypeArguments({}, decl.type.value, [...inDecl, decl]),
34
34
  });
35
35
  const createEntityIdentifierComment = () => "The entity’s identifier. A UUID or a locale code if it is registered as the locale entity.";
36
36
  export const addEphemeralUUIDToType = (decl) => ({
@@ -57,4 +57,4 @@ export const serializeEntityDecl = (type) => ({
57
57
  : type.displayName,
58
58
  displayNameCustomizer: type.displayNameCustomizer !== undefined,
59
59
  });
60
- export const getReferencesForEntityDecl = (decl, value) => getReferencesForObjectType(decl.type.value, value);
60
+ export const getReferencesForEntityDecl = (decl, value, inDecl) => getReferencesForObjectType(decl.type.value, value, [...inDecl, decl]);
@@ -29,17 +29,20 @@ export const EnumDecl = (sourceUrl, options) => {
29
29
  export { EnumDecl as Enum };
30
30
  export const isEnumDecl = node => node.kind === NodeKind.EnumDecl;
31
31
  export const getNestedDeclarationsInEnumDecl = (addedDecls, decl) => getNestedDeclarationsInEnumType(addedDecls, decl.type.value, decl);
32
- export const validateEnumDecl = (helpers, decl, args, value) => validateEnumType(helpers, resolveTypeArgumentsInEnumType(getTypeArgumentsRecord(decl, args), decl.type.value), value);
33
- export const resolveTypeArgumentsInEnumDecl = (args, decl) => EnumDecl(decl.sourceUrl, {
32
+ export const validateEnumDecl = (helpers, inDecls, decl, args, value) => validateEnumType(helpers, [...inDecls, decl], resolveTypeArgumentsInEnumType(getTypeArgumentsRecord(decl, args), decl.type.value, [
33
+ ...inDecls,
34
+ decl,
35
+ ]), value);
36
+ export const resolveTypeArgumentsInEnumDecl = (args, decl, inDecl) => EnumDecl(decl.sourceUrl, {
34
37
  name: decl.name,
35
38
  comment: decl.comment,
36
39
  isDeprecated: decl.isDeprecated,
37
- values: () => resolveTypeArgumentsInEnumType(args, decl.type.value).values,
40
+ values: () => resolveTypeArgumentsInEnumType(args, decl.type.value, [...inDecl, decl]).values,
38
41
  });
39
42
  export const serializeEnumDecl = decl => ({
40
43
  ...decl,
41
44
  type: serializeEnumType(decl.type.value),
42
45
  parameters: decl.parameters.map(param => serializeTypeParameter(param)),
43
46
  });
44
- export const getReferencesForEnumDecl = (decl, value) => getReferencesForEnumType(decl.type.value, value);
47
+ export const getReferencesForEnumDecl = (decl, value, inDecl) => getReferencesForEnumType(decl.type.value, value, [...inDecl, decl]);
45
48
  export const cases = (decl) => Object.values(decl.type.value.values);
@@ -3,7 +3,7 @@ import type { GetNestedDeclarations, GetReferences, Predicate, Serializer, TypeA
3
3
  import { NodeKind } from "../Node.ts";
4
4
  import type { TypeParameter } from "../TypeParameter.ts";
5
5
  import type { Type } from "../types/Type.ts";
6
- import type { BaseDecl, TypeArguments } from "./Declaration.ts";
6
+ import type { BaseDecl, Decl, TypeArguments } from "./Declaration.ts";
7
7
  export interface TypeAliasDecl<Name extends string = string, T extends Type = Type, Params extends TypeParameter[] = TypeParameter[]> extends BaseDecl<Name, Params> {
8
8
  kind: NodeKind["TypeAliasDecl"];
9
9
  type: Lazy<T>;
@@ -26,7 +26,7 @@ export declare const TypeAliasDecl: <Name extends string, T extends Type>(source
26
26
  export { TypeAliasDecl as TypeAlias };
27
27
  export declare const isTypeAliasDecl: Predicate<TypeAliasDecl>;
28
28
  export declare const getNestedDeclarationsInTypeAliasDecl: GetNestedDeclarations<TypeAliasDecl>;
29
- export declare const validateTypeAliasDecl: <Params extends TypeParameter[]>(helpers: Validators, decl: TypeAliasDecl<string, Type, Params>, args: TypeArguments<Params>, value: unknown) => Error[];
29
+ export declare const validateTypeAliasDecl: <Params extends TypeParameter[]>(helpers: Validators, inDecls: Decl[], decl: TypeAliasDecl<string, Type, Params>, args: TypeArguments<Params>, value: unknown) => Error[];
30
30
  export declare const resolveTypeArgumentsInTypeAliasDecl: TypeArgumentsResolver<TypeAliasDecl>;
31
31
  export declare const serializeTypeAliasDecl: Serializer<TypeAliasDecl>;
32
32
  export declare const getReferencesForTypeAliasDecl: GetReferences<TypeAliasDecl>;
@@ -27,14 +27,14 @@ export const TypeAliasDecl = (sourceUrl, options) => {
27
27
  export { TypeAliasDecl as TypeAlias };
28
28
  export const isTypeAliasDecl = node => node.kind === NodeKind.TypeAliasDecl;
29
29
  export const getNestedDeclarationsInTypeAliasDecl = (addedDecls, decl) => getNestedDeclarations(addedDecls, decl.type.value, decl);
30
- export const validateTypeAliasDecl = ((helpers, decl, args, value) => validateType(helpers, resolveTypeArguments(getTypeArgumentsRecord(decl, args), decl.type.value), value));
31
- export const resolveTypeArgumentsInTypeAliasDecl = (args, decl) => TypeAliasDecl(decl.sourceUrl, {
30
+ export const validateTypeAliasDecl = ((helpers, inDecls, decl, args, value) => validateType(helpers, [...inDecls, decl], resolveTypeArguments(getTypeArgumentsRecord(decl, args), decl.type.value, [...inDecls, decl]), value));
31
+ export const resolveTypeArgumentsInTypeAliasDecl = (args, decl, inDecl) => TypeAliasDecl(decl.sourceUrl, {
32
32
  ...decl,
33
- type: () => resolveTypeArguments(args, decl.type.value),
33
+ type: () => resolveTypeArguments(args, decl.type.value, [...inDecl, decl]),
34
34
  });
35
35
  export const serializeTypeAliasDecl = type => ({
36
36
  ...type,
37
37
  type: serializeNode(type.type.value),
38
38
  parameters: type.parameters.map(param => serializeTypeParameter(param)),
39
39
  });
40
- export const getReferencesForTypeAliasDecl = (decl, value) => getReferences(decl.type.value, value);
40
+ export const getReferencesForTypeAliasDecl = (decl, value, inDecl) => getReferences(decl.type.value, value, [...inDecl, decl]);
@@ -15,21 +15,21 @@ export const ArrayType = (items, options = {}) => ({
15
15
  export { ArrayType as Array };
16
16
  export const isArrayType = node => node.kind === NodeKind.ArrayType;
17
17
  export const getNestedDeclarationsInArrayType = (addedDecls, type, parentDecl) => getNestedDeclarations(addedDecls, type.items, parentDecl);
18
- export const validateArrayType = (helpers, type, value) => {
18
+ export const validateArrayType = (helpers, inDecls, type, value) => {
19
19
  if (!Array.isArray(value)) {
20
20
  return [TypeError(`expected an array, but got ${json(value, helpers.useStyling)}`)];
21
21
  }
22
22
  return parallelizeErrors([
23
23
  ...validateArrayConstraints(type, value),
24
- ...value.map((item, index) => wrapErrorsIfAny(`at index ${key(index.toString(), helpers.useStyling)}`, validateType(helpers, type.items, item))),
24
+ ...value.map((item, index) => wrapErrorsIfAny(`at index ${key(index.toString(), helpers.useStyling)}`, validateType(helpers, inDecls, type.items, item))),
25
25
  ]);
26
26
  };
27
- export const resolveTypeArgumentsInArrayType = (args, type) => ArrayType(resolveTypeArguments(args, type.items), {
27
+ export const resolveTypeArgumentsInArrayType = (args, type, inDecl) => ArrayType(resolveTypeArguments(args, type.items, inDecl), {
28
28
  ...type,
29
29
  });
30
30
  export const serializeArrayType = type => ({
31
31
  ...type,
32
32
  items: serializeNode(type.items),
33
33
  });
34
- export const getReferencesForArrayType = (type, value) => Array.isArray(value) ? value.flatMap(item => getReferences(type.items, item)) : [];
34
+ export const getReferencesForArrayType = (type, value, inDecl) => Array.isArray(value) ? value.flatMap(item => getReferences(type.items, item, inDecl)) : [];
35
35
  export const formatArrayValue = (type, value) => Array.isArray(value) ? value.map(item => formatValue(type.items, item)) : value;
@@ -10,7 +10,7 @@ export const EnumType = (values) => ({
10
10
  });
11
11
  export const isEnumType = node => node.kind === NodeKind.EnumType;
12
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
- export const validateEnumType = (helpers, type, value) => {
13
+ export const validateEnumType = (helpers, inDecls, 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)}`)];
16
16
  }
@@ -42,16 +42,16 @@ export const validateEnumType = (helpers, type, value) => {
42
42
  ];
43
43
  }
44
44
  return parallelizeErrors([
45
- wrapErrorsIfAny(`at enum case ${key(`"${caseName}"`, helpers.useStyling)}`, validateType(helpers, associatedType, value[caseName])),
45
+ wrapErrorsIfAny(`at enum case ${key(`"${caseName}"`, helpers.useStyling)}`, validateType(helpers, inDecls, associatedType, value[caseName])),
46
46
  ]);
47
47
  }
48
48
  return [];
49
49
  };
50
- export const resolveTypeArgumentsInEnumType = (args, type) => EnumType(Object.fromEntries(Object.entries(type.values).map(([key, { type, ...caseMember }]) => [
50
+ export const resolveTypeArgumentsInEnumType = (args, type, inDecl) => EnumType(Object.fromEntries(Object.entries(type.values).map(([key, { type, ...caseMember }]) => [
51
51
  key,
52
52
  {
53
53
  ...caseMember,
54
- type: type === null ? null : resolveTypeArguments(args, type),
54
+ type: type === null ? null : resolveTypeArguments(args, type, inDecl),
55
55
  },
56
56
  ])));
57
57
  export const EnumCaseDecl = (options) => ({
@@ -69,7 +69,7 @@ export const serializeEnumType = type => ({
69
69
  },
70
70
  ])),
71
71
  });
72
- export const getReferencesForEnumType = (type, value) => {
72
+ export const getReferencesForEnumType = (type, value, inDecl) => {
73
73
  if (typeof value !== "object" ||
74
74
  value === null ||
75
75
  Array.isArray(value) ||
@@ -82,7 +82,7 @@ export const getReferencesForEnumType = (type, value) => {
82
82
  type.values[enumCase] !== undefined &&
83
83
  type.values[enumCase].type !== null &&
84
84
  enumCase in value
85
- ? getReferences(type.values[enumCase].type, value[enumCase])
85
+ ? getReferences(type.values[enumCase].type, value[enumCase], inDecl)
86
86
  : [];
87
87
  };
88
88
  export const formatEnumType = (type, value) => {
@@ -26,7 +26,7 @@ export const ObjectType = (properties, options = {}) => {
26
26
  export { ObjectType as Object };
27
27
  export const isObjectType = node => node.kind === NodeKind.ObjectType;
28
28
  export const getNestedDeclarationsInObjectType = (addedDecls, type, parentDecl) => Object.values(type.properties).reduce((acc, prop) => getNestedDeclarations(acc, prop.type, parentDecl), addedDecls);
29
- export const validateObjectType = (helpers, type, value) => {
29
+ export const validateObjectType = (helpers, inDecls, 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)}`)];
32
32
  }
@@ -40,13 +40,13 @@ export const validateObjectType = (helpers, type, value) => {
40
40
  return TypeError(`missing required property ${keyColor(`"${key}"`, helpers.useStyling)}`);
41
41
  }
42
42
  else if (prop.isRequired || value[key] !== undefined) {
43
- return wrapErrorsIfAny(`at object key ${keyColor(`"${key}"`, helpers.useStyling)}`, validateType(helpers, prop.type, value[key]));
43
+ return wrapErrorsIfAny(`at object key ${keyColor(`"${key}"`, helpers.useStyling)}`, validateType(helpers, inDecls, prop.type, value[key]));
44
44
  }
45
45
  return undefined;
46
46
  }),
47
47
  ]);
48
48
  };
49
- export const resolveTypeArgumentsInObjectType = (args, type) => ObjectType(Object.fromEntries(Object.entries(type.properties).map(([key, config]) => [key, { ...config, type: resolveTypeArguments(args, config.type) }])), {
49
+ export const resolveTypeArgumentsInObjectType = (args, type, inDecl) => ObjectType(Object.fromEntries(Object.entries(type.properties).map(([key, config]) => [key, { ...config, type: resolveTypeArguments(args, config.type, inDecl) }])), {
50
50
  ...type,
51
51
  });
52
52
  const MemberDecl = (isRequired, type, comment, isDeprecated) => ({
@@ -68,8 +68,8 @@ export const serializeObjectType = (type) => ({
68
68
  },
69
69
  ])),
70
70
  });
71
- export const getReferencesForObjectType = (type, value) => typeof value === "object" && value !== null
72
- ? Object.entries(value).flatMap(([key, propValue]) => type.properties[key] ? getReferences(type.properties[key].type, propValue) : [])
71
+ export const getReferencesForObjectType = (type, value, inDecl) => typeof value === "object" && value !== null
72
+ ? Object.entries(value).flatMap(([key, propValue]) => type.properties[key] ? getReferences(type.properties[key].type, propValue, inDecl) : [])
73
73
  : [];
74
74
  export const formatObjectValue = (type, value) => typeof value === "object" && value !== null && !Array.isArray(value)
75
75
  ? sortObjectKeys(Object.fromEntries(Object.entries(value).map(([key, item]) => [
@@ -6,7 +6,7 @@ export const BooleanType = () => ({
6
6
  export { BooleanType as Boolean };
7
7
  export const isBooleanType = node => node.kind === NodeKind.BooleanType;
8
8
  export const getNestedDeclarationsInBooleanType = addedDecls => addedDecls;
9
- export const validateBooleanType = (helpers, _type, value) => {
9
+ export const validateBooleanType = (helpers, _inDecls, _type, value) => {
10
10
  if (typeof value !== "boolean") {
11
11
  return [TypeError(`expected a boolean value, but got ${json(value, helpers.useStyling)}`)];
12
12
  }
@@ -8,7 +8,7 @@ export const DateType = (options) => ({
8
8
  export { DateType as Date };
9
9
  export const isDateType = node => node.kind === NodeKind.DateType;
10
10
  export const getNestedDeclarationsInDateType = addedDecls => addedDecls;
11
- export const validateDateType = (helpers, type, value) => {
11
+ export const validateDateType = (helpers, _inDecls, type, value) => {
12
12
  if (typeof value !== "string") {
13
13
  return [TypeError(`expected a string, but got ${json(value, helpers.useStyling)}`)];
14
14
  }
@@ -8,7 +8,7 @@ export const FloatType = (options = {}) => ({
8
8
  export { FloatType as Float };
9
9
  export const isFloatType = node => node.kind === NodeKind.FloatType;
10
10
  export const getNestedDeclarationsInFloatType = addedDecls => addedDecls;
11
- export const validateFloatType = (helpers, type, value) => {
11
+ export const validateFloatType = (helpers, _inDecls, type, value) => {
12
12
  if (typeof value !== "number") {
13
13
  return [
14
14
  TypeError(`expected a floating-point number, but got ${json(value, helpers.useStyling)}`),
@@ -12,7 +12,7 @@ export const IntegerType = (options = {}) => ({
12
12
  export { IntegerType as Integer };
13
13
  export const isIntegerType = node => node.kind === NodeKind.IntegerType;
14
14
  export const getNestedDeclarationsInIntegerType = addedDecls => addedDecls;
15
- export const validateIntegerType = (helpers, type, value) => {
15
+ export const validateIntegerType = (helpers, _inDecls, type, value) => {
16
16
  if (typeof value !== "number" || !Number.isInteger(value)) {
17
17
  return [TypeError(`expected an integer, but got ${json(value, helpers.useStyling)}`)];
18
18
  }
@@ -8,7 +8,7 @@ export const StringType = (options = {}) => ({
8
8
  export { StringType as String };
9
9
  export const isStringType = node => node.kind === NodeKind.StringType;
10
10
  export const getNestedDeclarationsInStringType = addedDecls => addedDecls;
11
- export const validateStringType = (helpers, type, value) => {
11
+ export const validateStringType = (helpers, _inDecls, type, value) => {
12
12
  if (typeof value !== "string") {
13
13
  return [TypeError(`expected a string, but got ${json(value, helpers.useStyling)}`)];
14
14
  }
@@ -1,7 +1,7 @@
1
1
  import type { SerializedIncludeIdentifierType } from "../../../../shared/schema/types/IncludeIdentifierType.ts";
2
- import type { IncludableDeclP, TypeArguments } from "../../declarations/Declaration.ts";
2
+ import type { Decl, IncludableDeclP, TypeArguments } from "../../declarations/Declaration.ts";
3
3
  import type { EnumDecl } from "../../declarations/EnumDecl.ts";
4
- import type { TypeAliasDecl } from "../../declarations/TypeAliasDecl.ts";
4
+ import { type TypeAliasDecl } from "../../declarations/TypeAliasDecl.ts";
5
5
  import type { GetNestedDeclarations, GetReferences, Predicate, SerializedTypeParameters, Validator } from "../../Node.ts";
6
6
  import { NodeKind } from "../../Node.ts";
7
7
  import type { TypeParameter } from "../../TypeParameter.ts";
@@ -20,7 +20,7 @@ export { IncludeIdentifierType as IncludeIdentifier };
20
20
  export declare const isIncludeIdentifierType: Predicate<IncludeIdentifierType>;
21
21
  export declare const getNestedDeclarationsInIncludeIdentifierType: GetNestedDeclarations<IncludeIdentifierType>;
22
22
  export declare const validateIncludeIdentifierType: Validator<IncludeIdentifierType>;
23
- export declare const resolveTypeArgumentsInIncludeIdentifierType: <T extends IncludeIdentifierType>(args: Record<string, Type>, type: T) => T extends IncludeIdentifierType<[], IncludableDeclP<[]>> ? T : Type;
23
+ export declare const resolveTypeArgumentsInIncludeIdentifierType: <T extends IncludeIdentifierType>(args: Record<string, Type>, type: T, inDecl: Decl[]) => (T & IncludeIdentifierType<[], IncludableDeclP<[]>>) | (T extends IncludeIdentifierType<[], IncludableDeclP<[]>> ? T : Type);
24
24
  export declare const serializeIncludeIdentifierType: <Params extends TypeParameter[] = TypeParameter<string, Type>[], T extends TConstraint<Params> = TConstraint<Params>>(type: IncludeIdentifierType<Params, T>) => SerializedIncludeIdentifierType<SerializedTypeParameters<Params>>;
25
25
  export declare const getReferencesForIncludeIdentifierType: GetReferences<IncludeIdentifierType>;
26
26
  export declare const formatIncludeIdentifierValue: StructureFormatter<IncludeIdentifierType>;
@@ -1,7 +1,9 @@
1
- import { getTypeArgumentsRecord } from "../../declarations/Declaration.js";
1
+ import { getTypeArgumentsRecord, isDeclWithoutTypeParameters, } from "../../declarations/Declaration.js";
2
+ import { isTypeAliasDecl } from "../../declarations/TypeAliasDecl.js";
2
3
  import { getNestedDeclarations, getReferences, NodeKind, resolveTypeArguments, serializeNode, validateDecl, } from "../../Node.js";
3
4
  import { formatEnumType } from "../generic/EnumType.js";
4
5
  import { formatValue } from "../Type.js";
6
+ import { isTypeArgumentType } from "./TypeArgumentType.js";
5
7
  export const GenIncludeIdentifierType = (reference, args) => ({
6
8
  kind: NodeKind.IncludeIdentifierType,
7
9
  reference,
@@ -19,16 +21,38 @@ const isNoGenericIncludeIdentifierType = (node) => node.args.length === 0 && nod
19
21
  export const getNestedDeclarationsInIncludeIdentifierType = (addedDecls, type, parentDecl) => type.args.reduce((accAddedDecls, arg) => getNestedDeclarations(accAddedDecls, arg, parentDecl), addedDecls.includes(type.reference)
20
22
  ? addedDecls
21
23
  : getNestedDeclarations(addedDecls, type.reference, parentDecl));
22
- export const validateIncludeIdentifierType = (helpers, type, value) => validateDecl(helpers, type.reference, type.args, value);
23
- export const resolveTypeArgumentsInIncludeIdentifierType = ((args, type) => (isNoGenericIncludeIdentifierType(type)
24
- ? type
25
- : resolveTypeArguments(getTypeArgumentsRecord(type.reference, type.args.map(arg => resolveTypeArguments(args, arg))), type.reference).type.value));
24
+ export const validateIncludeIdentifierType = (helpers, inDecls, type, value) => validateDecl(helpers, inDecls, type.reference, type.args, value);
25
+ export const resolveTypeArgumentsInIncludeIdentifierType = ((args, type, inDecl) => {
26
+ if (isNoGenericIncludeIdentifierType(type)) {
27
+ return type;
28
+ }
29
+ else {
30
+ const parentDecl = inDecl[inDecl.length - 1];
31
+ const grandParentDecl = inDecl[inDecl.length - 2];
32
+ if (grandParentDecl?.name === "AdventurePointsDependingOnActiveInstancesMultiplier") {
33
+ console.log(type.args.every((arg, argIndex) => isTypeArgumentType(arg) && parentDecl?.parameters[argIndex] === arg.argument));
34
+ }
35
+ if (type.reference === parentDecl &&
36
+ parentDecl.parameters.length > 0 &&
37
+ grandParentDecl &&
38
+ isDeclWithoutTypeParameters(grandParentDecl) &&
39
+ isTypeAliasDecl(grandParentDecl) &&
40
+ type.args.every((arg, argIndex) => isTypeArgumentType(arg) && parentDecl.parameters[argIndex] === arg.argument)) {
41
+ const grandParentDeclType = grandParentDecl.type.value;
42
+ if (isIncludeIdentifierType(grandParentDeclType) &&
43
+ grandParentDeclType.reference === type.reference) {
44
+ return IncludeIdentifierType(grandParentDecl);
45
+ }
46
+ }
47
+ return resolveTypeArguments(getTypeArgumentsRecord(type.reference, type.args.map(arg => resolveTypeArguments(args, arg, inDecl))), type.reference, inDecl).type.value;
48
+ }
49
+ });
26
50
  export const serializeIncludeIdentifierType = ((type) => ({
27
51
  ...type,
28
52
  reference: type.reference.name,
29
53
  args: type.args.map(arg => serializeNode(arg)),
30
54
  }));
31
- export const getReferencesForIncludeIdentifierType = (type, value) => getReferences(resolveTypeArguments(getTypeArgumentsRecord(type.reference, type.args), type.reference), value);
55
+ export const getReferencesForIncludeIdentifierType = (type, value, inDecl) => getReferences(resolveTypeArguments(getTypeArgumentsRecord(type.reference, type.args), type.reference, inDecl), value, inDecl);
32
56
  export const formatIncludeIdentifierValue = (type, value) => {
33
57
  switch (type.reference.kind) {
34
58
  case NodeKind.TypeAliasDecl:
@@ -27,18 +27,18 @@ const _NestedEntityMapType = (options) => {
27
27
  };
28
28
  export const isNestedEntityMapType = node => node.kind === NodeKind.NestedEntityMapType;
29
29
  export const getNestedDeclarationsInNestedEntityMapType = (addedDecls, type, parentDecl) => getNestedDeclarations(getNestedDeclarations(addedDecls, type.secondaryEntity, parentDecl), type.type.value, parentDecl);
30
- export const validateNestedEntityMapType = (helpers, type, value) => {
30
+ export const validateNestedEntityMapType = (helpers, inDecls, 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)}`)];
33
33
  }
34
- return parallelizeErrors(Object.keys(value).map(key => wrapErrorsIfAny(`at nested entity map ${entity(`"${type.name}"`, helpers.useStyling)} at key ${keyColor(`"${key}"`, helpers.useStyling)}`, validateType(helpers, type.type.value, value[key]).concat(helpers.checkReferentialIntegrity({
34
+ return parallelizeErrors(Object.keys(value).map(key => wrapErrorsIfAny(`at nested entity map ${entity(`"${type.name}"`, helpers.useStyling)} at key ${keyColor(`"${key}"`, helpers.useStyling)}`, validateType(helpers, inDecls, type.type.value, value[key]).concat(helpers.checkReferentialIntegrity({
35
35
  name: type.secondaryEntity.name,
36
36
  value: key,
37
37
  })))));
38
38
  };
39
- export const resolveTypeArgumentsInNestedEntityMapType = (args, type) => _NestedEntityMapType({
39
+ export const resolveTypeArgumentsInNestedEntityMapType = (args, type, inDecl) => _NestedEntityMapType({
40
40
  ...type,
41
- type: () => resolveTypeArguments(args, type.type.value),
41
+ type: () => resolveTypeArguments(args, type.type.value, inDecl),
42
42
  });
43
43
  export const serializeNestedEntityMapType = type => ({
44
44
  ...type,
@@ -47,11 +47,11 @@ export const serializeNestedEntityMapType = type => ({
47
47
  ? serializeObjectType(type.type.value)
48
48
  : serializeIncludeIdentifierType(type.type.value),
49
49
  });
50
- export const getReferencesForNestedEntityMapType = (type, value) => typeof value === "object" && value !== null && !Array.isArray(value)
50
+ export const getReferencesForNestedEntityMapType = (type, value, inDecl) => typeof value === "object" && value !== null && !Array.isArray(value)
51
51
  ? Object.values(value)
52
52
  .flatMap(item => isObjectType(type.type.value)
53
- ? getReferencesForObjectType(type.type.value, item)
54
- : getReferencesForIncludeIdentifierType(type.type.value, item))
53
+ ? getReferencesForObjectType(type.type.value, item, inDecl)
54
+ : getReferencesForIncludeIdentifierType(type.type.value, item, inDecl))
55
55
  .concat(Object.keys(value))
56
56
  : [];
57
57
  export const formatNestedEntityMapValue = (type, value) => isObjectType(type.type.value)
@@ -9,7 +9,7 @@ export const isReferenceIdentifierType = (node) => node.kind === NodeKind.Refere
9
9
  export const getNestedDeclarationsInReferenceIdentifierType = (addedDecls, type, parentDecl) => addedDecls.includes(type.entity)
10
10
  ? addedDecls
11
11
  : getNestedDeclarations(addedDecls, type.entity, parentDecl);
12
- export const validateReferenceIdentifierType = (helpers, type, value) => validateType(helpers, createEntityIdentifierType(), value).concat(helpers.checkReferentialIntegrity({
12
+ export const validateReferenceIdentifierType = (helpers, inDecls, type, value) => validateType(helpers, inDecls, createEntityIdentifierType(), value).concat(helpers.checkReferentialIntegrity({
13
13
  name: type.entity.name,
14
14
  value: value,
15
15
  }));
@@ -7,7 +7,7 @@ export const TypeArgumentType = (argument) => ({
7
7
  export { TypeArgumentType as TypeArgument };
8
8
  export const isTypeArgumentType = (node) => node.kind === NodeKind.TypeArgumentType;
9
9
  export const getNestedDeclarationsInTypeArgumentType = addedDecls => addedDecls;
10
- export const validateTypeArgumentType = (_helpers, type) => {
10
+ export const validateTypeArgumentType = (_helpers, _inDecls, type) => {
11
11
  throw new TypeError(`generic argument "${type.argument.name}" has not been replaced with a concrete type`);
12
12
  };
13
13
  export const resolveTypeArgumentsInTypeArgumentType = ((args, type) => {
@@ -27,7 +27,7 @@ export const createInstance = async (dataRoot, localeEntity, instancesByEntityNa
27
27
  }
28
28
  };
29
29
  export const checkUpdateInstancePossible = (instancesByEntityName, entity, instanceContent) => {
30
- const validationErrors = validateEntityDecl(createValidators(instancesByEntityName, false), entity, instanceContent);
30
+ const validationErrors = validateEntityDecl(createValidators(instancesByEntityName, false), [], entity, instanceContent);
31
31
  if (validationErrors.length > 0) {
32
32
  return error([400, validationErrors.map(getErrorMessageForDisplay).join("\n\n")]);
33
33
  }
@@ -58,13 +58,13 @@ export const updateReferencesToInstances = (entitiesByName, referencesToInstance
58
58
  const entity = entitiesByName[entityName];
59
59
  if (entity) {
60
60
  if (oldInstance === undefined) {
61
- return addReferences(referencesToInstances, getReferencesForEntityDecl(entity, newInstance), instanceId);
61
+ return addReferences(referencesToInstances, getReferencesForEntityDecl(entity, newInstance, []), instanceId);
62
62
  }
63
63
  if (newInstance === undefined) {
64
- return removeReferences(referencesToInstances, getReferencesForEntityDecl(entity, oldInstance), instanceId);
64
+ return removeReferences(referencesToInstances, getReferencesForEntityDecl(entity, oldInstance, []), instanceId);
65
65
  }
66
- const oldReferences = getReferencesForEntityDecl(entity, oldInstance);
67
- const newReferences = getReferencesForEntityDecl(entity, newInstance);
66
+ const oldReferences = getReferencesForEntityDecl(entity, oldInstance, []);
67
+ const newReferences = getReferencesForEntityDecl(entity, newInstance, []);
68
68
  const { added, removed } = difference(oldReferences, newReferences);
69
69
  return removeReferences(addReferences(referencesToInstances, added, instanceId), removed, instanceId);
70
70
  }
@@ -24,11 +24,17 @@ type AttributedStringMarkdownNode = {
24
24
  attributes: Record<string, string | number | boolean>;
25
25
  content: InlineMarkdownNode[];
26
26
  };
27
+ type SuperscriptInlineNode = {
28
+ kind: "superscript";
29
+ content: InlineMarkdownNode[];
30
+ };
27
31
  type FootnoteRefInlineNode = {
28
32
  kind: "footnoteRef";
29
33
  label: string;
30
34
  };
31
- export type InlineMarkdownNode = BoldMarkdownNode | ItalicMarkdownNode | CodeMarkdownNode | LinkMarkdownNode | AttributedStringMarkdownNode | TextNode | FootnoteRefInlineNode;
35
+ export type InlineMarkdownNode = BoldMarkdownNode | ItalicMarkdownNode | CodeMarkdownNode | LinkMarkdownNode | AttributedStringMarkdownNode | TextNode | SuperscriptInlineNode | FootnoteRefInlineNode;
36
+ export declare const parseInlineMarkdown: (text: string) => InlineMarkdownNode[];
37
+ export declare const parseInlineMarkdownForSyntaxHighlighting: (text: string) => InlineMarkdownNode[];
32
38
  export declare const checkTableRowsAreSections: (rows: TableRowBlockNode[] | TableSectionBlockNode[]) => rows is TableSectionBlockNode[];
33
39
  export declare const syntaxNodeToString: (node: BlockSyntaxMarkdownNode) => string;
34
40
  export type ParagraphBlockNode = {
@@ -150,6 +150,17 @@ const attributedRule = {
150
150
  };
151
151
  },
152
152
  };
153
+ const superscriptRule = {
154
+ pattern: /\^(.*?)\^/,
155
+ map: (result, parseInside) => ({
156
+ kind: "superscript",
157
+ content: parseInside(result[1] ?? ""),
158
+ }),
159
+ mapHighlighting: (result, parseInside) => ({
160
+ kind: "superscript",
161
+ content: [textNode("^"), ...parseInside(result[1] ?? ""), textNode("^")],
162
+ }),
163
+ };
153
164
  const footnoteRefRule = {
154
165
  pattern: /(?<!\\)\[\^([a-zA-Z0-9*]+?)\]/,
155
166
  map: ([_match, label = ""]) => ({
@@ -185,6 +196,7 @@ const inlineRules = [
185
196
  italicWithBoldRule,
186
197
  boldRule,
187
198
  italicRule,
199
+ superscriptRule,
188
200
  footnoteRefRule,
189
201
  textRule,
190
202
  ];
@@ -210,7 +222,8 @@ const parseForInlineRules = (rules, text, forSyntaxHighlighting) => {
210
222
  return parseForInlineRules(rules.slice(1), text, forSyntaxHighlighting);
211
223
  }
212
224
  };
213
- const parseInlineMarkdown = (text, forSyntaxHighlighting) => parseForInlineRules(inlineRules, text, forSyntaxHighlighting);
225
+ export const parseInlineMarkdown = (text) => parseForInlineRules(inlineRules, text, false);
226
+ export const parseInlineMarkdownForSyntaxHighlighting = (text) => reduceSyntaxNodes(parseForInlineRules(inlineRules, text, true));
214
227
  const nodesForTrailingWhitespace = (text) => {
215
228
  const trailingWhitespace = text ?? "";
216
229
  return trailingWhitespace.length === 0 ? [] : [textNode(trailingWhitespace)];
@@ -222,7 +235,7 @@ const listRule = {
222
235
  ordered: /^\d+\. /.test(result[0]),
223
236
  content: (result[1] ?? "").split("\n").map(item => ({
224
237
  kind: "listItem",
225
- content: parseInlineMarkdown(item.replace(/^\d+\. |[-*] /, ""), false),
238
+ content: parseInlineMarkdown(item.replace(/^\d+\. |[-*] /, "")),
226
239
  })),
227
240
  }),
228
241
  mapHighlighting: result => [
@@ -231,7 +244,7 @@ const listRule = {
231
244
  kind: "listItemMarker",
232
245
  content: /^(\d+\. |[-*] )/.exec(item)?.[1] ?? "",
233
246
  },
234
- ...parseInlineMarkdown(item.replace(/^\d+\. |[-*] /, ""), true),
247
+ ...parseInlineMarkdownForSyntaxHighlighting(item.replace(/^\d+\. |[-*] /, "")),
235
248
  ...(index < array.length - 1 ? [textNode("\n")] : []),
236
249
  ]),
237
250
  ...nodesForTrailingWhitespace(result[2]),
@@ -241,10 +254,10 @@ const paragraphRule = {
241
254
  pattern: /^((?:[^\n]+?)(?:\n[^\n]+?)*)(\n{2,}|\s*$)/,
242
255
  map: ([_res, content = "", _trailingWhitespace]) => ({
243
256
  kind: "paragraph",
244
- content: parseInlineMarkdown(content, false),
257
+ content: parseInlineMarkdown(content),
245
258
  }),
246
259
  mapHighlighting: ([_res, content = "", trailingWhitespace]) => [
247
- ...parseInlineMarkdown(content, true),
260
+ ...parseInlineMarkdownForSyntaxHighlighting(content),
248
261
  ...nodesForTrailingWhitespace(trailingWhitespace),
249
262
  ],
250
263
  };
@@ -253,11 +266,11 @@ const headingRule = {
253
266
  map: result => ({
254
267
  kind: "heading",
255
268
  level: result[1]?.length ?? 1,
256
- content: parseInlineMarkdown(result[3] ?? "", false),
269
+ content: parseInlineMarkdown(result[3] ?? ""),
257
270
  }),
258
271
  mapHighlighting: result => [
259
272
  { kind: "headingMarker", content: (result[1] ?? "") + (result[2] ?? "") },
260
- ...parseInlineMarkdown(result[3] ?? "", true),
273
+ ...parseInlineMarkdownForSyntaxHighlighting(result[3] ?? ""),
261
274
  ...nodesForTrailingWhitespace(result[4]),
262
275
  ],
263
276
  };
@@ -279,7 +292,7 @@ const parseContentRow = (row) => row
279
292
  omitUndefinedKeys({
280
293
  kind: "tableCell",
281
294
  colSpan: colSpan !== undefined && colSpan > 1 ? colSpan : undefined,
282
- content: parseInlineMarkdown(segment.trim(), false),
295
+ content: parseInlineMarkdown(segment.trim()),
283
296
  }),
284
297
  ];
285
298
  }
@@ -287,7 +300,7 @@ const parseContentRow = (row) => row
287
300
  }, []);
288
301
  const parseContentRowForSyntaxHighlighting = (row) => row.split(/(\|+)/).reduce((acc, segment, index) => {
289
302
  if (index % 2 === 0) {
290
- return [...acc, ...parseInlineMarkdown(segment, true)];
303
+ return [...acc, ...parseInlineMarkdownForSyntaxHighlighting(segment)];
291
304
  }
292
305
  else {
293
306
  return [...acc, tableMarker(segment)];
@@ -313,7 +326,9 @@ const tableRule = {
313
326
  pattern: /^(?:(\|#)(.+?)(#\|)\n)?(\|)?(.+?(?:(?<!\\)\|.+?)+)((?<!\\)\|)?\n((?:\| *)?(?:-{3,}|:-{2,}|-{2,}:|:-+:)(?: *\| *(?:-{3,}|:-{2,}|-{2,}:|:-+:))*(?: *\|)?)((?:\n\|?.+?(?:(?<!\\)\|+.+?)*(?:(?<!\\)\|+)?)+)(\n{2,}|$)/,
314
327
  map: ([_res, _captionMarkerStart, caption, _captionMarkerEnd, _headerMarkerStart, headers, _headerMarkerEnd, bodySeparators = "", body, _trailingWhitespace,]) => omitUndefinedKeys({
315
328
  kind: "table",
316
- caption: caption !== undefined ? parseInlineMarkdown(caption.trim(), false) : undefined,
329
+ caption: caption !== undefined
330
+ ? parseInlineMarkdownForSyntaxHighlighting(caption.trim())
331
+ : undefined,
317
332
  columns: trimPipes(bodySeparators)
318
333
  .split("|")
319
334
  .map(col => omitUndefinedKeys({
@@ -387,7 +402,7 @@ const tableRule = {
387
402
  ...(caption !== undefined
388
403
  ? [
389
404
  tableMarker(captionMarkerStart ?? ""),
390
- ...parseInlineMarkdown(caption, true),
405
+ ...parseInlineMarkdownForSyntaxHighlighting(caption),
391
406
  tableMarker(captionMarkerEnd ?? ""),
392
407
  textNode("\n"),
393
408
  ]
@@ -396,8 +411,8 @@ const tableRule = {
396
411
  ...(headers
397
412
  ?.split("|")
398
413
  .flatMap((th, i) => i === 0
399
- ? parseInlineMarkdown(th, true)
400
- : [tableMarker("|"), ...parseInlineMarkdown(th, true)]) ?? []),
414
+ ? parseInlineMarkdownForSyntaxHighlighting(th)
415
+ : [tableMarker("|"), ...parseInlineMarkdownForSyntaxHighlighting(th)]) ?? []),
401
416
  tableMarker(headerMarkerEnd ?? ""),
402
417
  textNode("\n"),
403
418
  tableMarker(bodySeparators ?? ""),
@@ -439,6 +454,7 @@ export const syntaxNodeToString = (node) => {
439
454
  case "italic":
440
455
  case "link":
441
456
  case "attributed":
457
+ case "superscript":
442
458
  return node.content.map(syntaxNodeToString).join("");
443
459
  case "text":
444
460
  case "code":
@@ -461,6 +477,7 @@ const addIndentationToSyntax = (nodes, nextUpperNode) => nodes.reduce((accNodes,
461
477
  case "italic":
462
478
  case "link":
463
479
  case "attributed":
480
+ case "superscript":
464
481
  return [
465
482
  ...accNodes,
466
483
  {
@@ -516,7 +533,7 @@ const definitionListRule = {
516
533
  const terms = termsText
517
534
  .trim()
518
535
  .split("\n")
519
- .map(term => parseInlineMarkdown(term.trim(), false));
536
+ .map(term => parseInlineMarkdown(term.trim()));
520
537
  const definitions = definitionsText
521
538
  .split("\n:")
522
539
  .slice(1)
@@ -537,7 +554,7 @@ const definitionListRule = {
537
554
  const terms = termsText
538
555
  .split("\n")
539
556
  .flatMap((term, index, termArray) => [
540
- ...parseInlineMarkdown(term, true),
557
+ ...parseInlineMarkdownForSyntaxHighlighting(term),
541
558
  ...(index < termArray.length - 1 ? [textNode("\n")] : []),
542
559
  ]);
543
560
  const definitions = definitionsText
@@ -602,6 +619,7 @@ const reduceSyntaxNode = (node) => {
602
619
  case "bold":
603
620
  case "italic":
604
621
  case "link":
622
+ case "superscript":
605
623
  return { ...node, content: reduceSyntaxNodes(node.content) };
606
624
  case "code":
607
625
  case "attributed":
@@ -628,6 +646,7 @@ const syntaxNodeMergeRules = {
628
646
  headingMarker: (a, b) => ({ ...a, content: a.content + b.content }),
629
647
  sectionMarker: (a, b) => ({ ...a, content: a.content + b.content }),
630
648
  footnoteMarker: (a, b) => ({ ...a, content: a.content + b.content }),
649
+ superscript: (a, b) => ({ ...a, content: [...a.content, ...b.content] }),
631
650
  definitionMarker: (a, b) => ({ ...a, content: a.content + b.content }),
632
651
  footnoteRef: null,
633
652
  link: null,
@@ -26,7 +26,7 @@ export const Entity = () => {
26
26
  const gitClient = useContext(GitClientContext);
27
27
  const { reloadEntities } = useContext(EntitiesContext);
28
28
  const { declaration: entity, isLocaleEntity } = entityFromRoute ?? {};
29
- const [instances, reloadInstances] = useMappedAPIResource(getInstancesByEntityName, mapInstances, locales, name ?? "");
29
+ const [instances, reloadInstances] = useMappedAPIResource(getInstancesByEntityName, mapInstances, locales, entity?.name ?? "");
30
30
  const [localeInstances] = useMappedAPIResource(getLocaleInstances, localeMapper, locales, config.localeEntityName);
31
31
  useEffect(() => {
32
32
  document.title = toTitleCase(entity?.namePlural ?? name ?? "") + " — TSONDB";
@@ -39,11 +39,11 @@ export const Entity = () => {
39
39
  }
40
40
  }
41
41
  }, [created]);
42
- if (!name) {
42
+ if (entity?.name === undefined) {
43
43
  return _jsx(NotFound, {});
44
44
  }
45
- if (!entity || !instances) {
46
- return (_jsxs(Layout, { breadcrumbs: [{ url: "/", label: homeTitle }], children: [_jsxs("div", { class: "header-with-btns", children: [_jsx("h1", { children: toTitleCase(entity?.namePlural ?? name) }), _jsx("a", { class: "btn btn--primary", "aria-disabled": true, children: "Add" })] }), _jsx("p", { class: "loading", children: "Loading \u2026" })] }));
45
+ if (!instances) {
46
+ return (_jsxs(Layout, { breadcrumbs: [{ url: "/", label: homeTitle }], children: [_jsxs("div", { class: "header-with-btns", children: [_jsx("h1", { children: toTitleCase(entity.namePlural) }), _jsx("a", { class: "btn btn--primary", "aria-disabled": true, children: "Add" })] }), _jsx("p", { class: "loading", children: "Loading \u2026" })] }));
47
47
  }
48
48
  const lowerSearchText = searchText.toLowerCase();
49
49
  const filteredInstances = (searchText.length === 0
@@ -22,6 +22,8 @@ export const InlineMarkdown = ({ node }) => {
22
22
  const trailingNodes = node.content.slice(attributesEnd);
23
23
  return (_jsxs("span", { class: "attributed", ...Object.fromEntries(Object.entries(node.attributes).map(([k, v]) => [`data-${k}`, v.toString()])), children: [leadingNodes.map((inline, i) => (_jsx(InlineMarkdown, { node: inline }, i))), Array.from({ length: count }, (_, i) => (_jsxs(Fragment, { children: [_jsx("span", { class: "attributed__name", children: _jsx(InlineMarkdown, { node: attributes[i * 4] ?? emptyNode }) }), _jsx("span", { class: "attributed__separator", children: _jsx(InlineMarkdown, { node: attributes[i * 4 + 1] ?? emptyNode }) }), _jsx("span", { class: "attributed__value", children: _jsx(InlineMarkdown, { node: attributes[i * 4 + 2] ?? emptyNode }) }), i < count - 1 && (_jsx("span", { class: "attributed__separator", children: _jsx(InlineMarkdown, { node: attributes[i * 4 + 3] ?? emptyNode }) }))] }, `attr-${(i + 1).toString()}`))), trailingNodes.map((inline, i) => (_jsx(InlineMarkdown, { node: inline }, i)))] }));
24
24
  }
25
+ case "superscript":
26
+ return (_jsx("sup", { children: node.content.map((inline, i) => (_jsx(InlineMarkdown, { node: inline }, i))) }));
25
27
  case "footnoteRef": {
26
28
  const isNumeric = /^\d+$/.test(node.label);
27
29
  return (_jsx("sup", { class: "footnote-ref" + (isNumeric ? " footnote-ref--numeric" : ""), "data-reference": node.label, style: { "--label": isNumeric ? Number.parseInt(node.label) : node.label }, children: _jsx("span", { class: "footnote-label", children: node.label }) }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tsondb",
3
- "version": "0.10.1",
3
+ "version": "0.11.0",
4
4
  "description": "",
5
5
  "license": "ISC",
6
6
  "author": "Lukas Obermann",
@@ -32,19 +32,19 @@
32
32
  "release:sign": "commit-and-tag-version --sign --signoff"
33
33
  },
34
34
  "devDependencies": {
35
- "@eslint/js": "^9.36.0",
35
+ "@eslint/js": "^9.37.0",
36
36
  "@types/debug": "^4.1.12",
37
37
  "@types/express": "^5.0.3",
38
- "@types/node": "^24.6.2",
38
+ "@types/node": "^24.8.1",
39
39
  "commit-and-tag-version": "^12.6.0",
40
- "eslint": "^9.36.0",
40
+ "eslint": "^9.37.0",
41
41
  "eslint-plugin-react": "^7.37.5",
42
- "eslint-plugin-react-hooks": "^6.1.0",
42
+ "eslint-plugin-react-hooks": "^7.0.0",
43
43
  "globals": "^16.4.0",
44
44
  "prettier": "^3.6.2",
45
45
  "tsx": "^4.20.6",
46
46
  "typescript": "^5.9.3",
47
- "typescript-eslint": "^8.45.0"
47
+ "typescript-eslint": "^8.46.1"
48
48
  },
49
49
  "dependencies": {
50
50
  "@preact/signals": "^2.3.2",