@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,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic TypeScript identifiers for the declarations the type surface
|
|
3
|
+
* emits.
|
|
4
|
+
*
|
|
5
|
+
* Every name is a pure function of the transaction's selector plus the schema's
|
|
6
|
+
* role within that transaction. Naming by catalog position instead
|
|
7
|
+
* (`Transaction4Type2`) is stable under a document reorder but not under an
|
|
8
|
+
* *insertion*: a new endpoint that sorts first renumbers every declaration
|
|
9
|
+
* after it. The surface is committed and the diff against it **is** the
|
|
10
|
+
* staleness signal, so a positional name turns adding one endpoint into a
|
|
11
|
+
* whole-file diff — 282 changed lines on the demo description, for one added
|
|
12
|
+
* operation.
|
|
13
|
+
*
|
|
14
|
+
* SANITISATION IS NOT COSMETIC AND THE COLLISION SUFFIX IS NOT DEFENSIVE. A
|
|
15
|
+
* selector legitimately carries characters no identifier can: a method is an
|
|
16
|
+
* RFC 9110 section 5.6.2 token, paths carry `/`, `{`, `}` and percent-encoding,
|
|
17
|
+
* and media types carry `/`, `+`, `;` and `=`. Two distinct selectors therefore
|
|
18
|
+
* collapse onto one stem — methods `A-B` and `A.B` on the same path both
|
|
19
|
+
* sanitise to `AB` — so the suffix is reached by real input.
|
|
20
|
+
*
|
|
21
|
+
* THE NAME WE REFERENCE AND THE NAME THE LIBRARY DECLARES ARE ONE STRING.
|
|
22
|
+
* `json-schema-to-typescript` does not declare under the name it is handed: it
|
|
23
|
+
* declares under `toSafeString(name)`, which re-cases a lowercase letter that
|
|
24
|
+
* follows a digit (`V1beta` becomes `V1Beta`), collapses `_x` into `X` and
|
|
25
|
+
* upper-cases the first letter. A positional name is already a fixed point of
|
|
26
|
+
* that transform; a selector-derived one is not, and a name that changes on the
|
|
27
|
+
* way in is a dangling reference on the way out. {@link safeIdentifier} is the
|
|
28
|
+
* single boundary, and {@link NameRegistry} uniquifies AFTER it — so two
|
|
29
|
+
* candidates that sanitise onto one identifier get a suffix rather than one
|
|
30
|
+
* declaration emitted twice under two names.
|
|
31
|
+
*/
|
|
32
|
+
/**
|
|
33
|
+
* The fixed declarations `generate-type-surface.ts` emits around the
|
|
34
|
+
* generated ones. Shared by {@link NameRegistry} (so a generated declaration
|
|
35
|
+
* never shadows one of these) and by `DeclarationSet` (so a description
|
|
36
|
+
* component named after one of these — `Status`, say — is reserved out from
|
|
37
|
+
* under it rather than silently merged into it, which is what let a
|
|
38
|
+
* description declaring a `Status` component reach the committed surface as
|
|
39
|
+
* two conflicting `export type Status` and `export interface Status`
|
|
40
|
+
* declarations, `skipLibCheck` hiding the fault until a user's own hook
|
|
41
|
+
* compile — or, once the self-check gate is on, at generation time with an
|
|
42
|
+
* unattributed `TS2300`).
|
|
43
|
+
*/
|
|
44
|
+
export const FIXED_ROOT_NAMES = [
|
|
45
|
+
'Endpoints',
|
|
46
|
+
'Method',
|
|
47
|
+
'Path',
|
|
48
|
+
'RequestMediaType',
|
|
49
|
+
'ResponseMediaType',
|
|
50
|
+
'Responses',
|
|
51
|
+
'Selector',
|
|
52
|
+
'Status',
|
|
53
|
+
'StatusClass',
|
|
54
|
+
'TransactionResponse',
|
|
55
|
+
'WireMediaType',
|
|
56
|
+
];
|
|
57
|
+
/**
|
|
58
|
+
* Splits on every run of non-alphanumeric characters and upper-cases each
|
|
59
|
+
* remaining segment's first character, so `GET`, `astronauts`, `{id}` and
|
|
60
|
+
* `application/vnd.Example+JSON` become `Get`, `Astronauts`, `Id` and
|
|
61
|
+
* `ApplicationVndExampleJson`.
|
|
62
|
+
*
|
|
63
|
+
* The tail is lower-cased deliberately: a declaration NAME is not required to
|
|
64
|
+
* be byte-exact — only the emitted selector keys and union members are — and
|
|
65
|
+
* folding it keeps `JSON` and `json` from producing two visually
|
|
66
|
+
* indistinguishable identifiers.
|
|
67
|
+
*/
|
|
68
|
+
export function pascalSegments(value) {
|
|
69
|
+
return value
|
|
70
|
+
.split(/[^A-Za-z0-9]+/)
|
|
71
|
+
.filter((segment) => segment.length > 0)
|
|
72
|
+
.map((segment) => `${segment.charAt(0).toUpperCase()}${segment.slice(1).toLowerCase()}`)
|
|
73
|
+
.join('');
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* A valid identifier fragment for a parameter name. A parameter name may
|
|
77
|
+
* sanitise to nothing at all — `''` and `'-'` are both reachable header names
|
|
78
|
+
* in a description — and an empty fragment would silently merge `Header_` with
|
|
79
|
+
* the next one, so the empty case gets a name of its own rather than no name.
|
|
80
|
+
*/
|
|
81
|
+
function parameterSegment(name) {
|
|
82
|
+
const segment = pascalSegments(name);
|
|
83
|
+
return segment.length > 0 ? segment : 'Unnamed';
|
|
84
|
+
}
|
|
85
|
+
/** The role's contribution to a declaration name. */
|
|
86
|
+
export function roleSuffix(role) {
|
|
87
|
+
switch (role.kind) {
|
|
88
|
+
case 'request-body':
|
|
89
|
+
return 'RequestBody';
|
|
90
|
+
case 'response-body':
|
|
91
|
+
return 'ResponseBody';
|
|
92
|
+
case 'query-parameter':
|
|
93
|
+
return `QueryParam_${parameterSegment(role.parameter)}`;
|
|
94
|
+
case 'path-parameter':
|
|
95
|
+
return `PathParam_${parameterSegment(role.parameter)}`;
|
|
96
|
+
case 'request-header':
|
|
97
|
+
return `Header_${parameterSegment(role.parameter)}`;
|
|
98
|
+
case 'cookie':
|
|
99
|
+
return `Cookie_${parameterSegment(role.parameter)}`;
|
|
100
|
+
case 'response-header':
|
|
101
|
+
return `ResponseHeader_${parameterSegment(role.parameter)}`;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* The identifier a selector plus a role WANTS. Several sites may want the same
|
|
106
|
+
* one; {@link NameRegistry} is what turns wants into names.
|
|
107
|
+
*
|
|
108
|
+
* A method is an RFC 9110 token, so it may be all digits (`123 /x` is a legal
|
|
109
|
+
* selector), and a parameter name may start with one (`2fa`). Neither an
|
|
110
|
+
* identifier nor the library's own transform tolerates a leading digit, so the
|
|
111
|
+
* candidate leaves through {@link safeIdentifier} rather than through a local
|
|
112
|
+
* guard.
|
|
113
|
+
*/
|
|
114
|
+
export function candidateName(selector, role) {
|
|
115
|
+
const stem = pascalSegments(selector);
|
|
116
|
+
return safeIdentifier(`${stem.length > 0 ? stem : 'Schema'}${roleSuffix(role)}`);
|
|
117
|
+
}
|
|
118
|
+
const SAFE_CHARACTER = /[A-Za-z0-9_$]/;
|
|
119
|
+
const LOWERCASE = /[a-z]/;
|
|
120
|
+
const DIGIT = /[0-9]/;
|
|
121
|
+
/**
|
|
122
|
+
* A character after which the library's `toSafeString` upper-cases a following
|
|
123
|
+
* lowercase letter: a digit or `$` (`([\d$]+[a-zA-Z])` upper-cases the whole
|
|
124
|
+
* match) and an underscore (`_[a-z]` is collapsed into the upper-cased letter).
|
|
125
|
+
*/
|
|
126
|
+
const UPPERCASES_WHAT_FOLLOWS = /[0-9$_]/;
|
|
127
|
+
/**
|
|
128
|
+
* An identifier `json-schema-to-typescript`'s `toSafeString` leaves alone, for
|
|
129
|
+
* any input string.
|
|
130
|
+
*
|
|
131
|
+
* The contract is deliberately weaker than "reproduce `toSafeString`": the
|
|
132
|
+
* library never sees the original, only this function's output, so all that has
|
|
133
|
+
* to hold is that the output is a FIXED POINT of the library's transform. That
|
|
134
|
+
* is four conditions, and each is enforced by one branch below:
|
|
135
|
+
*
|
|
136
|
+
* - every character is in `[A-Za-z0-9_$]`, so nothing is replaced by whitespace;
|
|
137
|
+
* - the first character is never a digit, hence the `_` prefix;
|
|
138
|
+
* - no lowercase letter follows a digit, a `$` or an `_`;
|
|
139
|
+
* - the first character is never lowercase, so `upperFirst` is a no-op.
|
|
140
|
+
*
|
|
141
|
+
* A run of unusable characters is a word boundary rather than a deletion, so
|
|
142
|
+
* `foo bar` and `foo-bar` both become `FooBar` — the same convention
|
|
143
|
+
* {@link pascalSegments} uses, which is why applying both is harmless.
|
|
144
|
+
*/
|
|
145
|
+
export function safeIdentifier(value) {
|
|
146
|
+
let result = '';
|
|
147
|
+
let previous = '';
|
|
148
|
+
let atBoundary = true;
|
|
149
|
+
for (const character of value) {
|
|
150
|
+
if (!SAFE_CHARACTER.test(character)) {
|
|
151
|
+
atBoundary = true;
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
let next = character;
|
|
155
|
+
if (LOWERCASE.test(next) &&
|
|
156
|
+
(atBoundary ||
|
|
157
|
+
result.length === 0 ||
|
|
158
|
+
UPPERCASES_WHAT_FOLLOWS.test(previous))) {
|
|
159
|
+
next = next.toUpperCase();
|
|
160
|
+
}
|
|
161
|
+
if (result.length === 0 && DIGIT.test(next)) {
|
|
162
|
+
result = '_';
|
|
163
|
+
}
|
|
164
|
+
result += next;
|
|
165
|
+
previous = next;
|
|
166
|
+
atBoundary = false;
|
|
167
|
+
}
|
|
168
|
+
return result.length > 0 ? result : 'Schema';
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Hands out unique identifiers, remembering what each site was given.
|
|
172
|
+
*
|
|
173
|
+
* The suffix order is a function of the description rather than of traversal
|
|
174
|
+
* order, because the catalog is sorted by selector and each transaction's
|
|
175
|
+
* schemas are visited in a fixed role order. Adding a transaction that collides
|
|
176
|
+
* with an existing stem can renumber the colliding group, and only that group;
|
|
177
|
+
* adding a non-colliding one — the overwhelmingly common case — renames
|
|
178
|
+
* nothing.
|
|
179
|
+
*/
|
|
180
|
+
export class NameRegistry {
|
|
181
|
+
used;
|
|
182
|
+
byKey = new Map();
|
|
183
|
+
/**
|
|
184
|
+
* @param reserved names nothing may be assigned, such as the fixed
|
|
185
|
+
* declarations the surface emits around the generated ones.
|
|
186
|
+
*/
|
|
187
|
+
constructor(reserved = []) {
|
|
188
|
+
this.used = new Set(reserved);
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* The name for `selector` in `role`, minted the first time it is asked for
|
|
192
|
+
* and returned unchanged thereafter — so two references to one site cannot
|
|
193
|
+
* drift apart.
|
|
194
|
+
*/
|
|
195
|
+
nameFor(selector, role) {
|
|
196
|
+
const key = `${selector} ${roleSuffix(role)}`;
|
|
197
|
+
const existing = this.byKey.get(key);
|
|
198
|
+
if (existing !== undefined) {
|
|
199
|
+
return existing;
|
|
200
|
+
}
|
|
201
|
+
const candidate = candidateName(selector, role);
|
|
202
|
+
let name = candidate;
|
|
203
|
+
let suffix = 1;
|
|
204
|
+
while (this.used.has(name)) {
|
|
205
|
+
suffix += 1;
|
|
206
|
+
name = `${candidate}_${suffix}`;
|
|
207
|
+
}
|
|
208
|
+
this.used.add(name);
|
|
209
|
+
this.byKey.set(key, name);
|
|
210
|
+
return name;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
//# sourceMappingURL=type-names.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-names.js","sourceRoot":"","sources":["../../../src/generation/types/type-names.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { SamplerPaths } from '../../sampler-paths.js';
|
|
2
|
+
import { type TypeSurface } from './generate-type-surface.js';
|
|
3
|
+
/**
|
|
4
|
+
* The tsconfig `init` scaffolds, once.
|
|
5
|
+
*
|
|
6
|
+
* It is **user-owned from then on**: `sync` never rewrites it, because a user's
|
|
7
|
+
* edits here — a `types` entry, a stricter flag, an extra `include` — are
|
|
8
|
+
* legitimate and losing them silently would be worse than any convenience of
|
|
9
|
+
* keeping it current. A future plugin version needing a different tsconfig is a
|
|
10
|
+
* documented manual step, not an overwrite.
|
|
11
|
+
*
|
|
12
|
+
* The `paths` alias is what makes `@thymian/hooks` resolve in an editor. It is
|
|
13
|
+
* not what makes hooks *run*: the runtime resolves through a jiti alias, so a
|
|
14
|
+
* project with no tsconfig at all still executes its hooks.
|
|
15
|
+
*
|
|
16
|
+
* No `types` entry, deliberately. The generated surface needs no `@types/node`
|
|
17
|
+
* — `readFile` answers a `Uint8Array` and the encodings are spelled out — so a
|
|
18
|
+
* project without it still type-checks. A hook file that imports `node:fs`
|
|
19
|
+
* needs it and adds it here, which is a legitimate edit and the reason this
|
|
20
|
+
* file is scaffolded once rather than regenerated.
|
|
21
|
+
*/
|
|
22
|
+
export declare function scaffoldTsconfig(): string;
|
|
23
|
+
/**
|
|
24
|
+
* The note `init` prints about the repository's own tsconfig.
|
|
25
|
+
*
|
|
26
|
+
* The root tsconfig is never modified — it is the project's, not the sampler's —
|
|
27
|
+
* so the one thing a user has to do by hand is say so.
|
|
28
|
+
*/
|
|
29
|
+
export declare function rootExcludeNote(paths: SamplerPaths, cwd: string): string[];
|
|
30
|
+
/**
|
|
31
|
+
* Write the generated directory, wholesale.
|
|
32
|
+
*
|
|
33
|
+
* Wipe and rewrite rather than merge: a file left over from a description that
|
|
34
|
+
* no longer has that shape is exactly the stale artifact the virtual model
|
|
35
|
+
* exists to remove, and a merge cannot tell one from a file a user added.
|
|
36
|
+
* Everything outside `generated/` — the hooks, the tsconfig — is untouched.
|
|
37
|
+
*/
|
|
38
|
+
export declare function writeGenerated(paths: SamplerPaths, surface: TypeSurface): Promise<string[]>;
|
|
39
|
+
/**
|
|
40
|
+
* What is currently committed under `generated/`, file name → contents.
|
|
41
|
+
*
|
|
42
|
+
* Reads only the files the surface itself ever writes — {@link
|
|
43
|
+
* REQUEST_TYPES_FILE} and {@link HOOKS_API_FILE} — rather than every
|
|
44
|
+
* directory entry. `writeGenerated` wipes and rewrites the whole directory on
|
|
45
|
+
* every write, so anything else in it was never put there by the sampler: a
|
|
46
|
+
* macOS `.DS_Store`, an editor swap file, a stray subdirectory. `readdir`
|
|
47
|
+
* would hand all of it back with no way to tell a file from a directory
|
|
48
|
+
* without a second syscall per entry, and blindly `readFile`-ing a
|
|
49
|
+
* subdirectory throws `EISDIR` — crashing `sync --check`, `validate` and
|
|
50
|
+
* `thymian test` alike, mid-command, on a file the user never asked the
|
|
51
|
+
* sampler to look at. Naming the two files instead of listing the directory
|
|
52
|
+
* sidesteps both failure modes: a stray entry is neither read nor compared,
|
|
53
|
+
* so it is silently ignored rather than reported as spurious drift.
|
|
54
|
+
*/
|
|
55
|
+
export declare function readGenerated(paths: SamplerPaths): Promise<Record<string, string>>;
|
|
56
|
+
/** The surface as the file map it is written as, for comparison without I/O. */
|
|
57
|
+
export declare function surfaceAsFiles(surface: TypeSurface): Record<string, string>;
|
|
58
|
+
//# sourceMappingURL=write-type-surface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write-type-surface.d.ts","sourceRoot":"","sources":["../../../src/generation/types/write-type-surface.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAG3D,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,4BAA4B,CAAC;AAEpC;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAoBzC;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAa1E;AAED;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,MAAM,EAAE,CAAC,CAkBnB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAgBjC;AAED,gFAAgF;AAChF,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAK3E"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { mkdir, readFile, rm, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { join, relative } from 'node:path';
|
|
3
|
+
import { toTypeScriptPath } from '../../ts-path.js';
|
|
4
|
+
import { entryExists } from '../../utils.js';
|
|
5
|
+
import { HOOKS_API_FILE, REQUEST_TYPES_FILE, } from './generate-type-surface.js';
|
|
6
|
+
/**
|
|
7
|
+
* The tsconfig `init` scaffolds, once.
|
|
8
|
+
*
|
|
9
|
+
* It is **user-owned from then on**: `sync` never rewrites it, because a user's
|
|
10
|
+
* edits here — a `types` entry, a stricter flag, an extra `include` — are
|
|
11
|
+
* legitimate and losing them silently would be worse than any convenience of
|
|
12
|
+
* keeping it current. A future plugin version needing a different tsconfig is a
|
|
13
|
+
* documented manual step, not an overwrite.
|
|
14
|
+
*
|
|
15
|
+
* The `paths` alias is what makes `@thymian/hooks` resolve in an editor. It is
|
|
16
|
+
* not what makes hooks *run*: the runtime resolves through a jiti alias, so a
|
|
17
|
+
* project with no tsconfig at all still executes its hooks.
|
|
18
|
+
*
|
|
19
|
+
* No `types` entry, deliberately. The generated surface needs no `@types/node`
|
|
20
|
+
* — `readFile` answers a `Uint8Array` and the encodings are spelled out — so a
|
|
21
|
+
* project without it still type-checks. A hook file that imports `node:fs`
|
|
22
|
+
* needs it and adds it here, which is a legitimate edit and the reason this
|
|
23
|
+
* file is scaffolded once rather than regenerated.
|
|
24
|
+
*/
|
|
25
|
+
export function scaffoldTsconfig() {
|
|
26
|
+
return `${JSON.stringify({
|
|
27
|
+
compilerOptions: {
|
|
28
|
+
baseUrl: '.',
|
|
29
|
+
module: 'nodenext',
|
|
30
|
+
moduleResolution: 'nodenext',
|
|
31
|
+
target: 'es2023',
|
|
32
|
+
strict: true,
|
|
33
|
+
noEmit: true,
|
|
34
|
+
skipLibCheck: true,
|
|
35
|
+
paths: {
|
|
36
|
+
'@thymian/hooks': [`./generated/${HOOKS_API_FILE}`],
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
include: ['./hooks/**/*.ts', './generated/**/*.d.ts'],
|
|
40
|
+
}, null, 2)}\n`;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* The note `init` prints about the repository's own tsconfig.
|
|
44
|
+
*
|
|
45
|
+
* The root tsconfig is never modified — it is the project's, not the sampler's —
|
|
46
|
+
* so the one thing a user has to do by hand is say so.
|
|
47
|
+
*/
|
|
48
|
+
export function rootExcludeNote(paths, cwd) {
|
|
49
|
+
// A tsconfig `exclude` entry is a glob TypeScript matches against its own
|
|
50
|
+
// forward-slashed file names, so the hint has to be printed in that form on
|
|
51
|
+
// every platform — a Windows `\` here is a suggestion the user's own
|
|
52
|
+
// tsconfig would silently fail to honour.
|
|
53
|
+
const rootRelative = toTypeScriptPath(relative(cwd, paths.root) || paths.root);
|
|
54
|
+
return [
|
|
55
|
+
`Add ${JSON.stringify(rootRelative)} to the "exclude" list of your project's own tsconfig.json.`,
|
|
56
|
+
'Without it your project compiles the hooks with its own settings, and the sampler tsconfig — the one that knows where `@thymian/hooks` lives — never governs them.',
|
|
57
|
+
];
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Write the generated directory, wholesale.
|
|
61
|
+
*
|
|
62
|
+
* Wipe and rewrite rather than merge: a file left over from a description that
|
|
63
|
+
* no longer has that shape is exactly the stale artifact the virtual model
|
|
64
|
+
* exists to remove, and a merge cannot tell one from a file a user added.
|
|
65
|
+
* Everything outside `generated/` — the hooks, the tsconfig — is untouched.
|
|
66
|
+
*/
|
|
67
|
+
export async function writeGenerated(paths, surface) {
|
|
68
|
+
const before = await readGenerated(paths);
|
|
69
|
+
const fresh = surfaceAsFiles(surface);
|
|
70
|
+
await rm(paths.generatedDir, { recursive: true, force: true });
|
|
71
|
+
await mkdir(paths.generatedDir, { recursive: true });
|
|
72
|
+
for (const [name, contents] of Object.entries(fresh)) {
|
|
73
|
+
await writeFile(join(paths.generatedDir, name), contents, 'utf-8');
|
|
74
|
+
}
|
|
75
|
+
// Which files' *bytes* moved, which is not the same question as which types
|
|
76
|
+
// moved: the drift gate compares canonicalized, so a description edit is not
|
|
77
|
+
// drift — but it does change the file, and a user told "these match" while
|
|
78
|
+
// finding a diff in their working tree is owed the difference.
|
|
79
|
+
return [...new Set([...Object.keys(before), ...Object.keys(fresh)])]
|
|
80
|
+
.filter((name) => before[name] !== fresh[name])
|
|
81
|
+
.sort();
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* What is currently committed under `generated/`, file name → contents.
|
|
85
|
+
*
|
|
86
|
+
* Reads only the files the surface itself ever writes — {@link
|
|
87
|
+
* REQUEST_TYPES_FILE} and {@link HOOKS_API_FILE} — rather than every
|
|
88
|
+
* directory entry. `writeGenerated` wipes and rewrites the whole directory on
|
|
89
|
+
* every write, so anything else in it was never put there by the sampler: a
|
|
90
|
+
* macOS `.DS_Store`, an editor swap file, a stray subdirectory. `readdir`
|
|
91
|
+
* would hand all of it back with no way to tell a file from a directory
|
|
92
|
+
* without a second syscall per entry, and blindly `readFile`-ing a
|
|
93
|
+
* subdirectory throws `EISDIR` — crashing `sync --check`, `validate` and
|
|
94
|
+
* `thymian test` alike, mid-command, on a file the user never asked the
|
|
95
|
+
* sampler to look at. Naming the two files instead of listing the directory
|
|
96
|
+
* sidesteps both failure modes: a stray entry is neither read nor compared,
|
|
97
|
+
* so it is silently ignored rather than reported as spurious drift.
|
|
98
|
+
*/
|
|
99
|
+
export async function readGenerated(paths) {
|
|
100
|
+
if (!(await entryExists(paths.generatedDir))) {
|
|
101
|
+
return {};
|
|
102
|
+
}
|
|
103
|
+
const files = {};
|
|
104
|
+
for (const name of [HOOKS_API_FILE, REQUEST_TYPES_FILE].sort()) {
|
|
105
|
+
const path = join(paths.generatedDir, name);
|
|
106
|
+
if (await entryExists(path)) {
|
|
107
|
+
files[name] = await readFile(path, 'utf-8');
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return files;
|
|
111
|
+
}
|
|
112
|
+
/** The surface as the file map it is written as, for comparison without I/O. */
|
|
113
|
+
export function surfaceAsFiles(surface) {
|
|
114
|
+
return {
|
|
115
|
+
[HOOKS_API_FILE]: surface.hooksApi,
|
|
116
|
+
[REQUEST_TYPES_FILE]: surface.requestTypes,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=write-type-surface.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write-type-surface.js","sourceRoot":"","sources":["../../../src/generation/types/write-type-surface.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,24 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
import {
|
|
3
|
-
import type {
|
|
4
|
-
|
|
5
|
-
export
|
|
6
|
-
|
|
1
|
+
import { type HttpRequestTemplate, type HttpResponse, type HttpTestCaseResult } from '@thymian/core';
|
|
2
|
+
import type { Selector } from '../selectors/selector.js';
|
|
3
|
+
import type { EndpointRequest, EndpointResponse, Endpoints, HookUtils, RequestOptions } from './hook-utils.js';
|
|
4
|
+
/** What one hook call needs to know about where it came from and what it shapes. */
|
|
5
|
+
export type HookCallContext = {
|
|
6
|
+
/** Absolute directory of the hook file, for the file helpers. */
|
|
7
|
+
dir: string;
|
|
8
|
+
/** The request this hook is shaping, for the typed setters. */
|
|
9
|
+
request: HttpRequestTemplate | undefined;
|
|
10
|
+
/** Where a hook's assertions and messages land. */
|
|
11
|
+
results: HttpTestCaseResult[];
|
|
12
|
+
/**
|
|
13
|
+
* Runs a cross-endpoint request. Absent where there is no pipeline to run one
|
|
14
|
+
* through — a `defineSample` hook runs before any request exists.
|
|
15
|
+
*/
|
|
16
|
+
requestOther?: (selector: Selector, args: EndpointRequest, options: RequestOptions) => Promise<EndpointResponse>;
|
|
17
|
+
};
|
|
18
|
+
export declare function createHookUtils<E extends Endpoints>(context: HookCallContext): HookUtils<E>;
|
|
19
|
+
/**
|
|
20
|
+
* The body a hook sees, parsed when the response says it is JSON and left as
|
|
21
|
+
* the raw string when it does not.
|
|
22
|
+
*/
|
|
7
23
|
export declare function parseResponseBody(res: HttpResponse): unknown;
|
|
8
24
|
//# sourceMappingURL=create-hook-utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-hook-utils.d.ts","sourceRoot":"","sources":["../../src/hooks/create-hook-utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"create-hook-utils.d.ts","sourceRoot":"","sources":["../../src/hooks/create-hook-utils.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,KAAK,kBAAkB,EAExB,MAAM,eAAe,CAAC;AAEvB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEzD,OAAO,KAAK,EACV,eAAe,EACf,gBAAgB,EAChB,SAAS,EACT,SAAS,EACT,cAAc,EACf,MAAM,iBAAiB,CAAC;AAKzB,oFAAoF;AACpF,MAAM,MAAM,eAAe,GAAG;IAC5B,iEAAiE;IACjE,GAAG,EAAE,MAAM,CAAC;IACZ,+DAA+D;IAC/D,OAAO,EAAE,mBAAmB,GAAG,SAAS,CAAC;IACzC,mDAAmD;IACnD,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B;;;OAGG;IACH,YAAY,CAAC,EAAE,CACb,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,eAAe,EACrB,OAAO,EAAE,cAAc,KACpB,OAAO,CAAC,gBAAgB,CAAC,CAAC;CAChC,CAAC;AAEF,wBAAgB,eAAe,CAAC,CAAC,SAAS,SAAS,EACjD,OAAO,EAAE,eAAe,GACvB,SAAS,CAAC,CAAC,CAAC,CA2Hd;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAY5D"}
|