@thymian/plugin-sampler 0.3.0-canary.20261007-e6cb8dc → 0.3.0-canary.20261007-cdbe1d3
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/cli/check-result.d.ts +88 -0
- package/dist/cli/check-result.d.ts.map +1 -0
- package/dist/cli/check-result.js +160 -0
- package/dist/cli/check-result.js.map +1 -0
- package/dist/cli/commands/sampler/check.d.ts +32 -4
- package/dist/cli/commands/sampler/check.d.ts.map +1 -1
- package/dist/cli/commands/sampler/check.js +126 -88
- package/dist/cli/commands/sampler/check.js.map +1 -1
- package/dist/cli/commands/sampler/init.d.ts +4 -6
- package/dist/cli/commands/sampler/init.d.ts.map +1 -1
- package/dist/cli/commands/sampler/init.js +33 -49
- package/dist/cli/commands/sampler/init.js.map +1 -1
- package/dist/cli/commands/sampler/show.d.ts +11 -0
- package/dist/cli/commands/sampler/show.d.ts.map +1 -0
- package/dist/cli/commands/sampler/show.js +36 -0
- package/dist/cli/commands/sampler/show.js.map +1 -0
- package/dist/cli/commands/sampler/sync.d.ts +11 -0
- package/dist/cli/commands/sampler/sync.d.ts.map +1 -0
- package/dist/cli/commands/sampler/sync.js +65 -0
- package/dist/cli/commands/sampler/sync.js.map +1 -0
- package/dist/cli/commands/sampler/validate.d.ts +3 -10
- package/dist/cli/commands/sampler/validate.d.ts.map +1 -1
- package/dist/cli/commands/sampler/validate.js +57 -126
- package/dist/cli/commands/sampler/validate.js.map +1 -1
- package/dist/generation/closed-schema.d.ts +22 -0
- package/dist/generation/closed-schema.d.ts.map +1 -0
- package/dist/generation/closed-schema.js +45 -0
- package/dist/generation/closed-schema.js.map +1 -0
- package/dist/generation/content-type-strategies/json.content-type-strategy.d.ts.map +1 -1
- package/dist/generation/content-type-strategies/json.content-type-strategy.js +3 -1
- package/dist/generation/content-type-strategies/json.content-type-strategy.js.map +1 -1
- package/dist/generation/content-type-strategies/xml.content-type-strategy.d.ts.map +1 -1
- package/dist/generation/content-type-strategies/xml.content-type-strategy.js +3 -1
- package/dist/generation/content-type-strategies/xml.content-type-strategy.js.map +1 -1
- package/dist/generation/generate-request-sample.d.ts +12 -0
- package/dist/generation/generate-request-sample.d.ts.map +1 -0
- package/dist/generation/{generate-samples.js → generate-request-sample.js} +11 -4
- package/dist/generation/generate-request-sample.js.map +1 -0
- package/dist/generation/request-generators/default-request-generator.d.ts +14 -0
- package/dist/generation/request-generators/default-request-generator.d.ts.map +1 -1
- package/dist/generation/request-generators/default-request-generator.js +18 -1
- package/dist/generation/request-generators/default-request-generator.js.map +1 -1
- package/dist/generation/types/declaration-set.d.ts +124 -0
- package/dist/generation/types/declaration-set.d.ts.map +1 -0
- package/dist/generation/types/declaration-set.js +389 -0
- package/dist/generation/types/declaration-set.js.map +1 -0
- package/dist/generation/types/example-reflection.d.ts +21 -0
- package/dist/generation/types/example-reflection.d.ts.map +1 -0
- package/dist/generation/types/example-reflection.js +135 -0
- package/dist/generation/types/example-reflection.js.map +1 -0
- package/dist/generation/types/generate-type-surface.d.ts +23 -0
- package/dist/generation/types/generate-type-surface.d.ts.map +1 -0
- package/dist/generation/types/generate-type-surface.js +671 -0
- package/dist/generation/types/generate-type-surface.js.map +1 -0
- package/dist/generation/types/schema-type.d.ts +20 -0
- package/dist/generation/types/schema-type.d.ts.map +1 -0
- package/dist/generation/types/schema-type.js +203 -0
- package/dist/generation/types/schema-type.js.map +1 -0
- package/dist/generation/types/self-check-surface.d.ts +32 -0
- package/dist/generation/types/self-check-surface.d.ts.map +1 -0
- package/dist/generation/types/self-check-surface.js +92 -0
- package/dist/generation/types/self-check-surface.js.map +1 -0
- package/dist/generation/types/type-names.d.ts +135 -0
- package/dist/generation/types/type-names.d.ts.map +1 -0
- package/dist/generation/types/type-names.js +213 -0
- package/dist/generation/types/type-names.js.map +1 -0
- package/dist/generation/types/write-type-surface.d.ts +58 -0
- package/dist/generation/types/write-type-surface.d.ts.map +1 -0
- package/dist/generation/types/write-type-surface.js +119 -0
- package/dist/generation/types/write-type-surface.js.map +1 -0
- package/dist/hooks/create-hook-utils.d.ts +22 -6
- package/dist/hooks/create-hook-utils.d.ts.map +1 -1
- package/dist/hooks/create-hook-utils.js +74 -96
- package/dist/hooks/create-hook-utils.js.map +1 -1
- package/dist/hooks/hook-api.d.ts +49 -0
- package/dist/hooks/hook-api.d.ts.map +1 -0
- package/dist/hooks/hook-api.js +105 -0
- package/dist/hooks/hook-api.js.map +1 -0
- package/dist/hooks/hook-diagnostics.d.ts +45 -0
- package/dist/hooks/hook-diagnostics.d.ts.map +1 -0
- package/dist/hooks/hook-diagnostics.js +80 -0
- package/dist/hooks/hook-diagnostics.js.map +1 -0
- package/dist/hooks/hook-errors.d.ts +33 -0
- package/dist/hooks/hook-errors.d.ts.map +1 -1
- package/dist/hooks/hook-errors.js +46 -0
- package/dist/hooks/hook-errors.js.map +1 -1
- package/dist/hooks/hook-registration.d.ts +108 -0
- package/dist/hooks/hook-registration.d.ts.map +1 -0
- package/dist/hooks/hook-registration.js +69 -0
- package/dist/hooks/hook-registration.js.map +1 -0
- package/dist/hooks/hook-runner.d.ts +111 -11
- package/dist/hooks/hook-runner.d.ts.map +1 -1
- package/dist/hooks/hook-runner.js +309 -142
- package/dist/hooks/hook-runner.js.map +1 -1
- package/dist/hooks/hook-utils-factory.d.ts +19 -0
- package/dist/hooks/hook-utils-factory.d.ts.map +1 -0
- package/dist/hooks/hook-utils-factory.js +2 -0
- package/dist/hooks/hook-utils-factory.js.map +1 -0
- package/dist/hooks/hook-utils.d.ts +80 -12
- package/dist/hooks/hook-utils.d.ts.map +1 -1
- package/dist/hooks/invoke-hook.d.ts +71 -0
- package/dist/hooks/invoke-hook.d.ts.map +1 -0
- package/dist/hooks/invoke-hook.js +161 -0
- package/dist/hooks/invoke-hook.js.map +1 -0
- package/dist/hooks/load-user-hooks.d.ts +96 -0
- package/dist/hooks/load-user-hooks.d.ts.map +1 -0
- package/dist/hooks/load-user-hooks.js +432 -0
- package/dist/hooks/load-user-hooks.js.map +1 -0
- package/dist/hooks/nested-request.d.ts +21 -0
- package/dist/hooks/nested-request.d.ts.map +1 -0
- package/dist/hooks/nested-request.js +24 -0
- package/dist/hooks/nested-request.js.map +1 -0
- package/dist/hooks/overlay-args.d.ts +40 -0
- package/dist/hooks/overlay-args.d.ts.map +1 -0
- package/dist/hooks/overlay-args.js +84 -0
- package/dist/hooks/overlay-args.js.map +1 -0
- package/dist/hooks/resolve-targeting.d.ts +16 -0
- package/dist/hooks/resolve-targeting.d.ts.map +1 -0
- package/dist/hooks/resolve-targeting.js +168 -0
- package/dist/hooks/resolve-targeting.js.map +1 -0
- package/dist/hooks/run-scoped-hooks.d.ts +83 -0
- package/dist/hooks/run-scoped-hooks.d.ts.map +1 -0
- package/dist/hooks/run-scoped-hooks.js +153 -0
- package/dist/hooks/run-scoped-hooks.js.map +1 -0
- package/dist/index.d.ts +42 -19
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +152 -165
- package/dist/index.js.map +1 -1
- package/dist/request-sampler.d.ts +40 -11
- package/dist/request-sampler.d.ts.map +1 -1
- package/dist/request-sampler.js +51 -76
- package/dist/request-sampler.js.map +1 -1
- package/dist/sampler-paths.d.ts +19 -0
- package/dist/sampler-paths.d.ts.map +1 -0
- package/dist/sampler-paths.js +22 -0
- package/dist/sampler-paths.js.map +1 -0
- package/dist/selectors/nearest-paths.d.ts +14 -0
- package/dist/selectors/nearest-paths.d.ts.map +1 -0
- package/dist/selectors/nearest-paths.js +32 -0
- package/dist/selectors/nearest-paths.js.map +1 -0
- package/dist/selectors/path-glob.d.ts +94 -0
- package/dist/selectors/path-glob.d.ts.map +1 -0
- package/dist/selectors/path-glob.js +136 -0
- package/dist/selectors/path-glob.js.map +1 -0
- package/dist/selectors/selector-errors.d.ts +17 -0
- package/dist/selectors/selector-errors.d.ts.map +1 -0
- package/dist/selectors/selector-errors.js +139 -0
- package/dist/selectors/selector-errors.js.map +1 -0
- package/dist/selectors/selector.d.ts +55 -0
- package/dist/selectors/selector.d.ts.map +1 -0
- package/dist/selectors/selector.js +305 -0
- package/dist/selectors/selector.js.map +1 -0
- package/dist/selectors/transaction-catalog.d.ts +96 -0
- package/dist/selectors/transaction-catalog.d.ts.map +1 -0
- package/dist/selectors/transaction-catalog.js +193 -0
- package/dist/selectors/transaction-catalog.js.map +1 -0
- package/dist/selectors/transaction-filter.d.ts +119 -0
- package/dist/selectors/transaction-filter.d.ts.map +1 -0
- package/dist/selectors/transaction-filter.js +191 -0
- package/dist/selectors/transaction-filter.js.map +1 -0
- package/dist/ts-path.d.ts +36 -0
- package/dist/ts-path.d.ts.map +1 -0
- package/dist/ts-path.js +46 -0
- package/dist/ts-path.js.map +1 -0
- package/dist/utils.d.ts +1 -2
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +2 -20
- package/dist/utils.js.map +1 -1
- package/dist/validation/canonicalize.d.ts +17 -0
- package/dist/validation/canonicalize.d.ts.map +1 -0
- package/dist/validation/canonicalize.js +29 -0
- package/dist/validation/canonicalize.js.map +1 -0
- package/dist/validation/shared-compiler-host.d.ts +17 -0
- package/dist/validation/shared-compiler-host.d.ts.map +1 -0
- package/dist/validation/shared-compiler-host.js +58 -0
- package/dist/validation/shared-compiler-host.js.map +1 -0
- package/dist/validation/typecheck-hooks.d.ts +37 -0
- package/dist/validation/typecheck-hooks.d.ts.map +1 -0
- package/dist/validation/typecheck-hooks.js +169 -0
- package/dist/validation/typecheck-hooks.js.map +1 -0
- package/dist/validation/validate-sampler.d.ts +79 -0
- package/dist/validation/validate-sampler.d.ts.map +1 -0
- package/dist/validation/validate-sampler.js +89 -0
- package/dist/validation/validate-sampler.js.map +1 -0
- package/package.json +7 -11
- package/dist/cli/commands/sampler/generate/hook.d.ts +0 -10
- package/dist/cli/commands/sampler/generate/hook.d.ts.map +0 -1
- package/dist/cli/commands/sampler/generate/hook.js +0 -19
- package/dist/cli/commands/sampler/generate/hook.js.map +0 -1
- package/dist/cli/generate-hook.d.ts +0 -4
- package/dist/cli/generate-hook.d.ts.map +0 -1
- package/dist/cli/generate-hook.js +0 -96
- package/dist/cli/generate-hook.js.map +0 -1
- package/dist/cli/templates.d.ts +0 -4
- package/dist/cli/templates.d.ts.map +0 -1
- package/dist/cli/templates.js +0 -28
- package/dist/cli/templates.js.map +0 -1
- package/dist/constants.d.ts +0 -12
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants.js +0 -16
- package/dist/constants.js.map +0 -1
- package/dist/generation/generate-samples-for-thymian-format.d.ts +0 -4
- package/dist/generation/generate-samples-for-thymian-format.d.ts.map +0 -1
- package/dist/generation/generate-samples-for-thymian-format.js +0 -18
- package/dist/generation/generate-samples-for-thymian-format.js.map +0 -1
- package/dist/generation/generate-samples.d.ts +0 -4
- package/dist/generation/generate-samples.d.ts.map +0 -1
- package/dist/generation/generate-samples.js.map +0 -1
- package/dist/hooks/generate-request-types.d.ts +0 -34
- package/dist/hooks/generate-request-types.d.ts.map +0 -1
- package/dist/hooks/generate-request-types.js +0 -458
- package/dist/hooks/generate-request-types.js.map +0 -1
- package/dist/hooks/hook-types.d.ts +0 -7
- package/dist/hooks/hook-types.d.ts.map +0 -1
- package/dist/hooks/hook-types.js +0 -2
- package/dist/hooks/hook-types.js.map +0 -1
- package/dist/hooks/load-hooks-from-samples.d.ts +0 -3
- package/dist/hooks/load-hooks-from-samples.d.ts.map +0 -1
- package/dist/hooks/load-hooks-from-samples.js +0 -22
- package/dist/hooks/load-hooks-from-samples.js.map +0 -1
- package/dist/hooks/ts-config.d.ts +0 -10
- package/dist/hooks/ts-config.d.ts.map +0 -1
- package/dist/hooks/ts-config.js +0 -10
- package/dist/hooks/ts-config.js.map +0 -1
- package/dist/samples-structure/file-request-sample.d.ts +0 -20
- package/dist/samples-structure/file-request-sample.d.ts.map +0 -1
- package/dist/samples-structure/file-request-sample.js +0 -5
- package/dist/samples-structure/file-request-sample.js.map +0 -1
- package/dist/samples-structure/get-path-transaction-id.d.ts +0 -3
- package/dist/samples-structure/get-path-transaction-id.d.ts.map +0 -1
- package/dist/samples-structure/get-path-transaction-id.js +0 -22
- package/dist/samples-structure/get-path-transaction-id.js.map +0 -1
- package/dist/samples-structure/merge-tree.d.ts +0 -5
- package/dist/samples-structure/merge-tree.d.ts.map +0 -1
- package/dist/samples-structure/merge-tree.js +0 -118
- package/dist/samples-structure/merge-tree.js.map +0 -1
- package/dist/samples-structure/read-samples-from-dir.d.ts +0 -13
- package/dist/samples-structure/read-samples-from-dir.d.ts.map +0 -1
- package/dist/samples-structure/read-samples-from-dir.js +0 -205
- package/dist/samples-structure/read-samples-from-dir.js.map +0 -1
- package/dist/samples-structure/samples-from-transactions.d.ts +0 -5
- package/dist/samples-structure/samples-from-transactions.d.ts.map +0 -1
- package/dist/samples-structure/samples-from-transactions.js +0 -120
- package/dist/samples-structure/samples-from-transactions.js.map +0 -1
- package/dist/samples-structure/samples-tree-structure.d.ts +0 -106
- package/dist/samples-structure/samples-tree-structure.d.ts.map +0 -1
- package/dist/samples-structure/samples-tree-structure.js +0 -26
- package/dist/samples-structure/samples-tree-structure.js.map +0 -1
- package/dist/samples-structure/structure-meta-on-disc.d.ts +0 -11
- package/dist/samples-structure/structure-meta-on-disc.d.ts.map +0 -1
- package/dist/samples-structure/structure-meta-on-disc.js +0 -2
- package/dist/samples-structure/structure-meta-on-disc.js.map +0 -1
- package/dist/samples-structure/traverse.d.ts +0 -4
- package/dist/samples-structure/traverse.d.ts.map +0 -1
- package/dist/samples-structure/traverse.js +0 -13
- package/dist/samples-structure/traverse.js.map +0 -1
- package/dist/samples-structure/write-samples-to-dir.d.ts +0 -37
- package/dist/samples-structure/write-samples-to-dir.d.ts.map +0 -1
- package/dist/samples-structure/write-samples-to-dir.js +0 -183
- package/dist/samples-structure/write-samples-to-dir.js.map +0 -1
- package/dist/validation/validate-sampler-output.d.ts +0 -38
- package/dist/validation/validate-sampler-output.d.ts.map +0 -1
- package/dist/validation/validate-sampler-output.js +0 -288
- package/dist/validation/validate-sampler-output.js.map +0 -1
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The set of declarations the type surface emits, with one copy of each.
|
|
3
|
+
*
|
|
4
|
+
* `json-schema-to-typescript` compiles one schema at a time and each call
|
|
5
|
+
* returns a self-contained unit: the root declaration plus every named
|
|
6
|
+
* component it references. Two transactions that both reference `Astronaut`
|
|
7
|
+
* therefore arrive carrying their own copy of it — nine copies of it, on the
|
|
8
|
+
* demo description, and nine copies of `AstronautInput` and `LaunchInput`
|
|
9
|
+
* beside them.
|
|
10
|
+
*
|
|
11
|
+
* That is not merely noisy. It compiles only for as long as every duplicated
|
|
12
|
+
* component happens to be an `interface`, because identical interfaces merge; a
|
|
13
|
+
* component that compiles to a type ALIAS — an enum, a union, an array — is
|
|
14
|
+
* `TS2300: Duplicate identifier` the moment a second transaction references it.
|
|
15
|
+
* And the drift gate cannot see either, because it compiles hooks with
|
|
16
|
+
* `skipLibCheck: true`, which is exactly the flag that stops TypeScript from
|
|
17
|
+
* reporting errors inside a `.d.ts`.
|
|
18
|
+
*
|
|
19
|
+
* De-duplicating also keeps the committed diff proportionate: editing one
|
|
20
|
+
* component used to move as many lines as there are transactions using it.
|
|
21
|
+
*/
|
|
22
|
+
import { createHash } from 'node:crypto';
|
|
23
|
+
import ts from 'typescript';
|
|
24
|
+
const DECLARATION_LINE = /^export (?:interface|type) ([A-Za-z0-9_$]+)/;
|
|
25
|
+
/**
|
|
26
|
+
* Splits one `compile()` result into its top-level declarations.
|
|
27
|
+
*
|
|
28
|
+
* Safe on the emitter's output rather than on TypeScript in general: every
|
|
29
|
+
* top-level declaration begins at column zero and everything nested is
|
|
30
|
+
* indented, so a column-zero `export` line — or the `/**` opening the JSDoc
|
|
31
|
+
* block that belongs to it — is a boundary.
|
|
32
|
+
*/
|
|
33
|
+
export function splitDeclarations(source) {
|
|
34
|
+
const lines = source.split('\n');
|
|
35
|
+
const starts = [];
|
|
36
|
+
lines.forEach((line, index) => {
|
|
37
|
+
if (line === '/**') {
|
|
38
|
+
starts.push(index);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
// A JSDoc block immediately above a declaration is part of it, so the
|
|
42
|
+
// comment already opened this chunk.
|
|
43
|
+
if (DECLARATION_LINE.test(line) && lines[index - 1]?.trim() !== '*/') {
|
|
44
|
+
starts.push(index);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
return starts.map((start, position) => {
|
|
48
|
+
const end = starts[position + 1] ?? lines.length;
|
|
49
|
+
const text = lines.slice(start, end).join('\n').trimEnd();
|
|
50
|
+
const declared = text
|
|
51
|
+
.split('\n')
|
|
52
|
+
.map((line) => DECLARATION_LINE.exec(line)?.[1])
|
|
53
|
+
.find((name) => name !== undefined);
|
|
54
|
+
if (declared === undefined) {
|
|
55
|
+
throw new Error(`The type generator produced a declaration it cannot name:\n${text}`);
|
|
56
|
+
}
|
|
57
|
+
return { name: declared, text };
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Every identifier in `text` that sits in a renameable position, whatever it
|
|
62
|
+
* refers to.
|
|
63
|
+
*
|
|
64
|
+
* The same AST walk {@link renameReferences} edits by, asking which names a
|
|
65
|
+
* declaration mentions rather than rewriting them. Deliberately NOT filtered
|
|
66
|
+
* by a unit's member names: the result then depends on the text alone, which
|
|
67
|
+
* is what lets {@link DeclarationSet} memoize it by text and parse each
|
|
68
|
+
* distinct declaration once per process rather than once per unit it recurs
|
|
69
|
+
* in.
|
|
70
|
+
*/
|
|
71
|
+
function renameableIdentifiers(text) {
|
|
72
|
+
const source = ts.createSourceFile('declaration.d.ts', text, ts.ScriptTarget.Latest,
|
|
73
|
+
/* setParentNodes */ true, ts.ScriptKind.TS);
|
|
74
|
+
const found = new Set();
|
|
75
|
+
const visit = (node) => {
|
|
76
|
+
if (ts.isIdentifier(node) && isRenameablePosition(node)) {
|
|
77
|
+
found.add(node.text);
|
|
78
|
+
}
|
|
79
|
+
ts.forEachChild(node, visit);
|
|
80
|
+
};
|
|
81
|
+
ts.forEachChild(source, visit);
|
|
82
|
+
return [...found];
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* What makes one declaration the same *variant* as another: its own text plus
|
|
86
|
+
* the text of everything it transitively references inside its unit.
|
|
87
|
+
*
|
|
88
|
+
* The raw text alone is not enough, because a declaration's references are
|
|
89
|
+
* resolved per unit. Two sources declaring `User = { address: Address }`
|
|
90
|
+
* byte-identically are the same text and **not** the same type when their
|
|
91
|
+
* `Address` differs — reusing the first source's alias for the second gave the
|
|
92
|
+
* second source a committed type describing the first source's API, with its
|
|
93
|
+
* own renamed `Address_2` emitted and never referenced. `checkSurface` stayed
|
|
94
|
+
* clean because the surface was internally consistent; it was just wrong.
|
|
95
|
+
*
|
|
96
|
+
* One key per member of the unit, computed from one adjacency map. The first
|
|
97
|
+
* version of this re-parsed every reachable declaration once per member, so a
|
|
98
|
+
* unit of *n* declarations cost O(n × reach) parses — a chain of 200 was
|
|
99
|
+
* 20,100 — and it paid that on every unit, conflict or not, per
|
|
100
|
+
* `generateTypeSurface`, which is per `init`, `sync` and `validate`. The
|
|
101
|
+
* parse is the only expensive step, so it happens at most once per member
|
|
102
|
+
* here and, through `references`, at most once per distinct text; deriving
|
|
103
|
+
* each closure is then a walk over a map.
|
|
104
|
+
*
|
|
105
|
+
* The key is a digest rather than the closure's text: `resolved` keeps one
|
|
106
|
+
* key per variant for the life of the set, and the text of a root's whole
|
|
107
|
+
* unit is the wrong thing to hold that many times.
|
|
108
|
+
*/
|
|
109
|
+
function variantKeys(unit, references) {
|
|
110
|
+
const texts = new Map(unit.map((member) => [member.name, member.text]));
|
|
111
|
+
const adjacency = new Map(unit.map((member) => [
|
|
112
|
+
member.name,
|
|
113
|
+
references(member.text).filter((name) => texts.has(name)),
|
|
114
|
+
]));
|
|
115
|
+
const keys = new Map();
|
|
116
|
+
for (const member of unit) {
|
|
117
|
+
const closure = new Set();
|
|
118
|
+
const pending = [member.name];
|
|
119
|
+
while (pending.length > 0) {
|
|
120
|
+
const name = pending.pop();
|
|
121
|
+
if (closure.has(name)) {
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
closure.add(name);
|
|
125
|
+
pending.push(...(adjacency.get(name) ?? []));
|
|
126
|
+
}
|
|
127
|
+
const hash = createHash('sha1');
|
|
128
|
+
for (const name of [...closure].sort()) {
|
|
129
|
+
hash
|
|
130
|
+
.update(name)
|
|
131
|
+
.update('\u0000')
|
|
132
|
+
.update(texts.get(name));
|
|
133
|
+
hash.update('\u0001');
|
|
134
|
+
}
|
|
135
|
+
keys.set(member.name, hash.digest('hex'));
|
|
136
|
+
}
|
|
137
|
+
return keys;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Whether `identifier` sits in a position a rename may touch: either it NAMES
|
|
141
|
+
* a top-level declaration this set controls, or it REFERS to one.
|
|
142
|
+
*
|
|
143
|
+
* Enumerated rather than inferred, because the alternative ("anything that
|
|
144
|
+
* isn't a property-name or string-literal position") is exactly the
|
|
145
|
+
* reasoning that let a text-level regex rename an identifier-shaped property
|
|
146
|
+
* key: `status: string` and `status: Status` are indistinguishable to a
|
|
147
|
+
* lexical match, but `ts.isPropertySignature(parent) && parent.name ===
|
|
148
|
+
* identifier` is false for the first and irrelevant to the second, because
|
|
149
|
+
* the second's `Status` is the type annotation, not the name.
|
|
150
|
+
*
|
|
151
|
+
* Naming positions — where a declaration's OWN name lives, which a rename
|
|
152
|
+
* must also rewrite so the definition and its references stay one string:
|
|
153
|
+
* - `InterfaceDeclaration.name`, `TypeAliasDeclaration.name`.
|
|
154
|
+
*
|
|
155
|
+
* Reference positions:
|
|
156
|
+
* - `TypeReferenceNode.typeName` — `Status`, `Array<Status>`, `Status[]` (an
|
|
157
|
+
* `ArrayTypeNode` wrapping a `TypeReferenceNode`).
|
|
158
|
+
* - `ExpressionWithTypeArguments.expression` — `interface X extends Status`,
|
|
159
|
+
* the shape `allOf` composition emits.
|
|
160
|
+
* - `TypeQueryNode.exprName` — `typeof Status`.
|
|
161
|
+
*
|
|
162
|
+
* A qualified name (`Foo.Status`) never reaches here as an `Identifier`: its
|
|
163
|
+
* `typeName`/`exprName` is a `QualifiedName`, which this function does not
|
|
164
|
+
* match, so a dotted reference is correctly left alone — none of the emitter's
|
|
165
|
+
* own declarations are namespaced.
|
|
166
|
+
*/
|
|
167
|
+
function isRenameablePosition(identifier) {
|
|
168
|
+
const parent = identifier.parent;
|
|
169
|
+
if (!parent) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
if (ts.isInterfaceDeclaration(parent) || ts.isTypeAliasDeclaration(parent)) {
|
|
173
|
+
return parent.name === identifier;
|
|
174
|
+
}
|
|
175
|
+
if (ts.isTypeReferenceNode(parent)) {
|
|
176
|
+
return parent.typeName === identifier;
|
|
177
|
+
}
|
|
178
|
+
if (ts.isExpressionWithTypeArguments(parent)) {
|
|
179
|
+
return parent.expression === identifier;
|
|
180
|
+
}
|
|
181
|
+
if (ts.isTypeQueryNode(parent)) {
|
|
182
|
+
return parent.exprName === identifier;
|
|
183
|
+
}
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Rewrites a unit's own declaration names and every reference to them.
|
|
188
|
+
*
|
|
189
|
+
* Scoped to one compiled unit, where an identifier can only mean that unit's
|
|
190
|
+
* own declaration. Parses `text` with the TypeScript API and edits only the
|
|
191
|
+
* identifiers {@link isRenameablePosition} approves — never a property name
|
|
192
|
+
* (identifier-shaped or not), never the contents of a string literal, and
|
|
193
|
+
* never a comment, because none of those are nodes the parser hands to a
|
|
194
|
+
* visitor at all. The edits are applied as raw text splices at the
|
|
195
|
+
* identifiers' own positions, back to front, so everything else — formatting,
|
|
196
|
+
* comments, unrelated text — survives byte-for-byte.
|
|
197
|
+
*/
|
|
198
|
+
function renameReferences(text, renames) {
|
|
199
|
+
if (renames.size === 0) {
|
|
200
|
+
return text;
|
|
201
|
+
}
|
|
202
|
+
const source = ts.createSourceFile('declaration.d.ts', text, ts.ScriptTarget.Latest,
|
|
203
|
+
/* setParentNodes */ true, ts.ScriptKind.TS);
|
|
204
|
+
const edits = [];
|
|
205
|
+
const visit = (node) => {
|
|
206
|
+
if (ts.isIdentifier(node) && isRenameablePosition(node)) {
|
|
207
|
+
const replacement = renames.get(node.text);
|
|
208
|
+
if (replacement !== undefined) {
|
|
209
|
+
edits.push({
|
|
210
|
+
start: node.getStart(source),
|
|
211
|
+
end: node.getEnd(),
|
|
212
|
+
replacement,
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
ts.forEachChild(node, visit);
|
|
217
|
+
};
|
|
218
|
+
visit(source);
|
|
219
|
+
let result = text;
|
|
220
|
+
// Back to front, so an earlier edit's offsets never shift a later one's.
|
|
221
|
+
for (const edit of edits.sort((a, b) => b.start - a.start)) {
|
|
222
|
+
result =
|
|
223
|
+
result.slice(0, edit.start) + edit.replacement + result.slice(edit.end);
|
|
224
|
+
}
|
|
225
|
+
return result;
|
|
226
|
+
}
|
|
227
|
+
export class DeclarationSet {
|
|
228
|
+
byName = new Map();
|
|
229
|
+
/**
|
|
230
|
+
* Every name that may not be handed to a new declaration as-is: every name
|
|
231
|
+
* already committed to {@link byName}, plus the {@link reserved} fixed
|
|
232
|
+
* roots the caller seeds the set with. A name can be in here without being
|
|
233
|
+
* in `byName` — a reserved root nothing has collided with yet — which is
|
|
234
|
+
* exactly what makes a reservation free to check and free of output: {@link
|
|
235
|
+
* all} only ever reads `byName`.
|
|
236
|
+
*/
|
|
237
|
+
used;
|
|
238
|
+
/**
|
|
239
|
+
* For each ORIGINAL declaration name, the raw (pre-rename) text of every
|
|
240
|
+
* variant this set has already resolved a final name for — whether that
|
|
241
|
+
* final name is the bare name itself (the non-conflict branch) or a
|
|
242
|
+
* renamed alias (the conflict branch).
|
|
243
|
+
*
|
|
244
|
+
* What makes this safe to reuse across separate `add()` calls: two
|
|
245
|
+
* declarations that share both a name and byte-identical text are the same
|
|
246
|
+
* declaration by this set's own definition of "conflict" (`text !==
|
|
247
|
+
* text`), so pointing a later occurrence at an earlier resolution is never
|
|
248
|
+
* a merge of two DIFFERENT things — only ever the same thing recognized
|
|
249
|
+
* twice. Keyed by the RAW text (before this call's renames are applied),
|
|
250
|
+
* because every occurrence of, say, a `Status`-named component carries that
|
|
251
|
+
* same raw form regardless of which final name it ends up resolving to —
|
|
252
|
+
* that is the one constant a repeat occurrence can be recognized by.
|
|
253
|
+
*
|
|
254
|
+
* Without this, a component that conflicts with a fixed root — or with
|
|
255
|
+
* another document's differently-bodied same-named component — mints a
|
|
256
|
+
* FRESH suffix every single time it recurs (`Status_2`, `Status_3`, …one
|
|
257
|
+
* per referencing transaction), because the conflict branch used to treat
|
|
258
|
+
* every conflicting unit as unprecedented. That defeats the set's own
|
|
259
|
+
* purpose: "one declaration per component" is exactly the guarantee this
|
|
260
|
+
* index restores for the conflict branch, matching what the non-conflict
|
|
261
|
+
* branch already gives for free.
|
|
262
|
+
*/
|
|
263
|
+
resolved = new Map();
|
|
264
|
+
/**
|
|
265
|
+
* The renameable identifiers of every declaration text this set has seen,
|
|
266
|
+
* so a component that recurs in forty units — the demo description's
|
|
267
|
+
* shape — is parsed once, not forty times.
|
|
268
|
+
*/
|
|
269
|
+
identifiersByText = new Map();
|
|
270
|
+
/**
|
|
271
|
+
* @param reserved the fixed root names {@link NameRegistry} mints around
|
|
272
|
+
* the generated declarations — `Status`, `Method`, `Endpoints` and the
|
|
273
|
+
* rest. A component whose OWN name collides with one of these can never be
|
|
274
|
+
* merged into it (they are never the same declaration), so a reservation
|
|
275
|
+
* has to force the conflict branch even though nothing with that name has
|
|
276
|
+
* been committed yet. Sharing the exact list `NameRegistry` was
|
|
277
|
+
* constructed with is what keeps the two reservations from drifting apart.
|
|
278
|
+
*/
|
|
279
|
+
constructor(reserved = []) {
|
|
280
|
+
this.used = new Set(reserved);
|
|
281
|
+
}
|
|
282
|
+
/** Records that `originalName`/`variant` resolved to `finalName`, and commits `finalName`/`finalText` as held. */
|
|
283
|
+
commit(finalName, finalText, originalName, variant) {
|
|
284
|
+
this.byName.set(finalName, finalText);
|
|
285
|
+
this.used.add(finalName);
|
|
286
|
+
let variants = this.resolved.get(originalName);
|
|
287
|
+
if (!variants) {
|
|
288
|
+
variants = new Map();
|
|
289
|
+
this.resolved.set(originalName, variants);
|
|
290
|
+
}
|
|
291
|
+
variants.set(variant, finalName);
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Adds one compiled unit and returns the name its root ended up with.
|
|
295
|
+
*
|
|
296
|
+
* A unit whose declarations are all either new or byte-identical to what is
|
|
297
|
+
* already held is merged into it, which is the case every single-document
|
|
298
|
+
* description produces: one `$defs` name is one schema, so every copy of
|
|
299
|
+
* `Astronaut` is the same `Astronaut`.
|
|
300
|
+
*
|
|
301
|
+
* A unit that genuinely conflicts is given fresh names for **all** of its
|
|
302
|
+
* declarations rather than only the conflicting ones. Renaming part of a
|
|
303
|
+
* unit would leave the rest sharing declarations with whichever unit got
|
|
304
|
+
* there first, and "this component is the one my own root was compiled
|
|
305
|
+
* against" is the property worth keeping. Two shapes reach this branch:
|
|
306
|
+
* same component name, different body — which two separate description
|
|
307
|
+
* files can both declare — and a component named after one of the fixed
|
|
308
|
+
* roots this set was seeded with, which is a conflict on sight because a
|
|
309
|
+
* user's component and the surface's own `Status` are never the same
|
|
310
|
+
* declaration.
|
|
311
|
+
*
|
|
312
|
+
* "Fresh" does not mean "unconditionally new", though: {@link resolved}
|
|
313
|
+
* recognizes a (name, text) pair this set has already renamed once and
|
|
314
|
+
* reuses that name rather than minting another alias for it, so a
|
|
315
|
+
* component that conflicts with a fixed root — or with another document's
|
|
316
|
+
* component of the same name — is still deduplicated across every site
|
|
317
|
+
* that declares it identically, exactly as a non-conflicting component
|
|
318
|
+
* already is.
|
|
319
|
+
*/
|
|
320
|
+
add(unit, rootName) {
|
|
321
|
+
if (unit.length === 0) {
|
|
322
|
+
return rootName;
|
|
323
|
+
}
|
|
324
|
+
const conflicts = unit.some((declaration) => {
|
|
325
|
+
if (!this.used.has(declaration.name)) {
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
return this.byName.get(declaration.name) !== declaration.text;
|
|
329
|
+
});
|
|
330
|
+
// One key per member, computed before anything is committed: a variant is
|
|
331
|
+
// the declaration *and its references' contents*, so the key cannot be
|
|
332
|
+
// derived after a rename has already been chosen.
|
|
333
|
+
const keys = variantKeys(unit, (text) => this.identifiersOf(text));
|
|
334
|
+
if (!conflicts) {
|
|
335
|
+
for (const declaration of unit) {
|
|
336
|
+
this.commit(declaration.name, declaration.text, declaration.name, keys.get(declaration.name));
|
|
337
|
+
}
|
|
338
|
+
return rootName;
|
|
339
|
+
}
|
|
340
|
+
const renames = new Map();
|
|
341
|
+
for (const declaration of unit) {
|
|
342
|
+
// A variant this set already resolved — same text *and* the same
|
|
343
|
+
// references resolving to the same contents — so reuse its alias rather
|
|
344
|
+
// than minting another for the same type.
|
|
345
|
+
const reused = this.resolved
|
|
346
|
+
.get(declaration.name)
|
|
347
|
+
?.get(keys.get(declaration.name));
|
|
348
|
+
renames.set(declaration.name, reused ?? this.freeName(declaration.name));
|
|
349
|
+
}
|
|
350
|
+
for (const declaration of unit) {
|
|
351
|
+
const name = renames.get(declaration.name);
|
|
352
|
+
// Already resolved by an earlier `add()` call: its text is already
|
|
353
|
+
// correct, and re-deriving it here would just repeat that work.
|
|
354
|
+
if (this.byName.has(name)) {
|
|
355
|
+
continue;
|
|
356
|
+
}
|
|
357
|
+
this.commit(name, renameReferences(declaration.text, renames), declaration.name, keys.get(declaration.name));
|
|
358
|
+
}
|
|
359
|
+
return renames.get(rootName) ?? rootName;
|
|
360
|
+
}
|
|
361
|
+
/** Every declaration held, in name order. */
|
|
362
|
+
all() {
|
|
363
|
+
return [...this.byName.keys()].sort().map((name) => {
|
|
364
|
+
return this.byName.get(name);
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
identifiersOf(text) {
|
|
368
|
+
let identifiers = this.identifiersByText.get(text);
|
|
369
|
+
if (identifiers === undefined) {
|
|
370
|
+
identifiers = renameableIdentifiers(text);
|
|
371
|
+
this.identifiersByText.set(text, identifiers);
|
|
372
|
+
}
|
|
373
|
+
return identifiers;
|
|
374
|
+
}
|
|
375
|
+
freeName(candidate) {
|
|
376
|
+
let name = candidate;
|
|
377
|
+
let suffix = 1;
|
|
378
|
+
while (this.used.has(name)) {
|
|
379
|
+
suffix += 1;
|
|
380
|
+
name = `${candidate}_${suffix}`;
|
|
381
|
+
}
|
|
382
|
+
// Claimed immediately: the caller assigns every name in a unit before it
|
|
383
|
+
// writes any of them, so two members of one unit must not pick the same
|
|
384
|
+
// free name.
|
|
385
|
+
this.used.add(name);
|
|
386
|
+
return name;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
//# sourceMappingURL=declaration-set.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"declaration-set.js","sourceRoot":"","sources":["../../../src/generation/types/declaration-set.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reflects a schema's `examples` into the types its properties get.
|
|
3
|
+
*
|
|
4
|
+
* **Property-level only.** An example value pushes down into the property (or
|
|
5
|
+
* array element type) it belongs to, recursively, and a primitive property with
|
|
6
|
+
* examples becomes `'A' | 'B' | (base & {})` — the literals autocomplete while
|
|
7
|
+
* the type stays open.
|
|
8
|
+
*
|
|
9
|
+
* An object body is **never** emitted as a union of example-shaped object types,
|
|
10
|
+
* and that is not a stylistic preference. Hooks mutate the request in place, and
|
|
11
|
+
* on a union TypeScript checks a property *write* against the intersection of
|
|
12
|
+
* the members' property types and rejects any property missing from a member —
|
|
13
|
+
* so a union of closed example objects turns ordinary mutation into a compile
|
|
14
|
+
* error. That is exactly the flaw the earlier attempt shipped.
|
|
15
|
+
*
|
|
16
|
+
* The mechanism is `json-schema-to-typescript`'s `tsType` keyword: the schema is
|
|
17
|
+
* annotated and the emitter prints the annotation verbatim, so nothing here has
|
|
18
|
+
* to know how a schema becomes a type.
|
|
19
|
+
*/
|
|
20
|
+
export declare function reflectExamples(schema: unknown): unknown;
|
|
21
|
+
//# sourceMappingURL=example-reflection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"example-reflection.d.ts","sourceRoot":"","sources":["../../../src/generation/types/example-reflection.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAExD"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { isRecord } from '@thymian/core';
|
|
2
|
+
/**
|
|
3
|
+
* Reflects a schema's `examples` into the types its properties get.
|
|
4
|
+
*
|
|
5
|
+
* **Property-level only.** An example value pushes down into the property (or
|
|
6
|
+
* array element type) it belongs to, recursively, and a primitive property with
|
|
7
|
+
* examples becomes `'A' | 'B' | (base & {})` — the literals autocomplete while
|
|
8
|
+
* the type stays open.
|
|
9
|
+
*
|
|
10
|
+
* An object body is **never** emitted as a union of example-shaped object types,
|
|
11
|
+
* and that is not a stylistic preference. Hooks mutate the request in place, and
|
|
12
|
+
* on a union TypeScript checks a property *write* against the intersection of
|
|
13
|
+
* the members' property types and rejects any property missing from a member —
|
|
14
|
+
* so a union of closed example objects turns ordinary mutation into a compile
|
|
15
|
+
* error. That is exactly the flaw the earlier attempt shipped.
|
|
16
|
+
*
|
|
17
|
+
* The mechanism is `json-schema-to-typescript`'s `tsType` keyword: the schema is
|
|
18
|
+
* annotated and the emitter prints the annotation verbatim, so nothing here has
|
|
19
|
+
* to know how a schema becomes a type.
|
|
20
|
+
*/
|
|
21
|
+
export function reflectExamples(schema) {
|
|
22
|
+
return annotate(schema, []);
|
|
23
|
+
}
|
|
24
|
+
/** Keywords whose branches describe the same value as the node holding them. */
|
|
25
|
+
const COMPOSITION_KEYWORDS = ['allOf', 'anyOf', 'oneOf'];
|
|
26
|
+
/**
|
|
27
|
+
* Where named component schemas live. `$defs` is the 2020-12 spelling and
|
|
28
|
+
* `definitions` the draft-07 one; both are handled because the rename to
|
|
29
|
+
* `definitions` happens elsewhere and this walk must not depend on the order.
|
|
30
|
+
*/
|
|
31
|
+
const DEFINITION_KEYWORDS = ['$defs', 'definitions'];
|
|
32
|
+
/** The examples a schema node declares, in the order it declared them. */
|
|
33
|
+
function examplesOf(node) {
|
|
34
|
+
const fromPlural = Array.isArray(node['examples']) ? node['examples'] : [];
|
|
35
|
+
const fromSingular = 'example' in node ? [node['example']] : [];
|
|
36
|
+
return [...fromPlural, ...fromSingular];
|
|
37
|
+
}
|
|
38
|
+
function annotate(schema, inherited) {
|
|
39
|
+
if (!isRecord(schema)) {
|
|
40
|
+
return schema;
|
|
41
|
+
}
|
|
42
|
+
const node = { ...schema };
|
|
43
|
+
const examples = [...examplesOf(node), ...inherited];
|
|
44
|
+
// `enum` and `const` are already closed unions, and widening them with
|
|
45
|
+
// `(base & {})` would say the opposite of what the description says.
|
|
46
|
+
const closed = 'enum' in node || 'const' in node;
|
|
47
|
+
if (isRecord(node['properties'])) {
|
|
48
|
+
const properties = {};
|
|
49
|
+
for (const [name, property] of Object.entries(node['properties'])) {
|
|
50
|
+
properties[name] = annotate(property,
|
|
51
|
+
// An object example is not a type: it is a set of property examples,
|
|
52
|
+
// one level down.
|
|
53
|
+
examples
|
|
54
|
+
.filter(isRecord)
|
|
55
|
+
.filter((example) => name in example)
|
|
56
|
+
.map((example) => example[name]));
|
|
57
|
+
}
|
|
58
|
+
node['properties'] = properties;
|
|
59
|
+
}
|
|
60
|
+
if (node['items'] !== undefined) {
|
|
61
|
+
node['items'] = annotate(node['items'],
|
|
62
|
+
// Likewise an array example: element examples, one level down.
|
|
63
|
+
examples.filter(Array.isArray).flat());
|
|
64
|
+
}
|
|
65
|
+
// A composition describes the *same* value as the node holding it, so the
|
|
66
|
+
// node's examples belong to each branch.
|
|
67
|
+
for (const keyword of COMPOSITION_KEYWORDS) {
|
|
68
|
+
const branches = node[keyword];
|
|
69
|
+
if (Array.isArray(branches)) {
|
|
70
|
+
node[keyword] = branches.map((branch) => annotate(branch, examples));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// A named component is a *separate* schema that anything may point at, so it
|
|
74
|
+
// is annotated on its own and never with the referring site's examples: an
|
|
75
|
+
// example beside a `$ref` describes the property that refers, not the
|
|
76
|
+
// component every other property shares.
|
|
77
|
+
//
|
|
78
|
+
// Reached at all only because a component's examples are otherwise dropped
|
|
79
|
+
// entirely — nothing descends through a `$ref`, and named components are how
|
|
80
|
+
// essentially every real description is written.
|
|
81
|
+
for (const keyword of DEFINITION_KEYWORDS) {
|
|
82
|
+
const definitions = node[keyword];
|
|
83
|
+
if (isRecord(definitions)) {
|
|
84
|
+
node[keyword] = Object.fromEntries(Object.entries(definitions).map(([name, definition]) => [
|
|
85
|
+
name,
|
|
86
|
+
annotate(definition, []),
|
|
87
|
+
]));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (!closed) {
|
|
91
|
+
const literals = openLiteralUnion(node, examples);
|
|
92
|
+
if (literals) {
|
|
93
|
+
node['tsType'] = literals;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return node;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* `'A' | 'B' | (base & {})` for a primitive node with examples, or `undefined`
|
|
100
|
+
* when there is nothing to reflect.
|
|
101
|
+
*
|
|
102
|
+
* The `& {}` is what keeps the union open: without it TypeScript widens the
|
|
103
|
+
* whole thing back to `string` and the literals stop autocompleting.
|
|
104
|
+
*/
|
|
105
|
+
function openLiteralUnion(node, examples) {
|
|
106
|
+
const base = primitiveBase(node);
|
|
107
|
+
if (!base) {
|
|
108
|
+
return undefined;
|
|
109
|
+
}
|
|
110
|
+
// Sorted, not merely de-duplicated by insertion order: the union is
|
|
111
|
+
// reflected from the `examples` array, and an author reordering that array
|
|
112
|
+
// is not a change to what the API returns, so it must not be a change to
|
|
113
|
+
// the committed surface either.
|
|
114
|
+
const literals = [
|
|
115
|
+
...new Set(examples
|
|
116
|
+
.filter((example) => typeof example === base)
|
|
117
|
+
.map((example) => JSON.stringify(example))),
|
|
118
|
+
].sort();
|
|
119
|
+
if (literals.length === 0) {
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
122
|
+
return `${literals.join(' | ')} | (${base} & {})`;
|
|
123
|
+
}
|
|
124
|
+
/** The TypeScript primitive a node describes, if it describes exactly one. */
|
|
125
|
+
function primitiveBase(node) {
|
|
126
|
+
const type = node['type'];
|
|
127
|
+
if (type === 'string') {
|
|
128
|
+
return 'string';
|
|
129
|
+
}
|
|
130
|
+
if (type === 'number' || type === 'integer') {
|
|
131
|
+
return 'number';
|
|
132
|
+
}
|
|
133
|
+
return undefined;
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=example-reflection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"example-reflection.js","sourceRoot":"","sources":["../../../src/generation/types/example-reflection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { TransactionCatalog } from '../../selectors/transaction-catalog.js';
|
|
2
|
+
/** The two files the committed surface consists of. */
|
|
3
|
+
export type TypeSurface = {
|
|
4
|
+
/** `Endpoints`, the spec-derived unions, and the schema declarations. */
|
|
5
|
+
requestTypes: string;
|
|
6
|
+
/** The `@thymian/hooks` authoring surface, typed against `Endpoints`. */
|
|
7
|
+
hooksApi: string;
|
|
8
|
+
};
|
|
9
|
+
export declare const REQUEST_TYPES_FILE = "request-types.d.ts";
|
|
10
|
+
export declare const HOOKS_API_FILE = "hooks-api.d.ts";
|
|
11
|
+
/**
|
|
12
|
+
* Emit the committed type surface for a loaded description.
|
|
13
|
+
*
|
|
14
|
+
* Deterministic by construction: unions are sorted, parameters are emitted in
|
|
15
|
+
* name order, declaration names come from the selector and the schema's role
|
|
16
|
+
* within the transaction (see `type-names.ts`), and `Endpoints` follows catalog
|
|
17
|
+
* order — which is sorted by selector. So reordering the source document, or
|
|
18
|
+
* renaming its title, changes nothing here; and because no name is positional,
|
|
19
|
+
* inserting an endpoint touches only the lines that endpoint owns plus the
|
|
20
|
+
* unions its method, status, path and media types widen.
|
|
21
|
+
*/
|
|
22
|
+
export declare function generateTypeSurface(catalog: TransactionCatalog): Promise<TypeSurface>;
|
|
23
|
+
//# sourceMappingURL=generate-type-surface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-type-surface.d.ts","sourceRoot":"","sources":["../../../src/generation/types/generate-type-surface.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAMjF,uDAAuD;AACvD,MAAM,MAAM,WAAW,GAAG;IACxB,yEAAyE;IACzE,YAAY,EAAE,MAAM,CAAC;IACrB,yEAAyE;IACzE,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,eAAO,MAAM,kBAAkB,uBAAuB,CAAC;AACvD,eAAO,MAAM,cAAc,mBAAmB,CAAC;AAoI/C;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,WAAW,CAAC,CAqNtB"}
|