tsondb 0.21.0 → 0.21.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/node/config.d.ts +2 -2
- package/dist/src/node/git.d.ts +4 -4
- package/dist/src/node/index.d.ts +39 -4
- package/dist/src/node/index.js +112 -11
- package/dist/src/node/renderers/jsonschema/render.js +7 -0
- package/dist/src/node/renderers/ts/render.d.ts +8 -0
- package/dist/src/node/renderers/ts/render.js +12 -0
- package/dist/src/node/schema/dsl/declarations/Decl.d.ts +3 -2
- package/dist/src/node/schema/dsl/declarations/Decl.js +2 -1
- package/dist/src/node/schema/dsl/declarations/SingletonEntityDecl.d.ts +35 -0
- package/dist/src/node/schema/dsl/declarations/SingletonEntityDecl.js +23 -0
- package/dist/src/node/schema/dsl/index.d.ts +1 -0
- package/dist/src/node/schema/dsl/index.js +1 -0
- package/dist/src/node/schema/generatedTypeHelpers.d.ts +18 -0
- package/dist/src/node/schema/guards.d.ts +1 -0
- package/dist/src/node/schema/guards.js +1 -0
- package/dist/src/node/schema/helpers.js +1 -0
- package/dist/src/node/schema/index.d.ts +12 -1
- package/dist/src/node/schema/index.js +44 -0
- package/dist/src/node/schema/treeOperations/customConstraints.d.ts +2 -1
- package/dist/src/node/schema/treeOperations/customConstraints.js +10 -10
- package/dist/src/node/schema/treeOperations/implicitSchema.js +1 -0
- package/dist/src/node/schema/treeOperations/references.js +1 -0
- package/dist/src/node/schema/treeOperations/serialization.d.ts +4 -1
- package/dist/src/node/schema/treeOperations/serialization.js +8 -0
- package/dist/src/node/schema/treeOperations/typeResolution.d.ts +4 -1
- package/dist/src/node/schema/treeOperations/typeResolution.js +6 -0
- package/dist/src/node/schema/treeOperations/validation.js +2 -0
- package/dist/src/node/server/api/declarations.js +165 -23
- package/dist/src/node/transaction.d.ts +28 -11
- package/dist/src/node/transaction.js +93 -0
- package/dist/src/node/utils/customConstraints.d.ts +6 -5
- package/dist/src/node/utils/customConstraints.js +34 -15
- package/dist/src/node/utils/databaseInMemory.d.ts +20 -8
- package/dist/src/node/utils/databaseInMemory.js +67 -9
- package/dist/src/node/utils/databaseOnDisk.js +27 -30
- package/dist/src/node/utils/files.d.ts +7 -2
- package/dist/src/node/utils/files.js +9 -0
- package/dist/src/node/utils/references.d.ts +2 -0
- package/dist/src/node/utils/references.js +6 -1
- package/dist/src/shared/api.d.ts +41 -2
- package/dist/src/shared/schema/Node.d.ts +5 -1
- package/dist/src/shared/schema/Node.js +6 -0
- package/dist/src/shared/schema/declarations/Declaration.d.ts +3 -2
- package/dist/src/shared/schema/declarations/SingletonEntityDecl.d.ts +18 -0
- package/dist/src/shared/schema/declarations/SingletonEntityDecl.js +8 -0
- package/dist/src/shared/utils/childInstances.d.ts +4 -0
- package/dist/src/shared/utils/instances.d.ts +4 -0
- package/dist/src/web/web.js +573 -130
- package/package.json +1 -1
- package/public/css/styles.css +1 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { FormatterOptions as MarkdownFormatterOptions } from "@elyukai/markdown/format";
|
|
2
2
|
import type { DefaultTSONDBTypes, ValidationOptions } from "./index.ts";
|
|
3
3
|
import type { Output } from "./output.ts";
|
|
4
|
-
import type { EntityDecl } from "./schema/dsl/index.ts";
|
|
4
|
+
import type { EntityDecl, SingletonEntityDecl } from "./schema/dsl/index.ts";
|
|
5
5
|
import type { Schema } from "./schema/index.ts";
|
|
6
6
|
/**
|
|
7
7
|
* The main configuration type for TSONDB.
|
|
@@ -33,7 +33,7 @@ export type ServerOptions = {
|
|
|
33
33
|
export type HomeLayoutSection = {
|
|
34
34
|
title: string;
|
|
35
35
|
comment?: string;
|
|
36
|
-
entities: EntityDecl[];
|
|
36
|
+
entities: (EntityDecl | SingletonEntityDecl)[];
|
|
37
37
|
};
|
|
38
38
|
/**
|
|
39
39
|
* The configuration type required for generation commands.
|
package/dist/src/node/git.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { SimpleGit } from "simple-git";
|
|
2
2
|
import type { InstanceContainerOverview } from "../shared/utils/instances.ts";
|
|
3
|
-
import type { DefaultTSONDBTypes,
|
|
3
|
+
import type { DefaultTSONDBTypes, StoringEntityName, TSONDB } from "./index.ts";
|
|
4
4
|
import type { DatabaseInMemory } from "./utils/databaseInMemory.ts";
|
|
5
5
|
export declare class Git<T extends DefaultTSONDBTypes = DefaultTSONDBTypes> {
|
|
6
6
|
#private;
|
|
@@ -36,7 +36,7 @@ export declare class Git<T extends DefaultTSONDBTypes = DefaultTSONDBTypes> {
|
|
|
36
36
|
*
|
|
37
37
|
* @throws {HTTPError} when no git repository is found
|
|
38
38
|
*/
|
|
39
|
-
stage(entity?:
|
|
39
|
+
stage(entity?: StoringEntityName<T>, id?: string): Promise<void>;
|
|
40
40
|
/**
|
|
41
41
|
* Removes files from the git staging area.
|
|
42
42
|
*
|
|
@@ -46,7 +46,7 @@ export declare class Git<T extends DefaultTSONDBTypes = DefaultTSONDBTypes> {
|
|
|
46
46
|
*
|
|
47
47
|
* @throws {HTTPError} when no git repository is found
|
|
48
48
|
*/
|
|
49
|
-
unstage(entity?:
|
|
49
|
+
unstage(entity?: StoringEntityName<T>, id?: string): Promise<void>;
|
|
50
50
|
/**
|
|
51
51
|
* Restores files in the git repository to their last committed state.
|
|
52
52
|
*
|
|
@@ -56,7 +56,7 @@ export declare class Git<T extends DefaultTSONDBTypes = DefaultTSONDBTypes> {
|
|
|
56
56
|
*
|
|
57
57
|
* @throws {HTTPError} when no git repository is found
|
|
58
58
|
*/
|
|
59
|
-
restore(entity?:
|
|
59
|
+
restore(entity?: StoringEntityName<T>, id?: string): Promise<void>;
|
|
60
60
|
/**
|
|
61
61
|
* Commits staged changes to the git repository with the provided commit message.
|
|
62
62
|
*
|
package/dist/src/node/index.d.ts
CHANGED
|
@@ -1,23 +1,27 @@
|
|
|
1
|
-
import type { InstanceContainer, InstanceContainerOverview } from "../shared/utils/instances.ts";
|
|
1
|
+
import type { InstanceContainer, InstanceContainerOverview, SingletonInstanceContainer } from "../shared/utils/instances.ts";
|
|
2
2
|
import type { FormatterOptions } from "./config.ts";
|
|
3
3
|
import { Git } from "./git.js";
|
|
4
4
|
import type { Output } from "./output.ts";
|
|
5
5
|
import { type EntityDecl } from "./schema/dsl/index.ts";
|
|
6
|
-
import type { AnyChildEntityMap, AnyEntityMap, AnyEnumMap, AnyTypeAliasMap } from "./schema/generatedTypeHelpers.ts";
|
|
6
|
+
import type { AnyChildEntityMap, AnyEntityMap, AnyEnumMap, AnySingletonEntityMap, AnyTypeAliasMap } from "./schema/generatedTypeHelpers.ts";
|
|
7
7
|
import { type IdArgsVariant } from "./schema/generatedTypeHelpers.ts";
|
|
8
8
|
import type { Schema } from "./schema/index.ts";
|
|
9
9
|
import { Transaction } from "./transaction.ts";
|
|
10
10
|
export interface DefaultTSONDBTypes {
|
|
11
11
|
entityMap: AnyEntityMap;
|
|
12
|
+
singletonEntityMap: AnySingletonEntityMap;
|
|
12
13
|
childEntityMap: AnyChildEntityMap;
|
|
13
14
|
enumMap: AnyEnumMap;
|
|
14
15
|
typeAliasMap: AnyTypeAliasMap;
|
|
15
16
|
}
|
|
16
17
|
export type Entity<T extends DefaultTSONDBTypes, E extends EntityName<T>> = T["entityMap"][E];
|
|
17
18
|
export type EntityName<T extends DefaultTSONDBTypes> = Extract<keyof T["entityMap"], string>;
|
|
19
|
+
export type SingletonEntity<T extends DefaultTSONDBTypes, E extends SingletonEntityName<T>> = T["singletonEntityMap"][E];
|
|
20
|
+
export type SingletonEntityName<T extends DefaultTSONDBTypes> = Extract<keyof T["singletonEntityMap"], string>;
|
|
18
21
|
export type EnumName<T extends DefaultTSONDBTypes> = Extract<keyof T["enumMap"], string>;
|
|
19
22
|
export type TypeAliasName<T extends DefaultTSONDBTypes> = Extract<keyof T["typeAliasMap"], string>;
|
|
20
|
-
export type
|
|
23
|
+
export type StoringEntityName<T extends DefaultTSONDBTypes> = EntityName<T> | SingletonEntityName<T>;
|
|
24
|
+
export type DeclarationName<T extends DefaultTSONDBTypes> = EntityName<T> | SingletonEntityName<T> | EnumName<T> | TypeAliasName<T>;
|
|
21
25
|
export type ChildEntity<T extends DefaultTSONDBTypes, E extends ChildEntityName<T>> = T["childEntityMap"][E][0];
|
|
22
26
|
export type ChildEntityConfig<T extends DefaultTSONDBTypes, E extends ChildEntityName<T>> = T["childEntityMap"][E];
|
|
23
27
|
export type ChildEntityName<T extends DefaultTSONDBTypes> = Extract<keyof T["childEntityMap"], string>;
|
|
@@ -148,7 +152,7 @@ export declare class TSONDB<T extends DefaultTSONDBTypes = DefaultTSONDBTypes> {
|
|
|
148
152
|
* The provided function is called with a `Transaction` object, which can be used to create, update, or delete instances. If an error is thrown during the execution of the function, the transaction is rolled back and no changes are made to the database.
|
|
149
153
|
* @throws {Error} when the transaction could not be completed
|
|
150
154
|
*/
|
|
151
|
-
runTransaction<R>(fn: (transaction: Transaction<T["entityMap"]>) => [Transaction<T["entityMap"]>, R]): Promise<R>;
|
|
155
|
+
runTransaction<R>(fn: (transaction: Transaction<T["entityMap"], T["singletonEntityMap"]>) => [Transaction<T["entityMap"], T["singletonEntityMap"]>, R]): Promise<R>;
|
|
152
156
|
/**
|
|
153
157
|
* Creates a new instance in the database.
|
|
154
158
|
*
|
|
@@ -168,6 +172,25 @@ export declare class TSONDB<T extends DefaultTSONDBTypes = DefaultTSONDBTypes> {
|
|
|
168
172
|
* @throws {Error} when the instance could not be deleted
|
|
169
173
|
*/
|
|
170
174
|
deleteInstance<E extends EntityName<T>>(entityName: E, id: string): Promise<Entity<T, E>>;
|
|
175
|
+
/**
|
|
176
|
+
* Creates a new singleton instance in the database.
|
|
177
|
+
*
|
|
178
|
+
* If the instance is of the locale entity, a locale identifier must be provided as `id`.
|
|
179
|
+
* @throws {Error} when the instance could not be created
|
|
180
|
+
*/
|
|
181
|
+
createSingletonInstance<E extends SingletonEntityName<T>>(entityName: E, content: SingletonEntity<T, E>): Promise<SingletonInstanceContainer<SingletonEntity<T, E>>>;
|
|
182
|
+
/**
|
|
183
|
+
* Updates a singleton instance in the database.
|
|
184
|
+
*
|
|
185
|
+
* @throws {Error} when the instance could not be updated
|
|
186
|
+
*/
|
|
187
|
+
updateSingletonInstance<E extends SingletonEntityName<T>>(entityName: E, content: SingletonEntity<T, E>): Promise<SingletonInstanceContainer<SingletonEntity<T, E>>>;
|
|
188
|
+
/**
|
|
189
|
+
* Deletes a singleton instance in the database.
|
|
190
|
+
*
|
|
191
|
+
* @throws {Error} when the instance could not be deleted
|
|
192
|
+
*/
|
|
193
|
+
deleteSingletonInstance<E extends SingletonEntityName<T>>(entityName: E): Promise<SingletonEntity<T, E>>;
|
|
171
194
|
/**
|
|
172
195
|
* Retrieves an instance of the specified entity by its identifier.
|
|
173
196
|
*/
|
|
@@ -192,10 +215,22 @@ export declare class TSONDB<T extends DefaultTSONDBTypes = DefaultTSONDBTypes> {
|
|
|
192
215
|
* Retrieves all instance overviews of the specified entity.
|
|
193
216
|
*/
|
|
194
217
|
getAllInstanceOverviewsOfEntity(entity: EntityDecl<EntityName<T>> | EntityName<T>): InstanceContainerOverview[];
|
|
218
|
+
/**
|
|
219
|
+
* Retrieves an instance of the specified entity by its identifier.
|
|
220
|
+
*/
|
|
221
|
+
getSingletonInstanceOfEntity<E extends SingletonEntityName<T>>(entityName: E): T["singletonEntityMap"][E] | undefined;
|
|
222
|
+
/**
|
|
223
|
+
* Retrieves the instance container of the specified entity by its identifier.
|
|
224
|
+
*/
|
|
225
|
+
getSingletonInstanceContainerOfEntity<E extends SingletonEntityName<T>>(entityName: E): SingletonInstanceContainer<T["singletonEntityMap"][E]> | undefined;
|
|
195
226
|
/**
|
|
196
227
|
* Counts the number of instances registered for the specified entity.
|
|
197
228
|
*/
|
|
198
229
|
countInstancesOfEntity(entityName: EntityName<T>): number;
|
|
230
|
+
/**
|
|
231
|
+
* Returns whether the singleton entity has an instance.
|
|
232
|
+
*/
|
|
233
|
+
hasInstanceOfSingletonEntity(entityName: SingletonEntityName<T>): boolean;
|
|
199
234
|
/**
|
|
200
235
|
* Retrieves overviews for all instances in the database, grouped by entity name.
|
|
201
236
|
*/
|
package/dist/src/node/index.js
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
import { on } from "@elyukai/utils/function";
|
|
2
2
|
import { Lazy } from "@elyukai/utils/lazy";
|
|
3
|
+
import { nullableToArray } from "@elyukai/utils/nullable";
|
|
3
4
|
import { compareNumber, reduceCompare } from "@elyukai/utils/ordering";
|
|
4
5
|
import { isError } from "@elyukai/utils/result";
|
|
6
|
+
import { assertExhaustive } from "@elyukai/utils/typeSafety";
|
|
5
7
|
import Debug from "debug";
|
|
6
8
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
7
9
|
import { join, sep } from "node:path";
|
|
8
10
|
import { stderr } from "node:process";
|
|
9
11
|
import { styleText } from "node:util";
|
|
10
12
|
import { simpleGit } from "simple-git";
|
|
13
|
+
import { NodeKind } from "../shared/schema/Node.js";
|
|
11
14
|
import { parallelizeErrors } from "../shared/utils/validation.js";
|
|
12
15
|
import { Git } from "./git.js";
|
|
13
16
|
import { getDisplayName, getDisplayNameWithId } from "./schema/detached.js";
|
|
14
17
|
import {} from "./schema/dsl/index.js";
|
|
15
18
|
import {} from "./schema/generatedTypeHelpers.js";
|
|
16
|
-
import { isEntityDeclWithParentReference } from "./schema/guards.js";
|
|
19
|
+
import { isEntityDecl, isEntityDeclWithParentReference } from "./schema/guards.js";
|
|
17
20
|
import { serializeNode } from "./schema/treeOperations/serialization.js";
|
|
18
21
|
import { createEntityNameValidator, createReferenceValidator, validateDeclReferentialIntegrity, validateDeclStructuralIntegrity, } from "./schema/treeOperations/validation.js";
|
|
19
22
|
import { Transaction } from "./transaction.js";
|
|
@@ -22,7 +25,7 @@ import { DatabaseInMemory } from "./utils/databaseInMemory.js";
|
|
|
22
25
|
import { applyStepsToDisk } from "./utils/databaseOnDisk.js";
|
|
23
26
|
import { getAllInstanceOverviewsByEntityName, getDisplayNameFromEntityInstance, getInstanceOverview, getInstanceOverviewsByEntityName, } from "./utils/displayName.js";
|
|
24
27
|
import { countError, countErrors, getErrorMessageForDisplay, HTTPError, wrapErrorsIfAny, } from "./utils/error.js";
|
|
25
|
-
import { formatInstance, getFileNameForId, readInstance, writeInstance } from "./utils/files.js";
|
|
28
|
+
import { formatInstance, getFileNameForId, getSingletonFileName, readInstance, readSingletonInstance, writeInstance, writeSingletonInstance, } from "./utils/files.js";
|
|
26
29
|
import { attachGitStatusToDatabaseInMemory } from "./utils/git.js";
|
|
27
30
|
import { getReferencesToInstances, isReferencedByOtherInstances, } from "./utils/references.js";
|
|
28
31
|
import { checkUniqueConstraintsForAllEntities } from "./utils/unique.js";
|
|
@@ -64,7 +67,7 @@ const checkLocales = (schema, data, locales) => {
|
|
|
64
67
|
};
|
|
65
68
|
const initData = async (dataRootPath, schema, locales, git, gitStatus, skipReferenceCache) => {
|
|
66
69
|
debug("loading database into memory ...");
|
|
67
|
-
let data = await DatabaseInMemory.load(dataRootPath, schema.entities);
|
|
70
|
+
let data = await DatabaseInMemory.load(dataRootPath, schema.entities, schema.singletonEntities);
|
|
68
71
|
debug("done");
|
|
69
72
|
checkLocales(schema, data, locales);
|
|
70
73
|
const serializedDeclarationsByName = Object.fromEntries(schema.resolvedDeclarations.map(decl => [decl.name, serializeNode(decl)]));
|
|
@@ -172,7 +175,7 @@ export class TSONDB {
|
|
|
172
175
|
#validate(data, options = {}) {
|
|
173
176
|
const { checkReferentialIntegrity, checkOnlyEntities } = this.#validationOptions;
|
|
174
177
|
const { skipStructuralValidation = false, logToConsole = true, changedEntities: changedEntityNames, } = options;
|
|
175
|
-
const entities = this.#schema.entities;
|
|
178
|
+
const entities = [...this.#schema.entities, ...this.#schema.singletonEntities];
|
|
176
179
|
const getEntity = this.#schema.getEntity.bind(this.#schema);
|
|
177
180
|
for (const onlyEntity of checkOnlyEntities) {
|
|
178
181
|
if (!entities.find(entity => entity.name === onlyEntity)) {
|
|
@@ -193,9 +196,23 @@ export class TSONDB {
|
|
|
193
196
|
if (!skipStructuralValidation) {
|
|
194
197
|
debug("Checking structural integrity ...");
|
|
195
198
|
const structureErrors = onlyEntities
|
|
196
|
-
.flatMap(entity =>
|
|
197
|
-
|
|
198
|
-
|
|
199
|
+
.flatMap(entity => {
|
|
200
|
+
switch (entity.kind) {
|
|
201
|
+
case NodeKind.EntityDecl:
|
|
202
|
+
return parallelizeErrors(data
|
|
203
|
+
.getAllInstanceContainersOfEntity(entity.name)
|
|
204
|
+
.map(instance => wrapErrorsIfAny(`in file ${styleText("white", `"${this.#dataRootPath}${sep}${styleText("bold", join(entity.name, getFileNameForId(instance.id)))}"`)}`, validateDeclStructuralIntegrity(validationContext, [], entity, [], instance.content))));
|
|
205
|
+
case NodeKind.SingletonEntityDecl: {
|
|
206
|
+
const instance = data.getSingletonInstanceContainerOfEntity(entity.name);
|
|
207
|
+
if (instance) {
|
|
208
|
+
return nullableToArray(wrapErrorsIfAny(`in file ${styleText("white", `"${this.#dataRootPath}${sep}${styleText("bold", getSingletonFileName(entity.name))}"`)}`, validateDeclStructuralIntegrity(validationContext, [], entity, [], instance.content)));
|
|
209
|
+
}
|
|
210
|
+
return [];
|
|
211
|
+
}
|
|
212
|
+
default:
|
|
213
|
+
return assertExhaustive(entity);
|
|
214
|
+
}
|
|
215
|
+
})
|
|
199
216
|
.toSorted((a, b) => a.message.localeCompare(b.message));
|
|
200
217
|
if (structureErrors.length > 0) {
|
|
201
218
|
const errorCount = countErrors(structureErrors);
|
|
@@ -213,9 +230,23 @@ export class TSONDB {
|
|
|
213
230
|
const entityNameValidator = createEntityNameValidator(this.#schema.isEntityName.bind(this.#schema), true);
|
|
214
231
|
const referenceValidator = createReferenceValidator(this.#schema.isEntityName.bind(this.#schema), data, true);
|
|
215
232
|
const referenceErrors = onlyEntities
|
|
216
|
-
.flatMap(entity =>
|
|
217
|
-
|
|
218
|
-
|
|
233
|
+
.flatMap(entity => {
|
|
234
|
+
switch (entity.kind) {
|
|
235
|
+
case NodeKind.EntityDecl:
|
|
236
|
+
return parallelizeErrors(data
|
|
237
|
+
.getAllInstanceContainersOfEntity(entity.name)
|
|
238
|
+
.map(instance => wrapErrorsIfAny(`in file ${styleText("white", `"${this.#dataRootPath}${sep}${styleText("bold", join(entity.name, getFileNameForId(instance.id)))}"`)}`, validateDeclReferentialIntegrity(validationContext, entityNameValidator, referenceValidator, [], entity, [], instance.content))));
|
|
239
|
+
case NodeKind.SingletonEntityDecl: {
|
|
240
|
+
const instance = data.getSingletonInstanceContainerOfEntity(entity.name);
|
|
241
|
+
if (instance) {
|
|
242
|
+
return nullableToArray(wrapErrorsIfAny(`in file ${styleText("white", `"${this.#dataRootPath}${sep}${styleText("bold", getSingletonFileName(entity.name))}"`)}`, validateDeclReferentialIntegrity(validationContext, entityNameValidator, referenceValidator, [], entity, [], instance.content)));
|
|
243
|
+
}
|
|
244
|
+
return [];
|
|
245
|
+
}
|
|
246
|
+
default:
|
|
247
|
+
return assertExhaustive(entity);
|
|
248
|
+
}
|
|
249
|
+
})
|
|
219
250
|
.toSorted((a, b) => a.message.localeCompare(b.message));
|
|
220
251
|
if (referenceErrors.length > 0) {
|
|
221
252
|
const errorCount = countErrors(referenceErrors);
|
|
@@ -232,7 +263,7 @@ export class TSONDB {
|
|
|
232
263
|
}
|
|
233
264
|
debug("Checking unique constraints ...");
|
|
234
265
|
const instanceOverviewsByEntityName = getAllInstanceOverviewsByEntityName(getEntity, data, this.#locales);
|
|
235
|
-
const uniqueConstraintResult = checkUniqueConstraintsForAllEntities(data, changedEntities ?? onlyEntities, instanceOverviewsByEntityName);
|
|
266
|
+
const uniqueConstraintResult = checkUniqueConstraintsForAllEntities(data, (changedEntities ?? onlyEntities).filter(e => isEntityDecl(e)), instanceOverviewsByEntityName);
|
|
236
267
|
if (isError(uniqueConstraintResult)) {
|
|
237
268
|
const errorCount = countError(uniqueConstraintResult.error);
|
|
238
269
|
debug(`${errorCount.toString()} unique constraint violation${errorCount === 1 ? "" : "s"} found`);
|
|
@@ -286,6 +317,11 @@ export class TSONDB {
|
|
|
286
317
|
const entity = this.#schema.getEntity(entityName);
|
|
287
318
|
await writeInstance(this.#dataRootPath, entity, instance.id, instance.content, this.#formatterOptions);
|
|
288
319
|
}, true);
|
|
320
|
+
await this.#data.forEachSingletonInstance(async (entityName, instance) => {
|
|
321
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
322
|
+
const entity = this.#schema.getSingletonEntity(entityName);
|
|
323
|
+
await writeSingletonInstance(this.#dataRootPath, entity, instance.content, this.#formatterOptions);
|
|
324
|
+
}, true);
|
|
289
325
|
debug("All data is formatted");
|
|
290
326
|
}
|
|
291
327
|
/**
|
|
@@ -306,6 +342,17 @@ export class TSONDB {
|
|
|
306
342
|
}
|
|
307
343
|
total++;
|
|
308
344
|
}, true);
|
|
345
|
+
await this.#data.forEachSingletonInstance(async (entityName, instance) => {
|
|
346
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
347
|
+
const entity = this.#schema.getSingletonEntity(entityName);
|
|
348
|
+
const instanceOnDisk = await readSingletonInstance(this.#dataRootPath, entity);
|
|
349
|
+
const currentFormatted = formatInstance(entity, instance.content, this.#formatterOptions);
|
|
350
|
+
if (instanceOnDisk !== currentFormatted) {
|
|
351
|
+
console.log(`Singleton instance of entity ${styleText("cyan", entityName)} is not formatted correctly.`);
|
|
352
|
+
counter++;
|
|
353
|
+
}
|
|
354
|
+
total++;
|
|
355
|
+
}, true);
|
|
309
356
|
if (counter === 0) {
|
|
310
357
|
console.log(styleText("green", `All ${total.toFixed()} instance${total === 1 ? "" : "s"} are formatted correctly`));
|
|
311
358
|
return true;
|
|
@@ -342,9 +389,11 @@ export class TSONDB {
|
|
|
342
389
|
this.#locked = true;
|
|
343
390
|
try {
|
|
344
391
|
const getEntity = this.#schema.getEntity.bind(this.#schema);
|
|
392
|
+
const getSingletonEntity = this.#schema.getSingletonEntity.bind(this.#schema);
|
|
345
393
|
const [txn, res] = fn(new Transaction({
|
|
346
394
|
data: this.#data,
|
|
347
395
|
getEntity,
|
|
396
|
+
getSingletonEntity,
|
|
348
397
|
referencesToInstances: this.#referencesToInstances,
|
|
349
398
|
validate: this.#strucurallyValidateInstance.bind(this),
|
|
350
399
|
localeEntity: this.#schema.localeEntity,
|
|
@@ -426,6 +475,40 @@ export class TSONDB {
|
|
|
426
475
|
txn.deleteInstance(this.#schema.getEntity(entityName), id));
|
|
427
476
|
return res.content;
|
|
428
477
|
}
|
|
478
|
+
/**
|
|
479
|
+
* Creates a new singleton instance in the database.
|
|
480
|
+
*
|
|
481
|
+
* If the instance is of the locale entity, a locale identifier must be provided as `id`.
|
|
482
|
+
* @throws {Error} when the instance could not be created
|
|
483
|
+
*/
|
|
484
|
+
async createSingletonInstance(entityName, content) {
|
|
485
|
+
const res = await this.runTransaction(txn =>
|
|
486
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
487
|
+
txn.createSingletonInstance(this.#schema.getSingletonEntity(entityName), content));
|
|
488
|
+
return res;
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* Updates a singleton instance in the database.
|
|
492
|
+
*
|
|
493
|
+
* @throws {Error} when the instance could not be updated
|
|
494
|
+
*/
|
|
495
|
+
async updateSingletonInstance(entityName, content) {
|
|
496
|
+
const res = await this.runTransaction(txn =>
|
|
497
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
498
|
+
txn.updateSingletonInstance(this.#schema.getSingletonEntity(entityName), content));
|
|
499
|
+
return res;
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* Deletes a singleton instance in the database.
|
|
503
|
+
*
|
|
504
|
+
* @throws {Error} when the instance could not be deleted
|
|
505
|
+
*/
|
|
506
|
+
async deleteSingletonInstance(entityName) {
|
|
507
|
+
const res = await this.runTransaction(txn =>
|
|
508
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
509
|
+
txn.deleteSingletonInstance(this.#schema.getSingletonEntity(entityName)));
|
|
510
|
+
return res.content;
|
|
511
|
+
}
|
|
429
512
|
/**
|
|
430
513
|
* Retrieves an instance of the specified entity by its identifier.
|
|
431
514
|
*/
|
|
@@ -466,12 +549,30 @@ export class TSONDB {
|
|
|
466
549
|
}
|
|
467
550
|
return getInstanceOverviewsByEntityName(this.getInstanceContainerOfEntityById.bind(this), this.getAllChildInstanceContainersForParent.bind(this), this.#schema.getEntity.bind(this.#schema), normEntity, this.getAllInstanceContainersOfEntity(normEntity.name), this.#locales);
|
|
468
551
|
}
|
|
552
|
+
/**
|
|
553
|
+
* Retrieves an instance of the specified entity by its identifier.
|
|
554
|
+
*/
|
|
555
|
+
getSingletonInstanceOfEntity(entityName) {
|
|
556
|
+
return this.#data.getSingletonInstanceOfEntity(entityName);
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* Retrieves the instance container of the specified entity by its identifier.
|
|
560
|
+
*/
|
|
561
|
+
getSingletonInstanceContainerOfEntity(entityName) {
|
|
562
|
+
return this.#data.getSingletonInstanceContainerOfEntity(entityName);
|
|
563
|
+
}
|
|
469
564
|
/**
|
|
470
565
|
* Counts the number of instances registered for the specified entity.
|
|
471
566
|
*/
|
|
472
567
|
countInstancesOfEntity(entityName) {
|
|
473
568
|
return this.#data.countInstancesOfEntity(entityName);
|
|
474
569
|
}
|
|
570
|
+
/**
|
|
571
|
+
* Returns whether the singleton entity has an instance.
|
|
572
|
+
*/
|
|
573
|
+
hasInstanceOfSingletonEntity(entityName) {
|
|
574
|
+
return this.#data.hasInstanceOfSingletonEntity(entityName);
|
|
575
|
+
}
|
|
475
576
|
/**
|
|
476
577
|
* Retrieves overviews for all instances in the database, grouped by entity name.
|
|
477
578
|
*/
|
|
@@ -156,6 +156,11 @@ const renderEntityDecl = (options, decl) => ({
|
|
|
156
156
|
deprecated: decl.isDeprecated,
|
|
157
157
|
...renderType(options, addEphemeralUUIDToType(decl)),
|
|
158
158
|
});
|
|
159
|
+
const renderSingletonEntityDecl = (options, decl) => ({
|
|
160
|
+
description: decl.comment,
|
|
161
|
+
deprecated: decl.isDeprecated,
|
|
162
|
+
...renderType(options, decl.type.value),
|
|
163
|
+
});
|
|
159
164
|
const renderEnumDecl = (options, decl) => ({
|
|
160
165
|
description: decl.comment,
|
|
161
166
|
deprecated: decl.isDeprecated,
|
|
@@ -170,6 +175,8 @@ const renderDecl = (options, decl) => {
|
|
|
170
175
|
switch (decl.kind) {
|
|
171
176
|
case NodeKind.EntityDecl:
|
|
172
177
|
return renderEntityDecl({ ...options, parentDecl: decl }, decl);
|
|
178
|
+
case NodeKind.SingletonEntityDecl:
|
|
179
|
+
return renderSingletonEntityDecl({ ...options, parentDecl: decl }, decl);
|
|
173
180
|
case NodeKind.EnumDecl:
|
|
174
181
|
return renderEnumDecl({ ...options, parentDecl: decl }, decl);
|
|
175
182
|
case NodeKind.TypeAliasDecl:
|
|
@@ -8,6 +8,10 @@ export type TypeScriptRendererOptions = {
|
|
|
8
8
|
* If `true` or a string, generates an object type with all names of the entities as the key and their corresponding generated type as their respective value. Uses `EntityMap` as a default name when using `true` or the string if set to a string.
|
|
9
9
|
*/
|
|
10
10
|
entityMap: boolean | string;
|
|
11
|
+
/**
|
|
12
|
+
* If `true` or a string, generates an object type with all names of the singleton entities as the key and their corresponding generated type as their respective value. Uses `SingletonEntityMap` as a default name when using `true` or the string if set to a string.
|
|
13
|
+
*/
|
|
14
|
+
singletonEntityMap: boolean | string;
|
|
11
15
|
/**
|
|
12
16
|
* If `true` or a string, generates an object type with all names of entities with parent references as the key and their corresponding generated type as well as their parent reference key as their respective value. Uses `ChildEntityMap` as a default name when using `true` or the string if set to a string.
|
|
13
17
|
*/
|
|
@@ -32,6 +36,10 @@ export type TypeScriptRendererOptions = {
|
|
|
32
36
|
* @default "string"
|
|
33
37
|
*/
|
|
34
38
|
defaultTranslationParameterType?: "string" | "StringableTranslationParameter";
|
|
39
|
+
/**
|
|
40
|
+
* New formatter types can be introduced to MF2 messages. This option allows you to specify a mapping of formatter names to their corresponding TypeScript types. For example, a list formatter could be defined as `{ list: "string[]" }`, which would infer the type of a translation parameter using the `list` formatter as `string[]`.
|
|
41
|
+
*/
|
|
42
|
+
otherTypes?: Record<string, string>;
|
|
35
43
|
};
|
|
36
44
|
/**
|
|
37
45
|
* The generated type to use for Date types. The data is always stored as a string, but Date can be helpful if you need to differenciate between a string and a date in code. Defaults to `string`.
|
|
@@ -9,6 +9,7 @@ import { extractParameterTypeNamesFromMessage, mapParameterTypeNames, } from "..
|
|
|
9
9
|
import { asDecl } from "../../schema/dsl/declarations/Decl.js";
|
|
10
10
|
import { addEphemeralUUIDToType, createEntityIdentifierTypeAsDecl, isEntityDecl, isEntityDeclWithParentReference, } from "../../schema/dsl/declarations/EntityDecl.js";
|
|
11
11
|
import { isEnumDecl } from "../../schema/dsl/declarations/EnumDecl.js";
|
|
12
|
+
import { isSingletonEntityDecl, } from "../../schema/dsl/declarations/SingletonEntityDecl.js";
|
|
12
13
|
import { isTypeAliasDecl, TypeAliasDecl } from "../../schema/dsl/declarations/TypeAliasDecl.js";
|
|
13
14
|
import { isNestedEntityMapType } from "../../schema/dsl/types/NestedEntityMapType.js";
|
|
14
15
|
import { isObjectType } from "../../schema/dsl/types/ObjectType.js";
|
|
@@ -90,6 +91,12 @@ const mapTypeNameToType = (options, typeName) => {
|
|
|
90
91
|
return "Date";
|
|
91
92
|
case null:
|
|
92
93
|
default:
|
|
94
|
+
if (typeName !== null &&
|
|
95
|
+
options.inferTranslationParameters?.otherTypes !== undefined &&
|
|
96
|
+
typeName in options.inferTranslationParameters.otherTypes) {
|
|
97
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- already checked that the key exists
|
|
98
|
+
return options.inferTranslationParameters.otherTypes[typeName];
|
|
99
|
+
}
|
|
93
100
|
return (options.inferTranslationParameters?.defaultTranslationParameterType ??
|
|
94
101
|
defaultTranslationParameterType);
|
|
95
102
|
}
|
|
@@ -142,6 +149,7 @@ const renderType = (options, type) => {
|
|
|
142
149
|
}
|
|
143
150
|
};
|
|
144
151
|
const renderEntityDecl = (options, decl) => syntax `${renderDocumentation(decl.comment, decl.isDeprecated)}export ${options.objectTypeKeyword} ${decl.name} ${options.objectTypeKeyword === "type" ? "= " : ""}${renderType(options, options.addIdentifierToEntities ? addEphemeralUUIDToType(decl) : decl.type.value)}`;
|
|
152
|
+
const renderSingletonEntityDecl = (options, decl) => syntax `${renderDocumentation(decl.comment, decl.isDeprecated)}export ${options.objectTypeKeyword} ${decl.name} ${options.objectTypeKeyword === "type" ? "= " : ""}${renderType(options, decl.type.value)}`;
|
|
145
153
|
const renderEnumDecl = (options, decl) => syntax `${renderDocumentation(decl.comment, decl.isDeprecated)}export type ${decl.name}${renderTypeParameters(options, decl.parameters)} =${renderEnumType(options, decl.type.value)}`;
|
|
146
154
|
const renderTypeAliasDecl = (options, decl) => isObjectType(decl.type.value)
|
|
147
155
|
? syntax `${renderDocumentation(decl.comment, decl.isDeprecated)}export ${options.objectTypeKeyword} ${decl.name}${renderTypeParameters(options, decl.parameters)} ${options.objectTypeKeyword === "type" ? "= " : ""}${renderType(options, decl.type.value)}`
|
|
@@ -150,6 +158,8 @@ const renderDecl = (options, decl) => {
|
|
|
150
158
|
switch (decl.kind) {
|
|
151
159
|
case NodeKind.EntityDecl:
|
|
152
160
|
return renderEntityDecl(options, decl);
|
|
161
|
+
case NodeKind.SingletonEntityDecl:
|
|
162
|
+
return renderSingletonEntityDecl(options, decl);
|
|
153
163
|
case NodeKind.EnumDecl:
|
|
154
164
|
return renderEnumDecl(options, decl);
|
|
155
165
|
case NodeKind.TypeAliasDecl:
|
|
@@ -187,6 +197,7 @@ const renderMapHelperType = (options, declarations, key, defaultName, filterFn,
|
|
|
187
197
|
: "";
|
|
188
198
|
};
|
|
189
199
|
const renderEntityMapType = (options, declarations) => renderMapHelperType(options, declarations, "entityMap", "EntityMap", isEntityDecl);
|
|
200
|
+
const renderSingletonEntityMapType = (options, declarations) => renderMapHelperType(options, declarations, "singletonEntityMap", "SingletonEntityMap", isSingletonEntityDecl);
|
|
190
201
|
const renderChildEntityMapType = (options, declarations) => renderMapHelperType(options, declarations, "childEntityMap", "ChildEntityMap", decl => isEntityDecl(decl) && isEntityDeclWithParentReference(decl), decl => `${decl.name}: [${decl.name}, "${decl.parentReferenceKey}", ${decl.name}["${decl.parentReferenceKey}"]]`);
|
|
191
202
|
const renderEnumMapType = (options, declarations) => renderMapHelperType(options, declarations, "enumMap", "EnumMap", isEnumDecl);
|
|
192
203
|
const renderTypeAliasMapType = (options, declarations) => renderMapHelperType(options, declarations, "typeAliasMap", "TypeAliasMap", isTypeAliasDecl);
|
|
@@ -249,6 +260,7 @@ export const render = (options = defaultOptions, declarations) => {
|
|
|
249
260
|
return undefined;
|
|
250
261
|
}, declarations));
|
|
251
262
|
return (renderEntityMapType(finalOptions, declarations) +
|
|
263
|
+
renderSingletonEntityMapType(finalOptions, declarations) +
|
|
252
264
|
renderChildEntityMapType(finalOptions, declarations) +
|
|
253
265
|
renderEnumMapType(finalOptions, declarations) +
|
|
254
266
|
renderTypeAliasMapType(finalOptions, declarations) +
|
|
@@ -5,14 +5,15 @@ import type { EnumCaseDecl } from "../types/EnumType.ts";
|
|
|
5
5
|
import type { Type } from "../types/Type.ts";
|
|
6
6
|
import type { EntityDecl } from "./EntityDecl.ts";
|
|
7
7
|
import type { EnumDecl } from "./EnumDecl.ts";
|
|
8
|
+
import { type SingletonEntityDecl } from "./SingletonEntityDecl.ts";
|
|
8
9
|
import type { TypeAliasDecl } from "./TypeAliasDecl.ts";
|
|
9
10
|
export type TypeArguments<Params extends TypeParameter[]> = {
|
|
10
11
|
[K in keyof Params]: Params[K] extends TypeParameter<string, infer T> ? T : Type;
|
|
11
12
|
};
|
|
12
13
|
export declare const getParameterNames: (decl: Decl) => string[];
|
|
13
14
|
export declare const getTypeArgumentsRecord: <Params extends TypeParameter[]>(decl: DeclP<Params>, args: TypeArguments<Params>) => Record<string, Type>;
|
|
14
|
-
export type Decl<Name extends string = string> = EntityDecl<Name> | EnumDecl<Name> | TypeAliasDecl<Name>;
|
|
15
|
-
export type DeclP<Params extends TypeParameter[] = TypeParameter[]> = EntityDecl | EnumDecl<string, Record<string, EnumCaseDecl>, Params> | TypeAliasDecl<string, Type, Params>;
|
|
15
|
+
export type Decl<Name extends string = string> = EntityDecl<Name> | SingletonEntityDecl<Name> | EnumDecl<Name> | TypeAliasDecl<Name>;
|
|
16
|
+
export type DeclP<Params extends TypeParameter[] = TypeParameter[]> = EntityDecl | SingletonEntityDecl | EnumDecl<string, Record<string, EnumCaseDecl>, Params> | TypeAliasDecl<string, Type, Params>;
|
|
16
17
|
export type IncludableDeclP<Params extends TypeParameter[] = TypeParameter[]> = EnumDecl<string, Record<string, EnumCaseDecl>, Params> | TypeAliasDecl<string, Type, Params>;
|
|
17
18
|
export type SecondaryDecl = EnumDecl | TypeAliasDecl;
|
|
18
19
|
export declare const isDecl: (node: Node) => node is Decl;
|
|
@@ -2,12 +2,13 @@ import { walkTypeNodeTree } from "../../helpers.js";
|
|
|
2
2
|
import { resolveTypeArguments } from "../../treeOperations/typeResolution.js";
|
|
3
3
|
import { isEntityDecl } from "./EntityDecl.js";
|
|
4
4
|
import { isEnumDecl } from "./EnumDecl.js";
|
|
5
|
+
import { isSingletonEntityDecl } from "./SingletonEntityDecl.js";
|
|
5
6
|
import { isTypeAliasDecl } from "./TypeAliasDecl.js";
|
|
6
7
|
export const getParameterNames = (decl) => decl.parameters.map(param => param.name);
|
|
7
8
|
export const getTypeArgumentsRecord = (decl, args) => Object.fromEntries(
|
|
8
9
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
9
10
|
args.slice(0, decl.parameters.length).map((arg, i) => [decl.parameters[i].name, arg]));
|
|
10
|
-
export const isDecl = (node) => isEntityDecl(node) || isEnumDecl(node) || isTypeAliasDecl(node);
|
|
11
|
+
export const isDecl = (node) => isEntityDecl(node) || isSingletonEntityDecl(node) || isEnumDecl(node) || isTypeAliasDecl(node);
|
|
11
12
|
export const asDecl = (node) => node && isDecl(node) ? node : undefined;
|
|
12
13
|
const declNamePattern = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
|
|
13
14
|
export const validateDeclName = (name) => {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Lazy } from "@elyukai/utils/lazy";
|
|
2
|
+
import { NodeKind } from "../../../../shared/schema/Node.ts";
|
|
3
|
+
import type { SortOrder } from "../../../../shared/schema/utils/sortOrder.ts";
|
|
4
|
+
import type { CustomConstraint, TypedCustomConstraint } from "../../../utils/customConstraints.ts";
|
|
5
|
+
import type { Node } from "../index.ts";
|
|
6
|
+
import type { MemberDecl, ObjectType } from "../types/ObjectType.ts";
|
|
7
|
+
import type { BaseDecl } from "./Decl.ts";
|
|
8
|
+
type TConstraint = Record<string, MemberDecl>;
|
|
9
|
+
export interface SingletonEntityDecl<Name extends string = string, T extends TConstraint = TConstraint> extends BaseDecl<Name, []> {
|
|
10
|
+
kind: NodeKind["SingletonEntityDecl"];
|
|
11
|
+
/**
|
|
12
|
+
* Changes the appearance of the entity’s name in singular form.
|
|
13
|
+
*/
|
|
14
|
+
displayName?: string;
|
|
15
|
+
type: Lazy<ObjectType<T>>;
|
|
16
|
+
isDeprecated?: boolean;
|
|
17
|
+
customConstraints?: CustomConstraint;
|
|
18
|
+
/**
|
|
19
|
+
* The order in which instances of an entity are sorted in the editor. This affects entity details pages and reference options.
|
|
20
|
+
*/
|
|
21
|
+
sortOrder?: SortOrder;
|
|
22
|
+
}
|
|
23
|
+
export declare const SingletonEntityDecl: <Name extends string, T extends TConstraint>(sourceUrl: string, options: {
|
|
24
|
+
name: Name;
|
|
25
|
+
/**
|
|
26
|
+
* Changes the appearance of the entity’s name in singular form.
|
|
27
|
+
*/
|
|
28
|
+
displayName?: string;
|
|
29
|
+
comment?: string;
|
|
30
|
+
type: () => ObjectType<T>;
|
|
31
|
+
isDeprecated?: boolean;
|
|
32
|
+
customConstraints?: TypedCustomConstraint<Name>;
|
|
33
|
+
}) => SingletonEntityDecl<Name, T>;
|
|
34
|
+
export { SingletonEntityDecl as SingletonEntity };
|
|
35
|
+
export declare const isSingletonEntityDecl: (node: Node) => node is SingletonEntityDecl;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Lazy } from "@elyukai/utils/lazy";
|
|
2
|
+
import { NodeKind } from "../../../../shared/schema/Node.js";
|
|
3
|
+
import { validateDeclName } from "./Decl.js";
|
|
4
|
+
export const SingletonEntityDecl = (sourceUrl, options) => {
|
|
5
|
+
validateDeclName(options.name);
|
|
6
|
+
return {
|
|
7
|
+
...options,
|
|
8
|
+
kind: NodeKind.SingletonEntityDecl,
|
|
9
|
+
sourceUrl,
|
|
10
|
+
parameters: [],
|
|
11
|
+
type: Lazy.of(() => {
|
|
12
|
+
const type = options.type();
|
|
13
|
+
Object.keys(type.properties).forEach(key => {
|
|
14
|
+
if (key === "id") {
|
|
15
|
+
throw new TypeError(`Invalid object key "${key}" for entity "${options.name}". The key "id" is reserved for the entity identifier.`);
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
return type;
|
|
19
|
+
}),
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
export { SingletonEntityDecl as SingletonEntity };
|
|
23
|
+
export const isSingletonEntityDecl = (node) => node.kind === NodeKind.SingletonEntityDecl;
|
|
@@ -5,6 +5,7 @@ export { Param, TypeParameter } from "./TypeParameter.ts";
|
|
|
5
5
|
export { type Decl, type DeclP, type IncludableDeclP, type SecondaryDecl, } from "./declarations/Decl.ts";
|
|
6
6
|
export { Entity, EntityDecl, type EntityDeclWithParentReference, type EntityDisplayName, } from "./declarations/EntityDecl.ts";
|
|
7
7
|
export { Enum, EnumDecl, GenEnum, GenEnumDecl } from "./declarations/EnumDecl.ts";
|
|
8
|
+
export { SingletonEntity, SingletonEntityDecl } from "./declarations/SingletonEntityDecl.ts";
|
|
8
9
|
export { GenTypeAlias, GenTypeAliasDecl, TypeAlias, TypeAliasDecl, } from "./declarations/TypeAliasDecl.ts";
|
|
9
10
|
export { Array, ArrayType } from "./types/ArrayType.ts";
|
|
10
11
|
export { Boolean, BooleanType } from "./types/BooleanType.ts";
|
|
@@ -2,6 +2,7 @@ export { Param, TypeParameter } from "./TypeParameter.js";
|
|
|
2
2
|
export {} from "./declarations/Decl.js";
|
|
3
3
|
export { Entity, EntityDecl, } from "./declarations/EntityDecl.js";
|
|
4
4
|
export { Enum, EnumDecl, GenEnum, GenEnumDecl } from "./declarations/EnumDecl.js";
|
|
5
|
+
export { SingletonEntity, SingletonEntityDecl } from "./declarations/SingletonEntityDecl.js";
|
|
5
6
|
export { GenTypeAlias, GenTypeAliasDecl, TypeAlias, TypeAliasDecl, } from "./declarations/TypeAliasDecl.js";
|
|
6
7
|
export { Array, ArrayType } from "./types/ArrayType.js";
|
|
7
8
|
export { Boolean, BooleanType } from "./types/BooleanType.js";
|
|
@@ -8,6 +8,7 @@ import type { DisplayNameResult } from "../../shared/utils/displayName.ts";
|
|
|
8
8
|
import type { InstanceContainer, InstanceContainerOverview, InstanceContent } from "../../shared/utils/instances.ts";
|
|
9
9
|
import type { DeclarationName, DefaultTSONDBTypes } from "../index.ts";
|
|
10
10
|
import type { EntityDecl } from "./dsl/declarations/EntityDecl.ts";
|
|
11
|
+
import type { SingletonEntityDecl } from "./dsl/declarations/SingletonEntityDecl.ts";
|
|
11
12
|
export interface Register {
|
|
12
13
|
}
|
|
13
14
|
export type AnyEntityMap = Record<string, InstanceContent>;
|
|
@@ -19,6 +20,15 @@ export type RegisteredEntity<Name extends string, T = Register> = T extends {
|
|
|
19
20
|
[K in Name]: InstanceContent;
|
|
20
21
|
};
|
|
21
22
|
} ? T["entityMap"][Name] : InstanceContent;
|
|
23
|
+
export type AnySingletonEntityMap = Record<string, InstanceContent>;
|
|
24
|
+
export type RegisteredSingletonEntityMap<T = Register> = T extends {
|
|
25
|
+
singletonEntityMap: AnySingletonEntityMap;
|
|
26
|
+
} ? T["singletonEntityMap"] : AnySingletonEntityMap;
|
|
27
|
+
export type RegisteredSingletonEntity<Name extends string, T = Register> = T extends {
|
|
28
|
+
singletonEntityMap: {
|
|
29
|
+
[K in Name]: InstanceContent;
|
|
30
|
+
};
|
|
31
|
+
} ? T["singletonEntityMap"][Name] : InstanceContent;
|
|
22
32
|
export type AnyChildEntityMap = Record<string, [
|
|
23
33
|
content: InstanceContent,
|
|
24
34
|
parentKey: string,
|
|
@@ -133,6 +143,14 @@ export type GetDisplayNameAndId<T extends AnyEntityMap = RegisteredEntityMap> =
|
|
|
133
143
|
* A function that retrieves an entity declaration by its name.
|
|
134
144
|
*/
|
|
135
145
|
export type GetEntityByName<T extends AnyEntityMap = RegisteredEntityMap> = <E extends Extract<keyof T, string> = Extract<keyof T, string>>(name: E) => EntityDecl<E> | undefined;
|
|
146
|
+
/**
|
|
147
|
+
* A function that retrieves an entity declaration by its name.
|
|
148
|
+
*/
|
|
149
|
+
export type GetSingletonEntityByName<T extends AnySingletonEntityMap = RegisteredSingletonEntityMap> = <E extends Extract<keyof T, string> = Extract<keyof T, string>>(name: E) => SingletonEntityDecl<E> | undefined;
|
|
150
|
+
/**
|
|
151
|
+
* A function that retrieves the singleton instance by its entity if available.
|
|
152
|
+
*/
|
|
153
|
+
export type GetSingletonInstance<T extends AnySingletonEntityMap = RegisteredSingletonEntityMap> = <E extends Extract<keyof T, string> = Extract<keyof T, string>>(entity: E) => T[E] | undefined;
|
|
136
154
|
/**
|
|
137
155
|
* A type guard function that checks if a given string is a valid declaration name.
|
|
138
156
|
*/
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { isDecl, isDeclWithoutTypeParameters } from "./dsl/declarations/Decl.ts";
|
|
2
2
|
export { isEntityDecl, isEntityDeclWithParentReference } from "./dsl/declarations/EntityDecl.ts";
|
|
3
3
|
export { isEnumDecl } from "./dsl/declarations/EnumDecl.ts";
|
|
4
|
+
export { isSingletonEntityDecl } from "./dsl/declarations/SingletonEntityDecl.ts";
|
|
4
5
|
export { isTypeAliasDecl } from "./dsl/declarations/TypeAliasDecl.ts";
|
|
5
6
|
export { isArrayType } from "./dsl/types/ArrayType.ts";
|
|
6
7
|
export { isBooleanType } from "./dsl/types/BooleanType.ts";
|