firebase-contract 0.1.0-rc.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/README.md +560 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/lib/_internal/compiler/compiler.d.ts +71 -0
- package/dist/lib/_internal/compiler/compiler.d.ts.map +1 -0
- package/dist/lib/_internal/compiler/compiler.js +104 -0
- package/dist/lib/_internal/compiler/index.d.ts +3 -0
- package/dist/lib/_internal/compiler/index.d.ts.map +1 -0
- package/dist/lib/_internal/compiler/index.js +1 -0
- package/dist/lib/_internal/diagnostics.d.ts +29 -0
- package/dist/lib/_internal/diagnostics.d.ts.map +1 -0
- package/dist/lib/_internal/diagnostics.js +26 -0
- package/dist/lib/_internal/format-diagnostics.d.ts +8 -0
- package/dist/lib/_internal/format-diagnostics.d.ts.map +1 -0
- package/dist/lib/_internal/format-diagnostics.js +10 -0
- package/dist/lib/_internal/generators/api/api-dto-generator.d.ts +8 -0
- package/dist/lib/_internal/generators/api/api-dto-generator.d.ts.map +1 -0
- package/dist/lib/_internal/generators/api/api-dto-generator.js +134 -0
- package/dist/lib/_internal/generators/api/api-types-generator.d.ts +8 -0
- package/dist/lib/_internal/generators/api/api-types-generator.d.ts.map +1 -0
- package/dist/lib/_internal/generators/api/api-types-generator.js +105 -0
- package/dist/lib/_internal/generators/api/api-validation-generator.d.ts +7 -0
- package/dist/lib/_internal/generators/api/api-validation-generator.d.ts.map +1 -0
- package/dist/lib/_internal/generators/api/api-validation-generator.js +73 -0
- package/dist/lib/_internal/generators/api/task-payload-generator.d.ts +9 -0
- package/dist/lib/_internal/generators/api/task-payload-generator.d.ts.map +1 -0
- package/dist/lib/_internal/generators/api/task-payload-generator.js +96 -0
- package/dist/lib/_internal/generators/config/config-generator.d.ts +9 -0
- package/dist/lib/_internal/generators/config/config-generator.d.ts.map +1 -0
- package/dist/lib/_internal/generators/config/config-generator.js +71 -0
- package/dist/lib/_internal/generators/data-connect/adapter-generator.d.ts +8 -0
- package/dist/lib/_internal/generators/data-connect/adapter-generator.d.ts.map +1 -0
- package/dist/lib/_internal/generators/data-connect/adapter-generator.js +142 -0
- package/dist/lib/_internal/generators/data-connect/graphql-generator.d.ts +15 -0
- package/dist/lib/_internal/generators/data-connect/graphql-generator.d.ts.map +1 -0
- package/dist/lib/_internal/generators/data-connect/graphql-generator.js +209 -0
- package/dist/lib/_internal/generators/data-connect/operations-generator.d.ts +18 -0
- package/dist/lib/_internal/generators/data-connect/operations-generator.d.ts.map +1 -0
- package/dist/lib/_internal/generators/data-connect/operations-generator.js +539 -0
- package/dist/lib/_internal/generators/firestore/firestore-projection-generator.d.ts +11 -0
- package/dist/lib/_internal/generators/firestore/firestore-projection-generator.d.ts.map +1 -0
- package/dist/lib/_internal/generators/firestore/firestore-projection-generator.js +112 -0
- package/dist/lib/_internal/generators/firestore/firestore-split-generator.d.ts +11 -0
- package/dist/lib/_internal/generators/firestore/firestore-split-generator.d.ts.map +1 -0
- package/dist/lib/_internal/generators/firestore/firestore-split-generator.js +375 -0
- package/dist/lib/_internal/generators/firestore/firestore-type-generator.d.ts +12 -0
- package/dist/lib/_internal/generators/firestore/firestore-type-generator.d.ts.map +1 -0
- package/dist/lib/_internal/generators/firestore/firestore-type-generator.js +81 -0
- package/dist/lib/_internal/generators/generator.d.ts +23 -0
- package/dist/lib/_internal/generators/generator.d.ts.map +1 -0
- package/dist/lib/_internal/generators/generator.js +1 -0
- package/dist/lib/_internal/generators/id/id-codec-generator.d.ts +16 -0
- package/dist/lib/_internal/generators/id/id-codec-generator.d.ts.map +1 -0
- package/dist/lib/_internal/generators/id/id-codec-generator.js +140 -0
- package/dist/lib/_internal/generators/index.d.ts +31 -0
- package/dist/lib/_internal/generators/index.d.ts.map +1 -0
- package/dist/lib/_internal/generators/index.js +64 -0
- package/dist/lib/_internal/generators/registry.d.ts +15 -0
- package/dist/lib/_internal/generators/registry.d.ts.map +1 -0
- package/dist/lib/_internal/generators/registry.js +24 -0
- package/dist/lib/_internal/generators/sql/sql-migration-generator.d.ts +9 -0
- package/dist/lib/_internal/generators/sql/sql-migration-generator.d.ts.map +1 -0
- package/dist/lib/_internal/generators/sql/sql-migration-generator.js +44 -0
- package/dist/lib/_internal/generators/support/constraints.d.ts +8 -0
- package/dist/lib/_internal/generators/support/constraints.d.ts.map +1 -0
- package/dist/lib/_internal/generators/support/constraints.js +39 -0
- package/dist/lib/_internal/generators/support/header.d.ts +13 -0
- package/dist/lib/_internal/generators/support/header.d.ts.map +1 -0
- package/dist/lib/_internal/generators/support/header.js +17 -0
- package/dist/lib/_internal/generators/support/naming.d.ts +10 -0
- package/dist/lib/_internal/generators/support/naming.d.ts.map +1 -0
- package/dist/lib/_internal/generators/support/naming.js +30 -0
- package/dist/lib/_internal/generators/support/relations.d.ts +12 -0
- package/dist/lib/_internal/generators/support/relations.d.ts.map +1 -0
- package/dist/lib/_internal/generators/support/relations.js +11 -0
- package/dist/lib/_internal/generators/support/split.d.ts +34 -0
- package/dist/lib/_internal/generators/support/split.d.ts.map +1 -0
- package/dist/lib/_internal/generators/support/split.js +75 -0
- package/dist/lib/_internal/generators/typescript/typescript-generator.d.ts +18 -0
- package/dist/lib/_internal/generators/typescript/typescript-generator.d.ts.map +1 -0
- package/dist/lib/_internal/generators/typescript/typescript-generator.js +99 -0
- package/dist/lib/_internal/generators/typescript/typescript-split-generator.d.ts +10 -0
- package/dist/lib/_internal/generators/typescript/typescript-split-generator.d.ts.map +1 -0
- package/dist/lib/_internal/generators/typescript/typescript-split-generator.js +175 -0
- package/dist/lib/_internal/generators/union/union-generator.d.ts +8 -0
- package/dist/lib/_internal/generators/union/union-generator.d.ts.map +1 -0
- package/dist/lib/_internal/generators/union/union-generator.js +37 -0
- package/dist/lib/_internal/generators/zod/zod-generator.d.ts +7 -0
- package/dist/lib/_internal/generators/zod/zod-generator.d.ts.map +1 -0
- package/dist/lib/_internal/generators/zod/zod-generator.js +68 -0
- package/dist/lib/_internal/generators/zod/zod-split-generator.d.ts +9 -0
- package/dist/lib/_internal/generators/zod/zod-split-generator.d.ts.map +1 -0
- package/dist/lib/_internal/generators/zod/zod-split-generator.js +136 -0
- package/dist/lib/_internal/ir/build-ir.d.ts +18 -0
- package/dist/lib/_internal/ir/build-ir.d.ts.map +1 -0
- package/dist/lib/_internal/ir/build-ir.js +430 -0
- package/dist/lib/_internal/ir/ir.d.ts +393 -0
- package/dist/lib/_internal/ir/ir.d.ts.map +1 -0
- package/dist/lib/_internal/ir/ir.js +22 -0
- package/dist/lib/_internal/parser/parse.d.ts +9 -0
- package/dist/lib/_internal/parser/parse.d.ts.map +1 -0
- package/dist/lib/_internal/parser/parse.js +682 -0
- package/dist/lib/_internal/parser/raw-document.d.ts +230 -0
- package/dist/lib/_internal/parser/raw-document.d.ts.map +1 -0
- package/dist/lib/_internal/parser/raw-document.js +6 -0
- package/dist/lib/_internal/resolver/import-resolver.d.ts +25 -0
- package/dist/lib/_internal/resolver/import-resolver.d.ts.map +1 -0
- package/dist/lib/_internal/resolver/import-resolver.js +73 -0
- package/dist/lib/_internal/resolver/module-loader.d.ts +25 -0
- package/dist/lib/_internal/resolver/module-loader.d.ts.map +1 -0
- package/dist/lib/_internal/resolver/module-loader.js +62 -0
- package/dist/lib/_internal/runtime/data-connect-adapter.d.ts +25 -0
- package/dist/lib/_internal/runtime/data-connect-adapter.d.ts.map +1 -0
- package/dist/lib/_internal/runtime/data-connect-adapter.js +24 -0
- package/dist/lib/_internal/runtime/index.d.ts +3 -0
- package/dist/lib/_internal/runtime/index.d.ts.map +1 -0
- package/dist/lib/_internal/runtime/index.js +1 -0
- package/dist/lib/_internal/validation/rules.d.ts +32 -0
- package/dist/lib/_internal/validation/rules.d.ts.map +1 -0
- package/dist/lib/_internal/validation/rules.js +282 -0
- package/dist/lib/_internal/validation/validate.d.ts +9 -0
- package/dist/lib/_internal/validation/validate.d.ts.map +1 -0
- package/dist/lib/_internal/validation/validate.js +6 -0
- package/dist/lib/cli/commands/generate.d.ts +3 -0
- package/dist/lib/cli/commands/generate.d.ts.map +1 -0
- package/dist/lib/cli/commands/generate.js +66 -0
- package/dist/lib/cli/commands/index.d.ts +4 -0
- package/dist/lib/cli/commands/index.d.ts.map +1 -0
- package/dist/lib/cli/commands/index.js +11 -0
- package/dist/lib/cli/commands/init.d.ts +3 -0
- package/dist/lib/cli/commands/init.d.ts.map +1 -0
- package/dist/lib/cli/commands/init.js +72 -0
- package/dist/lib/cli/commands/inspect.d.ts +3 -0
- package/dist/lib/cli/commands/inspect.d.ts.map +1 -0
- package/dist/lib/cli/commands/inspect.js +23 -0
- package/dist/lib/cli/commands/validate.d.ts +3 -0
- package/dist/lib/cli/commands/validate.d.ts.map +1 -0
- package/dist/lib/cli/commands/validate.js +23 -0
- package/dist/lib/cli/config.d.ts +12 -0
- package/dist/lib/cli/config.d.ts.map +1 -0
- package/dist/lib/cli/config.js +20 -0
- package/dist/lib/cli/index.d.ts +3 -0
- package/dist/lib/cli/index.d.ts.map +1 -0
- package/dist/lib/cli/index.js +13 -0
- package/dist/lib/cli/version.d.ts +3 -0
- package/dist/lib/cli/version.d.ts.map +1 -0
- package/dist/lib/cli/version.js +15 -0
- package/dist/lib/modules/runtime.d.ts +2 -0
- package/dist/lib/modules/runtime.d.ts.map +1 -0
- package/dist/lib/modules/runtime.js +3 -0
- package/package.json +60 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { GeneratorRegistry } from './registry.js';
|
|
2
|
+
export type { GeneratedFile, Generator, GeneratorContext } from './generator.js';
|
|
3
|
+
export { GeneratorRegistry } from './registry.js';
|
|
4
|
+
export { createTypeScriptGenerator } from './typescript/typescript-generator.js';
|
|
5
|
+
export { createTypeScriptSplitGenerator } from './typescript/typescript-split-generator.js';
|
|
6
|
+
export type { TypeScriptGeneratorOptions } from './typescript/typescript-generator.js';
|
|
7
|
+
export { createZodGenerator } from './zod/zod-generator.js';
|
|
8
|
+
export { createZodSplitGenerator } from './zod/zod-split-generator.js';
|
|
9
|
+
export { createDataConnectGraphqlGenerator, createDataConnectGraphqlSplitGenerator } from './data-connect/graphql-generator.js';
|
|
10
|
+
export { createDataConnectAdapterGenerator } from './data-connect/adapter-generator.js';
|
|
11
|
+
export { createDataConnectOperationsGenerator, createDataConnectOperationsSplitGenerator } from './data-connect/operations-generator.js';
|
|
12
|
+
export { createFirestoreTypeGenerator } from './firestore/firestore-type-generator.js';
|
|
13
|
+
export type { FirestoreGeneratorOptions } from './firestore/firestore-type-generator.js';
|
|
14
|
+
export { createFirestoreProjectionGenerator } from './firestore/firestore-projection-generator.js';
|
|
15
|
+
export { createFirestoreSplitGenerator } from './firestore/firestore-split-generator.js';
|
|
16
|
+
export { createApiTypesGenerator } from './api/api-types-generator.js';
|
|
17
|
+
export { createApiValidationGenerator } from './api/api-validation-generator.js';
|
|
18
|
+
export { createApiDtoGenerator } from './api/api-dto-generator.js';
|
|
19
|
+
export { createTaskPayloadGenerator } from './api/task-payload-generator.js';
|
|
20
|
+
export { createSqlMigrationGenerator } from './sql/sql-migration-generator.js';
|
|
21
|
+
export { createIdCodecGenerator } from './id/id-codec-generator.js';
|
|
22
|
+
export type { IdCodecGeneratorOptions } from './id/id-codec-generator.js';
|
|
23
|
+
export { createUnionGenerator } from './union/union-generator.js';
|
|
24
|
+
export { createConfigGenerator } from './config/config-generator.js';
|
|
25
|
+
/**
|
|
26
|
+
* Build a registry populated with the built-in generators:
|
|
27
|
+
* TypeScript, Zod, Data Connect (GraphQL schema / operations / adapter),
|
|
28
|
+
* Firestore types, and the API layer (types / request validation).
|
|
29
|
+
*/
|
|
30
|
+
export declare const createDefaultRegistry: () => GeneratorRegistry;
|
|
31
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/_internal/generators/index.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAMjD,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAChF,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAA;AAChF,OAAO,EAAE,8BAA8B,EAAE,MAAM,4CAA4C,CAAA;AAC3F,YAAY,EAAE,0BAA0B,EAAE,MAAM,sCAAsC,CAAA;AACtF,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AAC3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAA;AACtE,OAAO,EAAE,iCAAiC,EAAE,sCAAsC,EAAE,MAAM,qCAAqC,CAAA;AAC/H,OAAO,EAAE,iCAAiC,EAAE,MAAM,qCAAqC,CAAA;AACvF,OAAO,EAAE,oCAAoC,EAAE,yCAAyC,EAAE,MAAM,wCAAwC,CAAA;AACxI,OAAO,EAAE,4BAA4B,EAAE,MAAM,yCAAyC,CAAA;AACtF,YAAY,EAAE,yBAAyB,EAAE,MAAM,yCAAyC,CAAA;AACxF,OAAO,EAAE,kCAAkC,EAAE,MAAM,+CAA+C,CAAA;AAClG,OAAO,EAAE,6BAA6B,EAAE,MAAM,0CAA0C,CAAA;AACxF,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAA;AACtE,OAAO,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAA;AAChF,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAA;AAClE,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAA;AAC5E,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAA;AAC9E,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAA;AACnE,YAAY,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAA;AACzE,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAA;AAEpE;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,QAAO,iBAqBH,CAAA"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { createApiDtoGenerator } from './api/api-dto-generator.js';
|
|
2
|
+
import { createApiTypesGenerator } from './api/api-types-generator.js';
|
|
3
|
+
import { createApiValidationGenerator } from './api/api-validation-generator.js';
|
|
4
|
+
import { createTaskPayloadGenerator } from './api/task-payload-generator.js';
|
|
5
|
+
import { createConfigGenerator } from './config/config-generator.js';
|
|
6
|
+
import { createDataConnectAdapterGenerator } from './data-connect/adapter-generator.js';
|
|
7
|
+
import { createDataConnectGraphqlGenerator, createDataConnectGraphqlSplitGenerator } from './data-connect/graphql-generator.js';
|
|
8
|
+
import { createDataConnectOperationsGenerator, createDataConnectOperationsSplitGenerator } from './data-connect/operations-generator.js';
|
|
9
|
+
import { createFirestoreProjectionGenerator } from './firestore/firestore-projection-generator.js';
|
|
10
|
+
import { createFirestoreSplitGenerator } from './firestore/firestore-split-generator.js';
|
|
11
|
+
import { createFirestoreTypeGenerator } from './firestore/firestore-type-generator.js';
|
|
12
|
+
import { createIdCodecGenerator } from './id/id-codec-generator.js';
|
|
13
|
+
import { createSqlMigrationGenerator } from './sql/sql-migration-generator.js';
|
|
14
|
+
import { createUnionGenerator } from './union/union-generator.js';
|
|
15
|
+
import { GeneratorRegistry } from './registry.js';
|
|
16
|
+
import { createTypeScriptGenerator } from './typescript/typescript-generator.js';
|
|
17
|
+
import { createTypeScriptSplitGenerator } from './typescript/typescript-split-generator.js';
|
|
18
|
+
import { createZodGenerator } from './zod/zod-generator.js';
|
|
19
|
+
import { createZodSplitGenerator } from './zod/zod-split-generator.js';
|
|
20
|
+
export { GeneratorRegistry } from './registry.js';
|
|
21
|
+
export { createTypeScriptGenerator } from './typescript/typescript-generator.js';
|
|
22
|
+
export { createTypeScriptSplitGenerator } from './typescript/typescript-split-generator.js';
|
|
23
|
+
export { createZodGenerator } from './zod/zod-generator.js';
|
|
24
|
+
export { createZodSplitGenerator } from './zod/zod-split-generator.js';
|
|
25
|
+
export { createDataConnectGraphqlGenerator, createDataConnectGraphqlSplitGenerator } from './data-connect/graphql-generator.js';
|
|
26
|
+
export { createDataConnectAdapterGenerator } from './data-connect/adapter-generator.js';
|
|
27
|
+
export { createDataConnectOperationsGenerator, createDataConnectOperationsSplitGenerator } from './data-connect/operations-generator.js';
|
|
28
|
+
export { createFirestoreTypeGenerator } from './firestore/firestore-type-generator.js';
|
|
29
|
+
export { createFirestoreProjectionGenerator } from './firestore/firestore-projection-generator.js';
|
|
30
|
+
export { createFirestoreSplitGenerator } from './firestore/firestore-split-generator.js';
|
|
31
|
+
export { createApiTypesGenerator } from './api/api-types-generator.js';
|
|
32
|
+
export { createApiValidationGenerator } from './api/api-validation-generator.js';
|
|
33
|
+
export { createApiDtoGenerator } from './api/api-dto-generator.js';
|
|
34
|
+
export { createTaskPayloadGenerator } from './api/task-payload-generator.js';
|
|
35
|
+
export { createSqlMigrationGenerator } from './sql/sql-migration-generator.js';
|
|
36
|
+
export { createIdCodecGenerator } from './id/id-codec-generator.js';
|
|
37
|
+
export { createUnionGenerator } from './union/union-generator.js';
|
|
38
|
+
export { createConfigGenerator } from './config/config-generator.js';
|
|
39
|
+
/**
|
|
40
|
+
* Build a registry populated with the built-in generators:
|
|
41
|
+
* TypeScript, Zod, Data Connect (GraphQL schema / operations / adapter),
|
|
42
|
+
* Firestore types, and the API layer (types / request validation).
|
|
43
|
+
*/
|
|
44
|
+
export const createDefaultRegistry = () => new GeneratorRegistry()
|
|
45
|
+
.register(createTypeScriptGenerator())
|
|
46
|
+
.register(createTypeScriptSplitGenerator())
|
|
47
|
+
.register(createZodGenerator())
|
|
48
|
+
.register(createZodSplitGenerator())
|
|
49
|
+
.register(createDataConnectGraphqlGenerator())
|
|
50
|
+
.register(createDataConnectGraphqlSplitGenerator())
|
|
51
|
+
.register(createDataConnectOperationsGenerator())
|
|
52
|
+
.register(createDataConnectOperationsSplitGenerator())
|
|
53
|
+
.register(createDataConnectAdapterGenerator())
|
|
54
|
+
.register(createFirestoreTypeGenerator())
|
|
55
|
+
.register(createFirestoreProjectionGenerator())
|
|
56
|
+
.register(createFirestoreSplitGenerator())
|
|
57
|
+
.register(createApiTypesGenerator())
|
|
58
|
+
.register(createApiValidationGenerator())
|
|
59
|
+
.register(createApiDtoGenerator())
|
|
60
|
+
.register(createTaskPayloadGenerator())
|
|
61
|
+
.register(createSqlMigrationGenerator())
|
|
62
|
+
.register(createIdCodecGenerator())
|
|
63
|
+
.register(createUnionGenerator())
|
|
64
|
+
.register(createConfigGenerator());
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Generator } from './generator.js';
|
|
2
|
+
/**
|
|
3
|
+
* Holds the set of available generators keyed by name. The compiler resolves
|
|
4
|
+
* requested generators through the registry, so adding a new generator is just
|
|
5
|
+
* a `register` call — no existing code changes.
|
|
6
|
+
*/
|
|
7
|
+
export declare class GeneratorRegistry {
|
|
8
|
+
private readonly generators;
|
|
9
|
+
register(generator: Generator): this;
|
|
10
|
+
has(name: string): boolean;
|
|
11
|
+
get(name: string): Generator | undefined;
|
|
12
|
+
names(): string[];
|
|
13
|
+
list(): Generator[];
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../../src/lib/_internal/generators/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAE1C;;;;GAIG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA+B;IAE1D,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI;IAKpC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1B,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAIxC,KAAK,IAAI,MAAM,EAAE;IAIjB,IAAI,IAAI,SAAS,EAAE;CAGpB"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Holds the set of available generators keyed by name. The compiler resolves
|
|
3
|
+
* requested generators through the registry, so adding a new generator is just
|
|
4
|
+
* a `register` call — no existing code changes.
|
|
5
|
+
*/
|
|
6
|
+
export class GeneratorRegistry {
|
|
7
|
+
generators = new Map();
|
|
8
|
+
register(generator) {
|
|
9
|
+
this.generators.set(generator.name, generator);
|
|
10
|
+
return this;
|
|
11
|
+
}
|
|
12
|
+
has(name) {
|
|
13
|
+
return this.generators.has(name);
|
|
14
|
+
}
|
|
15
|
+
get(name) {
|
|
16
|
+
return this.generators.get(name);
|
|
17
|
+
}
|
|
18
|
+
names() {
|
|
19
|
+
return [...this.generators.keys()];
|
|
20
|
+
}
|
|
21
|
+
list() {
|
|
22
|
+
return [...this.generators.values()];
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Generator } from '../generator.js';
|
|
2
|
+
/**
|
|
3
|
+
* Generates raw SQL migrations for constraints Data Connect cannot express:
|
|
4
|
+
* composite foreign keys, CHECK constraints, and extra indexes — constraints
|
|
5
|
+
* that otherwise live only as hand-written schema comments with no executable
|
|
6
|
+
* artifact. This turns them into a runnable `.sql` file.
|
|
7
|
+
*/
|
|
8
|
+
export declare const createSqlMigrationGenerator: () => Generator;
|
|
9
|
+
//# sourceMappingURL=sql-migration-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql-migration-generator.d.ts","sourceRoot":"","sources":["../../../../../src/lib/_internal/generators/sql/sql-migration-generator.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiB,SAAS,EAAoB,MAAM,iBAAiB,CAAA;AA+B5E;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,QAAO,SAY7C,CAAA"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { pluralize, snakeCase } from '../support/naming.js';
|
|
2
|
+
import { headerBlocks } from '../support/header.js';
|
|
3
|
+
const tableName = (model) => model.table ?? pluralize(snakeCase(model.name));
|
|
4
|
+
const renderModelSql = (model) => {
|
|
5
|
+
const sql = model.sql;
|
|
6
|
+
if (!sql)
|
|
7
|
+
return [];
|
|
8
|
+
const table = tableName(model);
|
|
9
|
+
const statements = [];
|
|
10
|
+
sql.checks.forEach((expr, i) => {
|
|
11
|
+
const name = `${table}_chk_${i + 1}`;
|
|
12
|
+
statements.push(`ALTER TABLE "${table}" ADD CONSTRAINT "${name}" CHECK (${expr});`);
|
|
13
|
+
});
|
|
14
|
+
for (const fk of sql.foreignKeys) {
|
|
15
|
+
const name = fk.name ?? `${table}_${fk.columns.join('_')}_fkey`;
|
|
16
|
+
const cols = fk.columns.map(c => `"${c}"`).join(', ');
|
|
17
|
+
statements.push(`ALTER TABLE "${table}" ADD CONSTRAINT "${name}" FOREIGN KEY (${cols}) REFERENCES ${fk.references};`);
|
|
18
|
+
}
|
|
19
|
+
for (const idx of sql.indexes) {
|
|
20
|
+
const name = idx.name ?? `${table}_${idx.columns.join('_')}_${idx.unique ? 'uidx' : 'idx'}`;
|
|
21
|
+
const cols = idx.columns.map(c => `"${c}"`).join(', ');
|
|
22
|
+
statements.push(`CREATE ${idx.unique ? 'UNIQUE ' : ''}INDEX "${name}" ON "${table}" (${cols});`);
|
|
23
|
+
}
|
|
24
|
+
return statements.length > 0 ? [`-- ${model.name} (${table})`, ...statements] : [];
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Generates raw SQL migrations for constraints Data Connect cannot express:
|
|
28
|
+
* composite foreign keys, CHECK constraints, and extra indexes — constraints
|
|
29
|
+
* that otherwise live only as hand-written schema comments with no executable
|
|
30
|
+
* artifact. This turns them into a runnable `.sql` file.
|
|
31
|
+
*/
|
|
32
|
+
export const createSqlMigrationGenerator = () => ({
|
|
33
|
+
name: 'sql-migrations',
|
|
34
|
+
description: 'Raw SQL migrations for composite FK / CHECK / index constraints',
|
|
35
|
+
generate(ir, context) {
|
|
36
|
+
const blocks = ir.models.flatMap(renderModelSql);
|
|
37
|
+
if (blocks.length === 0) {
|
|
38
|
+
return [];
|
|
39
|
+
}
|
|
40
|
+
const banner = headerBlocks(context, header => header.replace(/^\/\/ ?/gm, '-- '));
|
|
41
|
+
const content = `${[...banner, blocks.join('\n')].join('\n\n')}\n`;
|
|
42
|
+
return [{ path: 'migrations/constraints.sql', content }];
|
|
43
|
+
},
|
|
44
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { IrField } from '../../ir/ir.js';
|
|
2
|
+
/**
|
|
3
|
+
* Zod constraint chain for a field. For list fields the constraints apply to the
|
|
4
|
+
* array (length); otherwise to the value. Returned as a suffix to append after
|
|
5
|
+
* the base schema (and after `z.array(...)` for lists).
|
|
6
|
+
*/
|
|
7
|
+
export declare const zodConstraints: (field: IrField) => string;
|
|
8
|
+
//# sourceMappingURL=constraints.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constraints.d.ts","sourceRoot":"","sources":["../../../../../src/lib/_internal/generators/support/constraints.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAQxC;;;;GAIG;AACH,eAAO,MAAM,cAAc,GAAI,OAAO,OAAO,KAAG,MAqB/C,CAAA"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const isNumber = (field) => field.type.kind === 'scalar' && (field.type.name === 'int' || field.type.name === 'int64' || field.type.name === 'float');
|
|
2
|
+
const isStringy = (field) => field.type.kind === 'scalar' && (field.type.name === 'string' || field.type.name === 'id');
|
|
3
|
+
/**
|
|
4
|
+
* Zod constraint chain for a field. For list fields the constraints apply to the
|
|
5
|
+
* array (length); otherwise to the value. Returned as a suffix to append after
|
|
6
|
+
* the base schema (and after `z.array(...)` for lists).
|
|
7
|
+
*/
|
|
8
|
+
export const zodConstraints = (field) => {
|
|
9
|
+
const c = field.constraints;
|
|
10
|
+
const parts = [];
|
|
11
|
+
if (field.list) {
|
|
12
|
+
if (c.minLength !== undefined)
|
|
13
|
+
parts.push(`.min(${c.minLength})`);
|
|
14
|
+
if (c.maxLength !== undefined)
|
|
15
|
+
parts.push(`.max(${c.maxLength})`);
|
|
16
|
+
if (c.nonempty)
|
|
17
|
+
parts.push('.nonempty()');
|
|
18
|
+
return parts.join('');
|
|
19
|
+
}
|
|
20
|
+
if (isNumber(field)) {
|
|
21
|
+
if (c.min !== undefined)
|
|
22
|
+
parts.push(`.min(${c.min})`);
|
|
23
|
+
if (c.max !== undefined)
|
|
24
|
+
parts.push(`.max(${c.max})`);
|
|
25
|
+
}
|
|
26
|
+
if (isStringy(field)) {
|
|
27
|
+
if (c.email)
|
|
28
|
+
parts.push('.email()');
|
|
29
|
+
if (c.url)
|
|
30
|
+
parts.push('.url()');
|
|
31
|
+
if (c.nonempty || c.minLength !== undefined)
|
|
32
|
+
parts.push(`.min(${c.minLength ?? 1})`);
|
|
33
|
+
if (c.maxLength !== undefined)
|
|
34
|
+
parts.push(`.max(${c.maxLength})`);
|
|
35
|
+
if (c.pattern)
|
|
36
|
+
parts.push(`.regex(/${c.pattern}/)`);
|
|
37
|
+
}
|
|
38
|
+
return parts.join('');
|
|
39
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { GeneratorContext } from '../generator.js';
|
|
2
|
+
/** Default banner marking a file as generated (do-not-edit). */
|
|
3
|
+
export declare const DEFAULT_HEADER: string;
|
|
4
|
+
/** Turn raw header text into `//` comment lines; `default` selects the built-in banner. */
|
|
5
|
+
export declare const toHeaderComment: (text: string) => string;
|
|
6
|
+
/** The configured header in `//` comment form, or `''` when none is configured. */
|
|
7
|
+
export declare const headerFor: (context: GeneratorContext | undefined) => string;
|
|
8
|
+
/**
|
|
9
|
+
* The header as a leading block list — empty when no header is configured, so
|
|
10
|
+
* generators can spread it without emitting blank lines.
|
|
11
|
+
*/
|
|
12
|
+
export declare const headerBlocks: (context: GeneratorContext | undefined, transform?: (header: string) => string) => string[];
|
|
13
|
+
//# sourceMappingURL=header.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"header.d.ts","sourceRoot":"","sources":["../../../../../src/lib/_internal/generators/support/header.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAElD,gEAAgE;AAChE,eAAO,MAAM,cAAc,QAGf,CAAA;AAEZ,2FAA2F;AAC3F,eAAO,MAAM,eAAe,GAAI,MAAM,MAAM,KAAG,MACwD,CAAA;AAEvG,mFAAmF;AACnF,eAAO,MAAM,SAAS,GAAI,SAAS,gBAAgB,GAAG,SAAS,KAAG,MAA+B,CAAA;AAEjG;;;GAGG;AACH,eAAO,MAAM,YAAY,GACvB,SAAS,gBAAgB,GAAG,SAAS,EACrC,YAAW,CAAC,MAAM,EAAE,MAAM,KAAK,MAAyB,KACvD,MAAM,EAGR,CAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Default banner marking a file as generated (do-not-edit). */
|
|
2
|
+
export const DEFAULT_HEADER = [
|
|
3
|
+
'// AUTO-GENERATED by firebase-contract. Do not edit by hand.',
|
|
4
|
+
'// Regenerate with: fbc generate',
|
|
5
|
+
].join('\n');
|
|
6
|
+
/** Turn raw header text into `//` comment lines; `default` selects the built-in banner. */
|
|
7
|
+
export const toHeaderComment = (text) => text === 'default' ? DEFAULT_HEADER : text.split('\n').map(line => `// ${line}`.trimEnd()).join('\n');
|
|
8
|
+
/** The configured header in `//` comment form, or `''` when none is configured. */
|
|
9
|
+
export const headerFor = (context) => context?.header ?? '';
|
|
10
|
+
/**
|
|
11
|
+
* The header as a leading block list — empty when no header is configured, so
|
|
12
|
+
* generators can spread it without emitting blank lines.
|
|
13
|
+
*/
|
|
14
|
+
export const headerBlocks = (context, transform = header => header) => {
|
|
15
|
+
const header = headerFor(context);
|
|
16
|
+
return header ? [transform(header)] : [];
|
|
17
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Stateless naming helpers shared by generators. Pure functions only. */
|
|
2
|
+
export declare const pascalCase: (value: string) => string;
|
|
3
|
+
export declare const camelCase: (value: string) => string;
|
|
4
|
+
export declare const constantCase: (value: string) => string;
|
|
5
|
+
export declare const snakeCase: (value: string) => string;
|
|
6
|
+
/** Naive English pluralization sufficient for table naming. */
|
|
7
|
+
export declare const pluralize: (value: string) => string;
|
|
8
|
+
/** Escape a string for use inside a single-quoted TypeScript literal. */
|
|
9
|
+
export declare const singleQuote: (value: string) => string;
|
|
10
|
+
//# sourceMappingURL=naming.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"naming.d.ts","sourceRoot":"","sources":["../../../../../src/lib/_internal/generators/support/naming.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAU1E,eAAO,MAAM,UAAU,GAAI,OAAO,MAAM,KAAG,MAG9B,CAAA;AAEb,eAAO,MAAM,SAAS,GAAI,OAAO,MAAM,KAAG,MAGzC,CAAA;AAED,eAAO,MAAM,YAAY,GAAI,OAAO,MAAM,KAAG,MAG/B,CAAA;AAEd,eAAO,MAAM,SAAS,GAAI,OAAO,MAAM,KAAG,MAG5B,CAAA;AAEd,+DAA+D;AAC/D,eAAO,MAAM,SAAS,GAAI,OAAO,MAAM,KAAG,MAIzC,CAAA;AAED,yEAAyE;AACzE,eAAO,MAAM,WAAW,GAAI,OAAO,MAAM,KAAG,MAAkE,CAAA"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** Stateless naming helpers shared by generators. Pure functions only. */
|
|
2
|
+
const words = (value) => value
|
|
3
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
|
|
4
|
+
.replace(/[_\-\s]+/g, ' ')
|
|
5
|
+
.trim()
|
|
6
|
+
.split(' ')
|
|
7
|
+
.filter(Boolean);
|
|
8
|
+
export const pascalCase = (value) => words(value)
|
|
9
|
+
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
|
10
|
+
.join('');
|
|
11
|
+
export const camelCase = (value) => {
|
|
12
|
+
const pascal = pascalCase(value);
|
|
13
|
+
return pascal.charAt(0).toLowerCase() + pascal.slice(1);
|
|
14
|
+
};
|
|
15
|
+
export const constantCase = (value) => words(value)
|
|
16
|
+
.map(word => word.toUpperCase())
|
|
17
|
+
.join('_');
|
|
18
|
+
export const snakeCase = (value) => words(value)
|
|
19
|
+
.map(word => word.toLowerCase())
|
|
20
|
+
.join('_');
|
|
21
|
+
/** Naive English pluralization sufficient for table naming. */
|
|
22
|
+
export const pluralize = (value) => {
|
|
23
|
+
if (/[^aeiou]y$/.test(value))
|
|
24
|
+
return `${value.slice(0, -1)}ies`;
|
|
25
|
+
if (/(s|x|z|ch|sh)$/.test(value))
|
|
26
|
+
return `${value}es`;
|
|
27
|
+
return `${value}s`;
|
|
28
|
+
};
|
|
29
|
+
/** Escape a string for use inside a single-quoted TypeScript literal. */
|
|
30
|
+
export const singleQuote = (value) => `'${value.replace(/\\/g, '\\\\').replace(/'/g, "\\'")}'`;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Ir, IrField, ScalarType } from '../../ir/ir.js';
|
|
2
|
+
/** A model-typed field that is a foreign-key relation (not an embedded value object). */
|
|
3
|
+
export declare const isRelation: (field: IrField) => boolean;
|
|
4
|
+
/**
|
|
5
|
+
* Foreign-key column name for a relation field. Data Connect stores a relation
|
|
6
|
+
* `owner: User` as an `ownerId` column, so the entity/row/Firestore types expose
|
|
7
|
+
* the id, matching how the value is actually persisted and projected.
|
|
8
|
+
*/
|
|
9
|
+
export declare const relationFkName: (field: IrField) => string;
|
|
10
|
+
/** Scalar type of a relation's foreign key (the related model's id type). */
|
|
11
|
+
export declare const relationFkType: (ir: Ir, field: IrField) => ScalarType;
|
|
12
|
+
//# sourceMappingURL=relations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relations.d.ts","sourceRoot":"","sources":["../../../../../src/lib/_internal/generators/support/relations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAElE,yFAAyF;AACzF,eAAO,MAAM,UAAU,GAAI,OAAO,OAAO,KAAG,OAAwD,CAAA;AAEpG;;;;GAIG;AACH,eAAO,MAAM,cAAc,GAAI,OAAO,OAAO,KAAG,MAA2B,CAAA;AAE3E,6EAA6E;AAC7E,eAAO,MAAM,cAAc,GAAI,IAAI,EAAE,EAAE,OAAO,OAAO,KAAG,UACgB,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { idTypeOf } from '../../ir/ir.js';
|
|
2
|
+
/** A model-typed field that is a foreign-key relation (not an embedded value object). */
|
|
3
|
+
export const isRelation = (field) => field.relation && field.type.kind === 'model';
|
|
4
|
+
/**
|
|
5
|
+
* Foreign-key column name for a relation field. Data Connect stores a relation
|
|
6
|
+
* `owner: User` as an `ownerId` column, so the entity/row/Firestore types expose
|
|
7
|
+
* the id, matching how the value is actually persisted and projected.
|
|
8
|
+
*/
|
|
9
|
+
export const relationFkName = (field) => `${field.name}Id`;
|
|
10
|
+
/** Scalar type of a relation's foreign key (the related model's id type). */
|
|
11
|
+
export const relationFkType = (ir, field) => field.type.kind === 'model' ? idTypeOf(ir, field.type.name) : 'string';
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Ir, IrModel } from '../../ir/ir.js';
|
|
2
|
+
/** Whether a model is a real table (vs an embedded value object). */
|
|
3
|
+
export declare const isTable: (model: IrModel) => boolean;
|
|
4
|
+
export declare const tableNameOf: (model: IrModel) => string;
|
|
5
|
+
export declare const kebabCase: (value: string) => string;
|
|
6
|
+
export interface HostedDeps {
|
|
7
|
+
/** Enum names in first-reference order. */
|
|
8
|
+
enums: string[];
|
|
9
|
+
/** Embedded model names in dependency (topological) order. */
|
|
10
|
+
models: string[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Transitive enum/embedded-model dependencies of `roots`, in stable order:
|
|
14
|
+
* enums by first reference, embedded models dependencies-first so their
|
|
15
|
+
* declarations can be emitted top-down without forward references.
|
|
16
|
+
*/
|
|
17
|
+
export declare const collectDeps: (ir: Ir, roots: IrModel[]) => HostedDeps;
|
|
18
|
+
export interface SplitGroups {
|
|
19
|
+
tables: IrModel[];
|
|
20
|
+
/** enum name → hosting table model name */
|
|
21
|
+
enumHome: Map<string, string>;
|
|
22
|
+
/** embedded model name → hosting table model name */
|
|
23
|
+
modelHome: Map<string, string>;
|
|
24
|
+
/** Enums referenced by no table (api-only etc.). */
|
|
25
|
+
leftoverEnums: string[];
|
|
26
|
+
/** Embedded models referenced by no table. */
|
|
27
|
+
leftoverModels: string[];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Assign every enum and embedded model to the first table model that
|
|
31
|
+
* (transitively) references it; the rest become shared leftovers.
|
|
32
|
+
*/
|
|
33
|
+
export declare const splitGroups: (ir: Ir) => SplitGroups;
|
|
34
|
+
//# sourceMappingURL=split.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"split.d.ts","sourceRoot":"","sources":["../../../../../src/lib/_internal/generators/support/split.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,EAAE,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAIvD,qEAAqE;AACrE,eAAO,MAAM,OAAO,GAAI,OAAO,OAAO,KAAG,OAAiE,CAAA;AAE1G,eAAO,MAAM,WAAW,GAAI,OAAO,OAAO,KAAG,MAAyD,CAAA;AAEtG,eAAO,MAAM,SAAS,GAAI,OAAO,MAAM,KAAG,MAA6C,CAAA;AAavF,MAAM,WAAW,UAAU;IACzB,2CAA2C;IAC3C,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,8DAA8D;IAC9D,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB;AAED;;;;GAIG;AACH,eAAO,MAAM,WAAW,GAAI,IAAI,EAAE,EAAE,OAAO,OAAO,EAAE,KAAG,UAuBtD,CAAA;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,OAAO,EAAE,CAAA;IACjB,2CAA2C;IAC3C,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B,qDAAqD;IACrD,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC9B,oDAAoD;IACpD,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,8CAA8C;IAC9C,cAAc,EAAE,MAAM,EAAE,CAAA;CACzB;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW,GAAI,IAAI,EAAE,KAAG,WAepC,CAAA"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { findModel } from '../../ir/ir.js';
|
|
2
|
+
import { pluralize, snakeCase } from './naming.js';
|
|
3
|
+
import { isRelation } from './relations.js';
|
|
4
|
+
/** Whether a model is a real table (vs an embedded value object). */
|
|
5
|
+
export const isTable = (model) => model.key.length > 0 || model.fields.some(f => f.isId);
|
|
6
|
+
export const tableNameOf = (model) => model.table ?? pluralize(snakeCase(model.name));
|
|
7
|
+
export const kebabCase = (value) => snakeCase(value).replace(/_/g, '-');
|
|
8
|
+
/** Direct enum/embedded-model dependencies of a model (relations excluded). */
|
|
9
|
+
const directDeps = (model) => {
|
|
10
|
+
const enums = [];
|
|
11
|
+
const models = [];
|
|
12
|
+
for (const field of model.fields) {
|
|
13
|
+
if (field.type.kind === 'enum')
|
|
14
|
+
enums.push(field.type.name);
|
|
15
|
+
else if (field.type.kind === 'model' && !isRelation(field))
|
|
16
|
+
models.push(field.type.name);
|
|
17
|
+
}
|
|
18
|
+
return { enums, models };
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Transitive enum/embedded-model dependencies of `roots`, in stable order:
|
|
22
|
+
* enums by first reference, embedded models dependencies-first so their
|
|
23
|
+
* declarations can be emitted top-down without forward references.
|
|
24
|
+
*/
|
|
25
|
+
export const collectDeps = (ir, roots) => {
|
|
26
|
+
const enums = [];
|
|
27
|
+
const models = [];
|
|
28
|
+
const seenEnums = new Set();
|
|
29
|
+
const seenModels = new Set();
|
|
30
|
+
const visit = (model) => {
|
|
31
|
+
const deps = directDeps(model);
|
|
32
|
+
for (const name of deps.models) {
|
|
33
|
+
if (seenModels.has(name))
|
|
34
|
+
continue;
|
|
35
|
+
seenModels.add(name);
|
|
36
|
+
const embedded = findModel(ir, name);
|
|
37
|
+
if (embedded)
|
|
38
|
+
visit(embedded); // dependencies of the dependency come first
|
|
39
|
+
models.push(name);
|
|
40
|
+
}
|
|
41
|
+
for (const name of deps.enums) {
|
|
42
|
+
if (!seenEnums.has(name)) {
|
|
43
|
+
seenEnums.add(name);
|
|
44
|
+
enums.push(name);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
for (const root of roots)
|
|
49
|
+
visit(root);
|
|
50
|
+
return { enums, models };
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Assign every enum and embedded model to the first table model that
|
|
54
|
+
* (transitively) references it; the rest become shared leftovers.
|
|
55
|
+
*/
|
|
56
|
+
export const splitGroups = (ir) => {
|
|
57
|
+
const tables = ir.models.filter(isTable);
|
|
58
|
+
const enumHome = new Map();
|
|
59
|
+
const modelHome = new Map();
|
|
60
|
+
for (const table of tables) {
|
|
61
|
+
const deps = collectDeps(ir, [table]);
|
|
62
|
+
for (const name of deps.enums)
|
|
63
|
+
if (!enumHome.has(name))
|
|
64
|
+
enumHome.set(name, table.name);
|
|
65
|
+
for (const name of deps.models)
|
|
66
|
+
if (!modelHome.has(name))
|
|
67
|
+
modelHome.set(name, table.name);
|
|
68
|
+
}
|
|
69
|
+
const leftoverEnums = ir.enums.map(e => e.name).filter(name => !enumHome.has(name));
|
|
70
|
+
const leftoverModels = ir.models
|
|
71
|
+
.filter(model => !isTable(model))
|
|
72
|
+
.map(model => model.name)
|
|
73
|
+
.filter(name => !modelHome.has(name));
|
|
74
|
+
return { tables, enumHome, modelHome, leftoverEnums, leftoverModels };
|
|
75
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Generator } from '../generator.js';
|
|
2
|
+
export interface TypeScriptGeneratorOptions {
|
|
3
|
+
/**
|
|
4
|
+
* How enums are emitted. `const` (default) produces a frozen const object plus
|
|
5
|
+
* a `Key` type and a value type — giving runtime values and types from one
|
|
6
|
+
* source. `union` produces a plain
|
|
7
|
+
* string-literal union.
|
|
8
|
+
*/
|
|
9
|
+
enumStyle?: 'const' | 'union';
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Generates TypeScript types: an interface per model and, per enum, either a
|
|
13
|
+
* frozen const object (default — runtime values + `Key`/value types) or a
|
|
14
|
+
* plain string-literal union. This is the highest-priority
|
|
15
|
+
* generator and the shape other TS-facing generators reference.
|
|
16
|
+
*/
|
|
17
|
+
export declare const createTypeScriptGenerator: (options?: TypeScriptGeneratorOptions) => Generator;
|
|
18
|
+
//# sourceMappingURL=typescript-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typescript-generator.d.ts","sourceRoot":"","sources":["../../../../../src/lib/_internal/generators/typescript/typescript-generator.ts"],"names":[],"mappings":"AACA,OAAO,EAAiB,SAAS,EAAoB,MAAM,iBAAiB,CAAA;AAK5E,MAAM,WAAW,0BAA0B;IACzC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,GAAG,OAAO,CAAA;CAC9B;AA+ED;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,GAAI,UAAS,0BAA+B,KAAG,SAyBpF,CAAA"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { headerBlocks } from '../support/header.js';
|
|
2
|
+
import { constantCase, singleQuote } from '../support/naming.js';
|
|
3
|
+
import { isRelation, relationFkName, relationFkType } from '../support/relations.js';
|
|
4
|
+
const SCALAR_TS = {
|
|
5
|
+
string: 'string',
|
|
6
|
+
int: 'number',
|
|
7
|
+
int64: 'number',
|
|
8
|
+
float: 'number',
|
|
9
|
+
boolean: 'boolean',
|
|
10
|
+
timestamp: 'string',
|
|
11
|
+
date: 'string',
|
|
12
|
+
json: 'Json',
|
|
13
|
+
id: 'string',
|
|
14
|
+
};
|
|
15
|
+
const JSON_TYPE = [
|
|
16
|
+
'export type Json =',
|
|
17
|
+
' | string',
|
|
18
|
+
' | number',
|
|
19
|
+
' | boolean',
|
|
20
|
+
' | null',
|
|
21
|
+
' | Json[]',
|
|
22
|
+
' | { [key: string]: Json }',
|
|
23
|
+
].join('\n');
|
|
24
|
+
const renderRef = (ref) => {
|
|
25
|
+
switch (ref.kind) {
|
|
26
|
+
case 'scalar':
|
|
27
|
+
return SCALAR_TS[ref.name];
|
|
28
|
+
case 'enum':
|
|
29
|
+
case 'model':
|
|
30
|
+
return ref.name;
|
|
31
|
+
default:
|
|
32
|
+
return 'unknown';
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
const renderFieldType = (field) => {
|
|
36
|
+
const base = renderRef(field.type);
|
|
37
|
+
return field.list ? `${base}[]` : base;
|
|
38
|
+
};
|
|
39
|
+
const renderField = (field, ir) => {
|
|
40
|
+
const optional = field.optional ? '?' : '';
|
|
41
|
+
const doc = field.description ? ` /** ${field.description} */\n` : '';
|
|
42
|
+
if (field.literal !== undefined) {
|
|
43
|
+
const type = field.list ? `${singleQuote(field.literal)}[]` : singleQuote(field.literal);
|
|
44
|
+
return `${doc} ${field.name}${optional}: ${type}`;
|
|
45
|
+
}
|
|
46
|
+
// Relation: expose the foreign-key id (matching the persisted/projected shape).
|
|
47
|
+
if (isRelation(field)) {
|
|
48
|
+
const base = SCALAR_TS[relationFkType(ir, field)];
|
|
49
|
+
const type = field.list ? `${base}[]` : base;
|
|
50
|
+
return `${doc} ${relationFkName(field)}${optional}: ${type}`;
|
|
51
|
+
}
|
|
52
|
+
return `${doc} ${field.name}${optional}: ${renderFieldType(field)}`;
|
|
53
|
+
};
|
|
54
|
+
const usesJson = (ir) => ir.models.some(model => model.fields.some(field => field.type.kind === 'scalar' && field.type.name === 'json'));
|
|
55
|
+
const renderEnumUnion = (irEnum) => {
|
|
56
|
+
const doc = irEnum.description ? `/** ${irEnum.description} */\n` : '';
|
|
57
|
+
const union = irEnum.values.map(value => singleQuote(value)).join(' | ') || 'never';
|
|
58
|
+
return `${doc}export type ${irEnum.name} = ${union}`;
|
|
59
|
+
};
|
|
60
|
+
const renderEnumConst = (irEnum) => {
|
|
61
|
+
const doc = irEnum.description ? `/** ${irEnum.description} */\n` : '';
|
|
62
|
+
const constName = constantCase(irEnum.name);
|
|
63
|
+
const entries = irEnum.values.map(value => ` ${constantCase(value)}: ${singleQuote(value)},`).join('\n');
|
|
64
|
+
return [
|
|
65
|
+
`${doc}export const ${constName} = Object.freeze({`,
|
|
66
|
+
entries,
|
|
67
|
+
`} as const)`,
|
|
68
|
+
`export type ${irEnum.name}Key = keyof typeof ${constName}`,
|
|
69
|
+
`export type ${irEnum.name} = (typeof ${constName})[${irEnum.name}Key]`,
|
|
70
|
+
].join('\n');
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Generates TypeScript types: an interface per model and, per enum, either a
|
|
74
|
+
* frozen const object (default — runtime values + `Key`/value types) or a
|
|
75
|
+
* plain string-literal union. This is the highest-priority
|
|
76
|
+
* generator and the shape other TS-facing generators reference.
|
|
77
|
+
*/
|
|
78
|
+
export const createTypeScriptGenerator = (options = {}) => {
|
|
79
|
+
const enumStyle = options.enumStyle ?? 'const';
|
|
80
|
+
return {
|
|
81
|
+
name: 'typescript',
|
|
82
|
+
description: 'TypeScript interfaces and enum const/union types',
|
|
83
|
+
generate(ir, context) {
|
|
84
|
+
const blocks = [...headerBlocks(context)];
|
|
85
|
+
if (usesJson(ir)) {
|
|
86
|
+
blocks.push(JSON_TYPE);
|
|
87
|
+
}
|
|
88
|
+
for (const irEnum of ir.enums) {
|
|
89
|
+
blocks.push(enumStyle === 'const' ? renderEnumConst(irEnum) : renderEnumUnion(irEnum));
|
|
90
|
+
}
|
|
91
|
+
for (const model of ir.models) {
|
|
92
|
+
const doc = model.description ? `/** ${model.description} */\n` : '';
|
|
93
|
+
const fields = model.fields.map(field => renderField(field, ir)).join('\n');
|
|
94
|
+
blocks.push(`${doc}export interface ${model.name} {\n${fields}\n}`);
|
|
95
|
+
}
|
|
96
|
+
return [{ path: 'types.ts', content: `${blocks.join('\n\n')}\n` }];
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Generator } from '../generator.js';
|
|
2
|
+
/**
|
|
3
|
+
* Split variant of the TypeScript generator: one file per table at
|
|
4
|
+
* `types/<table-name>.ts` (kebab-case), with enums and embedded value objects
|
|
5
|
+
* co-located in the file of the first table that references them. Shared
|
|
6
|
+
* leftovers (and the `Json` type) live in `types/_shared.ts`, and `types.ts`
|
|
7
|
+
* is a barrel re-exporting every file.
|
|
8
|
+
*/
|
|
9
|
+
export declare const createTypeScriptSplitGenerator: () => Generator;
|
|
10
|
+
//# sourceMappingURL=typescript-split-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typescript-split-generator.d.ts","sourceRoot":"","sources":["../../../../../src/lib/_internal/generators/typescript/typescript-split-generator.ts"],"names":[],"mappings":"AACA,OAAO,EAAiB,SAAS,EAAoB,MAAM,iBAAiB,CAAA;AA2F5E;;;;;;GAMG;AACH,eAAO,MAAM,8BAA8B,QAAO,SAyEhD,CAAA"}
|