@conduit-client/generator-ts 3.16.0 → 3.17.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.
- package/dist/types/v1/files/file.d.ts +14 -0
- package/dist/types/v1/generators/bindings-generator.d.ts +56 -0
- package/dist/types/v1/normalization/graphql-type-registry-generator.d.ts +3 -1
- package/dist/types/v1/normalization/type-registry-generator.d.ts +3 -1
- package/dist/types/v1/types/type-definition.d.ts +4 -0
- package/dist/v1/index.js +196 -11
- package/dist/v1/index.js.map +1 -1
- package/package.json +7 -7
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type NamedService, type ServiceDescriptor } from '@conduit-client/utils';
|
|
2
2
|
import { Code } from './code';
|
|
3
|
+
import type { ImportableTypeReference, ImportableValueReference } from './code';
|
|
3
4
|
/**
|
|
4
5
|
* Service that builds TypeScript source files.
|
|
5
6
|
*/
|
|
@@ -66,6 +67,19 @@ export declare class File {
|
|
|
66
67
|
* @returns this
|
|
67
68
|
*/
|
|
68
69
|
pushTo(block: Symbol, ...chunks: any[]): this;
|
|
70
|
+
private reExports;
|
|
71
|
+
/** Registers a value re-export: `export { symbol [as alias] } from "…";` */
|
|
72
|
+
reExport(ref: ImportableValueReference & {
|
|
73
|
+
filename: string;
|
|
74
|
+
exportedSymbol: string;
|
|
75
|
+
}, alias?: string): void;
|
|
76
|
+
/** Registers a type re-export: `export type { symbol [as alias] } from "…";` */
|
|
77
|
+
reExportType(ref: ImportableTypeReference & {
|
|
78
|
+
filename: string;
|
|
79
|
+
exportedSymbol: string;
|
|
80
|
+
}, alias?: string): void;
|
|
81
|
+
/** Registers a wildcard type re-export: `export type * from "…";` */
|
|
82
|
+
reExportTypeAll(targetFilename: string): void;
|
|
69
83
|
/**
|
|
70
84
|
* Returns the code for this File, with ImportableReferences resolved.
|
|
71
85
|
*
|
|
@@ -7,6 +7,7 @@ import { WireAdapterBindingGenerator } from './wire-binding-generator';
|
|
|
7
7
|
import { GraphQLImperativeAdapterBindingGenerator } from './graphql-imperative-binding-generator';
|
|
8
8
|
import { GraphQLWireAdapterBindingGenerator } from './graphql-wire-binding-generator';
|
|
9
9
|
import { GraphQLMutationAdapterBindingGenerator } from './graphql-mutation-binding-generator';
|
|
10
|
+
import type { File, ImportableValueReference } from '../files';
|
|
10
11
|
import type { ICommandModel, ServiceDependency } from '../model/base-command-model';
|
|
11
12
|
import type { NamedTypeRegistryGeneratorService, TypeRegistryGenerator } from '../normalization/type-registry-generator';
|
|
12
13
|
import type { NamedGraphQLTypeRegistryGeneratorService } from '../normalization/graphql-type-registry-generator';
|
|
@@ -42,6 +43,7 @@ export declare class BindingsGenerator {
|
|
|
42
43
|
protected rootTypesInstantiationSymbol: symbol;
|
|
43
44
|
protected exportsTypeMembersSymbol: symbol;
|
|
44
45
|
protected exportsAssignmentsSymbol: symbol;
|
|
46
|
+
protected initGeneratedBindingsExtraParamsSymbol: symbol;
|
|
45
47
|
/**
|
|
46
48
|
* Template for generating the binding structure in the output file.
|
|
47
49
|
* Includes placeholders for adapter declarations, service requirements, and adapter invocations.
|
|
@@ -62,6 +64,60 @@ export declare class BindingsGenerator {
|
|
|
62
64
|
* This method coordinates with individual binding generators to compile the necessary elements into a single file.
|
|
63
65
|
*/
|
|
64
66
|
build(): void;
|
|
67
|
+
/**
|
|
68
|
+
* Emits re-export statements from bindings-core so that custom bindings modules
|
|
69
|
+
* can import generated internals from a single stable entry point.
|
|
70
|
+
*/
|
|
71
|
+
protected buildReExports(coreFile: File, refs: {
|
|
72
|
+
typeRegistryRef?: ImportableValueReference & {
|
|
73
|
+
filename: string;
|
|
74
|
+
exportedSymbol: string;
|
|
75
|
+
};
|
|
76
|
+
graphqlTypeRegistryRef?: ImportableValueReference & {
|
|
77
|
+
filename: string;
|
|
78
|
+
exportedSymbol: string;
|
|
79
|
+
};
|
|
80
|
+
}): void;
|
|
81
|
+
/**
|
|
82
|
+
* Re-exports per-command symbols: `buildCommandClass` (aliased to `build<Capitalized>CommandClass`),
|
|
83
|
+
* `CONFIG_SCHEMA` (aliased to `<UPPER>_CONFIG_SCHEMA`), and the `Config` type
|
|
84
|
+
* (aliased to `<Capitalized>Config`).
|
|
85
|
+
*
|
|
86
|
+
* The CONFIG_SCHEMA alias uses a simple uppercase of the commandName (e.g. `getItemsByIds`
|
|
87
|
+
* becomes `GETITEMSBYIDS_CONFIG_SCHEMA`) to avoid ambiguity from word-boundary heuristics.
|
|
88
|
+
*/
|
|
89
|
+
protected buildCommandReExports(coreFile: File): void;
|
|
90
|
+
/**
|
|
91
|
+
* Re-exports the `TypeRegistry` (REST) and/or `GraphQLTypeRegistry` (GraphQL) classes
|
|
92
|
+
* so custom bindings can construct or extend them.
|
|
93
|
+
*/
|
|
94
|
+
protected buildTypeRegistryReExports(coreFile: File, refs: {
|
|
95
|
+
typeRegistryRef?: ImportableValueReference & {
|
|
96
|
+
filename: string;
|
|
97
|
+
exportedSymbol: string;
|
|
98
|
+
};
|
|
99
|
+
graphqlTypeRegistryRef?: ImportableValueReference & {
|
|
100
|
+
filename: string;
|
|
101
|
+
exportedSymbol: string;
|
|
102
|
+
};
|
|
103
|
+
}): void;
|
|
104
|
+
/**
|
|
105
|
+
* Re-exports individual generated type repository classes (e.g. `RecordRepresentationRepository`)
|
|
106
|
+
* so custom bindings can extend or reference them without importing from internal paths.
|
|
107
|
+
*
|
|
108
|
+
* If both REST and GraphQL registries produce a repository with the same exported symbol,
|
|
109
|
+
* the GraphQL version is aliased with a `GraphQL_` prefix to avoid collisions.
|
|
110
|
+
*/
|
|
111
|
+
protected buildTypeRepositoryReExports(coreFile: File): void;
|
|
112
|
+
/**
|
|
113
|
+
* Re-exports all generated entity types so custom bindings can reference
|
|
114
|
+
* domain models (e.g. `api_Item`) without importing from internal paths.
|
|
115
|
+
*
|
|
116
|
+
* The barrel `types/index.ts` is built incrementally by TypeDefinitionService
|
|
117
|
+
* as types are generated; we just re-export it from bindings-core.
|
|
118
|
+
* GraphQL-only specs produce no REST types so the barrel is never created.
|
|
119
|
+
*/
|
|
120
|
+
protected buildEntityTypeReExports(coreFile: File): void;
|
|
65
121
|
buildTypeInvalidation(typesWithNormalization: TypeRegistryGenerator['invalidatableTypes']): {
|
|
66
122
|
definitions: Code[];
|
|
67
123
|
declarations: Code[];
|
|
@@ -4,7 +4,7 @@ import type { NamedFileService, File, ImportableValueReference, ImportableRefere
|
|
|
4
4
|
import type { NamedService } from '@conduit-client/utils';
|
|
5
5
|
import type { GraphQLSchemaModel } from '../model/graphql-schema-model';
|
|
6
6
|
import type { GraphQLObjectType } from './graphql-type-generator';
|
|
7
|
-
type GraphQLTypeRepositoryReference = {
|
|
7
|
+
export type GraphQLTypeRepositoryReference = {
|
|
8
8
|
propertyName: string;
|
|
9
9
|
typeClassRef: ImportableValueReference;
|
|
10
10
|
typeName: string;
|
|
@@ -16,6 +16,7 @@ type Options = {
|
|
|
16
16
|
export type IGraphQLTypeRegistryGeneratorService = {
|
|
17
17
|
build(): ImportableValueReference;
|
|
18
18
|
buildGraphQLType(options: Options): GraphQLTypeRepositoryReference;
|
|
19
|
+
readonly registeredTypes: ReadonlyMap<string, GraphQLTypeRepositoryReference>;
|
|
19
20
|
};
|
|
20
21
|
export type NamedGraphQLTypeRegistryGeneratorService<Name extends string = 'graphqlTypeRegistryGenerator'> = NamedService<Name, IGraphQLTypeRegistryGeneratorService>;
|
|
21
22
|
export declare const NAMED_CACHE_CONTROLLER_SERVICE: ImportableReference;
|
|
@@ -35,6 +36,7 @@ export declare class GraphQLTypeRegistryGenerator implements IGraphQLTypeRegistr
|
|
|
35
36
|
protected typeInstantiationsSymbol: symbol;
|
|
36
37
|
protected typeGettersSymbol: symbol;
|
|
37
38
|
cache: Map<string, GraphQLTypeRepositoryReference>;
|
|
39
|
+
get registeredTypes(): ReadonlyMap<string, GraphQLTypeRepositoryReference>;
|
|
38
40
|
private get file();
|
|
39
41
|
private buildFile;
|
|
40
42
|
get template(): (symbol | import("..").Code)[];
|
|
@@ -6,7 +6,7 @@ import type { INormalizedTypeGenerator } from './normalized-type-generator';
|
|
|
6
6
|
import type { NamedService } from '@conduit-client/utils';
|
|
7
7
|
import type { File, ImportableValueReference, NamedFileService } from '../files';
|
|
8
8
|
import type { NamedNormalizeGeneratorService } from './normalize-code-gen/normalize-generator-service';
|
|
9
|
-
type TypeRepositoryReference = {
|
|
9
|
+
export type TypeRepositoryReference = {
|
|
10
10
|
propertyName: string;
|
|
11
11
|
typeClassRef: ImportableValueReference;
|
|
12
12
|
};
|
|
@@ -20,6 +20,7 @@ export type ITypeRegistryGeneratorService = {
|
|
|
20
20
|
build(): ImportableValueReference;
|
|
21
21
|
buildType(type: Type, options: Options): TypeRepositoryReference;
|
|
22
22
|
invalidatableTypes: TypeRepositoryReference[];
|
|
23
|
+
readonly registeredTypes: ReadonlyMap<string, TypeRepositoryReference>;
|
|
23
24
|
};
|
|
24
25
|
export type NamedTypeRegistryGeneratorService<Name extends string = 'typeRegistryGenerator'> = NamedService<Name, ITypeRegistryGeneratorService>;
|
|
25
26
|
/**
|
|
@@ -40,6 +41,7 @@ export declare class TypeRegistryGenerator implements ITypeRegistryGeneratorServ
|
|
|
40
41
|
* after all operations precessing is complete.
|
|
41
42
|
*/
|
|
42
43
|
invalidatableTypes: TypeRepositoryReference[];
|
|
44
|
+
get registeredTypes(): ReadonlyMap<string, TypeRepositoryReference>;
|
|
43
45
|
private get file();
|
|
44
46
|
private buildFile;
|
|
45
47
|
get template(): (symbol | Code)[];
|
|
@@ -9,6 +9,7 @@ export type TypeDefinitionForOptions = {
|
|
|
9
9
|
};
|
|
10
10
|
export type ITypeDefinitionService = {
|
|
11
11
|
build(type: Type | undefined): Code;
|
|
12
|
+
readonly hasTypes: boolean;
|
|
12
13
|
};
|
|
13
14
|
export type NamedTypeDefinitionService = NamedService<'typeDefinition', ITypeDefinitionService>;
|
|
14
15
|
export declare class TypeDefinitionService implements ITypeDefinitionService {
|
|
@@ -16,6 +17,7 @@ export declare class TypeDefinitionService implements ITypeDefinitionService {
|
|
|
16
17
|
private fileFor;
|
|
17
18
|
constructor(services: NamedAPIService & NamedFileService, fileFor?: (typename: string) => string);
|
|
18
19
|
cache: Map<string, ImportableReference>;
|
|
20
|
+
get hasTypes(): boolean;
|
|
19
21
|
build(type: Type | undefined, useReferences?: boolean): Code;
|
|
20
22
|
buildTypeCode(t: Type, options: TypeDefinitionForOptions): Code;
|
|
21
23
|
buildReferenceCode(refType: RefType, options: TypeDefinitionForOptions): Code;
|
|
@@ -32,4 +34,6 @@ export declare function typeDefinitions(services: NamedAPIService & NamedFileSer
|
|
|
32
34
|
fileFor?: (typename: string) => string;
|
|
33
35
|
}): TypeDefinitionService;
|
|
34
36
|
export declare const FILE_PER_TYPE: (typename: string) => string;
|
|
37
|
+
export declare const TYPES_SINGLE_FILE_PATH = "types/types.ts";
|
|
35
38
|
export declare const SINGLE_FILE: (_: string) => string;
|
|
39
|
+
export declare const TYPES_INDEX_PATH = "types/index.ts";
|
package/dist/v1/index.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import * as path from "path";
|
|
7
7
|
import { resolve } from "path";
|
|
8
8
|
import * as prettier from "prettier";
|
|
9
|
-
import { toTypeScriptSafeIdentifier, JSONStringify, ok, err, stringIsVersion, stableJSONStringify } from "@conduit-client/utils";
|
|
9
|
+
import { toTypeScriptSafeIdentifier, JSONStringify, ok, err, capitalizeFirst, stringIsVersion, stableJSONStringify } from "@conduit-client/utils";
|
|
10
10
|
import * as fs from "fs";
|
|
11
11
|
import { readFileSync } from "fs";
|
|
12
12
|
import { isAnyType, isRefType, isAllOfType, isOneOfType, isNotType, isObjectType as isObjectType$2, isDiscriminatedObjectType, isArrayType, isScalar, isEnumType as isEnumType$1, isNilType, isCanonicalStringType, isCanonicalNumberType, isBooleanType, typesEqual, isIdentifiableType as isIdentifiableType$1, canonicalizeType } from "@conduit-client/model/v1";
|
|
@@ -116,6 +116,10 @@ class Files {
|
|
|
116
116
|
function fileService() {
|
|
117
117
|
return new Files();
|
|
118
118
|
}
|
|
119
|
+
function resolveRelativeImportPath(fromFile, toFile) {
|
|
120
|
+
const rel = path.relative(path.dirname(fromFile), toFile).replace(/\.(js|ts)$/, "");
|
|
121
|
+
return rel.startsWith(".") ? rel : "./" + rel;
|
|
122
|
+
}
|
|
119
123
|
class Imports {
|
|
120
124
|
/**
|
|
121
125
|
* Constructor
|
|
@@ -156,10 +160,7 @@ class Imports {
|
|
|
156
160
|
}
|
|
157
161
|
let from;
|
|
158
162
|
if ("filename" in ref) {
|
|
159
|
-
from =
|
|
160
|
-
if (!from.startsWith(".")) {
|
|
161
|
-
from = "./" + from;
|
|
162
|
-
}
|
|
163
|
+
from = resolveRelativeImportPath(this.filename, ref.filename);
|
|
163
164
|
} else {
|
|
164
165
|
from = ref.module;
|
|
165
166
|
}
|
|
@@ -224,11 +225,59 @@ class Imports {
|
|
|
224
225
|
].join("");
|
|
225
226
|
}
|
|
226
227
|
}
|
|
228
|
+
class ReExports {
|
|
229
|
+
constructor(filename) {
|
|
230
|
+
this.filename = filename;
|
|
231
|
+
this.entries = {};
|
|
232
|
+
this.typeAllPaths = /* @__PURE__ */ new Set();
|
|
233
|
+
}
|
|
234
|
+
resolveFrom(targetFilename) {
|
|
235
|
+
return resolveRelativeImportPath(this.filename, targetFilename);
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Registers a value or type re-export: `export { symbol [as alias] } from "…";`
|
|
239
|
+
* @param targetFilename the filename of the target file to re-export
|
|
240
|
+
* @param exportedSymbol the symbol to export
|
|
241
|
+
* @param alias an optional alias for the symbol
|
|
242
|
+
* @param isType true if the re-export is for a type; false if it is for a value
|
|
243
|
+
*/
|
|
244
|
+
add(targetFilename, exportedSymbol, alias, isType2) {
|
|
245
|
+
const from = this.resolveFrom(targetFilename);
|
|
246
|
+
if (!this.entries[from]) {
|
|
247
|
+
this.entries[from] = [];
|
|
248
|
+
}
|
|
249
|
+
this.entries[from].push({ exportedSymbol, alias, isType: isType2 });
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Registers a wildcard type re-export: `export type * from "…";`
|
|
253
|
+
* @param targetFilename the filename of the target file to re-export
|
|
254
|
+
*/
|
|
255
|
+
addTypeAll(targetFilename) {
|
|
256
|
+
this.typeAllPaths.add(this.resolveFrom(targetFilename));
|
|
257
|
+
}
|
|
258
|
+
toString() {
|
|
259
|
+
const statements = [];
|
|
260
|
+
for (const from of Object.keys(this.entries)) {
|
|
261
|
+
const entries = this.entries[from];
|
|
262
|
+
for (const isType2 of [false, true]) {
|
|
263
|
+
const clauses = entries.filter((e) => e.isType === isType2).map((e) => e.alias ? `${e.exportedSymbol} as ${e.alias}` : e.exportedSymbol).join(",");
|
|
264
|
+
if (clauses) {
|
|
265
|
+
statements.push(`export ${isType2 ? "type " : ""}{${clauses}} from '${from}';`);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
for (const from of this.typeAllPaths) {
|
|
270
|
+
statements.push(`export type * from '${from}';`);
|
|
271
|
+
}
|
|
272
|
+
return statements.length > 0 ? statements.join("") : "";
|
|
273
|
+
}
|
|
274
|
+
}
|
|
227
275
|
const _File = class _File {
|
|
228
276
|
constructor(filename) {
|
|
229
277
|
this.filename = filename;
|
|
230
278
|
this.blocks = /* @__PURE__ */ new Map();
|
|
231
279
|
this.template = [_File.DEFAULT_BLOCK];
|
|
280
|
+
this.reExports = new ReExports(this.filename);
|
|
232
281
|
}
|
|
233
282
|
/**
|
|
234
283
|
* Appends new chunks of code to the default code block. Chunks are handled
|
|
@@ -256,6 +305,18 @@ const _File = class _File {
|
|
|
256
305
|
code2.push(...chunks);
|
|
257
306
|
return this;
|
|
258
307
|
}
|
|
308
|
+
/** Registers a value re-export: `export { symbol [as alias] } from "…";` */
|
|
309
|
+
reExport(ref, alias) {
|
|
310
|
+
this.reExports.add(ref.filename, ref.exportedSymbol, alias, false);
|
|
311
|
+
}
|
|
312
|
+
/** Registers a type re-export: `export type { symbol [as alias] } from "…";` */
|
|
313
|
+
reExportType(ref, alias) {
|
|
314
|
+
this.reExports.add(ref.filename, ref.exportedSymbol, alias, true);
|
|
315
|
+
}
|
|
316
|
+
/** Registers a wildcard type re-export: `export type * from "…";` */
|
|
317
|
+
reExportTypeAll(targetFilename) {
|
|
318
|
+
this.reExports.addTypeAll(targetFilename);
|
|
319
|
+
}
|
|
259
320
|
/**
|
|
260
321
|
* Returns the code for this File, with ImportableReferences resolved.
|
|
261
322
|
*
|
|
@@ -272,7 +333,7 @@ const _File = class _File {
|
|
|
272
333
|
const executableCode = finalCode.toString({
|
|
273
334
|
importStringifier: (ir) => imports.localSymbolFor(ir)
|
|
274
335
|
});
|
|
275
|
-
const code2 = imports.toString() + executableCode;
|
|
336
|
+
const code2 = imports.toString() + executableCode + this.reExports.toString();
|
|
276
337
|
if (options.prettified) {
|
|
277
338
|
try {
|
|
278
339
|
return prettier.format(code2, { parser: "typescript" });
|
|
@@ -395,6 +456,9 @@ class TypeDefinitionService {
|
|
|
395
456
|
this.fileFor = fileFor;
|
|
396
457
|
this.cache = /* @__PURE__ */ new Map();
|
|
397
458
|
}
|
|
459
|
+
get hasTypes() {
|
|
460
|
+
return this.cache.size > 0;
|
|
461
|
+
}
|
|
398
462
|
build(type, useReferences = true) {
|
|
399
463
|
return type ? this.buildTypeCode(type, {
|
|
400
464
|
referenceFor: (t) => {
|
|
@@ -581,6 +645,7 @@ class TypeDefinitionService {
|
|
|
581
645
|
this.cache.set(typename, result);
|
|
582
646
|
const declaration = code`export type ${exportedSymbol}=${this.build(type, false)};`;
|
|
583
647
|
this.services.file.build(filename).push(declaration);
|
|
648
|
+
this.services.file.build(TYPES_INDEX_PATH).reExportTypeAll(filename);
|
|
584
649
|
return result;
|
|
585
650
|
}
|
|
586
651
|
}
|
|
@@ -588,7 +653,9 @@ function typeDefinitions(services, options = {}) {
|
|
|
588
653
|
return new TypeDefinitionService(services, options.fileFor || SINGLE_FILE);
|
|
589
654
|
}
|
|
590
655
|
const FILE_PER_TYPE = (typename) => `types/${typename}.ts`;
|
|
591
|
-
const
|
|
656
|
+
const TYPES_SINGLE_FILE_PATH = "types/types.ts";
|
|
657
|
+
const SINGLE_FILE = (_) => TYPES_SINGLE_FILE_PATH;
|
|
658
|
+
const TYPES_INDEX_PATH = "types/index.ts";
|
|
592
659
|
const SCHEMA_FILE_PATH = "json-schema/index.ts";
|
|
593
660
|
const COMBINED_SCHEMA = {
|
|
594
661
|
filename: SCHEMA_FILE_PATH,
|
|
@@ -1453,6 +1520,9 @@ class TypeRegistryGenerator {
|
|
|
1453
1520
|
this.cache = /* @__PURE__ */ new Map();
|
|
1454
1521
|
this.invalidatableTypes = [];
|
|
1455
1522
|
}
|
|
1523
|
+
get registeredTypes() {
|
|
1524
|
+
return this.cache;
|
|
1525
|
+
}
|
|
1456
1526
|
get file() {
|
|
1457
1527
|
return this.buildFile();
|
|
1458
1528
|
}
|
|
@@ -2048,6 +2118,9 @@ class GraphQLTypeRegistryGenerator {
|
|
|
2048
2118
|
setGraphQLTypeGenerator(generator) {
|
|
2049
2119
|
this.graphqlTypeGenerator = generator;
|
|
2050
2120
|
}
|
|
2121
|
+
get registeredTypes() {
|
|
2122
|
+
return this.cache;
|
|
2123
|
+
}
|
|
2051
2124
|
get file() {
|
|
2052
2125
|
if (this._file) {
|
|
2053
2126
|
return this._file;
|
|
@@ -3530,6 +3603,9 @@ class BindingsGenerator {
|
|
|
3530
3603
|
this.rootTypesInstantiationSymbol = Symbol.for("rootTypesInstantiation");
|
|
3531
3604
|
this.exportsTypeMembersSymbol = Symbol.for("exportsTypeMembers");
|
|
3532
3605
|
this.exportsAssignmentsSymbol = Symbol.for("exportsAssignments");
|
|
3606
|
+
this.initGeneratedBindingsExtraParamsSymbol = Symbol.for(
|
|
3607
|
+
"initGeneratedBindingsExtraParams"
|
|
3608
|
+
);
|
|
3533
3609
|
}
|
|
3534
3610
|
/**
|
|
3535
3611
|
* Template for generating the binding structure in the output file.
|
|
@@ -3555,7 +3631,9 @@ class BindingsGenerator {
|
|
|
3555
3631
|
code`export const serviceRequirements=`,
|
|
3556
3632
|
this.serviceRequirementsSymbol,
|
|
3557
3633
|
code` as const;`,
|
|
3558
|
-
code`export function initGeneratedBindings
|
|
3634
|
+
code`export function initGeneratedBindings<S extends ${REQUESTED_SERVICES_TYPE}<typeof serviceRequirements>>(services: S, exports: BindingsExports`,
|
|
3635
|
+
this.initGeneratedBindingsExtraParamsSymbol,
|
|
3636
|
+
code`) {`,
|
|
3559
3637
|
this.typeRegistryInstantiationSymbol,
|
|
3560
3638
|
this.rootTypesInstantiationSymbol,
|
|
3561
3639
|
this.typeInvalidationDefinitionSymbol,
|
|
@@ -3703,11 +3781,18 @@ class BindingsGenerator {
|
|
|
3703
3781
|
const wrapperFilename = "artifacts/bindings.ts";
|
|
3704
3782
|
const wrapperFile = this.services.file.build(wrapperFilename);
|
|
3705
3783
|
wrapperFile.template = this.wrapperTemplate;
|
|
3784
|
+
let typeRegistryRef;
|
|
3785
|
+
let graphqlTypeRegistryRef;
|
|
3706
3786
|
if (this.hasRESTNormalization) {
|
|
3707
3787
|
const { typeRegistryGenerator } = this.services;
|
|
3788
|
+
typeRegistryRef = typeRegistryGenerator.build();
|
|
3789
|
+
coreFile.pushTo(
|
|
3790
|
+
this.initGeneratedBindingsExtraParamsSymbol,
|
|
3791
|
+
code`, typeRegistry?: ${typeRegistryRef}`
|
|
3792
|
+
);
|
|
3708
3793
|
coreFile.pushTo(
|
|
3709
3794
|
this.typeRegistryInstantiationSymbol,
|
|
3710
|
-
code`
|
|
3795
|
+
code`typeRegistry ??= new ${typeRegistryRef}(services);`
|
|
3711
3796
|
);
|
|
3712
3797
|
const { declarations, definitions } = this.buildTypeInvalidation(
|
|
3713
3798
|
typeRegistryGenerator.invalidatableTypes
|
|
@@ -3717,7 +3802,11 @@ class BindingsGenerator {
|
|
|
3717
3802
|
}
|
|
3718
3803
|
if (this.hasGraphQL) {
|
|
3719
3804
|
const { graphqlTypeRegistryGenerator } = this.services;
|
|
3720
|
-
|
|
3805
|
+
graphqlTypeRegistryRef = graphqlTypeRegistryGenerator.build();
|
|
3806
|
+
coreFile.pushTo(
|
|
3807
|
+
this.initGeneratedBindingsExtraParamsSymbol,
|
|
3808
|
+
code`, graphqlTypeRegistry?: ${graphqlTypeRegistryRef}`
|
|
3809
|
+
);
|
|
3721
3810
|
const firstGraphQLCommand = this.commandModels.find(
|
|
3722
3811
|
(model) => model.operationType === "graphql"
|
|
3723
3812
|
);
|
|
@@ -3737,7 +3826,7 @@ class BindingsGenerator {
|
|
|
3737
3826
|
}) : void 0;
|
|
3738
3827
|
coreFile.pushTo(
|
|
3739
3828
|
this.rootTypesInstantiationSymbol,
|
|
3740
|
-
code`
|
|
3829
|
+
code`graphqlTypeRegistry ??= new ${graphqlTypeRegistryRef}(services);
|
|
3741
3830
|
const ${QUERY_TYPE_VARIABLE_NAME} = graphqlTypeRegistry.${queryType.propertyName};`
|
|
3742
3831
|
);
|
|
3743
3832
|
if (mutationType) {
|
|
@@ -3801,6 +3890,100 @@ class BindingsGenerator {
|
|
|
3801
3890
|
"\n"
|
|
3802
3891
|
)
|
|
3803
3892
|
);
|
|
3893
|
+
this.buildReExports(coreFile, { typeRegistryRef, graphqlTypeRegistryRef });
|
|
3894
|
+
}
|
|
3895
|
+
/**
|
|
3896
|
+
* Emits re-export statements from bindings-core so that custom bindings modules
|
|
3897
|
+
* can import generated internals from a single stable entry point.
|
|
3898
|
+
*/
|
|
3899
|
+
buildReExports(coreFile, refs) {
|
|
3900
|
+
this.buildCommandReExports(coreFile);
|
|
3901
|
+
this.buildTypeRegistryReExports(coreFile, refs);
|
|
3902
|
+
this.buildTypeRepositoryReExports(coreFile);
|
|
3903
|
+
this.buildEntityTypeReExports(coreFile);
|
|
3904
|
+
}
|
|
3905
|
+
/**
|
|
3906
|
+
* Re-exports per-command symbols: `buildCommandClass` (aliased to `build<Capitalized>CommandClass`),
|
|
3907
|
+
* `CONFIG_SCHEMA` (aliased to `<UPPER>_CONFIG_SCHEMA`), and the `Config` type
|
|
3908
|
+
* (aliased to `<Capitalized>Config`).
|
|
3909
|
+
*
|
|
3910
|
+
* The CONFIG_SCHEMA alias uses a simple uppercase of the commandName (e.g. `getItemsByIds`
|
|
3911
|
+
* becomes `GETITEMSBYIDS_CONFIG_SCHEMA`) to avoid ambiguity from word-boundary heuristics.
|
|
3912
|
+
*/
|
|
3913
|
+
buildCommandReExports(coreFile) {
|
|
3914
|
+
for (const model of this.commandModels) {
|
|
3915
|
+
const capitalized = capitalizeFirst(model.commandName);
|
|
3916
|
+
const upper = model.commandName.toUpperCase();
|
|
3917
|
+
const buildRef = {
|
|
3918
|
+
filename: model.filePath,
|
|
3919
|
+
exportedSymbol: "buildCommandClass",
|
|
3920
|
+
isType: false
|
|
3921
|
+
};
|
|
3922
|
+
const schemaRef = {
|
|
3923
|
+
filename: model.filePath,
|
|
3924
|
+
exportedSymbol: "CONFIG_SCHEMA",
|
|
3925
|
+
isType: false
|
|
3926
|
+
};
|
|
3927
|
+
const configRef = {
|
|
3928
|
+
filename: model.filePath,
|
|
3929
|
+
exportedSymbol: "Config",
|
|
3930
|
+
isType: true
|
|
3931
|
+
};
|
|
3932
|
+
coreFile.reExport(buildRef, `build${capitalized}CommandClass`);
|
|
3933
|
+
coreFile.reExport(schemaRef, `${upper}_CONFIG_SCHEMA`);
|
|
3934
|
+
coreFile.reExportType(configRef, `${capitalized}Config`);
|
|
3935
|
+
}
|
|
3936
|
+
}
|
|
3937
|
+
/**
|
|
3938
|
+
* Re-exports the `TypeRegistry` (REST) and/or `GraphQLTypeRegistry` (GraphQL) classes
|
|
3939
|
+
* so custom bindings can construct or extend them.
|
|
3940
|
+
*/
|
|
3941
|
+
buildTypeRegistryReExports(coreFile, refs) {
|
|
3942
|
+
if (refs.typeRegistryRef) {
|
|
3943
|
+
coreFile.reExport(refs.typeRegistryRef);
|
|
3944
|
+
}
|
|
3945
|
+
if (refs.graphqlTypeRegistryRef) {
|
|
3946
|
+
coreFile.reExport(refs.graphqlTypeRegistryRef);
|
|
3947
|
+
}
|
|
3948
|
+
}
|
|
3949
|
+
/**
|
|
3950
|
+
* Re-exports individual generated type repository classes (e.g. `RecordRepresentationRepository`)
|
|
3951
|
+
* so custom bindings can extend or reference them without importing from internal paths.
|
|
3952
|
+
*
|
|
3953
|
+
* If both REST and GraphQL registries produce a repository with the same exported symbol,
|
|
3954
|
+
* the GraphQL version is aliased with a `GraphQL_` prefix to avoid collisions.
|
|
3955
|
+
*/
|
|
3956
|
+
buildTypeRepositoryReExports(coreFile) {
|
|
3957
|
+
const restRepos = this.hasRESTNormalization ? [...this.services.typeRegistryGenerator.registeredTypes.values()] : [];
|
|
3958
|
+
const graphqlRepos = this.hasGraphQL ? [...this.services.graphqlTypeRegistryGenerator.registeredTypes.values()] : [];
|
|
3959
|
+
const restNames = new Set(restRepos.map((r) => r.typeClassRef.exportedSymbol));
|
|
3960
|
+
const graphqlNames = new Set(graphqlRepos.map((r) => r.typeClassRef.exportedSymbol));
|
|
3961
|
+
const conflicts = new Set([...restNames].filter((n) => graphqlNames.has(n)));
|
|
3962
|
+
for (const { typeClassRef } of restRepos) {
|
|
3963
|
+
if (!("filename" in typeClassRef) || !typeClassRef.exportedSymbol) continue;
|
|
3964
|
+
coreFile.reExport(typeClassRef);
|
|
3965
|
+
}
|
|
3966
|
+
for (const { typeClassRef } of graphqlRepos) {
|
|
3967
|
+
if (!("filename" in typeClassRef) || !typeClassRef.exportedSymbol) continue;
|
|
3968
|
+
const alias = conflicts.has(typeClassRef.exportedSymbol) ? `GraphQL_${typeClassRef.exportedSymbol}` : void 0;
|
|
3969
|
+
coreFile.reExport(
|
|
3970
|
+
typeClassRef,
|
|
3971
|
+
alias
|
|
3972
|
+
);
|
|
3973
|
+
}
|
|
3974
|
+
}
|
|
3975
|
+
/**
|
|
3976
|
+
* Re-exports all generated entity types so custom bindings can reference
|
|
3977
|
+
* domain models (e.g. `api_Item`) without importing from internal paths.
|
|
3978
|
+
*
|
|
3979
|
+
* The barrel `types/index.ts` is built incrementally by TypeDefinitionService
|
|
3980
|
+
* as types are generated; we just re-export it from bindings-core.
|
|
3981
|
+
* GraphQL-only specs produce no REST types so the barrel is never created.
|
|
3982
|
+
*/
|
|
3983
|
+
buildEntityTypeReExports(coreFile) {
|
|
3984
|
+
if (this.services.typeDefinition.hasTypes) {
|
|
3985
|
+
coreFile.reExportTypeAll(TYPES_INDEX_PATH);
|
|
3986
|
+
}
|
|
3804
3987
|
}
|
|
3805
3988
|
buildTypeInvalidation(typesWithNormalization) {
|
|
3806
3989
|
return typesWithNormalization.reduce(
|
|
@@ -13653,6 +13836,8 @@ export {
|
|
|
13653
13836
|
NormalizedTypeGenerator,
|
|
13654
13837
|
SINGLE_FILE,
|
|
13655
13838
|
SINGLE_FILE_NORMALIZED,
|
|
13839
|
+
TYPES_INDEX_PATH,
|
|
13840
|
+
TYPES_SINGLE_FILE_PATH,
|
|
13656
13841
|
TYPE_REGISTRY_FILE,
|
|
13657
13842
|
TypeDefinitionService,
|
|
13658
13843
|
TypeRegistryGenerator,
|