ts-procedures 8.3.0 → 8.4.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/agent_config/claude-code/skills/ts-procedures/SKILL.md +26 -8
- package/agent_config/claude-code/skills/ts-procedures/templates/client.md +3 -3
- package/agent_config/claude-code/skills/ts-procedures/templates/hono.md +3 -3
- package/agent_config/claude-code/skills/ts-procedures/templates/procedure.md +3 -3
- package/agent_config/claude-code/skills/ts-procedures/templates/stream-procedure.md +3 -3
- package/build/client/call.js +1 -1
- package/build/client/call.js.map +1 -1
- package/build/client/index.d.ts +1 -1
- package/build/client/index.js +23 -1
- package/build/client/index.js.map +1 -1
- package/build/client/index.test.js +87 -0
- package/build/client/index.test.js.map +1 -1
- package/build/client/resolve-options.d.ts +5 -4
- package/build/client/resolve-options.js +18 -7
- package/build/client/resolve-options.js.map +1 -1
- package/build/client/resolve-options.test.js +53 -24
- package/build/client/resolve-options.test.js.map +1 -1
- package/build/client/stream.js +1 -1
- package/build/client/stream.js.map +1 -1
- package/build/client/types.d.ts +31 -3
- package/build/codegen/__fixtures__/make-envelope.d.ts +41 -0
- package/build/codegen/__fixtures__/make-envelope.js +38 -0
- package/build/codegen/__fixtures__/make-envelope.js.map +1 -0
- package/build/codegen/bin/cli.d.ts +11 -0
- package/build/codegen/bin/cli.js +30 -21
- package/build/codegen/bin/cli.js.map +1 -1
- package/build/codegen/bin/cli.test.js +36 -1
- package/build/codegen/bin/cli.test.js.map +1 -1
- package/build/codegen/bin/flag-specs.d.ts +10 -0
- package/build/codegen/bin/flag-specs.js +60 -0
- package/build/codegen/bin/flag-specs.js.map +1 -0
- package/build/codegen/bin/flag-specs.test.d.ts +1 -0
- package/build/codegen/bin/flag-specs.test.js +26 -0
- package/build/codegen/bin/flag-specs.test.js.map +1 -0
- package/build/codegen/collect-models.d.ts +37 -0
- package/build/codegen/collect-models.js +74 -0
- package/build/codegen/collect-models.js.map +1 -0
- package/build/codegen/collect-models.test.d.ts +1 -0
- package/build/codegen/collect-models.test.js +40 -0
- package/build/codegen/collect-models.test.js.map +1 -0
- package/build/codegen/emit-client-runtime.js +1 -0
- package/build/codegen/emit-client-runtime.js.map +1 -1
- package/build/codegen/emit-models.d.ts +26 -0
- package/build/codegen/emit-models.js +53 -0
- package/build/codegen/emit-models.js.map +1 -0
- package/build/codegen/emit-models.test.d.ts +1 -0
- package/build/codegen/emit-models.test.js +42 -0
- package/build/codegen/emit-models.test.js.map +1 -0
- package/build/codegen/emit-scope.d.ts +10 -0
- package/build/codegen/emit-scope.js +119 -34
- package/build/codegen/emit-scope.js.map +1 -1
- package/build/codegen/emit-types.d.ts +26 -1
- package/build/codegen/emit-types.js +27 -5
- package/build/codegen/emit-types.js.map +1 -1
- package/build/codegen/index.d.ts +5 -0
- package/build/codegen/index.js +2 -0
- package/build/codegen/index.js.map +1 -1
- package/build/codegen/model-refs.d.ts +27 -0
- package/build/codegen/model-refs.js +49 -0
- package/build/codegen/model-refs.js.map +1 -0
- package/build/codegen/model-refs.test.d.ts +1 -0
- package/build/codegen/model-refs.test.js +33 -0
- package/build/codegen/model-refs.test.js.map +1 -0
- package/build/codegen/pipeline.d.ts +3 -0
- package/build/codegen/pipeline.js +3 -1
- package/build/codegen/pipeline.js.map +1 -1
- package/build/codegen/schema-walk.d.ts +13 -0
- package/build/codegen/schema-walk.js +26 -0
- package/build/codegen/schema-walk.js.map +1 -0
- package/build/codegen/schema-walk.test.d.ts +1 -0
- package/build/codegen/schema-walk.test.js +35 -0
- package/build/codegen/schema-walk.test.js.map +1 -0
- package/build/codegen/targets/_shared/target-run.d.ts +5 -0
- package/build/codegen/targets/ts/run.js +28 -1
- package/build/codegen/targets/ts/run.js.map +1 -1
- package/build/codegen/targets/ts/shared-models.test.d.ts +1 -0
- package/build/codegen/targets/ts/shared-models.test.js +258 -0
- package/build/codegen/targets/ts/shared-models.test.js.map +1 -0
- package/build/doc-envelope.d.ts +13 -0
- package/build/doc-envelope.js +23 -0
- package/build/doc-envelope.js.map +1 -0
- package/build/doc-envelope.test.d.ts +1 -0
- package/build/doc-envelope.test.js +31 -0
- package/build/doc-envelope.test.js.map +1 -0
- package/build/exports.d.ts +2 -0
- package/build/exports.js +1 -0
- package/build/exports.js.map +1 -1
- package/docs/client-and-codegen.md +101 -0
- package/docs/handoffs/ajsc-named-type-collision.md +134 -0
- package/docs/handoffs/ajsc-named-type-support.md +181 -0
- package/docs/superpowers/plans/2026-06-05-dx-feedback-round.md +1292 -0
- package/docs/superpowers/specs/2026-06-05-dx-feedback-round-design.md +285 -0
- package/package.json +2 -2
- package/src/client/call.ts +1 -1
- package/src/client/index.test.ts +98 -0
- package/src/client/index.ts +32 -1
- package/src/client/resolve-options.test.ts +73 -26
- package/src/client/resolve-options.ts +23 -9
- package/src/client/stream.ts +1 -1
- package/src/client/types.ts +34 -3
- package/src/codegen/__fixtures__/make-envelope.ts +89 -0
- package/src/codegen/bin/cli.test.ts +38 -1
- package/src/codegen/bin/cli.ts +33 -22
- package/src/codegen/bin/flag-specs.test.ts +27 -0
- package/src/codegen/bin/flag-specs.ts +69 -0
- package/src/codegen/collect-models.test.ts +46 -0
- package/src/codegen/collect-models.ts +108 -0
- package/src/codegen/emit-client-runtime.ts +1 -0
- package/src/codegen/emit-models.test.ts +48 -0
- package/src/codegen/emit-models.ts +63 -0
- package/src/codegen/emit-scope.ts +145 -33
- package/src/codegen/emit-types.ts +48 -7
- package/src/codegen/index.ts +7 -0
- package/src/codegen/model-refs.test.ts +37 -0
- package/src/codegen/model-refs.ts +57 -0
- package/src/codegen/pipeline.ts +6 -1
- package/src/codegen/schema-walk.test.ts +37 -0
- package/src/codegen/schema-walk.ts +23 -0
- package/src/codegen/targets/_shared/target-run.ts +5 -0
- package/src/codegen/targets/ts/run.ts +33 -0
- package/src/codegen/targets/ts/shared-models.test.ts +283 -0
- package/src/doc-envelope.test.ts +35 -0
- package/src/doc-envelope.ts +30 -0
- package/src/exports.ts +2 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface FlagSpec {
|
|
2
|
+
name: string;
|
|
3
|
+
arg?: string;
|
|
4
|
+
description: string;
|
|
5
|
+
group: 'Source' | 'Output' | 'Codegen' | 'Targets' | 'Misc';
|
|
6
|
+
default?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare const FLAG_SPECS: readonly FlagSpec[];
|
|
9
|
+
export declare const KNOWN_FLAGS: readonly string[];
|
|
10
|
+
export declare function formatHelp(): string;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export const FLAG_SPECS = [
|
|
2
|
+
// Source
|
|
3
|
+
{ name: '--url', arg: '<url>', description: 'Fetch the doc envelope from a running server', group: 'Source' },
|
|
4
|
+
{ name: '--file', arg: '<path>', description: 'Read the doc envelope from a JSON file (see writeDocEnvelope)', group: 'Source' },
|
|
5
|
+
{ name: '--config', arg: '<path>', description: 'Load options from a JSON config file', group: 'Source' },
|
|
6
|
+
// Output
|
|
7
|
+
{ name: '--out', arg: '<dir>', description: 'Output directory for generated files', group: 'Output' },
|
|
8
|
+
{ name: '--dry-run', description: 'Print what would be written without touching disk', group: 'Output' },
|
|
9
|
+
{ name: '--clean-out-dir', description: 'Prune orphaned generator-owned files before writing', group: 'Output', default: 'on' },
|
|
10
|
+
{ name: '--no-clean-out-dir', description: 'Disable orphan pruning', group: 'Output' },
|
|
11
|
+
{ name: '--watch', description: 'Regenerate on envelope change', group: 'Output' },
|
|
12
|
+
{ name: '--interval', arg: '<ms>', description: 'Poll interval for --watch (default 3000)', group: 'Output' },
|
|
13
|
+
// Codegen
|
|
14
|
+
{ name: '--service-name', arg: '<name>', description: 'Service identifier driving generated names', group: 'Codegen', default: 'Api' },
|
|
15
|
+
{ name: '--namespace-types', description: 'Wrap types in nested namespaces', group: 'Codegen', default: 'on' },
|
|
16
|
+
{ name: '--no-namespace-types', description: 'Flat type names', group: 'Codegen' },
|
|
17
|
+
{ name: '--self-contained', description: 'Bundle the client runtime into the output dir', group: 'Codegen', default: 'on' },
|
|
18
|
+
{ name: '--no-self-contained', description: 'Import the client runtime from ts-procedures/client', group: 'Codegen' },
|
|
19
|
+
{ name: '--client-import-path', arg: '<path>', description: 'Override the client runtime import path', group: 'Codegen' },
|
|
20
|
+
{ name: '--share-models', description: 'Hoist $id-bearing schemas into a shared _models.ts', group: 'Codegen', default: 'on' },
|
|
21
|
+
{ name: '--no-share-models', description: 'Inline every type per route (legacy behaviour)', group: 'Codegen' },
|
|
22
|
+
{ name: '--jsdoc', description: 'Emit JSDoc on generated types', group: 'Codegen', default: 'on' },
|
|
23
|
+
{ name: '--no-jsdoc', description: 'Suppress JSDoc', group: 'Codegen' },
|
|
24
|
+
{ name: '--enum-style', arg: '<union|enum>', description: 'How to emit enums (namespace mode)', group: 'Codegen' },
|
|
25
|
+
{ name: '--depluralize', description: 'Depluralize extracted array-item type names', group: 'Codegen' },
|
|
26
|
+
{ name: '--array-item-naming', arg: '<name|false>', description: 'Naming for extracted array-item types', group: 'Codegen' },
|
|
27
|
+
{ name: '--uncountable-words', arg: '<csv>', description: 'Words exempt from depluralization', group: 'Codegen' },
|
|
28
|
+
// Targets
|
|
29
|
+
{ name: '--target', arg: '<ts|kotlin|swift>', description: 'Output language', group: 'Targets', default: 'ts' },
|
|
30
|
+
{ name: '--kotlin-package', arg: '<pkg>', description: 'Package for Kotlin output (required for --target kotlin)', group: 'Targets' },
|
|
31
|
+
{ name: '--kotlin-serializer', arg: '<kotlinx|none>', description: 'Kotlin serialization annotations', group: 'Targets', default: 'kotlinx' },
|
|
32
|
+
{ name: '--swift-serializer', arg: '<codable|none>', description: 'Swift Codable conformance', group: 'Targets', default: 'codable' },
|
|
33
|
+
{ name: '--swift-access-level', arg: '<public|internal>', description: 'Swift access level', group: 'Targets', default: 'public' },
|
|
34
|
+
{ name: '--unsupported-unions', arg: '<throw|fallback>', description: 'Behaviour for untagged oneOf schemas', group: 'Targets', default: 'throw' },
|
|
35
|
+
];
|
|
36
|
+
export const KNOWN_FLAGS = FLAG_SPECS.map((s) => s.name);
|
|
37
|
+
const GROUP_ORDER = ['Source', 'Output', 'Codegen', 'Targets', 'Misc'];
|
|
38
|
+
export function formatHelp() {
|
|
39
|
+
const lines = [];
|
|
40
|
+
lines.push('Usage: ts-procedures-codegen --out <dir> (--url <url> | --file <path>) [options]');
|
|
41
|
+
lines.push('');
|
|
42
|
+
lines.push('Generate a typed client from a ts-procedures doc envelope.');
|
|
43
|
+
lines.push('');
|
|
44
|
+
const col = Math.max(...FLAG_SPECS.map((s) => (s.name + (s.arg ? ' ' + s.arg : '')).length)) + 2;
|
|
45
|
+
for (const group of GROUP_ORDER) {
|
|
46
|
+
const specs = FLAG_SPECS.filter((s) => s.group === group);
|
|
47
|
+
if (specs.length === 0)
|
|
48
|
+
continue;
|
|
49
|
+
lines.push(`${group}:`);
|
|
50
|
+
for (const s of specs) {
|
|
51
|
+
const left = s.name + (s.arg ? ' ' + s.arg : '');
|
|
52
|
+
const def = s.default ? ` (default: ${s.default})` : '';
|
|
53
|
+
lines.push(` ${left.padEnd(col)}${s.description}${def}`);
|
|
54
|
+
}
|
|
55
|
+
lines.push('');
|
|
56
|
+
}
|
|
57
|
+
lines.push(' -h, --help Show this help and exit');
|
|
58
|
+
return lines.join('\n');
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=flag-specs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flag-specs.js","sourceRoot":"","sources":["../../../src/codegen/bin/flag-specs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { FLAG_SPECS, KNOWN_FLAGS, formatHelp } from './flag-specs.js';
|
|
3
|
+
describe('flag-specs', () => {
|
|
4
|
+
it('derives KNOWN_FLAGS from the spec table', () => {
|
|
5
|
+
expect(KNOWN_FLAGS).toContain('--url');
|
|
6
|
+
expect(KNOWN_FLAGS).toContain('--service-name');
|
|
7
|
+
expect(KNOWN_FLAGS).toContain('--target');
|
|
8
|
+
for (const spec of FLAG_SPECS)
|
|
9
|
+
expect(KNOWN_FLAGS).toContain(spec.name);
|
|
10
|
+
});
|
|
11
|
+
it('formatHelp lists every flag with its description, grouped', () => {
|
|
12
|
+
const help = formatHelp();
|
|
13
|
+
expect(help).toMatch(/Usage: ts-procedures-codegen/);
|
|
14
|
+
for (const spec of FLAG_SPECS) {
|
|
15
|
+
expect(help).toContain(spec.name);
|
|
16
|
+
expect(help).toContain(spec.description);
|
|
17
|
+
}
|
|
18
|
+
expect(help).toMatch(/Source/);
|
|
19
|
+
expect(help).toMatch(/Targets/);
|
|
20
|
+
});
|
|
21
|
+
it('does not list --help/-h as a real codegen flag in KNOWN_FLAGS', () => {
|
|
22
|
+
expect(KNOWN_FLAGS).not.toContain('--help');
|
|
23
|
+
expect(KNOWN_FLAGS).not.toContain('-h');
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
//# sourceMappingURL=flag-specs.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flag-specs.test.js","sourceRoot":"","sources":["../../../src/codegen/bin/flag-specs.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAErE,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;QACtC,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAA;QAC/C,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAA;QACzC,KAAK,MAAM,IAAI,IAAI,UAAU;YAAE,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACzE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,MAAM,IAAI,GAAG,UAAU,EAAE,CAAA;QACzB,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,8BAA8B,CAAC,CAAA;QACpD,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;YAC9B,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACjC,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;QAC1C,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QAC9B,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IACjC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;QACvE,MAAM,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAA;QAC3C,MAAM,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;IACzC,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { AnyHttpRouteDoc } from '../implementations/types.js';
|
|
2
|
+
/** A schema hoisted out of per-route inlining because it carries a `$id`. */
|
|
3
|
+
export interface CollectedModel {
|
|
4
|
+
/** The schema's `$id` — the stable identity key used for dedup and import mapping. */
|
|
5
|
+
id: string;
|
|
6
|
+
/** PascalCase TypeScript identifier for the emitted model (disambiguated on collision). */
|
|
7
|
+
name: string;
|
|
8
|
+
/** The model's JSON Schema (first-seen copy). */
|
|
9
|
+
schema: Record<string, unknown>;
|
|
10
|
+
}
|
|
11
|
+
/** Maps a model `$id` to an external import (module + exported name). */
|
|
12
|
+
export interface SharedTypeImport {
|
|
13
|
+
module: string;
|
|
14
|
+
name: string;
|
|
15
|
+
}
|
|
16
|
+
/** `$id` → external import. Models with a matching entry are imported rather than generated. */
|
|
17
|
+
export type SharedTypesImportMap = Record<string, SharedTypeImport>;
|
|
18
|
+
/** A {@link CollectedModel} tagged with its external import, if one was configured. */
|
|
19
|
+
export interface ResolvedModel extends CollectedModel {
|
|
20
|
+
import?: SharedTypeImport;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Deep-walks every route's `jsonSchema` and collects each subschema carrying a
|
|
24
|
+
* string `$id` exactly once (deduped by `$id`, first-seen order preserved).
|
|
25
|
+
*
|
|
26
|
+
* - Names are derived from `title` (or the last `$id` segment), PascalCased.
|
|
27
|
+
* - Distinct `$id`s that derive the same name are disambiguated deterministically
|
|
28
|
+
* by first-seen order (`Message`, `Message2`, `Message3`, …).
|
|
29
|
+
* - Two nodes sharing an `$id` but differing structurally throw (the `$id` is a
|
|
30
|
+
* broken identity contract).
|
|
31
|
+
*/
|
|
32
|
+
export declare function collectModels(routes: AnyHttpRouteDoc[]): CollectedModel[];
|
|
33
|
+
/**
|
|
34
|
+
* Tags each collected model with its external import when its `$id` is a key in
|
|
35
|
+
* the import map; models without a mapping keep `import` undefined (generated locally).
|
|
36
|
+
*/
|
|
37
|
+
export declare function resolveModelImports(models: CollectedModel[], map?: SharedTypesImportMap): ResolvedModel[];
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { toPascalCase } from './naming.js';
|
|
2
|
+
import { walkSubschemas } from './schema-walk.js';
|
|
3
|
+
/** Produces a stable structural key for collision detection (key order does not matter). */
|
|
4
|
+
function structuralKey(value) {
|
|
5
|
+
return JSON.stringify(value, (_k, v) => {
|
|
6
|
+
if (v && typeof v === 'object' && !Array.isArray(v)) {
|
|
7
|
+
const sorted = {};
|
|
8
|
+
for (const k of Object.keys(v).sort()) {
|
|
9
|
+
sorted[k] = v[k];
|
|
10
|
+
}
|
|
11
|
+
return sorted;
|
|
12
|
+
}
|
|
13
|
+
return v;
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
/** Derives a base PascalCase name from a schema's `title`, falling back to the last `$id` segment. */
|
|
17
|
+
function deriveBaseName(schema, id) {
|
|
18
|
+
const title = typeof schema.title === 'string' ? schema.title : undefined;
|
|
19
|
+
const source = title ?? id.split(/[/:#?]+/).filter(Boolean).pop() ?? id;
|
|
20
|
+
const pascal = toPascalCase(source);
|
|
21
|
+
return pascal.length > 0 ? pascal : 'Model';
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Deep-walks every route's `jsonSchema` and collects each subschema carrying a
|
|
25
|
+
* string `$id` exactly once (deduped by `$id`, first-seen order preserved).
|
|
26
|
+
*
|
|
27
|
+
* - Names are derived from `title` (or the last `$id` segment), PascalCased.
|
|
28
|
+
* - Distinct `$id`s that derive the same name are disambiguated deterministically
|
|
29
|
+
* by first-seen order (`Message`, `Message2`, `Message3`, …).
|
|
30
|
+
* - Two nodes sharing an `$id` but differing structurally throw (the `$id` is a
|
|
31
|
+
* broken identity contract).
|
|
32
|
+
*/
|
|
33
|
+
export function collectModels(routes) {
|
|
34
|
+
const byId = new Map();
|
|
35
|
+
const order = [];
|
|
36
|
+
const visit = (obj) => {
|
|
37
|
+
if (typeof obj.$id === 'string') {
|
|
38
|
+
const id = obj.$id;
|
|
39
|
+
const key = structuralKey(obj);
|
|
40
|
+
const existing = byId.get(id);
|
|
41
|
+
if (existing) {
|
|
42
|
+
if (existing.key !== key) {
|
|
43
|
+
throw new Error(`[ts-procedures-codegen] Conflicting schemas share $id "${id}". A $id must identify a single structural shape; found two divergent definitions.`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
byId.set(id, { schema: obj, key });
|
|
48
|
+
order.push(id);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
for (const route of routes)
|
|
53
|
+
walkSubschemas(route.jsonSchema, visit);
|
|
54
|
+
const usedNames = new Map();
|
|
55
|
+
return order.map((id) => {
|
|
56
|
+
const { schema } = byId.get(id);
|
|
57
|
+
const base = deriveBaseName(schema, id);
|
|
58
|
+
const seen = usedNames.get(base) ?? 0;
|
|
59
|
+
usedNames.set(base, seen + 1);
|
|
60
|
+
const name = seen === 0 ? base : `${base}${seen + 1}`;
|
|
61
|
+
return { id, name, schema };
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Tags each collected model with its external import when its `$id` is a key in
|
|
66
|
+
* the import map; models without a mapping keep `import` undefined (generated locally).
|
|
67
|
+
*/
|
|
68
|
+
export function resolveModelImports(models, map = {}) {
|
|
69
|
+
return models.map((model) => {
|
|
70
|
+
const mapped = map[model.id];
|
|
71
|
+
return mapped ? { ...model, import: mapped } : { ...model };
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=collect-models.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collect-models.js","sourceRoot":"","sources":["../../src/codegen/collect-models.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { it, expect } from 'vitest';
|
|
2
|
+
import { collectModels, resolveModelImports } from './collect-models.js';
|
|
3
|
+
const message = { type: 'object', $id: 'urn:msg', title: 'Message', properties: { id: { type: 'string' } } };
|
|
4
|
+
it('collects each $id subschema once, named from title', () => {
|
|
5
|
+
const routes = [
|
|
6
|
+
{ jsonSchema: { response: message } },
|
|
7
|
+
{ jsonSchema: { body: { type: 'object', properties: { msg: message } } } },
|
|
8
|
+
];
|
|
9
|
+
const models = collectModels(routes);
|
|
10
|
+
expect(models.map((m) => m.name)).toEqual(['Message']);
|
|
11
|
+
expect(models[0]?.id).toBe('urn:msg');
|
|
12
|
+
});
|
|
13
|
+
it('throws on $id collision with divergent body', () => {
|
|
14
|
+
const a = { type: 'object', $id: 'urn:x', title: 'X', properties: { a: { type: 'string' } } };
|
|
15
|
+
const b = { type: 'object', $id: 'urn:x', title: 'X', properties: { b: { type: 'number' } } };
|
|
16
|
+
expect(() => collectModels([{ jsonSchema: { response: a } }, { jsonSchema: { body: b } }])).toThrow(/urn:x/);
|
|
17
|
+
});
|
|
18
|
+
it('disambiguates distinct $ids that derive the same name', () => {
|
|
19
|
+
const m1 = { type: 'object', $id: 'urn:a/message', title: 'Message', properties: { a: { type: 'string' } } };
|
|
20
|
+
const m2 = { type: 'object', $id: 'urn:b/message', title: 'Message', properties: { b: { type: 'string' } } };
|
|
21
|
+
const models = collectModels([{ jsonSchema: { response: m1 } }, { jsonSchema: { body: m2 } }]);
|
|
22
|
+
expect(models.map((m) => m.name).sort()).toEqual(['Message', 'Message2']);
|
|
23
|
+
});
|
|
24
|
+
it('ignores schemas without $id', () => {
|
|
25
|
+
const routes = [{ jsonSchema: { response: { type: 'object', title: 'Loose', properties: {} } } }];
|
|
26
|
+
expect(collectModels(routes)).toEqual([]);
|
|
27
|
+
});
|
|
28
|
+
it('does NOT throw for ordinary schemas without the reserved prefix', () => {
|
|
29
|
+
const routes = [
|
|
30
|
+
{ jsonSchema: { response: { type: 'object', properties: { kind: { const: 'message' }, status: { enum: ['ok', 'error'] } } } } },
|
|
31
|
+
];
|
|
32
|
+
expect(() => collectModels(routes)).not.toThrow();
|
|
33
|
+
});
|
|
34
|
+
it('resolveModelImports tags mapped models and leaves others generated', () => {
|
|
35
|
+
const models = [{ id: 'urn:msg', name: 'Message', schema: {} }];
|
|
36
|
+
const mapped = resolveModelImports(models, { 'urn:msg': { module: '@shared/schemas', name: 'Message' } });
|
|
37
|
+
expect(mapped[0]?.import).toEqual({ module: '@shared/schemas', name: 'Message' });
|
|
38
|
+
expect(resolveModelImports(models, {})[0]?.import).toBeUndefined();
|
|
39
|
+
});
|
|
40
|
+
//# sourceMappingURL=collect-models.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collect-models.test.js","sourceRoot":"","sources":["../../src/codegen/collect-models.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emit-client-runtime.js","sourceRoot":"","sources":["../../src/codegen/emit-client-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAE/C,MAAM,YAAY,GAAG
|
|
1
|
+
{"version":3,"file":"emit-client-runtime.js","sourceRoot":"","sources":["../../src/codegen/emit-client-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAE/C,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA4BH,CAAA;AAElB;;;GAGG;AACH,MAAM,YAAY,GAAG;IACnB,WAAW;IACX,mBAAmB;IACnB,mBAAmB;IACnB,oBAAoB;IACpB,oBAAoB;IACpB,UAAU;IACV,SAAS;IACT,WAAW;IACX,kBAAkB;IAClB,UAAU;CACF,CAAA;AAEV;;;;;;;GAOG;AACH,SAAS,YAAY,CAAC,OAAe;IACnC,2DAA2D;IAC3D,OAAO,OAAO,CAAC,OAAO,CAAC,mDAAmD,EAAE,EAAE,CAAC,CAAA;AACjF,CAAC;AAED;;;;GAIG;AACH,SAAS,cAAc,CAAC,OAAe;IACrC,mFAAmF;IACnF,OAAO,OAAO,CAAC,OAAO,CAAC,gEAAgE,EAAE,EAAE,CAAC,CAAA;AAC9F,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB;IACzC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACjD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;IACrC,sEAAsE;IACtE,MAAM,WAAW,GAAG,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;IAC/C,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,EAAE,YAAY,CAAC,CAAA;IAEpD,gCAAgC;IAChC,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;QACzC,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;YAChC,MAAM,IAAI,KAAK,CACb,oDAAoD,IAAI,sBAAsB,QAAQ,IAAI;gBAC1F,8CAA8C,CAC/C,CAAA;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,MAAM,QAAQ,GAAa,EAAE,CAAA;IAE7B,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;QACzC,IAAI,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;QAE/C,mDAAmD;QACnD,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,CAAA;QAE/B,kDAAkD;QAClD,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;YACxB,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,CAAA;YACjC,0EAA0E;YAC1E,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,uBAAuB,EAAE,EAAE,CAAC,CAAA;QACxD,CAAC;QAED,yCAAyC;QACzC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;QAE5C,mCAAmC;QACnC,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAA;QAExB,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QACxB,CAAC;IACH,CAAC;IAED,OAAO,CAAC,cAAc,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,GAAG,QAAQ,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AAC3E,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type AjscOptions } from './emit-types.js';
|
|
2
|
+
import type { ResolvedModel } from './collect-models.js';
|
|
3
|
+
export interface EmitModelsOptions {
|
|
4
|
+
ajsc?: AjscOptions;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Emits the shared `_models.ts` hub: one named TypeScript type per `$id`-bearing
|
|
8
|
+
* schema so routes can reference a single entity type instead of inlining copies.
|
|
9
|
+
*
|
|
10
|
+
* Two kinds of model:
|
|
11
|
+
* - **Imported** (`model.import` set): re-exported from the user's package —
|
|
12
|
+
* `export { <PkgName>[ as <LocalName>] } from '<module>'`.
|
|
13
|
+
* - **Generated** (no `import`): converted from JSON Schema to a TS type via
|
|
14
|
+
* ajsc. Nested OTHER models are first rewritten to `x-named-type` nodes
|
|
15
|
+
* ({@link substituteModelRefs} with `skipSelfId` so the model's own root
|
|
16
|
+
* `$id` is not self-referenced); ajsc (≥7.3.0) then emits each nested model
|
|
17
|
+
* as a bare verbatim reference rather than re-inlining its shape.
|
|
18
|
+
*
|
|
19
|
+
* Declarations are kept FLAT at the top level regardless of `namespaceTypes` —
|
|
20
|
+
* scopes import these by bare name and TS `type` aliases permit forward
|
|
21
|
+
* references, so declaration order does not matter. Re-exports are emitted first,
|
|
22
|
+
* then generated declarations.
|
|
23
|
+
*
|
|
24
|
+
* Returns `null` when there are no models.
|
|
25
|
+
*/
|
|
26
|
+
export declare function emitModelsFile(models: ResolvedModel[], opts: EmitModelsOptions): Promise<string | null>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { jsonSchemaToTypeBody } from './emit-types.js';
|
|
2
|
+
import { substituteModelRefs } from './model-refs.js';
|
|
3
|
+
import { CODEGEN_HEADER } from './constants.js';
|
|
4
|
+
/**
|
|
5
|
+
* Emits the shared `_models.ts` hub: one named TypeScript type per `$id`-bearing
|
|
6
|
+
* schema so routes can reference a single entity type instead of inlining copies.
|
|
7
|
+
*
|
|
8
|
+
* Two kinds of model:
|
|
9
|
+
* - **Imported** (`model.import` set): re-exported from the user's package —
|
|
10
|
+
* `export { <PkgName>[ as <LocalName>] } from '<module>'`.
|
|
11
|
+
* - **Generated** (no `import`): converted from JSON Schema to a TS type via
|
|
12
|
+
* ajsc. Nested OTHER models are first rewritten to `x-named-type` nodes
|
|
13
|
+
* ({@link substituteModelRefs} with `skipSelfId` so the model's own root
|
|
14
|
+
* `$id` is not self-referenced); ajsc (≥7.3.0) then emits each nested model
|
|
15
|
+
* as a bare verbatim reference rather than re-inlining its shape.
|
|
16
|
+
*
|
|
17
|
+
* Declarations are kept FLAT at the top level regardless of `namespaceTypes` —
|
|
18
|
+
* scopes import these by bare name and TS `type` aliases permit forward
|
|
19
|
+
* references, so declaration order does not matter. Re-exports are emitted first,
|
|
20
|
+
* then generated declarations.
|
|
21
|
+
*
|
|
22
|
+
* Returns `null` when there are no models.
|
|
23
|
+
*/
|
|
24
|
+
export async function emitModelsFile(models, opts) {
|
|
25
|
+
if (models.length === 0)
|
|
26
|
+
return null;
|
|
27
|
+
const idToName = new Map(models.map((m) => [m.id, m.name]));
|
|
28
|
+
const reExports = [];
|
|
29
|
+
const declarations = [];
|
|
30
|
+
for (const model of models) {
|
|
31
|
+
if (model.import) {
|
|
32
|
+
const pkgName = model.import.name;
|
|
33
|
+
const localName = model.name;
|
|
34
|
+
const clause = pkgName === localName ? pkgName : `${pkgName} as ${localName}`;
|
|
35
|
+
reExports.push(`export { ${clause} } from '${model.import.module}'`);
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
// Generated model: rewrite nested OTHER models to `x-named-type` nodes so
|
|
39
|
+
// ajsc emits them as bare references, then convert to a TS body.
|
|
40
|
+
const substituted = substituteModelRefs(model.schema, idToName, model.id);
|
|
41
|
+
const body = await jsonSchemaToTypeBody(substituted.schema, opts.ajsc);
|
|
42
|
+
if (body == null)
|
|
43
|
+
continue;
|
|
44
|
+
declarations.push(`export type ${model.name} = ${body}`);
|
|
45
|
+
}
|
|
46
|
+
const blocks = [];
|
|
47
|
+
if (reExports.length > 0)
|
|
48
|
+
blocks.push(reExports.join('\n'));
|
|
49
|
+
for (const decl of declarations)
|
|
50
|
+
blocks.push(decl);
|
|
51
|
+
return [CODEGEN_HEADER, '', blocks.join('\n\n')].join('\n');
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=emit-models.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emit-models.js","sourceRoot":"","sources":["../../src/codegen/emit-models.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAoB,MAAM,iBAAiB,CAAA;AACxE,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAO/C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAuB,EACvB,IAAuB;IAEvB,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IAEpC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAE3D,MAAM,SAAS,GAAa,EAAE,CAAA;IAC9B,MAAM,YAAY,GAAa,EAAE,CAAA;IAEjC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAA;YACjC,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAA;YAC5B,MAAM,MAAM,GAAG,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,OAAO,SAAS,EAAE,CAAA;YAC7E,SAAS,CAAC,IAAI,CAAC,YAAY,MAAM,YAAY,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAA;YACpE,SAAQ;QACV,CAAC;QAED,0EAA0E;QAC1E,iEAAiE;QACjE,MAAM,WAAW,GAAG,mBAAmB,CAAC,KAAK,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,CAAA;QACzE,MAAM,IAAI,GAAG,MAAM,oBAAoB,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA;QACtE,IAAI,IAAI,IAAI,IAAI;YAAE,SAAQ;QAC1B,YAAY,CAAC,IAAI,CAAC,eAAe,KAAK,CAAC,IAAI,MAAM,IAAI,EAAE,CAAC,CAAA;IAC1D,CAAC;IAED,MAAM,MAAM,GAAa,EAAE,CAAA;IAC3B,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IAC3D,KAAK,MAAM,IAAI,IAAI,YAAY;QAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAElD,OAAO,CAAC,cAAc,EAAE,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AAC7D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { emitModelsFile } from './emit-models.js';
|
|
3
|
+
const thread = {
|
|
4
|
+
id: 'urn:thread', name: 'Thread',
|
|
5
|
+
schema: { type: 'object', $id: 'urn:thread', title: 'Thread',
|
|
6
|
+
properties: { id: { type: 'string' }, author: { type: 'object', $id: 'urn:msg', title: 'Message', properties: { id: { type: 'string' } } } } },
|
|
7
|
+
};
|
|
8
|
+
const messageGenerated = {
|
|
9
|
+
id: 'urn:msg', name: 'Message',
|
|
10
|
+
schema: { type: 'object', $id: 'urn:msg', title: 'Message', properties: { id: { type: 'string' } } },
|
|
11
|
+
};
|
|
12
|
+
const messageImported = {
|
|
13
|
+
id: 'urn:msg', name: 'Message', schema: {},
|
|
14
|
+
import: { module: '@shared/schemas', name: 'Message' },
|
|
15
|
+
};
|
|
16
|
+
describe('emitModelsFile', () => {
|
|
17
|
+
it('returns null when there are no models', async () => {
|
|
18
|
+
expect(await emitModelsFile([], { ajsc: {} })).toBeNull();
|
|
19
|
+
});
|
|
20
|
+
it('declares a generated model as a named type', async () => {
|
|
21
|
+
const code = await emitModelsFile([messageGenerated], { ajsc: {} });
|
|
22
|
+
expect(code).toMatch(/export type Message =/);
|
|
23
|
+
});
|
|
24
|
+
it('re-exports a mapped model from the user package', async () => {
|
|
25
|
+
const code = await emitModelsFile([messageImported], { ajsc: {} });
|
|
26
|
+
expect(code).toContain("export { Message } from '@shared/schemas'");
|
|
27
|
+
});
|
|
28
|
+
it('aliases a re-export when local name differs from the package name', async () => {
|
|
29
|
+
const m = { id: 'urn:msg', name: 'ChatMessage', schema: {}, import: { module: '@shared/schemas', name: 'Message' } };
|
|
30
|
+
const code = await emitModelsFile([m], { ajsc: {} });
|
|
31
|
+
expect(code).toContain("export { Message as ChatMessage } from '@shared/schemas'");
|
|
32
|
+
});
|
|
33
|
+
it('a generated model that nests another model references it by name, not inlined', async () => {
|
|
34
|
+
// Thread.author is the Message model — Thread should reference Message, not inline { id }
|
|
35
|
+
const code = await emitModelsFile([thread, messageGenerated], { ajsc: {} });
|
|
36
|
+
// Thread's author property is typed as Message (the model), referenced by bare name
|
|
37
|
+
expect(code).toMatch(/author\??:\s*Message/);
|
|
38
|
+
// and there is no leftover placeholder token
|
|
39
|
+
expect(code).not.toContain('__MODELREF__');
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
//# sourceMappingURL=emit-models.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emit-models.test.js","sourceRoot":"","sources":["../../src/codegen/emit-models.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,6 +12,16 @@ export interface EmitScopeOptions {
|
|
|
12
12
|
* so generated code never references undefined types.
|
|
13
13
|
*/
|
|
14
14
|
errorKeys?: Set<string>;
|
|
15
|
+
/**
|
|
16
|
+
* Maps a model `$id` to its shared model type name (built by the run module
|
|
17
|
+
* from ALL models — generated and imported). When present and non-empty,
|
|
18
|
+
* `$id` subschemas are rewritten to `x-named-type` nodes before ajsc; ajsc
|
|
19
|
+
* emits bare references and reports them via `referencedNamedTypes`, which
|
|
20
|
+
* drives the `import type { … } from './_models'` line. Absent/empty →
|
|
21
|
+
* identical inlining behaviour (the conversion wrappers short-circuit so
|
|
22
|
+
* output is byte-identical for envelopes without models).
|
|
23
|
+
*/
|
|
24
|
+
idToModelName?: Map<string, string>;
|
|
15
25
|
}
|
|
16
26
|
/**
|
|
17
27
|
* Generates a complete TypeScript scope file for a ScopeGroup.
|