@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,671 @@
|
|
|
1
|
+
import { formatRequestSelector } from '@thymian/core';
|
|
2
|
+
import { compareSelectors } from '../../selectors/selector.js';
|
|
3
|
+
import { PATH_GLOB_SOURCE } from '../../selectors/transaction-filter.js';
|
|
4
|
+
import { DeclarationSet } from './declaration-set.js';
|
|
5
|
+
import { generateSchemaType, isJsonMediaType } from './schema-type.js';
|
|
6
|
+
import { FIXED_ROOT_NAMES, NameRegistry } from './type-names.js';
|
|
7
|
+
export const REQUEST_TYPES_FILE = 'request-types.d.ts';
|
|
8
|
+
export const HOOKS_API_FILE = 'hooks-api.d.ts';
|
|
9
|
+
const BANNER = `/*
|
|
10
|
+
* ========================================================================
|
|
11
|
+
*
|
|
12
|
+
* WARNING: THIS FILE IS GENERATED. DO NOT EDIT.
|
|
13
|
+
*
|
|
14
|
+
* Regenerate it with \`thymian sampler sync\`, and commit the result: these
|
|
15
|
+
* types are the baseline the drift gate compares against, so an edit here is
|
|
16
|
+
* indistinguishable from the API description having changed.
|
|
17
|
+
*
|
|
18
|
+
* ========================================================================
|
|
19
|
+
*/
|
|
20
|
+
`;
|
|
21
|
+
/**
|
|
22
|
+
* The specifier one generated declaration file imports another by.
|
|
23
|
+
*
|
|
24
|
+
* A `.d.ts` file is imported by the module path it *declares* — `./x.js` — not
|
|
25
|
+
* by its own filename. Emitting `./x.d.ts` happened to resolve under the
|
|
26
|
+
* scaffolded tsconfig, which is exactly why it was worth fixing before some
|
|
27
|
+
* other configuration stopped tolerating it.
|
|
28
|
+
*/
|
|
29
|
+
function moduleSpecifierFor(declarationFile) {
|
|
30
|
+
return declarationFile.replace(/\.d\.ts$/, '.js');
|
|
31
|
+
}
|
|
32
|
+
/** A union type text, sorted so the emission does not depend on visit order. */
|
|
33
|
+
function union(values) {
|
|
34
|
+
const sorted = [...new Set(values)].sort();
|
|
35
|
+
return sorted.length === 0 ? 'never' : sorted.join(' | ');
|
|
36
|
+
}
|
|
37
|
+
function quote(value) {
|
|
38
|
+
return JSON.stringify(value);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* One parameter group as a type literal: `entries`, one per declared
|
|
42
|
+
* parameter, plus an open index signature so a hook can still set a
|
|
43
|
+
* parameter the description never mentioned.
|
|
44
|
+
*/
|
|
45
|
+
function parameterGroup(entries, indexSignature) {
|
|
46
|
+
return [`{`, ...entries, ` ${indexSignature}`, ` }`].join('\n');
|
|
47
|
+
}
|
|
48
|
+
/** One parameter group entry: the quoted name, `?` where the parameter is optional, and its type. */
|
|
49
|
+
function parameterEntry(name, parameter, type) {
|
|
50
|
+
return ` ${quote(name)}${parameter.required ? '' : '?'}: ${type};`;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Every parameter of one group as one type literal, each parameter typed from
|
|
54
|
+
* its declared schema.
|
|
55
|
+
*/
|
|
56
|
+
async function parametersType(parameters, indexSignature, nameFor, declarations) {
|
|
57
|
+
const entries = [];
|
|
58
|
+
for (const name of Object.keys(parameters).sort()) {
|
|
59
|
+
const parameter = parameters[name];
|
|
60
|
+
const generated = await generateSchemaType(parameter.schema, parameter.contentType ?? 'application/json', nameFor(name));
|
|
61
|
+
const type = declarations.add(generated.declarations, generated.type);
|
|
62
|
+
entries.push(parameterEntry(name, parameter, type));
|
|
63
|
+
}
|
|
64
|
+
return parameterGroup(entries, indexSignature);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* A header group, typed as the wire strings that actually cross it —
|
|
68
|
+
* `string | string[]` for every declared header, regardless of what the
|
|
69
|
+
* description's schema says it is.
|
|
70
|
+
*
|
|
71
|
+
* Unlike {@link parametersType}, this never calls `generateSchemaType`: a
|
|
72
|
+
* header is not a JSON value the way a body or a query parameter is, and
|
|
73
|
+
* typing it from its declared schema (an `integer` `X-Rate-Limit`, say) makes
|
|
74
|
+
* the surface describe a value the wire never carries — Node's own HTTP
|
|
75
|
+
* layer hands every header to a hook as a string or an array of strings, no
|
|
76
|
+
* matter what the description declares. A schema that cannot compile at all
|
|
77
|
+
* — one declaring a non-string header — used to fail generation outright;
|
|
78
|
+
* now it cannot, because the schema is never reached.
|
|
79
|
+
*/
|
|
80
|
+
function headersType(parameters, indexSignature) {
|
|
81
|
+
const entries = Object.keys(parameters)
|
|
82
|
+
.sort()
|
|
83
|
+
.map((name) => parameterEntry(name, parameters[name], 'string | string[]'));
|
|
84
|
+
return parameterGroup(entries, indexSignature);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The `Responses` entries, sorted, one operation per line group.
|
|
88
|
+
*
|
|
89
|
+
* Every member gets its own `|` line, single-member unions included, so
|
|
90
|
+
* declaring one more response of an operation adds exactly one line to the
|
|
91
|
+
* committed diff instead of rewriting the entry.
|
|
92
|
+
*/
|
|
93
|
+
function operations(byOperation) {
|
|
94
|
+
return [...byOperation.entries()]
|
|
95
|
+
.sort(([a], [b]) => compareSelectors(a, b))
|
|
96
|
+
.map(([operation, members]) => [` ${quote(operation)}:`, ...members.map((m) => ` | ${m}`)].join('\n') + ';');
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Emit the committed type surface for a loaded description.
|
|
100
|
+
*
|
|
101
|
+
* Deterministic by construction: unions are sorted, parameters are emitted in
|
|
102
|
+
* name order, declaration names come from the selector and the schema's role
|
|
103
|
+
* within the transaction (see `type-names.ts`), and `Endpoints` follows catalog
|
|
104
|
+
* order — which is sorted by selector. So reordering the source document, or
|
|
105
|
+
* renaming its title, changes nothing here; and because no name is positional,
|
|
106
|
+
* inserting an endpoint touches only the lines that endpoint owns plus the
|
|
107
|
+
* unions its method, status, path and media types widen.
|
|
108
|
+
*/
|
|
109
|
+
export async function generateTypeSurface(catalog) {
|
|
110
|
+
const declarations = new DeclarationSet(FIXED_ROOT_NAMES);
|
|
111
|
+
const endpoints = [];
|
|
112
|
+
// The request half of a selector is the operation a cross-endpoint call
|
|
113
|
+
// initiates; every Transaction sharing it is one response that operation
|
|
114
|
+
// declares. Grouping here is what makes `utils.request` able to answer with
|
|
115
|
+
// a union rather than a promise it cannot keep.
|
|
116
|
+
const responsesByOperation = new Map();
|
|
117
|
+
const methods = new Set();
|
|
118
|
+
const statuses = new Set();
|
|
119
|
+
const statusClasses = new Set();
|
|
120
|
+
const paths = new Set();
|
|
121
|
+
const requestMediaTypes = new Set();
|
|
122
|
+
const responseMediaTypes = new Set();
|
|
123
|
+
// The fixed declarations this file emits around the generated ones, so a
|
|
124
|
+
// generated name can never shadow one of them.
|
|
125
|
+
const names = new NameRegistry(FIXED_ROOT_NAMES);
|
|
126
|
+
for (const [selector, transaction] of catalog.entries()) {
|
|
127
|
+
const { thymianReq: req, thymianRes: res } = transaction;
|
|
128
|
+
methods.add(req.method.toUpperCase());
|
|
129
|
+
statuses.add(String(res.statusCode));
|
|
130
|
+
paths.add(req.path);
|
|
131
|
+
// A status class is the first digit, so a description declaring a 418 or a
|
|
132
|
+
// vendor's 499 gets a "4XX" it can actually target.
|
|
133
|
+
const firstDigit = String(res.statusCode)[0];
|
|
134
|
+
if (firstDigit && /[1-5]/.test(firstDigit)) {
|
|
135
|
+
statusClasses.add(`${firstDigit}XX`);
|
|
136
|
+
}
|
|
137
|
+
if (req.mediaType) {
|
|
138
|
+
requestMediaTypes.add(req.mediaType);
|
|
139
|
+
}
|
|
140
|
+
if (res.mediaType) {
|
|
141
|
+
responseMediaTypes.add(res.mediaType);
|
|
142
|
+
}
|
|
143
|
+
const requestBody = await generateSchemaType(req.body, req.mediaType, names.nameFor(selector, { kind: 'request-body' }));
|
|
144
|
+
const responseBody = await generateSchemaType(res.schema, res.mediaType, names.nameFor(selector, { kind: 'response-body' }));
|
|
145
|
+
const requestBodyType = declarations.add(requestBody.declarations, requestBody.type);
|
|
146
|
+
const responseBodyType = declarations.add(responseBody.declarations, responseBody.type);
|
|
147
|
+
const query = await parametersType(req.queryParameters, '[query: string]: unknown;', (parameter) => names.nameFor(selector, { kind: 'query-parameter', parameter }), declarations);
|
|
148
|
+
const path = await parametersType(req.pathParameters, '[param: string]: unknown;', (parameter) => names.nameFor(selector, { kind: 'path-parameter', parameter }), declarations);
|
|
149
|
+
const headers = headersType(req.headers, '[header: string]: string | string[] | undefined;');
|
|
150
|
+
const cookies = await parametersType(req.cookies, '[cookie: string]: unknown;', (parameter) => names.nameFor(selector, { kind: 'cookie', parameter }), declarations);
|
|
151
|
+
const responseHeaders = headersType(res.headers, '[header: string]: string | string[] | undefined;');
|
|
152
|
+
const operation = formatRequestSelector(req);
|
|
153
|
+
responsesByOperation.set(operation, [
|
|
154
|
+
...(responsesByOperation.get(operation) ?? []),
|
|
155
|
+
`TransactionResponse<${quote(selector)}>`,
|
|
156
|
+
]);
|
|
157
|
+
endpoints.push([
|
|
158
|
+
` ${quote(selector)}: {`,
|
|
159
|
+
// The description's own casing, which is what a hook actually sees.
|
|
160
|
+
// The uppercase form is the Selector's and the `Method` union's.
|
|
161
|
+
` method: ${quote(req.method)};`,
|
|
162
|
+
// The operation this Transaction is one response of — the request half
|
|
163
|
+
// of its own Selector, so it is derivable rather than invented.
|
|
164
|
+
` operation: ${quote(operation)};`,
|
|
165
|
+
` path: ${quote(req.path)};`,
|
|
166
|
+
` status: ${res.statusCode};`,
|
|
167
|
+
` requestMediaType: ${quote(req.mediaType)};`,
|
|
168
|
+
` responseMediaType: ${quote(res.mediaType)};`,
|
|
169
|
+
` authorize: boolean;`,
|
|
170
|
+
` req: {`,
|
|
171
|
+
` body${isJsonMediaType(req.mediaType) && req.body ? (req.bodyRequired ? '' : '?') : '?'}: ${requestBodyType};`,
|
|
172
|
+
` query?: ${query};`,
|
|
173
|
+
` path?: ${path};`,
|
|
174
|
+
` headers?: ${headers};`,
|
|
175
|
+
` cookies?: ${cookies};`,
|
|
176
|
+
` };`,
|
|
177
|
+
` res: {`,
|
|
178
|
+
` statusCode: ${res.statusCode};`,
|
|
179
|
+
` headers: ${responseHeaders};`,
|
|
180
|
+
` body: ${responseBodyType};`,
|
|
181
|
+
` };`,
|
|
182
|
+
` };`,
|
|
183
|
+
].join('\n'));
|
|
184
|
+
}
|
|
185
|
+
const requestTypes = [
|
|
186
|
+
BANNER,
|
|
187
|
+
...declarations.all(),
|
|
188
|
+
'',
|
|
189
|
+
'/** Every HTTP method the description uses. */',
|
|
190
|
+
`export type Method = ${union([...methods].map(quote))};`,
|
|
191
|
+
'',
|
|
192
|
+
'/** Every status code the description declares. */',
|
|
193
|
+
`export type Status = ${union(statuses)};`,
|
|
194
|
+
'',
|
|
195
|
+
'/** Every status class the declared statuses fall into. */',
|
|
196
|
+
`export type StatusClass = ${union([...statusClasses].map(quote))};`,
|
|
197
|
+
'',
|
|
198
|
+
'/** Every path template the description declares, base path included. */',
|
|
199
|
+
`export type Path = ${union([...paths].map(quote))};`,
|
|
200
|
+
'',
|
|
201
|
+
'/** Every media type a request node declares. */',
|
|
202
|
+
`export type RequestMediaType = ${union([...requestMediaTypes].map(quote))};`,
|
|
203
|
+
'',
|
|
204
|
+
'/** Every media type a response node declares. */',
|
|
205
|
+
`export type ResponseMediaType = ${union([...responseMediaTypes].map(quote))};`,
|
|
206
|
+
'',
|
|
207
|
+
'/**',
|
|
208
|
+
' * Every Transaction the description declares, keyed by its Selector.',
|
|
209
|
+
' *',
|
|
210
|
+
' * One key is exactly one Transaction, so a key carries its own status and',
|
|
211
|
+
' * media types — nothing about a *target* has to be narrowed. What the',
|
|
212
|
+
' * server answers with is a different question, and `Responses` answers it.',
|
|
213
|
+
' */',
|
|
214
|
+
'export type Endpoints = {',
|
|
215
|
+
...endpoints,
|
|
216
|
+
'};',
|
|
217
|
+
'',
|
|
218
|
+
'/** The address of exactly one Transaction. */',
|
|
219
|
+
'export type Selector = keyof Endpoints;',
|
|
220
|
+
'',
|
|
221
|
+
'/**',
|
|
222
|
+
' * A media type as the wire carries it: the essence, lowercased, with any',
|
|
223
|
+
' * parameters dropped.',
|
|
224
|
+
' *',
|
|
225
|
+
' * A description may declare `application/json; charset=utf-8`, but what a',
|
|
226
|
+
' * response reports is what actually crossed — the essence — so the',
|
|
227
|
+
' * declared literal is the wrong discriminator: narrowing on it compiles',
|
|
228
|
+
' * and then never matches. Normalizing the type is what keeps the two the',
|
|
229
|
+
' * same string. The declared spelling stays on `responseMediaType`, which',
|
|
230
|
+
' * is what a Selector is written with.',
|
|
231
|
+
' *',
|
|
232
|
+
' * Trimmed as well as lowercased, because the runtime trims: a content key',
|
|
233
|
+
' * spelled `application/json ; charset=utf-8` reports `application/json`,',
|
|
234
|
+
' * and typing it one space wider is the same never-matches one space away.',
|
|
235
|
+
' */',
|
|
236
|
+
'export type WireMediaType<T extends string> =',
|
|
237
|
+
' T extends `${infer Essence};${string}`',
|
|
238
|
+
' ? WireMediaType<Essence>',
|
|
239
|
+
' : T extends ` ${infer Trimmed}` | `${infer Trimmed} `',
|
|
240
|
+
' ? WireMediaType<Trimmed>',
|
|
241
|
+
' : Lowercase<T>;',
|
|
242
|
+
'',
|
|
243
|
+
'/**',
|
|
244
|
+
' * One declared response, as a cross-endpoint call sees it: the four fields',
|
|
245
|
+
' * a caller reads, narrowed by the literal `statusCode` and — where one',
|
|
246
|
+
' * status declares several media types — by `mediaType`.',
|
|
247
|
+
' */',
|
|
248
|
+
'export type TransactionResponse<T extends Selector> = {',
|
|
249
|
+
" statusCode: Endpoints[T]['status'];",
|
|
250
|
+
" mediaType: WireMediaType<Endpoints[T]['responseMediaType']>;",
|
|
251
|
+
" headers: Endpoints[T]['res']['headers'];",
|
|
252
|
+
" body: Endpoints[T]['res']['body'];",
|
|
253
|
+
'};',
|
|
254
|
+
'',
|
|
255
|
+
'/**',
|
|
256
|
+
' * Every response an operation declares, keyed by the request half of its',
|
|
257
|
+
' * Selectors.',
|
|
258
|
+
' *',
|
|
259
|
+
' * A selector initiates a Transaction; it cannot promise the outcome. This is',
|
|
260
|
+
' * what the server is allowed to answer with — anything else is an',
|
|
261
|
+
' * `UndeclaredResponseError`.',
|
|
262
|
+
' */',
|
|
263
|
+
'export type Responses = {',
|
|
264
|
+
...operations(responsesByOperation),
|
|
265
|
+
'};',
|
|
266
|
+
'',
|
|
267
|
+
].join('\n');
|
|
268
|
+
return { requestTypes, hooksApi: hooksApiSource() };
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* The `@thymian/hooks` surface, as a declaration file.
|
|
272
|
+
*
|
|
273
|
+
* Written as text rather than generated from the runtime module because it is a
|
|
274
|
+
* *contract*: the runtime resolves through a jiti alias and never reads this
|
|
275
|
+
* file, so what is committed here is what the author's editor sees, and it has
|
|
276
|
+
* to say what the author is allowed to write — not what the implementation
|
|
277
|
+
* happens to accept.
|
|
278
|
+
*/
|
|
279
|
+
function hooksApiSource() {
|
|
280
|
+
return `${BANNER}
|
|
281
|
+
import type {
|
|
282
|
+
Endpoints,
|
|
283
|
+
Method,
|
|
284
|
+
Path,
|
|
285
|
+
RequestMediaType,
|
|
286
|
+
ResponseMediaType,
|
|
287
|
+
Responses,
|
|
288
|
+
Selector,
|
|
289
|
+
Status,
|
|
290
|
+
StatusClass,
|
|
291
|
+
TransactionResponse,
|
|
292
|
+
} from './${moduleSpecifierFor(REQUEST_TYPES_FILE)}';
|
|
293
|
+
|
|
294
|
+
export type {
|
|
295
|
+
Endpoints,
|
|
296
|
+
Method,
|
|
297
|
+
Path,
|
|
298
|
+
RequestMediaType,
|
|
299
|
+
ResponseMediaType,
|
|
300
|
+
Responses,
|
|
301
|
+
Selector,
|
|
302
|
+
Status,
|
|
303
|
+
StatusClass,
|
|
304
|
+
TransactionResponse,
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* A path glob, by shape: at least one \`*\`.
|
|
309
|
+
*
|
|
310
|
+
* A string with no \`*\` is not a \`PathGlob\`, so it has to be an exact \`Path\` —
|
|
311
|
+
* which is what keeps a typo'd exact path a compile error while a glob stays a
|
|
312
|
+
* plain string. The shape deliberately never touches the \`Path\` union;
|
|
313
|
+
* vacuousness is reported by \`sampler validate\` and fails a run at load.
|
|
314
|
+
*
|
|
315
|
+
* \`*\` is exactly one path segment and a trailing \`**\` is one or more, so
|
|
316
|
+
* \`/admin/**\` is everything *under* \`/admin\` and not \`/admin\` itself.
|
|
317
|
+
*/
|
|
318
|
+
export type PathGlob = ${PATH_GLOB_SOURCE};
|
|
319
|
+
|
|
320
|
+
/** The fields a filter can constrain. Each value is spec-derived and closed. */
|
|
321
|
+
export type FilterFields = {
|
|
322
|
+
readonly method?: Method | readonly Method[];
|
|
323
|
+
readonly status?: Status | readonly Status[];
|
|
324
|
+
readonly statusClass?: StatusClass | readonly StatusClass[];
|
|
325
|
+
readonly path?: Path | PathGlob | readonly (Path | PathGlob)[];
|
|
326
|
+
readonly requestMediaType?: RequestMediaType | readonly RequestMediaType[];
|
|
327
|
+
readonly responseMediaType?: ResponseMediaType | readonly ResponseMediaType[];
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Targets a set of Transactions.
|
|
332
|
+
*
|
|
333
|
+
* Fields AND-combine; an array within a field OR-combines. \`not\` excludes, one
|
|
334
|
+
* level deep by construction.
|
|
335
|
+
*/
|
|
336
|
+
export type TransactionFilter = FilterFields & {
|
|
337
|
+
readonly not?: FilterFields | readonly FilterFields[];
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
/** What a per-transaction hook is aimed at. */
|
|
341
|
+
export type HookTarget = Selector | readonly Selector[] | TransactionFilter;
|
|
342
|
+
|
|
343
|
+
/** One parameter group of a Transaction's request, as a hook sees it. */
|
|
344
|
+
type GroupOf<
|
|
345
|
+
T extends Selector,
|
|
346
|
+
K extends 'query' | 'path' | 'headers' | 'cookies',
|
|
347
|
+
> = NonNullable<Endpoints[T]['req'][K]>;
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* The request a hook shapes, for one Transaction.
|
|
351
|
+
*
|
|
352
|
+
* Built field by field rather than by intersecting \`Endpoints[T]['req']\`. That
|
|
353
|
+
* intersection was wrong in a way the compiler could not warn about: \`req.path\`
|
|
354
|
+
* is the *path-parameter group*, while the live request's \`path\` is the URL
|
|
355
|
+
* template — so \`path\` came out as an object type intersected with a string
|
|
356
|
+
* literal. Assigning the template was a false compile error, and
|
|
357
|
+
* \`request.path.id = …\` compiled and then threw at run time.
|
|
358
|
+
*
|
|
359
|
+
* Distributive by construction (\`T\` is naked in the conditional), which is what
|
|
360
|
+
* turns a union of Selectors into a union of requests.
|
|
361
|
+
*/
|
|
362
|
+
export type RequestForSelector<T> = T extends Selector
|
|
363
|
+
? {
|
|
364
|
+
/**
|
|
365
|
+
* The method as the description spells it, casing included — which for an
|
|
366
|
+
* OpenAPI document is the lowercase path-item key. The uppercase form
|
|
367
|
+
* lives in \`Method\` and in Selectors, where it is canonical.
|
|
368
|
+
*/
|
|
369
|
+
method: Endpoints[T]['method'];
|
|
370
|
+
/** The path template, with its \`{param}\` placeholders intact. */
|
|
371
|
+
path: Endpoints[T]['path'];
|
|
372
|
+
origin: string;
|
|
373
|
+
authorize: boolean;
|
|
374
|
+
bodyEncoding?: string;
|
|
375
|
+
pathParameters: GroupOf<T, 'path'>;
|
|
376
|
+
query: GroupOf<T, 'query'>;
|
|
377
|
+
headers: GroupOf<T, 'headers'>;
|
|
378
|
+
cookies: GroupOf<T, 'cookies'>;
|
|
379
|
+
} & BodyOf<T>
|
|
380
|
+
: never;
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* The request a hook shapes, for whatever its target names.
|
|
384
|
+
*
|
|
385
|
+
* An **array of Selectors is the union of its members' requests** — the same
|
|
386
|
+
* safety a single Selector gets, distributed. Only a \`TransactionFilter\` falls
|
|
387
|
+
* back to \`GenericRequest\`: a filter's membership is decided at load time
|
|
388
|
+
* against the catalog, so there is no set of Transactions for the compiler to
|
|
389
|
+
* name.
|
|
390
|
+
*/
|
|
391
|
+
export type RequestOf<T> = T extends Selector
|
|
392
|
+
? RequestForSelector<T>
|
|
393
|
+
: T extends readonly Selector[]
|
|
394
|
+
? RequestForSelector<T[number]>
|
|
395
|
+
: GenericRequest;
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* The body field, required exactly when the Transaction requires a body.
|
|
399
|
+
*
|
|
400
|
+
* Declaring it optional unconditionally made the documented mutate-in-place
|
|
401
|
+
* idiom need a non-null assertion — \`draft.body!.rank = …\` — on every
|
|
402
|
+
* body-touching hook, for a body the description says is always there. An
|
|
403
|
+
* optional property does not satisfy a required one, so the check below lands
|
|
404
|
+
* on the right branch by itself.
|
|
405
|
+
*/
|
|
406
|
+
type BodyOf<T extends Selector> = Endpoints[T]['req'] extends { body: infer B }
|
|
407
|
+
? { body: B }
|
|
408
|
+
: { body?: Endpoints[T]['req']['body'] };
|
|
409
|
+
|
|
410
|
+
/** The request a hook shapes when its target covers more than one Transaction. */
|
|
411
|
+
export type GenericRequest = {
|
|
412
|
+
method: string;
|
|
413
|
+
path: Path;
|
|
414
|
+
origin: string;
|
|
415
|
+
authorize: boolean;
|
|
416
|
+
bodyEncoding?: string;
|
|
417
|
+
query: Record<string, unknown>;
|
|
418
|
+
pathParameters: Record<string, unknown>;
|
|
419
|
+
headers: Record<string, string | string[] | undefined>;
|
|
420
|
+
cookies: Record<string, unknown>;
|
|
421
|
+
body?: unknown;
|
|
422
|
+
};
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* A recursive partial: objects recurse, arrays and primitives replace whole.
|
|
426
|
+
*
|
|
427
|
+
* Arrays are deliberately not recursed into. "Merge the third element of this
|
|
428
|
+
* list" needs an index the caller cannot know is stable, and a partial element
|
|
429
|
+
* would be an element the schema does not describe.
|
|
430
|
+
*/
|
|
431
|
+
export type DeepPartial<T> = T extends readonly unknown[]
|
|
432
|
+
? T
|
|
433
|
+
: T extends object
|
|
434
|
+
? { [K in keyof T]?: DeepPartial<T[K]> }
|
|
435
|
+
: T;
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* What a cross-endpoint call may pass for one Transaction.
|
|
439
|
+
*
|
|
440
|
+
* Everything is optional, because the call **overlays** the generated request:
|
|
441
|
+
* what you leave out comes from the description, already shaped by the target's
|
|
442
|
+
* own \`defineSample\`. Parameter groups merge per key; the body deep-merges,
|
|
443
|
+
* so you state the one field that differs and nothing else.
|
|
444
|
+
*
|
|
445
|
+
* Requiring the full \`req\` here made the documented seeding idiom —
|
|
446
|
+
* \`utils.request(selector, {}, { authorize: true })\` — a compile error for
|
|
447
|
+
* every operation with a required body, which is the only kind anyone seeds
|
|
448
|
+
* with.
|
|
449
|
+
*/
|
|
450
|
+
export type RequestArgsOf<T extends Selector> = {
|
|
451
|
+
body?: DeepPartial<Endpoints[T]['req']['body']>;
|
|
452
|
+
query?: Partial<GroupOf<T, 'query'>>;
|
|
453
|
+
path?: Partial<GroupOf<T, 'path'>>;
|
|
454
|
+
headers?: Partial<GroupOf<T, 'headers'>>;
|
|
455
|
+
cookies?: Partial<GroupOf<T, 'cookies'>>;
|
|
456
|
+
};
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* Every response the operation behind \`T\` declares.
|
|
460
|
+
*
|
|
461
|
+
* A Selector says which Transaction to *initiate*; the server decides which one
|
|
462
|
+
* actually happens. So the answer is a discriminated union over every declared
|
|
463
|
+
* response of that operation — narrow it with \`if (res.statusCode === 201)\`,
|
|
464
|
+
* and where one status declares several media types, with \`res.mediaType\`.
|
|
465
|
+
*
|
|
466
|
+
* A status the description never declares is not in this union at all: it
|
|
467
|
+
* throws \`UndeclaredResponseError\`.
|
|
468
|
+
*/
|
|
469
|
+
export type ResponsesOf<T extends Selector> = Responses[Endpoints[T]['operation']];
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* The server answered with a status the description never declares for this
|
|
473
|
+
* operation.
|
|
474
|
+
*
|
|
475
|
+
* Not a union member, because the union is what the description promises and
|
|
476
|
+
* this is the case where the promise was broken. Catch it to react, or let it
|
|
477
|
+
* escape: at the transaction boundary it is caught for you, and the transaction
|
|
478
|
+
* is skipped with this seed and its actual status named.
|
|
479
|
+
*/
|
|
480
|
+
export declare class UndeclaredResponseError extends Error {
|
|
481
|
+
readonly selector: Selector;
|
|
482
|
+
readonly statusCode: number;
|
|
483
|
+
readonly headers: Record<string, string | string[] | undefined>;
|
|
484
|
+
readonly body: unknown;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
/** The response a hook observes, for one Transaction. Distributive. */
|
|
488
|
+
export type ResponseForSelector<T> = T extends Selector
|
|
489
|
+
? {
|
|
490
|
+
statusCode: Endpoints[T]['res']['statusCode'];
|
|
491
|
+
headers: Record<string, string | string[] | undefined>;
|
|
492
|
+
body?: string;
|
|
493
|
+
bodyEncoding?: string;
|
|
494
|
+
trailers: Record<string, string>;
|
|
495
|
+
duration: number;
|
|
496
|
+
}
|
|
497
|
+
: never;
|
|
498
|
+
|
|
499
|
+
/** The response a hook observes. An array target unions its members'. */
|
|
500
|
+
export type ResponseOf<T> = T extends Selector
|
|
501
|
+
? ResponseForSelector<T>
|
|
502
|
+
: T extends readonly Selector[]
|
|
503
|
+
? ResponseForSelector<T[number]>
|
|
504
|
+
: GenericResponse;
|
|
505
|
+
|
|
506
|
+
/** The response a hook observes when its target covers more than one Transaction. */
|
|
507
|
+
export type GenericResponse = {
|
|
508
|
+
statusCode: Status;
|
|
509
|
+
headers: Record<string, string | string[] | undefined>;
|
|
510
|
+
body?: string;
|
|
511
|
+
bodyEncoding?: string;
|
|
512
|
+
trailers: Record<string, string>;
|
|
513
|
+
duration: number;
|
|
514
|
+
};
|
|
515
|
+
|
|
516
|
+
/** Options for a cross-endpoint request. */
|
|
517
|
+
export type RequestOptions = {
|
|
518
|
+
/**
|
|
519
|
+
* Run the target's own \`beforeEach\` → \`authorize\` → \`afterEach\` pipeline, so
|
|
520
|
+
* a seeding call behaves like the real run. Default \`true\`; \`false\` is the
|
|
521
|
+
* raw-seeding escape, and the way out of a cycle.
|
|
522
|
+
*/
|
|
523
|
+
runHooks?: boolean;
|
|
524
|
+
/** Force authorization on or off for this call. */
|
|
525
|
+
authorize?: boolean;
|
|
526
|
+
};
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* The typed setters, the file helpers and everything else a hook is handed.
|
|
530
|
+
*
|
|
531
|
+
* Setters write into the same request direct mutation does — a setter is a place
|
|
532
|
+
* for the compiler to know a name and a value type, not a second mechanism.
|
|
533
|
+
*/
|
|
534
|
+
export interface HookUtils<T = unknown> {
|
|
535
|
+
setHeader(name: string, value: string | string[] | undefined): void;
|
|
536
|
+
setQuery(name: string, value: unknown): void;
|
|
537
|
+
setPathParam(name: string, value: unknown): void;
|
|
538
|
+
setCookie(name: string, value: unknown): void;
|
|
539
|
+
setBody(body: unknown): void;
|
|
540
|
+
setAuthorize(authorize: boolean): void;
|
|
541
|
+
|
|
542
|
+
/** Reads a file **beside the hook that asks for it**. */
|
|
543
|
+
readFile(path: string): Uint8Array;
|
|
544
|
+
readText(path: string, encoding?: FileEncoding): string;
|
|
545
|
+
readJson<R = unknown>(path: string): R;
|
|
546
|
+
|
|
547
|
+
skip(message: string): never;
|
|
548
|
+
fail(message: string): never;
|
|
549
|
+
info(message: string): void;
|
|
550
|
+
warn(message: string, details?: string): void;
|
|
551
|
+
assertionSuccess(message: string, assertion?: string): void;
|
|
552
|
+
assertionFailure(
|
|
553
|
+
message: string,
|
|
554
|
+
details?: { assertion?: string; expected?: unknown; actual?: unknown },
|
|
555
|
+
): void;
|
|
556
|
+
timeout(message: string, durationMs: number): void;
|
|
557
|
+
randomString(length?: number): string;
|
|
558
|
+
|
|
559
|
+
/**
|
|
560
|
+
* Call another Transaction, addressed by its Selector.
|
|
561
|
+
*
|
|
562
|
+
* \`args\` overlays the generated request, so state only what differs. The
|
|
563
|
+
* answer is every response that operation declares — branch on
|
|
564
|
+
* \`statusCode\` — because initiating a Transaction is not the same as
|
|
565
|
+
* getting one. There is no \`forStatusCode\`: the Selector carries the status
|
|
566
|
+
* you asked for.
|
|
567
|
+
*/
|
|
568
|
+
request<R extends Selector>(
|
|
569
|
+
selector: R,
|
|
570
|
+
args?: RequestArgsOf<R>,
|
|
571
|
+
options?: RequestOptions,
|
|
572
|
+
): Promise<ResponsesOf<R>>;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* The encodings \`readText\` understands.
|
|
577
|
+
*
|
|
578
|
+
* Spelled out rather than reusing \`BufferEncoding\`, and \`readFile\` answers
|
|
579
|
+
* \`Uint8Array\` rather than \`Buffer\`, so this surface needs no \`@types/node\`.
|
|
580
|
+
* A hook file that imports \`node:fs\` needs it and can add
|
|
581
|
+
* \`"types": ["node"]\` — the scaffolded tsconfig is the author's from the
|
|
582
|
+
* moment it is written.
|
|
583
|
+
*/
|
|
584
|
+
export type FileEncoding =
|
|
585
|
+
| 'utf-8'
|
|
586
|
+
| 'utf8'
|
|
587
|
+
| 'ascii'
|
|
588
|
+
| 'latin1'
|
|
589
|
+
| 'base64'
|
|
590
|
+
| 'base64url'
|
|
591
|
+
| 'hex'
|
|
592
|
+
| 'ucs-2'
|
|
593
|
+
| 'utf-16le';
|
|
594
|
+
|
|
595
|
+
/** What a registration is, opaquely. Export one from a hook file to load it. */
|
|
596
|
+
export type HookRegistration = { readonly __hook: unique symbol };
|
|
597
|
+
|
|
598
|
+
/** What a \`beforeAll\` may return to be run on close. */
|
|
599
|
+
export type CleanupFn = () => void | Promise<void>;
|
|
600
|
+
|
|
601
|
+
/**
|
|
602
|
+
* Shapes the generated request for a Transaction, at generation time.
|
|
603
|
+
*
|
|
604
|
+
* At most one per Transaction: a second is a conflict, reported at load.
|
|
605
|
+
*/
|
|
606
|
+
export declare function defineSample<const T extends HookTarget>(
|
|
607
|
+
target: T,
|
|
608
|
+
callback: (draft: RequestOf<T>, utils: HookUtils<T>) => void,
|
|
609
|
+
): HookRegistration;
|
|
610
|
+
|
|
611
|
+
/** Runs before each request of the targeted Transaction(s). */
|
|
612
|
+
export declare function beforeEach<const T extends HookTarget>(
|
|
613
|
+
target: T,
|
|
614
|
+
callback: (
|
|
615
|
+
request: RequestOf<T>,
|
|
616
|
+
ctx: unknown,
|
|
617
|
+
utils: HookUtils<T>,
|
|
618
|
+
) => void | Promise<void>,
|
|
619
|
+
): HookRegistration;
|
|
620
|
+
|
|
621
|
+
/** Runs after each response of the targeted Transaction(s). */
|
|
622
|
+
export declare function afterEach<const T extends HookTarget>(
|
|
623
|
+
target: T,
|
|
624
|
+
callback: (
|
|
625
|
+
response: ResponseOf<T>,
|
|
626
|
+
ctx: unknown,
|
|
627
|
+
utils: HookUtils<T>,
|
|
628
|
+
) => void | Promise<void>,
|
|
629
|
+
): HookRegistration;
|
|
630
|
+
|
|
631
|
+
/**
|
|
632
|
+
* Supplies credentials. \`authorize(fn)\` is global; \`authorize(target, fn)\` is
|
|
633
|
+
* targeted and wins for the Transactions it covers.
|
|
634
|
+
*
|
|
635
|
+
* Whether it runs is decided by the run option and the request's own
|
|
636
|
+
* \`authorize\` flag, so a registered hook is necessary but not sufficient.
|
|
637
|
+
*/
|
|
638
|
+
export declare function authorize(
|
|
639
|
+
callback: (
|
|
640
|
+
request: GenericRequest,
|
|
641
|
+
ctx: unknown,
|
|
642
|
+
utils: HookUtils,
|
|
643
|
+
) => void | Promise<void>,
|
|
644
|
+
): HookRegistration;
|
|
645
|
+
export declare function authorize<const T extends HookTarget>(
|
|
646
|
+
target: T,
|
|
647
|
+
callback: (
|
|
648
|
+
request: RequestOf<T>,
|
|
649
|
+
ctx: unknown,
|
|
650
|
+
utils: HookUtils<T>,
|
|
651
|
+
) => void | Promise<void>,
|
|
652
|
+
): HookRegistration;
|
|
653
|
+
|
|
654
|
+
/**
|
|
655
|
+
* Runs once before the first request of the run, in registration order. A throw
|
|
656
|
+
* aborts the run. May return a cleanup closure to be run on close.
|
|
657
|
+
*/
|
|
658
|
+
export declare function beforeAll(
|
|
659
|
+
callback: (utils: HookUtils) => void | CleanupFn | Promise<void | CleanupFn>,
|
|
660
|
+
): HookRegistration;
|
|
661
|
+
|
|
662
|
+
/**
|
|
663
|
+
* Runs on close, together with the cleanups \`beforeAll\` returned: one
|
|
664
|
+
* reverse-ordered list, best-effort, and only if the run sent a request.
|
|
665
|
+
*/
|
|
666
|
+
export declare function afterAll(
|
|
667
|
+
callback: (utils: HookUtils) => void | Promise<void>,
|
|
668
|
+
): HookRegistration;
|
|
669
|
+
`;
|
|
670
|
+
}
|
|
671
|
+
//# sourceMappingURL=generate-type-surface.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-type-surface.js","sourceRoot":"","sources":["../../../src/generation/types/generate-type-surface.ts"],"names":[],"mappings":"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"}
|