tsondb 0.6.2 → 0.7.1

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.
@@ -1,6 +1,6 @@
1
- import type { DisplayNameResult } from "../../../shared/utils/displayName.ts";
2
1
  import { Lazy } from "../../../shared/utils/lazy.ts";
3
2
  import type { Leaves } from "../../../shared/utils/object.ts";
3
+ import type { DisplayNameCustomizer } from "../../utils/displayName.ts";
4
4
  import type { GetNestedDeclarations, GetReferences, Predicate, Serializer, TypeArgumentsResolver, Validator } from "../Node.ts";
5
5
  import { NodeKind } from "../Node.ts";
6
6
  import type { MemberDecl, ObjectType } from "../types/generic/ObjectType.ts";
@@ -8,12 +8,10 @@ import { StringType } from "../types/primitives/StringType.ts";
8
8
  import type { AsType } from "../types/Type.ts";
9
9
  import type { BaseDecl } from "./Declaration.ts";
10
10
  import { TypeAliasDecl } from "./TypeAliasDecl.ts";
11
- export type GenericDisplayNameFn = (instance: unknown, instanceDisplayName: string, getInstanceById: (id: string) => unknown, getDisplayNameForInstanceId: (id: string) => string | undefined, locales: string[]) => string;
12
11
  export type GenericEntityDisplayName = string | {
13
12
  pathToLocaleMap?: string;
14
13
  pathInLocaleMap?: string;
15
14
  } | null;
16
- export type DisplayNameFn<T extends ObjectType = ObjectType> = (instance: AsType<T>, instanceDisplayName: string, instanceDisplayNameLocaleId: string | undefined, getInstanceById: (id: string) => unknown, getDisplayNameForInstanceId: (id: string) => string | undefined, locales: string[]) => DisplayNameResult;
17
15
  export type EntityDisplayName<T extends TConstraint> = Leaves<AsType<ObjectType<T>>> | {
18
16
  /**
19
17
  * @default "translations"
@@ -34,7 +32,7 @@ export interface EntityDecl<Name extends string = string, T extends TConstraint
34
32
  * @default "name"
35
33
  */
36
34
  displayName?: EntityDisplayName<T>;
37
- displayNameCustomizer?: DisplayNameFn<ObjectType<T>>;
35
+ displayNameCustomizer?: DisplayNameCustomizer<ObjectType<T>>;
38
36
  isDeprecated?: boolean;
39
37
  }
40
38
  export interface EntityDeclWithParentReference<Name extends string = string, T extends TConstraint = TConstraint, FK extends keyof T & string = keyof T & string> extends EntityDecl<Name, T, FK> {
@@ -49,7 +47,7 @@ export declare const EntityDecl: {
49
47
  * @default "name"
50
48
  */
51
49
  displayName?: EntityDisplayName<T>;
52
- displayNameCustomizer?: DisplayNameFn<ObjectType<T>>;
50
+ displayNameCustomizer?: DisplayNameCustomizer<ObjectType<T>>;
53
51
  isDeprecated?: boolean;
54
52
  }): EntityDecl<Name, T, undefined>;
55
53
  <Name extends string, T extends TConstraint, FK extends keyof T & string>(sourceUrl: string, options: {
@@ -62,7 +60,7 @@ export declare const EntityDecl: {
62
60
  * @default "name"
63
61
  */
64
62
  displayName?: EntityDisplayName<T>;
65
- displayNameCustomizer?: DisplayNameFn<ObjectType<T>>;
63
+ displayNameCustomizer?: DisplayNameCustomizer<ObjectType<T>>;
66
64
  isDeprecated?: boolean;
67
65
  }): EntityDecl<Name, T, FK>;
68
66
  };
@@ -7,6 +7,7 @@ import { isEnumDecl } from "../../schema/declarations/EnumDecl.js";
7
7
  import { isTypeAliasDecl } from "../../schema/declarations/TypeAliasDecl.js";
8
8
  import { serializeNode } from "../../schema/index.js";
9
9
  import { getChildInstances } from "../../utils/childInstances.js";
10
+ import { createChildInstancesForInstanceIdGetter } from "../utils/childInstances.js";
10
11
  import { createInstance, deleteInstance, updateInstance } from "../utils/instanceOperations.js";
11
12
  const debug = Debug("tsondb:server:api:declarations");
12
13
  export const declarationsApi = express.Router();
@@ -61,9 +62,10 @@ declarationsApi.get("/:name/instances", (req, res) => {
61
62
  res.status(400).send(`Declaration "${decl.name}" is not an entity`);
62
63
  return;
63
64
  }
65
+ const getChildInstancesForInstanceId = createChildInstancesForInstanceIdGetter(req);
64
66
  const body = {
65
67
  instances: req.instancesByEntityName[req.params.name]
66
- ?.map(instanceContainer => getInstanceContainerOverview(decl, instanceContainer, req.getInstanceById, req.locales))
68
+ ?.map(instanceContainer => getInstanceContainerOverview(decl, instanceContainer, req.getInstanceById, getChildInstancesForInstanceId, req.locales))
67
69
  .toSorted((a, b) => a.displayName.localeCompare(b.displayName, undefined, { numeric: true })) ?? [],
68
70
  isLocaleEntity: decl === req.localeEntity,
69
71
  };
@@ -5,6 +5,7 @@ import { hasFileChanges } 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";
8
+ import { createChildInstancesForInstanceIdGetter } from "../utils/childInstances.js";
8
9
  const debug = Debug("tsondb:server:api:git");
9
10
  export const gitApi = express.Router();
10
11
  gitApi.use((req, res, next) => {
@@ -20,6 +21,7 @@ gitApi.get("/status", async (req, res) => {
20
21
  attachGitStatusToInstancesByEntityName(req.instancesByEntityName, req.dataRoot,
21
22
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
22
23
  req.gitRoot, status);
24
+ const getChildInstancesForInstanceId = createChildInstancesForInstanceIdGetter(req);
23
25
  const body = {
24
26
  commitsAhead: status.ahead,
25
27
  commitsBehind: status.behind,
@@ -29,7 +31,7 @@ gitApi.get("/status", async (req, res) => {
29
31
  .filter(instance => hasFileChanges(instance.gitStatus))
30
32
  .map(instance => getInstanceContainerOverview(
31
33
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
32
- req.entitiesByName[entityName], instance, req.getInstanceById, req.locales)),
34
+ req.entitiesByName[entityName], instance, req.getInstanceById, getChildInstancesForInstanceId, req.locales)),
33
35
  ])),
34
36
  };
35
37
  res.json(body);
@@ -1,6 +1,7 @@
1
1
  import Debug from "debug";
2
2
  import express from "express";
3
3
  import { getDisplayNameFromEntityInstance } from "../../utils/displayName.js";
4
+ import { createChildInstancesForInstanceIdGetter } from "../utils/childInstances.js";
4
5
  const debug = Debug("tsondb:server:api:instances");
5
6
  export const instancesApi = express.Router();
6
7
  instancesApi.use((req, _res, next) => {
@@ -8,6 +9,7 @@ instancesApi.use((req, _res, next) => {
8
9
  next();
9
10
  });
10
11
  instancesApi.get("/", (req, res) => {
12
+ const getChildInstancesForInstanceId = createChildInstancesForInstanceIdGetter(req);
11
13
  const body = {
12
14
  instances: Object.fromEntries(Object.entries(req.instancesByEntityName)
13
15
  .filter(([entityName]) => Object.hasOwn(req.entitiesByName, entityName))
@@ -16,7 +18,7 @@ instancesApi.get("/", (req, res) => {
16
18
  instances.map(instance => {
17
19
  const { name, localeId } = getDisplayNameFromEntityInstance(
18
20
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
19
- req.entitiesByName[entityName], instance.content, req.getInstanceById, req.locales);
21
+ req.entitiesByName[entityName], instance, req.getInstanceById, getChildInstancesForInstanceId, req.locales);
20
22
  return {
21
23
  id: instance.id,
22
24
  name,
@@ -1,4 +1,6 @@
1
1
  import { type Result } from "../../../shared/utils/result.ts";
2
- import type { EntityTaggedInstanceContainerWithChildInstances, UnsafeEntityTaggedInstanceContainerWithChildInstances } from "../../utils/childInstances.ts";
2
+ import { type EntityTaggedInstanceContainerWithChildInstances, type UnsafeEntityTaggedInstanceContainerWithChildInstances } from "../../utils/childInstances.ts";
3
+ import type { GetChildInstancesForInstanceId } from "../../utils/displayName.ts";
3
4
  import type { TSONDBRequestLocals } from "../index.ts";
4
5
  export declare const updateLocalsAfterInstanceTreeChangeToReflectDiskState: (locals: TSONDBRequestLocals, parentId: string | undefined, parentEntityName: string, oldChildInstances: EntityTaggedInstanceContainerWithChildInstances[], childInstances: UnsafeEntityTaggedInstanceContainerWithChildInstances[]) => Promise<Result<void, [code: number, message: string]>>;
6
+ export declare const createChildInstancesForInstanceIdGetter: (locals: TSONDBRequestLocals) => GetChildInstancesForInstanceId;
@@ -1,4 +1,6 @@
1
1
  import { error, ok } from "../../../shared/utils/result.js";
2
+ import { isEntityDeclWithParentReference } from "../../schema/index.js";
3
+ import { getChildInstancesFromEntity, } from "../../utils/childInstances.js";
2
4
  import { updateLocalsAfterInstanceChangeToReflectDiskState } from "./instanceOperations.js";
3
5
  export const updateLocalsAfterInstanceTreeChangeToReflectDiskState = async (locals, parentId, parentEntityName, oldChildInstances, childInstances) => {
4
6
  const parentEntity = locals.entitiesByName[parentEntityName];
@@ -39,3 +41,13 @@ export const updateLocalsAfterInstanceTreeChangeToReflectDiskState = async (loca
39
41
  }
40
42
  return ok();
41
43
  };
44
+ export const createChildInstancesForInstanceIdGetter = (locals) => (parentEntityName, parentId, childEntityName) => {
45
+ const parentEntity = locals.entitiesByName[parentEntityName];
46
+ const childEntity = locals.entitiesByName[childEntityName];
47
+ if (parentEntity === undefined ||
48
+ childEntity === undefined ||
49
+ !isEntityDeclWithParentReference(childEntity)) {
50
+ return [];
51
+ }
52
+ return getChildInstancesFromEntity(locals.instancesByEntityName, parentEntity, parentId, childEntity);
53
+ };
@@ -1,7 +1,7 @@
1
1
  import type { GitFileStatus } from "../../shared/utils/git.ts";
2
- import type { InstancesByEntityName } from "../../shared/utils/instances.ts";
2
+ import type { InstanceContainer, InstancesByEntityName } from "../../shared/utils/instances.ts";
3
3
  import { type Result } from "../../shared/utils/result.ts";
4
- import type { EntityDecl } from "../schema/declarations/EntityDecl.ts";
4
+ import type { EntityDecl, EntityDeclWithParentReference } from "../schema/declarations/EntityDecl.ts";
5
5
  import { type ReferencesToInstances } from "./references.ts";
6
6
  export interface ChildInstanceContainer {
7
7
  id?: string;
@@ -27,6 +27,7 @@ export interface GenEntityTaggedInstanceContainerWithChildInstances<ID extends s
27
27
  content: unknown;
28
28
  childInstances: C[];
29
29
  }
30
- export declare const getChildInstances: (instancesByEntityName: InstancesByEntityName, parentEntity: EntityDecl, parentId: string) => EntityTaggedInstanceContainerWithChildInstances[];
30
+ export declare const getChildInstancesFromEntity: (instancesByEntityName: InstancesByEntityName, parentEntity: EntityDecl, parentId: string, childEntity: EntityDeclWithParentReference) => InstanceContainer[];
31
+ export declare const getChildInstances: (instancesByEntityName: InstancesByEntityName, parentEntity: EntityDecl, parentId: string, recursive?: boolean) => EntityTaggedInstanceContainerWithChildInstances[];
31
32
  export declare const checkWriteInstanceTreePossible: (entitiesByName: Record<string, EntityDecl>, instancesByEntityName: InstancesByEntityName, referencesToInstances: ReferencesToInstances, parentId: string | undefined, parentEntityName: string, oldChildInstances: EntityTaggedInstanceContainerWithChildInstances[], childInstances: UnsafeEntityTaggedInstanceContainerWithChildInstances[]) => Result<void, [code: number, message: string]>;
32
33
  export declare const unsafeApplyInstanceTree: (dataRoot: string, entitiesByName: Record<string, EntityDecl>, instancesByEntityName: InstancesByEntityName, parentId: string | undefined, parentEntityName: string, oldChildInstances: EntityTaggedInstanceContainerWithChildInstances[], childInstances: UnsafeEntityTaggedInstanceContainerWithChildInstances[]) => Promise<Result<void, [code: number, message: string]>>;
@@ -17,18 +17,19 @@ const isParentReferenceReferencingParent = (value, parentEntityName, parentId) =
17
17
  return false;
18
18
  }
19
19
  };
20
- export const getChildInstances = (instancesByEntityName, parentEntity, parentId) => {
20
+ export const getChildInstancesFromEntity = (instancesByEntityName, parentEntity, parentId, childEntity) => instancesByEntityName[childEntity.name]?.filter(instanceContainer => typeof instanceContainer.content === "object" &&
21
+ instanceContainer.content !== null &&
22
+ hasKey(instanceContainer.content, childEntity.parentReferenceKey) &&
23
+ isParentReferenceReferencingParent(instanceContainer.content[childEntity.parentReferenceKey], parentEntity.name, parentId)) ?? [];
24
+ export const getChildInstances = (instancesByEntityName, parentEntity, parentId, recursive = true) => {
21
25
  const childEntities = reduceNodes((_parentNodes, node, collectedResults) => isChildEntitiesType(node) ? [...collectedResults, node.entity] : collectedResults, [parentEntity], { followIncludes: true });
22
- return childEntities.flatMap(childEntity => instancesByEntityName[childEntity.name]
23
- ?.filter(instanceContainer => typeof instanceContainer.content === "object" &&
24
- instanceContainer.content !== null &&
25
- hasKey(instanceContainer.content, childEntity.parentReferenceKey) &&
26
- isParentReferenceReferencingParent(instanceContainer.content[childEntity.parentReferenceKey], parentEntity.name, parentId))
27
- .map(container => ({
26
+ return childEntities.flatMap(childEntity => getChildInstancesFromEntity(instancesByEntityName, parentEntity, parentId, childEntity).map(container => ({
28
27
  ...container,
29
28
  entityName: childEntity.name,
30
- childInstances: getChildInstances(instancesByEntityName, childEntity, container.id),
31
- })) ?? []);
29
+ childInstances: recursive
30
+ ? getChildInstances(instancesByEntityName, childEntity, container.id)
31
+ : [],
32
+ })));
32
33
  };
33
34
  export const checkWriteInstanceTreePossible = (entitiesByName, instancesByEntityName, referencesToInstances, parentId, parentEntityName, oldChildInstances, childInstances) => {
34
35
  const parentEntity = entitiesByName[parentEntityName];
@@ -1,4 +1,17 @@
1
- import { type EntityDecl } from "../../node/schema/index.ts";
2
1
  import type { GetInstanceById } from "../../node/server/index.ts";
3
2
  import { type DisplayNameResult } from "../../shared/utils/displayName.ts";
4
- export declare const getDisplayNameFromEntityInstance: (entity: EntityDecl, instance: unknown, getInstanceById: GetInstanceById, locales: string[], defaultName?: string, useCustomizer?: boolean) => DisplayNameResult;
3
+ import type { InstanceContainer } from "../../shared/utils/instances.ts";
4
+ import { type EntityDecl } from "../schema/declarations/EntityDecl.ts";
5
+ import type { AsType, Type } from "../schema/types/Type.ts";
6
+ export type GetChildInstancesForInstanceId = (parentEntityName: string, parentId: string, childEntityName: string) => unknown[];
7
+ export type DisplayNameCustomizer<T extends Type> = (params: {
8
+ instance: AsType<T>;
9
+ instanceId: string;
10
+ instanceDisplayName: string;
11
+ instanceDisplayNameLocaleId: string | undefined;
12
+ locales: string[];
13
+ getInstanceById: (id: string) => unknown;
14
+ getDisplayNameForInstanceId: (id: string) => string | undefined;
15
+ getChildInstancesForInstanceId: GetChildInstancesForInstanceId;
16
+ }) => DisplayNameResult;
17
+ export declare const getDisplayNameFromEntityInstance: (entity: EntityDecl, instanceContainer: InstanceContainer, getInstanceById: GetInstanceById, getChildInstancesForInstanceId: GetChildInstancesForInstanceId, locales: string[], defaultName?: string, useCustomizer?: boolean) => DisplayNameResult;
@@ -1,20 +1,29 @@
1
- import { serializeEntityDecl } from "../../node/schema/index.js";
2
1
  import { getSerializedDisplayNameFromEntityInstance, } from "../../shared/utils/displayName.js";
3
- export const getDisplayNameFromEntityInstance = (entity, instance, getInstanceById, locales, defaultName = "", useCustomizer = true) => {
2
+ import { serializeEntityDecl } from "../schema/declarations/EntityDecl.js";
3
+ export const getDisplayNameFromEntityInstance = (entity, instanceContainer, getInstanceById, getChildInstancesForInstanceId, locales, defaultName = "", useCustomizer = true) => {
4
4
  if (useCustomizer && entity.displayNameCustomizer) {
5
- const calculatedName = getDisplayNameFromEntityInstance(entity, instance, getInstanceById, locales, defaultName, false);
6
- return entity.displayNameCustomizer(instance, calculatedName.name, calculatedName.localeId, id => getInstanceById(id)?.instance.content, id => {
7
- const result = getInstanceById(id);
8
- if (result) {
9
- const { entity, instance } = result;
10
- return getDisplayNameFromEntityInstance(entity, instance.content, getInstanceById, locales, id).name;
11
- }
12
- else {
13
- return undefined;
14
- }
15
- }, locales);
5
+ const calculatedName = getDisplayNameFromEntityInstance(entity, instanceContainer, getInstanceById, getChildInstancesForInstanceId, locales, defaultName, false);
6
+ return entity.displayNameCustomizer({
7
+ instance: instanceContainer.content,
8
+ instanceId: instanceContainer.id,
9
+ instanceDisplayName: calculatedName.name,
10
+ instanceDisplayNameLocaleId: calculatedName.localeId,
11
+ locales,
12
+ getInstanceById: id => getInstanceById(id)?.instance.content,
13
+ getDisplayNameForInstanceId: id => {
14
+ const result = getInstanceById(id);
15
+ if (result) {
16
+ const { entity, instance } = result;
17
+ return getDisplayNameFromEntityInstance(entity, instance, getInstanceById, getChildInstancesForInstanceId, locales, id).name;
18
+ }
19
+ else {
20
+ return undefined;
21
+ }
22
+ },
23
+ getChildInstancesForInstanceId,
24
+ });
16
25
  }
17
26
  else {
18
- return getSerializedDisplayNameFromEntityInstance(serializeEntityDecl(entity), instance, defaultName, locales);
27
+ return getSerializedDisplayNameFromEntityInstance(serializeEntityDecl(entity), instanceContainer.content, defaultName, locales);
19
28
  }
20
29
  };
@@ -1,5 +1,6 @@
1
1
  import type { EntityDecl } from "../../node/schema/index.ts";
2
2
  import type { GetInstanceById } from "../../node/server/index.ts";
3
+ import { type GetChildInstancesForInstanceId } from "../../node/utils/displayName.ts";
3
4
  import type { GitFileStatus } from "./git.ts";
4
5
  export interface InstanceContainer {
5
6
  id: string;
@@ -12,5 +13,5 @@ export interface InstanceContainerOverview {
12
13
  displayName: string;
13
14
  displayNameLocaleId?: string;
14
15
  }
15
- export declare const getInstanceContainerOverview: (entity: EntityDecl, instanceContainer: InstanceContainer, getInstanceById: GetInstanceById, locales: string[]) => InstanceContainerOverview;
16
+ export declare const getInstanceContainerOverview: (entity: EntityDecl, instanceContainer: InstanceContainer, getInstanceById: GetInstanceById, getChildInstancesForInstanceId: GetChildInstancesForInstanceId, locales: string[]) => InstanceContainerOverview;
16
17
  export type InstancesByEntityName = Record<string, InstanceContainer[]>;
@@ -1,7 +1,7 @@
1
- import { getDisplayNameFromEntityInstance } from "../../node/utils/displayName.js";
2
- export const getInstanceContainerOverview = (entity, instanceContainer, getInstanceById, locales) => {
1
+ import { getDisplayNameFromEntityInstance, } from "../../node/utils/displayName.js";
2
+ export const getInstanceContainerOverview = (entity, instanceContainer, getInstanceById, getChildInstancesForInstanceId, locales) => {
3
3
  const { content: _, ...rest } = instanceContainer;
4
- const { name: displayName, localeId: displayNameLocaleId } = getDisplayNameFromEntityInstance(entity, instanceContainer.content, getInstanceById, locales);
4
+ const { name: displayName, localeId: displayNameLocaleId } = getDisplayNameFromEntityInstance(entity, instanceContainer, getInstanceById, getChildInstancesForInstanceId, locales);
5
5
  return {
6
6
  ...rest,
7
7
  displayName,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tsondb",
3
- "version": "0.6.2",
3
+ "version": "0.7.1",
4
4
  "description": "",
5
5
  "license": "ISC",
6
6
  "author": "Lukas Obermann",