@prisma-next/contract-authoring 0.7.0-dev.7 → 0.8.0-dev.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.
- package/dist/index.d.mts +57 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +32 -1
- package/dist/index.mjs.map +1 -0
- package/package.json +6 -6
- package/src/composed-helpers-scaffolding.ts +142 -0
- package/src/index.ts +10 -0
package/dist/index.d.mts
CHANGED
|
@@ -1,3 +1,59 @@
|
|
|
1
|
+
import { AuthoringEntityContext, AuthoringEntityTypeDescriptor, AuthoringEntityTypeNamespace } from "@prisma-next/framework-components/authoring";
|
|
2
|
+
|
|
3
|
+
//#region src/composed-helpers-scaffolding.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Family-agnostic merge / instantiation scaffolding for pack-bag-driven
|
|
6
|
+
* authoring contributions. The per-namespace shape (`field`, `type`,
|
|
7
|
+
* `entityTypes`) is parameterized by the discriminator key so each
|
|
8
|
+
* namespace can reuse the same extractor + cross-pack merger without
|
|
9
|
+
* re-deriving the template per family. Call sites flatten merged
|
|
10
|
+
* `entityTypes` onto the user-facing top-level helpers surface
|
|
11
|
+
* alongside the built-in `model` / `rel` (e.g. `helpers.enum(...)`).
|
|
12
|
+
* The contribution data structure stays as
|
|
13
|
+
* `authoring.entityTypes.<name>` — pack authors keep contributing
|
|
14
|
+
* through the namespace; the composed-helpers template performs the
|
|
15
|
+
* rename in the type system.
|
|
16
|
+
*
|
|
17
|
+
* SQL-specific composition (the `field` / `model` / `rel` / `type` core
|
|
18
|
+
* helpers, the SQL index-types merge) lives in the SQL contract-ts
|
|
19
|
+
* package and imports from here.
|
|
20
|
+
*/
|
|
21
|
+
type UnionToIntersection<U> = (U extends unknown ? (value: U) => void : never) extends ((value: infer I) => void) ? I : never;
|
|
22
|
+
type AuthoringNamespaceKey = 'field' | 'type' | 'entityTypes';
|
|
23
|
+
type ExtractAuthoringNamespaceFromPack<Pack, Key extends AuthoringNamespaceKey, EmptyNamespace> = Pack extends {
|
|
24
|
+
readonly authoring?: { readonly [P in Key]?: infer Namespace };
|
|
25
|
+
} ? Namespace extends Record<string, unknown> ? Namespace : EmptyNamespace : EmptyNamespace;
|
|
26
|
+
type MergeExtensionAuthoringNamespaces<ExtensionPacks, Key extends AuthoringNamespaceKey, EmptyNamespace = Record<never, never>> = ExtensionPacks extends Record<string, unknown> ? keyof ExtensionPacks extends never ? EmptyNamespace : UnionToIntersection<{ [K in keyof ExtensionPacks]: ExtractAuthoringNamespaceFromPack<ExtensionPacks[K], Key, EmptyNamespace> }[keyof ExtensionPacks]> : EmptyNamespace;
|
|
27
|
+
/**
|
|
28
|
+
* Entity-helper shape derivation. Mirrors `FieldHelpersFromNamespace` /
|
|
29
|
+
* `TypeHelpersFromNamespace` in the SQL package: leaf descriptors become
|
|
30
|
+
* callable helpers; nested namespaces recurse.
|
|
31
|
+
*/
|
|
32
|
+
type ExtractFactoryInputAndOutput<Descriptor extends AuthoringEntityTypeDescriptor> = Descriptor['output'] extends {
|
|
33
|
+
readonly factory: (input: infer Input, ctx: AuthoringEntityContext) => infer Output;
|
|
34
|
+
} ? {
|
|
35
|
+
input: Input;
|
|
36
|
+
output: Output;
|
|
37
|
+
} : {
|
|
38
|
+
input: unknown;
|
|
39
|
+
output: unknown;
|
|
40
|
+
};
|
|
41
|
+
type EntityHelperFunction<Descriptor extends AuthoringEntityTypeDescriptor> = ExtractFactoryInputAndOutput<Descriptor> extends {
|
|
42
|
+
input: infer Input;
|
|
43
|
+
output: infer Output;
|
|
44
|
+
} ? (input: Input) => Output : never;
|
|
45
|
+
type EntityHelpersFromNamespace<Namespace> = { readonly [K in keyof Namespace]: Namespace[K] extends AuthoringEntityTypeDescriptor ? EntityHelperFunction<Namespace[K]> : Namespace[K] extends Record<string, unknown> ? EntityHelpersFromNamespace<Namespace[K]> : never };
|
|
46
|
+
interface EntityHelperFactoryOptions {
|
|
47
|
+
readonly ctx: AuthoringEntityContext;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Walks an entity-type namespace (after cross-pack merge) and produces the
|
|
51
|
+
* runtime callable surface mirroring its tree shape. Each leaf
|
|
52
|
+
* descriptor becomes a function `(input) => factory(input, ctx)`;
|
|
53
|
+
* nested namespace objects recurse.
|
|
54
|
+
*/
|
|
55
|
+
declare function createEntityHelpersFromNamespace(namespace: AuthoringEntityTypeNamespace, options: EntityHelperFactoryOptions, path?: readonly string[]): Record<string, unknown>;
|
|
56
|
+
//#endregion
|
|
1
57
|
//#region src/descriptors.d.ts
|
|
2
58
|
interface IndexDef {
|
|
3
59
|
readonly columns: readonly string[];
|
|
@@ -10,5 +66,5 @@ interface ForeignKeyDefaultsState {
|
|
|
10
66
|
readonly index: boolean;
|
|
11
67
|
}
|
|
12
68
|
//#endregion
|
|
13
|
-
export { type ForeignKeyDefaultsState, type IndexDef };
|
|
69
|
+
export { type AuthoringNamespaceKey, type EntityHelperFactoryOptions, type EntityHelperFunction, type EntityHelpersFromNamespace, type ExtractAuthoringNamespaceFromPack, type ForeignKeyDefaultsState, type IndexDef, type MergeExtensionAuthoringNamespaces, type UnionToIntersection, createEntityHelpersFromNamespace };
|
|
14
70
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/descriptors.ts"],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/composed-helpers-scaffolding.ts","../src/descriptors.ts"],"mappings":";;;;;AAyBA;;;;;;;;;;;;;AAMA;;KANY,mBAAA,OAA0B,CAAA,oBAAqB,KAAA,EAAO,CAAA,6BAChE,KAAA,sBAEE,CAAA;AAAA,KAGQ,qBAAA;AAAA,KAEA,iCAAA,mBAEE,qBAAA,oBAEV,IAAA;EAAA,SACO,SAAA,oBAA6B,GAAA;AAAA,IAEpC,SAAA,SAAkB,MAAA,oBAChB,SAAA,GACA,cAAA,GACF,cAAA;AAAA,KAEQ,iCAAA,6BAEE,qBAAA,mBACK,MAAA,kBAEjB,cAAA,SAAuB,MAAA,0BACb,cAAA,iBACJ,cAAA,GACA,mBAAA,eAEgB,cAAA,GAAiB,iCAAA,CAC3B,cAAA,CAAe,CAAA,GACf,GAAA,EACA,cAAA,UAEI,cAAA,KAEZ,cAAA;;;;;;KAOD,4BAAA,oBAAgD,6BAAA,IACnD,UAAA;EAAA,SACW,OAAA,GAAU,KAAA,eAAoB,GAAA,EAAK,sBAAA;AAAA;EAExC,KAAA,EAAO,KAAA;EAAO,MAAA,EAAQ,MAAA;AAAA;EACtB,KAAA;EAAgB,MAAA;AAAA;AAAA,KAEZ,oBAAA,oBAAwC,6BAAA,IAClD,4BAAA,CAA6B,UAAA;EAAsB,KAAA;EAAoB,MAAA;AAAA,KAClE,KAAA,EAAO,KAAA,KAAU,MAAA;AAAA,KAGZ,0BAAA,qCACW,SAAA,GAAY,SAAA,CAAU,CAAA,UAAW,6BAAA,GAClD,oBAAA,CAAqB,SAAA,CAAU,CAAA,KAC/B,SAAA,CAAU,CAAA,UAAW,MAAA,oBACnB,0BAAA,CAA2B,SAAA,CAAU,CAAA;AAAA,UAI5B,0BAAA;EAAA,SACN,GAAA,EAAK,sBAAA;AAAA;;;;;;;iBASA,gCAAA,CACd,SAAA,EAAW,4BAAA,EACX,OAAA,EAAS,0BAAA,EACT,IAAA,uBACC,MAAA;;;UCvGc,QAAA;EAAA,SACN,OAAA;EAAA,SACA,IAAA;EAAA,SACA,IAAA;EAAA,SACA,OAAA,GAAU,MAAA;AAAA;AAAA,UAGJ,uBAAA;EAAA,SACN,UAAA;EAAA,SACA,KAAA;AAAA"}
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1,32 @@
|
|
|
1
|
-
|
|
1
|
+
import { instantiateAuthoringEntityType } from "@prisma-next/framework-components/authoring";
|
|
2
|
+
//#region src/composed-helpers-scaffolding.ts
|
|
3
|
+
/**
|
|
4
|
+
* Walks an entity-type namespace (after cross-pack merge) and produces the
|
|
5
|
+
* runtime callable surface mirroring its tree shape. Each leaf
|
|
6
|
+
* descriptor becomes a function `(input) => factory(input, ctx)`;
|
|
7
|
+
* nested namespace objects recurse.
|
|
8
|
+
*/
|
|
9
|
+
function createEntityHelpersFromNamespace(namespace, options, path = []) {
|
|
10
|
+
const result = {};
|
|
11
|
+
for (const [key, value] of Object.entries(namespace)) {
|
|
12
|
+
const currentPath = [...path, key];
|
|
13
|
+
if (isLeafEntityDescriptor(value)) {
|
|
14
|
+
result[key] = createEntityHelper(currentPath.join("."), value, options);
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) result[key] = createEntityHelpersFromNamespace(value, options, currentPath);
|
|
18
|
+
}
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
function isLeafEntityDescriptor(value) {
|
|
22
|
+
if (typeof value !== "object" || value === null || value.kind !== "entity") return false;
|
|
23
|
+
const discriminator = value.discriminator;
|
|
24
|
+
return typeof discriminator === "string" && discriminator.length > 0;
|
|
25
|
+
}
|
|
26
|
+
function createEntityHelper(helperPath, descriptor, options) {
|
|
27
|
+
return (...args) => instantiateAuthoringEntityType(helperPath, descriptor, args, options.ctx);
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { createEntityHelpersFromNamespace };
|
|
31
|
+
|
|
32
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/composed-helpers-scaffolding.ts"],"sourcesContent":["import type {\n AuthoringEntityContext,\n AuthoringEntityTypeDescriptor,\n AuthoringEntityTypeNamespace,\n} from '@prisma-next/framework-components/authoring';\nimport { instantiateAuthoringEntityType } from '@prisma-next/framework-components/authoring';\n\n/**\n * Family-agnostic merge / instantiation scaffolding for pack-bag-driven\n * authoring contributions. The per-namespace shape (`field`, `type`,\n * `entityTypes`) is parameterized by the discriminator key so each\n * namespace can reuse the same extractor + cross-pack merger without\n * re-deriving the template per family. Call sites flatten merged\n * `entityTypes` onto the user-facing top-level helpers surface\n * alongside the built-in `model` / `rel` (e.g. `helpers.enum(...)`).\n * The contribution data structure stays as\n * `authoring.entityTypes.<name>` — pack authors keep contributing\n * through the namespace; the composed-helpers template performs the\n * rename in the type system.\n *\n * SQL-specific composition (the `field` / `model` / `rel` / `type` core\n * helpers, the SQL index-types merge) lives in the SQL contract-ts\n * package and imports from here.\n */\n\nexport type UnionToIntersection<U> = (U extends unknown ? (value: U) => void : never) extends (\n value: infer I,\n) => void\n ? I\n : never;\n\nexport type AuthoringNamespaceKey = 'field' | 'type' | 'entityTypes';\n\nexport type ExtractAuthoringNamespaceFromPack<\n Pack,\n Key extends AuthoringNamespaceKey,\n EmptyNamespace,\n> = Pack extends {\n readonly authoring?: { readonly [P in Key]?: infer Namespace };\n}\n ? Namespace extends Record<string, unknown>\n ? Namespace\n : EmptyNamespace\n : EmptyNamespace;\n\nexport type MergeExtensionAuthoringNamespaces<\n ExtensionPacks,\n Key extends AuthoringNamespaceKey,\n EmptyNamespace = Record<never, never>,\n> =\n ExtensionPacks extends Record<string, unknown>\n ? keyof ExtensionPacks extends never\n ? EmptyNamespace\n : UnionToIntersection<\n {\n [K in keyof ExtensionPacks]: ExtractAuthoringNamespaceFromPack<\n ExtensionPacks[K],\n Key,\n EmptyNamespace\n >;\n }[keyof ExtensionPacks]\n >\n : EmptyNamespace;\n\n/**\n * Entity-helper shape derivation. Mirrors `FieldHelpersFromNamespace` /\n * `TypeHelpersFromNamespace` in the SQL package: leaf descriptors become\n * callable helpers; nested namespaces recurse.\n */\ntype ExtractFactoryInputAndOutput<Descriptor extends AuthoringEntityTypeDescriptor> =\n Descriptor['output'] extends {\n readonly factory: (input: infer Input, ctx: AuthoringEntityContext) => infer Output;\n }\n ? { input: Input; output: Output }\n : { input: unknown; output: unknown };\n\nexport type EntityHelperFunction<Descriptor extends AuthoringEntityTypeDescriptor> =\n ExtractFactoryInputAndOutput<Descriptor> extends { input: infer Input; output: infer Output }\n ? (input: Input) => Output\n : never;\n\nexport type EntityHelpersFromNamespace<Namespace> = {\n readonly [K in keyof Namespace]: Namespace[K] extends AuthoringEntityTypeDescriptor\n ? EntityHelperFunction<Namespace[K]>\n : Namespace[K] extends Record<string, unknown>\n ? EntityHelpersFromNamespace<Namespace[K]>\n : never;\n};\n\nexport interface EntityHelperFactoryOptions {\n readonly ctx: AuthoringEntityContext;\n}\n\n/**\n * Walks an entity-type namespace (after cross-pack merge) and produces the\n * runtime callable surface mirroring its tree shape. Each leaf\n * descriptor becomes a function `(input) => factory(input, ctx)`;\n * nested namespace objects recurse.\n */\nexport function createEntityHelpersFromNamespace(\n namespace: AuthoringEntityTypeNamespace,\n options: EntityHelperFactoryOptions,\n path: readonly string[] = [],\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(namespace)) {\n const currentPath = [...path, key];\n if (isLeafEntityDescriptor(value)) {\n result[key] = createEntityHelper(currentPath.join('.'), value, options);\n continue;\n }\n if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n result[key] = createEntityHelpersFromNamespace(\n value as AuthoringEntityTypeNamespace,\n options,\n currentPath,\n );\n }\n }\n return result;\n}\n\nfunction isLeafEntityDescriptor(value: unknown): value is AuthoringEntityTypeDescriptor {\n if (\n typeof value !== 'object' ||\n value === null ||\n (value as { kind?: unknown }).kind !== 'entity'\n ) {\n return false;\n }\n const discriminator = (value as { discriminator?: unknown }).discriminator;\n return typeof discriminator === 'string' && discriminator.length > 0;\n}\n\nfunction createEntityHelper(\n helperPath: string,\n descriptor: AuthoringEntityTypeDescriptor,\n options: EntityHelperFactoryOptions,\n): (...args: readonly unknown[]) => unknown {\n return (...args: readonly unknown[]) =>\n instantiateAuthoringEntityType(helperPath, descriptor, args, options.ctx);\n}\n"],"mappings":";;;;;;;;AAmGA,SAAgB,iCACd,WACA,SACA,OAA0B,EAAE,EACH;CACzB,MAAM,SAAkC,EAAE;CAC1C,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,UAAU,EAAE;EACpD,MAAM,cAAc,CAAC,GAAG,MAAM,IAAI;EAClC,IAAI,uBAAuB,MAAM,EAAE;GACjC,OAAO,OAAO,mBAAmB,YAAY,KAAK,IAAI,EAAE,OAAO,QAAQ;GACvE;;EAEF,IAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM,EACtE,OAAO,OAAO,iCACZ,OACA,SACA,YACD;;CAGL,OAAO;;AAGT,SAAS,uBAAuB,OAAwD;CACtF,IACE,OAAO,UAAU,YACjB,UAAU,QACT,MAA6B,SAAS,UAEvC,OAAO;CAET,MAAM,gBAAiB,MAAsC;CAC7D,OAAO,OAAO,kBAAkB,YAAY,cAAc,SAAS;;AAGrE,SAAS,mBACP,YACA,YACA,SAC0C;CAC1C,QAAQ,GAAG,SACT,+BAA+B,YAAY,YAAY,MAAM,QAAQ,IAAI"}
|
package/package.json
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/contract-authoring",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0-dev.1",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"description": "Target-agnostic authored storage descriptor types for Prisma Next",
|
|
8
|
-
"dependencies": {
|
|
8
|
+
"dependencies": {
|
|
9
|
+
"@prisma-next/framework-components": "0.8.0-dev.1"
|
|
10
|
+
},
|
|
9
11
|
"devDependencies": {
|
|
10
|
-
"@prisma-next/tsconfig": "0.
|
|
11
|
-
"@prisma-next/tsdown": "0.
|
|
12
|
+
"@prisma-next/tsconfig": "0.8.0-dev.1",
|
|
13
|
+
"@prisma-next/tsdown": "0.8.0-dev.1",
|
|
12
14
|
"tsdown": "0.22.0",
|
|
13
15
|
"typescript": "5.9.3",
|
|
14
16
|
"vitest": "4.1.5"
|
|
@@ -21,8 +23,6 @@
|
|
|
21
23
|
".": "./dist/index.mjs",
|
|
22
24
|
"./package.json": "./package.json"
|
|
23
25
|
},
|
|
24
|
-
"main": "./dist/index.mjs",
|
|
25
|
-
"module": "./dist/index.mjs",
|
|
26
26
|
"types": "./dist/index.d.mts",
|
|
27
27
|
"repository": {
|
|
28
28
|
"type": "git",
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AuthoringEntityContext,
|
|
3
|
+
AuthoringEntityTypeDescriptor,
|
|
4
|
+
AuthoringEntityTypeNamespace,
|
|
5
|
+
} from '@prisma-next/framework-components/authoring';
|
|
6
|
+
import { instantiateAuthoringEntityType } from '@prisma-next/framework-components/authoring';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Family-agnostic merge / instantiation scaffolding for pack-bag-driven
|
|
10
|
+
* authoring contributions. The per-namespace shape (`field`, `type`,
|
|
11
|
+
* `entityTypes`) is parameterized by the discriminator key so each
|
|
12
|
+
* namespace can reuse the same extractor + cross-pack merger without
|
|
13
|
+
* re-deriving the template per family. Call sites flatten merged
|
|
14
|
+
* `entityTypes` onto the user-facing top-level helpers surface
|
|
15
|
+
* alongside the built-in `model` / `rel` (e.g. `helpers.enum(...)`).
|
|
16
|
+
* The contribution data structure stays as
|
|
17
|
+
* `authoring.entityTypes.<name>` — pack authors keep contributing
|
|
18
|
+
* through the namespace; the composed-helpers template performs the
|
|
19
|
+
* rename in the type system.
|
|
20
|
+
*
|
|
21
|
+
* SQL-specific composition (the `field` / `model` / `rel` / `type` core
|
|
22
|
+
* helpers, the SQL index-types merge) lives in the SQL contract-ts
|
|
23
|
+
* package and imports from here.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
export type UnionToIntersection<U> = (U extends unknown ? (value: U) => void : never) extends (
|
|
27
|
+
value: infer I,
|
|
28
|
+
) => void
|
|
29
|
+
? I
|
|
30
|
+
: never;
|
|
31
|
+
|
|
32
|
+
export type AuthoringNamespaceKey = 'field' | 'type' | 'entityTypes';
|
|
33
|
+
|
|
34
|
+
export type ExtractAuthoringNamespaceFromPack<
|
|
35
|
+
Pack,
|
|
36
|
+
Key extends AuthoringNamespaceKey,
|
|
37
|
+
EmptyNamespace,
|
|
38
|
+
> = Pack extends {
|
|
39
|
+
readonly authoring?: { readonly [P in Key]?: infer Namespace };
|
|
40
|
+
}
|
|
41
|
+
? Namespace extends Record<string, unknown>
|
|
42
|
+
? Namespace
|
|
43
|
+
: EmptyNamespace
|
|
44
|
+
: EmptyNamespace;
|
|
45
|
+
|
|
46
|
+
export type MergeExtensionAuthoringNamespaces<
|
|
47
|
+
ExtensionPacks,
|
|
48
|
+
Key extends AuthoringNamespaceKey,
|
|
49
|
+
EmptyNamespace = Record<never, never>,
|
|
50
|
+
> =
|
|
51
|
+
ExtensionPacks extends Record<string, unknown>
|
|
52
|
+
? keyof ExtensionPacks extends never
|
|
53
|
+
? EmptyNamespace
|
|
54
|
+
: UnionToIntersection<
|
|
55
|
+
{
|
|
56
|
+
[K in keyof ExtensionPacks]: ExtractAuthoringNamespaceFromPack<
|
|
57
|
+
ExtensionPacks[K],
|
|
58
|
+
Key,
|
|
59
|
+
EmptyNamespace
|
|
60
|
+
>;
|
|
61
|
+
}[keyof ExtensionPacks]
|
|
62
|
+
>
|
|
63
|
+
: EmptyNamespace;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Entity-helper shape derivation. Mirrors `FieldHelpersFromNamespace` /
|
|
67
|
+
* `TypeHelpersFromNamespace` in the SQL package: leaf descriptors become
|
|
68
|
+
* callable helpers; nested namespaces recurse.
|
|
69
|
+
*/
|
|
70
|
+
type ExtractFactoryInputAndOutput<Descriptor extends AuthoringEntityTypeDescriptor> =
|
|
71
|
+
Descriptor['output'] extends {
|
|
72
|
+
readonly factory: (input: infer Input, ctx: AuthoringEntityContext) => infer Output;
|
|
73
|
+
}
|
|
74
|
+
? { input: Input; output: Output }
|
|
75
|
+
: { input: unknown; output: unknown };
|
|
76
|
+
|
|
77
|
+
export type EntityHelperFunction<Descriptor extends AuthoringEntityTypeDescriptor> =
|
|
78
|
+
ExtractFactoryInputAndOutput<Descriptor> extends { input: infer Input; output: infer Output }
|
|
79
|
+
? (input: Input) => Output
|
|
80
|
+
: never;
|
|
81
|
+
|
|
82
|
+
export type EntityHelpersFromNamespace<Namespace> = {
|
|
83
|
+
readonly [K in keyof Namespace]: Namespace[K] extends AuthoringEntityTypeDescriptor
|
|
84
|
+
? EntityHelperFunction<Namespace[K]>
|
|
85
|
+
: Namespace[K] extends Record<string, unknown>
|
|
86
|
+
? EntityHelpersFromNamespace<Namespace[K]>
|
|
87
|
+
: never;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export interface EntityHelperFactoryOptions {
|
|
91
|
+
readonly ctx: AuthoringEntityContext;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Walks an entity-type namespace (after cross-pack merge) and produces the
|
|
96
|
+
* runtime callable surface mirroring its tree shape. Each leaf
|
|
97
|
+
* descriptor becomes a function `(input) => factory(input, ctx)`;
|
|
98
|
+
* nested namespace objects recurse.
|
|
99
|
+
*/
|
|
100
|
+
export function createEntityHelpersFromNamespace(
|
|
101
|
+
namespace: AuthoringEntityTypeNamespace,
|
|
102
|
+
options: EntityHelperFactoryOptions,
|
|
103
|
+
path: readonly string[] = [],
|
|
104
|
+
): Record<string, unknown> {
|
|
105
|
+
const result: Record<string, unknown> = {};
|
|
106
|
+
for (const [key, value] of Object.entries(namespace)) {
|
|
107
|
+
const currentPath = [...path, key];
|
|
108
|
+
if (isLeafEntityDescriptor(value)) {
|
|
109
|
+
result[key] = createEntityHelper(currentPath.join('.'), value, options);
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
113
|
+
result[key] = createEntityHelpersFromNamespace(
|
|
114
|
+
value as AuthoringEntityTypeNamespace,
|
|
115
|
+
options,
|
|
116
|
+
currentPath,
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return result;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function isLeafEntityDescriptor(value: unknown): value is AuthoringEntityTypeDescriptor {
|
|
124
|
+
if (
|
|
125
|
+
typeof value !== 'object' ||
|
|
126
|
+
value === null ||
|
|
127
|
+
(value as { kind?: unknown }).kind !== 'entity'
|
|
128
|
+
) {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
const discriminator = (value as { discriminator?: unknown }).discriminator;
|
|
132
|
+
return typeof discriminator === 'string' && discriminator.length > 0;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function createEntityHelper(
|
|
136
|
+
helperPath: string,
|
|
137
|
+
descriptor: AuthoringEntityTypeDescriptor,
|
|
138
|
+
options: EntityHelperFactoryOptions,
|
|
139
|
+
): (...args: readonly unknown[]) => unknown {
|
|
140
|
+
return (...args: readonly unknown[]) =>
|
|
141
|
+
instantiateAuthoringEntityType(helperPath, descriptor, args, options.ctx);
|
|
142
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1 +1,11 @@
|
|
|
1
|
+
export type {
|
|
2
|
+
AuthoringNamespaceKey,
|
|
3
|
+
EntityHelperFactoryOptions,
|
|
4
|
+
EntityHelperFunction,
|
|
5
|
+
EntityHelpersFromNamespace,
|
|
6
|
+
ExtractAuthoringNamespaceFromPack,
|
|
7
|
+
MergeExtensionAuthoringNamespaces,
|
|
8
|
+
UnionToIntersection,
|
|
9
|
+
} from './composed-helpers-scaffolding';
|
|
10
|
+
export { createEntityHelpersFromNamespace } from './composed-helpers-scaffolding';
|
|
1
11
|
export type { ForeignKeyDefaultsState, IndexDef } from './descriptors';
|