@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,305 @@
|
|
|
1
|
+
import { canonicalPath, encodeMediaType, encodeMethod, encodePath, errorSuggestions, formatRequestSelector, formatResponseSelector, formatSelector, SELECTOR_METHOD_CHARS, selectorForTransaction, } from '@thymian/core';
|
|
2
|
+
import { malformedSelectorError } from './selector-errors.js';
|
|
3
|
+
/**
|
|
4
|
+
* The selector grammar, plugin side: everything that reads a selector.
|
|
5
|
+
*
|
|
6
|
+
* **Rendering lives in `@thymian/core`** (`selector/render-selector.ts`) and is
|
|
7
|
+
* re-exported here, because a selector is two things at once — the sampler's
|
|
8
|
+
* *address* of a Transaction and the application's *label* for one — and every
|
|
9
|
+
* surface core prints has to render the same grammar the sampler resolves
|
|
10
|
+
* (ADR-0022). What stays here is what only an address needs: parsing back,
|
|
11
|
+
* near-miss diagnostics and the catalog's ordering.
|
|
12
|
+
*
|
|
13
|
+
* The reader below is the inverse of core's encoders. The two are one grammar
|
|
14
|
+
* split across two packages, so the round-trip property — every rendered
|
|
15
|
+
* selector parses, and parses back to what it was rendered from — is the test
|
|
16
|
+
* that keeps them honest.
|
|
17
|
+
*/
|
|
18
|
+
export { canonicalPath, encodeMediaType, encodeMethod, encodePath, formatRequestSelector, formatResponseSelector, formatSelector, selectorForTransaction, };
|
|
19
|
+
const METHOD_TOKEN = new RegExp(`^[${SELECTOR_METHOD_CHARS}]+$`);
|
|
20
|
+
const UPPERCASE_METHOD = new RegExp(`^[A-Z0-9!#$%&'*+.^_\`|~-]+$`);
|
|
21
|
+
/** Reads a quoted component starting at `open`, and says where it ended. */
|
|
22
|
+
function readQuoted(value, open) {
|
|
23
|
+
let content = '';
|
|
24
|
+
for (let i = open + 1; i < value.length; i++) {
|
|
25
|
+
const char = value[i];
|
|
26
|
+
if (char === '\\') {
|
|
27
|
+
const next = value[i + 1];
|
|
28
|
+
if (next === undefined) {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
content += next;
|
|
32
|
+
i++;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (char === '"') {
|
|
36
|
+
return { content, end: i };
|
|
37
|
+
}
|
|
38
|
+
content += char;
|
|
39
|
+
}
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Reads a media group starting at the `(` at `open`, and says where it ended.
|
|
44
|
+
*
|
|
45
|
+
* The inverse of core's media-type encoder: outside a quoted string a `\`
|
|
46
|
+
* escapes the next character and is dropped, a `"` opens quote state, and the
|
|
47
|
+
* first unescaped, unquoted `)` ends the group. Inside a quoted string
|
|
48
|
+
* everything is carried through, quoted-pairs included, because that text is
|
|
49
|
+
* the media type's own.
|
|
50
|
+
*/
|
|
51
|
+
function readMediaGroup(value, open) {
|
|
52
|
+
let content = '';
|
|
53
|
+
let inQuotes = false;
|
|
54
|
+
for (let i = open + 1; i < value.length; i++) {
|
|
55
|
+
const char = value[i];
|
|
56
|
+
if (inQuotes) {
|
|
57
|
+
if (char === '\\' && i + 1 < value.length) {
|
|
58
|
+
content += char + value[i + 1];
|
|
59
|
+
i++;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
if (char === '"') {
|
|
63
|
+
inQuotes = false;
|
|
64
|
+
}
|
|
65
|
+
content += char;
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (char === '\\') {
|
|
69
|
+
const next = value[i + 1];
|
|
70
|
+
if (next === undefined) {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
content += next;
|
|
74
|
+
i++;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (char === '"') {
|
|
78
|
+
inQuotes = true;
|
|
79
|
+
content += char;
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if (char === ')') {
|
|
83
|
+
return { content, end: i };
|
|
84
|
+
}
|
|
85
|
+
content += char;
|
|
86
|
+
}
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Total order on selectors, by UTF-16 code unit.
|
|
91
|
+
*
|
|
92
|
+
* Deliberately not `localeCompare`: the catalog's order is the order of the
|
|
93
|
+
* generated type surface, and a locale-sensitive comparison would make the
|
|
94
|
+
* committed types depend on the machine that generated them.
|
|
95
|
+
*/
|
|
96
|
+
export function compareSelectors(a, b) {
|
|
97
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Splits a selector into its five components.
|
|
101
|
+
*
|
|
102
|
+
* This hand-written reader is the **only** description of the grammar's read
|
|
103
|
+
* direction. An equivalent regex used to sit beside it as a shape test, and the
|
|
104
|
+
* two disagreed: a media type containing a newline rendered into a selector the
|
|
105
|
+
* regex rejected, because `.` excludes line terminators. One grammar, one
|
|
106
|
+
* reader.
|
|
107
|
+
*
|
|
108
|
+
* Returns `undefined` for anything that is not a selector; the caller decides
|
|
109
|
+
* whether that is a diagnostic or a hint attempt.
|
|
110
|
+
*/
|
|
111
|
+
function splitSelector(value) {
|
|
112
|
+
let at = 0;
|
|
113
|
+
const method = readComponent(value, at);
|
|
114
|
+
if (!method) {
|
|
115
|
+
return undefined;
|
|
116
|
+
}
|
|
117
|
+
if (!method.quoted && !METHOD_TOKEN.test(method.content)) {
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
at = method.end;
|
|
121
|
+
if (value[at] !== ' ') {
|
|
122
|
+
return undefined;
|
|
123
|
+
}
|
|
124
|
+
at += 1;
|
|
125
|
+
const path = readComponent(value, at);
|
|
126
|
+
if (!path || !path.content.startsWith('/')) {
|
|
127
|
+
return undefined;
|
|
128
|
+
}
|
|
129
|
+
at = path.end;
|
|
130
|
+
let requestMediaType;
|
|
131
|
+
if (value.startsWith(' (', at)) {
|
|
132
|
+
const group = readMediaGroup(value, at + 1);
|
|
133
|
+
if (!group) {
|
|
134
|
+
return undefined;
|
|
135
|
+
}
|
|
136
|
+
requestMediaType = group.content;
|
|
137
|
+
at = group.end + 1;
|
|
138
|
+
}
|
|
139
|
+
if (!value.startsWith(' -> ', at)) {
|
|
140
|
+
return undefined;
|
|
141
|
+
}
|
|
142
|
+
at += 4;
|
|
143
|
+
const statusEnd = value.indexOf(' ', at);
|
|
144
|
+
const status = value.slice(at, statusEnd === -1 ? undefined : statusEnd);
|
|
145
|
+
if (status.length === 0 || /[\s()]/.test(status)) {
|
|
146
|
+
return undefined;
|
|
147
|
+
}
|
|
148
|
+
let responseMediaType;
|
|
149
|
+
if (statusEnd !== -1) {
|
|
150
|
+
at = statusEnd;
|
|
151
|
+
if (!value.startsWith(' (', at)) {
|
|
152
|
+
return undefined;
|
|
153
|
+
}
|
|
154
|
+
const group = readMediaGroup(value, at + 1);
|
|
155
|
+
if (!group || group.end !== value.length - 1) {
|
|
156
|
+
return undefined;
|
|
157
|
+
}
|
|
158
|
+
responseMediaType = group.content;
|
|
159
|
+
}
|
|
160
|
+
return {
|
|
161
|
+
method: method.content,
|
|
162
|
+
path: path.content,
|
|
163
|
+
requestMediaType,
|
|
164
|
+
status: Number(status),
|
|
165
|
+
responseMediaType,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Reads a method or path: a quoted string when it begins with `"`, otherwise the
|
|
170
|
+
* run of characters up to the next space.
|
|
171
|
+
*/
|
|
172
|
+
function readComponent(value, at) {
|
|
173
|
+
if (at >= value.length) {
|
|
174
|
+
return undefined;
|
|
175
|
+
}
|
|
176
|
+
if (value[at] === '"') {
|
|
177
|
+
const read = readQuoted(value, at);
|
|
178
|
+
return read
|
|
179
|
+
? { content: read.content, end: read.end + 1, quoted: true }
|
|
180
|
+
: undefined;
|
|
181
|
+
}
|
|
182
|
+
const space = value.indexOf(' ', at);
|
|
183
|
+
const end = space === -1 ? value.length : space;
|
|
184
|
+
const content = value.slice(at, end);
|
|
185
|
+
return content.length > 0 ? { content, end, quoted: false } : undefined;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Parses a selector back into its components.
|
|
189
|
+
*
|
|
190
|
+
* For DIAGNOSTICS ONLY. Resolution is a map lookup
|
|
191
|
+
* (`TransactionCatalog.resolve`); a parse happens only after a miss, to decide
|
|
192
|
+
* whether the value was malformed or merely unknown. Do not move a parse onto
|
|
193
|
+
* the happy path.
|
|
194
|
+
*/
|
|
195
|
+
export function parseSelector(value) {
|
|
196
|
+
const parts = splitSelector(value);
|
|
197
|
+
if (!parts) {
|
|
198
|
+
throw malformedSelectorError(value, canonicalFormHint(value));
|
|
199
|
+
}
|
|
200
|
+
return parts;
|
|
201
|
+
}
|
|
202
|
+
/** Whether `value` is a syntactically well-formed selector. */
|
|
203
|
+
export function isSelector(value) {
|
|
204
|
+
return splitSelector(value) !== undefined;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* The suggestions a malformed selector's diagnostic carries — the grammar,
|
|
208
|
+
* an example, and a canonical-form guess when the value is close. Never
|
|
209
|
+
* throws.
|
|
210
|
+
*
|
|
211
|
+
* Reads `malformedSelectorError`'s own message composition rather than
|
|
212
|
+
* duplicating it, so a hook-target diagnostic for a malformed Selector and
|
|
213
|
+
* the error `catalog.resolve` throws for one typed on the CLI say exactly the
|
|
214
|
+
* same thing — one grammar, one set of hints, two call sites.
|
|
215
|
+
*/
|
|
216
|
+
export function malformedSelectorHints(value) {
|
|
217
|
+
return errorSuggestions(malformedSelectorError(value, canonicalFormHint(value)));
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* The grammar relaxed on exactly the three axes a hand-authored selector slips
|
|
221
|
+
* on — method case, the leading slash, and a zero-padded status. Used ONLY to
|
|
222
|
+
* turn a rejection into a "did you mean …?" suggestion; it never decides whether
|
|
223
|
+
* a selector is valid.
|
|
224
|
+
*/
|
|
225
|
+
const LENIENT_SHAPE = new RegExp(`^([${SELECTOR_METHOD_CHARS}]+) (\\S+)(?: \\(([^()]*)\\))? -> (\\d+)(?: \\(([^()]*)\\))?$`);
|
|
226
|
+
/**
|
|
227
|
+
* Whether prepending the missing leading slash would be a correction rather than
|
|
228
|
+
* an invention. Without this the hint manufactures paths out of URLs.
|
|
229
|
+
*
|
|
230
|
+
* A path that merely lost its slash begins with a path *segment*, so the
|
|
231
|
+
* judgement is made on the first segment alone: a `:` there is a scheme or an
|
|
232
|
+
* authority port, a `.` there is a host label or a relative-path marker, and a
|
|
233
|
+
* leading `(`, `?` or `#` is a media type, query string or fragment promoted
|
|
234
|
+
* into the path slot. Judging only the first segment keeps a legal slash-less
|
|
235
|
+
* path such as `users/{id}:activate` eligible.
|
|
236
|
+
*/
|
|
237
|
+
function canonicalizablePath(path) {
|
|
238
|
+
if (path.startsWith('/')) {
|
|
239
|
+
return true;
|
|
240
|
+
}
|
|
241
|
+
if (/^[(?#]/.test(path)) {
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
const firstSegment = path.split('/', 1)[0] ?? path;
|
|
245
|
+
return !(firstSegment.includes(':') || firstSegment.includes('.'));
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Strips a status's zero padding, but only when what is left is a status code —
|
|
249
|
+
* three digits, per RFC 9110 §15. Reinterpreting through `Number` instead would
|
|
250
|
+
* turn `007` into `7`, suggesting a selector no transaction can carry.
|
|
251
|
+
*/
|
|
252
|
+
function canonicalStatus(status) {
|
|
253
|
+
const stripped = status.replace(/^0+/, '');
|
|
254
|
+
return /^[1-9]\d\d$/.test(stripped) ? stripped : status;
|
|
255
|
+
}
|
|
256
|
+
function joinWithAnd(items) {
|
|
257
|
+
if (items.length < 2) {
|
|
258
|
+
return items.join('');
|
|
259
|
+
}
|
|
260
|
+
return `${items.slice(0, -1).join(', ')} and ${items[items.length - 1] ?? ''}`;
|
|
261
|
+
}
|
|
262
|
+
/** States only the corrections the hint actually made. */
|
|
263
|
+
function describeNormalizations(method, path, status) {
|
|
264
|
+
const rules = [];
|
|
265
|
+
if (!UPPERCASE_METHOD.test(method)) {
|
|
266
|
+
rules.push('spells its method in uppercase');
|
|
267
|
+
}
|
|
268
|
+
if (!path.startsWith('/')) {
|
|
269
|
+
rules.push('spells its path with a leading "/"');
|
|
270
|
+
}
|
|
271
|
+
if (canonicalStatus(status) !== status) {
|
|
272
|
+
rules.push('spells its status without leading zeros');
|
|
273
|
+
}
|
|
274
|
+
return rules.length > 0 ? `A selector ${joinWithAnd(rules)}. ` : '';
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Suggests the canonical spelling of a value that is *nearly* a selector:
|
|
278
|
+
* lowercase method, missing leading slash, zero-padded status. Returns nothing
|
|
279
|
+
* when the value is not recognizable or already canonical.
|
|
280
|
+
*/
|
|
281
|
+
function canonicalFormHint(value) {
|
|
282
|
+
const match = LENIENT_SHAPE.exec(value);
|
|
283
|
+
if (!match) {
|
|
284
|
+
return [];
|
|
285
|
+
}
|
|
286
|
+
const method = match[1];
|
|
287
|
+
const path = match[2];
|
|
288
|
+
const status = match[4];
|
|
289
|
+
if (method === undefined || path === undefined || status === undefined) {
|
|
290
|
+
return [];
|
|
291
|
+
}
|
|
292
|
+
if (!canonicalizablePath(path)) {
|
|
293
|
+
return [];
|
|
294
|
+
}
|
|
295
|
+
const requestMedia = match[3] ? ` (${match[3]})` : '';
|
|
296
|
+
const responseMedia = match[5] ? ` (${match[5]})` : '';
|
|
297
|
+
const canonical = `${method.toUpperCase()} ${encodePath(path)}${requestMedia} -> ${canonicalStatus(status)}${responseMedia}`;
|
|
298
|
+
if (canonical === value || !isSelector(canonical)) {
|
|
299
|
+
return [];
|
|
300
|
+
}
|
|
301
|
+
return [
|
|
302
|
+
`${describeNormalizations(method, path, status)}Did you mean "${canonical}"?`,
|
|
303
|
+
];
|
|
304
|
+
}
|
|
305
|
+
//# sourceMappingURL=selector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selector.js","sourceRoot":"","sources":["../../src/selectors/selector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { ThymianFormat, ThymianHttpTransaction } from '@thymian/core';
|
|
2
|
+
import { type Selector, type SelectorParts } from './selector.js';
|
|
3
|
+
export type TransactionCatalogEntry = readonly [
|
|
4
|
+
Selector,
|
|
5
|
+
ThymianHttpTransaction
|
|
6
|
+
];
|
|
7
|
+
/**
|
|
8
|
+
* A bijection between the selectors of a loaded `ThymianFormat` and its
|
|
9
|
+
* transactions.
|
|
10
|
+
*
|
|
11
|
+
* Built once per format load and thrown away with the format — it is cheap, and
|
|
12
|
+
* caching it on `format.toHash()` would reintroduce exactly the staleness the
|
|
13
|
+
* selector exists to remove.
|
|
14
|
+
*/
|
|
15
|
+
export declare class TransactionCatalog {
|
|
16
|
+
private readonly bySelector;
|
|
17
|
+
private readonly orderedEntries;
|
|
18
|
+
private readonly selectorByTransactionId;
|
|
19
|
+
private readonly distinctPaths;
|
|
20
|
+
private readonly byOperation;
|
|
21
|
+
private constructor();
|
|
22
|
+
/**
|
|
23
|
+
* One pass over `format.getThymianHttpTransactions()`, then a sort.
|
|
24
|
+
*
|
|
25
|
+
* @throws `SelectorCollisionError` as soon as two transactions render the same
|
|
26
|
+
* selector. That is the only hard error here. Rendering is total and
|
|
27
|
+
* injective, so no description can make catalog construction impossible and no
|
|
28
|
+
* two *distinct* transactions can collide by accident of encoding: a collision
|
|
29
|
+
* means two sources describe the same method, path, status and media types,
|
|
30
|
+
* and a selector is host-stripped, so nothing distinguishes them. Silently
|
|
31
|
+
* picking one would make a hook target whichever load order won.
|
|
32
|
+
*/
|
|
33
|
+
static fromThymianFormat(format: ThymianFormat): TransactionCatalog;
|
|
34
|
+
get size(): number;
|
|
35
|
+
/**
|
|
36
|
+
* Selectors sorted by selector.
|
|
37
|
+
*
|
|
38
|
+
* The order is a decision, not an accident: it is the order the generated type
|
|
39
|
+
* surface is emitted in, so sorting is what makes reordering paths or schemas
|
|
40
|
+
* in the source document a drift non-event. Correctness never depends on it.
|
|
41
|
+
*/
|
|
42
|
+
selectors(): readonly Selector[];
|
|
43
|
+
entries(): readonly TransactionCatalogEntry[];
|
|
44
|
+
/**
|
|
45
|
+
* Every distinct path the catalog holds, sorted — the universe a path glob is
|
|
46
|
+
* matched against, and the set a vacuous glob fails against.
|
|
47
|
+
*
|
|
48
|
+
* Derived once at construction, like the selector index: both are read once
|
|
49
|
+
* per hook that targets by filter, and the catalog is rebuilt per format load
|
|
50
|
+
* anyway.
|
|
51
|
+
*/
|
|
52
|
+
paths(): readonly string[];
|
|
53
|
+
/**
|
|
54
|
+
* Every Transaction the same operation declares — the responses a call to
|
|
55
|
+
* `transaction` may legitimately be answered with.
|
|
56
|
+
*
|
|
57
|
+
* Grouped by the **request half of the selector**, which is what the
|
|
58
|
+
* generated `Responses` map is keyed by, so the union the types promise and
|
|
59
|
+
* the set the runtime checks against are built by one rule. Two sources
|
|
60
|
+
* describing the same operation contribute to one group; that is a superset,
|
|
61
|
+
* and a superset is the safe direction — it never calls a declared response
|
|
62
|
+
* undeclared.
|
|
63
|
+
*/
|
|
64
|
+
responsesOf(transaction: ThymianHttpTransaction): readonly TransactionCatalogEntry[];
|
|
65
|
+
/** The selector one transaction renders as, for a diagnostic that has the id. */
|
|
66
|
+
selectorFor(transactionId: string): Selector | undefined;
|
|
67
|
+
/** Every Transaction, in catalog order. */
|
|
68
|
+
transactions(): readonly ThymianHttpTransaction[];
|
|
69
|
+
/** Never throws. Use where a miss is an expected outcome. */
|
|
70
|
+
tryResolve(selector: string): ThymianHttpTransaction | undefined;
|
|
71
|
+
/**
|
|
72
|
+
* A plain map lookup. Parsing happens only after a miss, to tell the caller
|
|
73
|
+
* whether the selector was malformed or merely unknown — never on the happy
|
|
74
|
+
* path.
|
|
75
|
+
*
|
|
76
|
+
* @throws `MalformedSelectorError` when the input is not a selector,
|
|
77
|
+
* `UnknownSelectorError` when it is well-formed but names nothing loaded.
|
|
78
|
+
*/
|
|
79
|
+
resolve(selector: string): ThymianHttpTransaction;
|
|
80
|
+
/**
|
|
81
|
+
* What to say to someone who named a selector nothing answers to.
|
|
82
|
+
*
|
|
83
|
+
* Public because the hook loader needs the same sentences without wanting the
|
|
84
|
+
* throw: it has already missed through {@link tryResolve}, and asking for the
|
|
85
|
+
* diagnostic by catching a second, deliberately failing lookup would make the
|
|
86
|
+
* error channel do the work of a query.
|
|
87
|
+
*/
|
|
88
|
+
nearMissSuggestions(parts: SelectorParts): string[];
|
|
89
|
+
/**
|
|
90
|
+
* Deterministic rank buckets, in catalog order: same method and path first,
|
|
91
|
+
* then the same path under another method. No fuzzy matching — it would add a
|
|
92
|
+
* dependency and make the ordering unexplainable.
|
|
93
|
+
*/
|
|
94
|
+
private nearMisses;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=transaction-catalog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction-catalog.d.ts","sourceRoot":"","sources":["../../src/selectors/transaction-catalog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAG3E,OAAO,EAML,KAAK,QAAQ,EAEb,KAAK,aAAa,EACnB,MAAM,eAAe,CAAC;AASvB,MAAM,MAAM,uBAAuB,GAAG,SAAS;IAC7C,QAAQ;IACR,sBAAsB;CACvB,CAAC;AAEF;;;;;;;GAOG;AACH,qBAAa,kBAAkB;IAE3B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,uBAAuB;IACxC,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAL9B,OAAO;IAWP;;;;;;;;;;OAUG;IACH,MAAM,CAAC,iBAAiB,CAAC,MAAM,EAAE,aAAa,GAAG,kBAAkB;IA+CnE,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;;;;;OAMG;IACH,SAAS,IAAI,SAAS,QAAQ,EAAE;IAIhC,OAAO,IAAI,SAAS,uBAAuB,EAAE;IAI7C;;;;;;;OAOG;IACH,KAAK,IAAI,SAAS,MAAM,EAAE;IAI1B;;;;;;;;;;OAUG;IACH,WAAW,CACT,WAAW,EAAE,sBAAsB,GAClC,SAAS,uBAAuB,EAAE;IAMrC,iFAAiF;IACjF,WAAW,CAAC,aAAa,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS;IAIxD,2CAA2C;IAC3C,YAAY,IAAI,SAAS,sBAAsB,EAAE;IAIjD,6DAA6D;IAC7D,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,sBAAsB,GAAG,SAAS;IAIhE;;;;;;;OAOG;IACH,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,sBAAsB;IAajD;;;;;;;OAOG;IACH,mBAAmB,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,EAAE;IAgCnD;;;;OAIG;IACH,OAAO,CAAC,UAAU;CAmBnB"}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { nearestPathHints } from './nearest-paths.js';
|
|
2
|
+
import { canonicalPath, compareSelectors, encodePath, formatRequestSelector, parseSelector, selectorForTransaction, } from './selector.js';
|
|
3
|
+
import { selectorCollisionError, unknownSelectorError, } from './selector-errors.js';
|
|
4
|
+
import { pathOf } from './transaction-filter.js';
|
|
5
|
+
const MAX_NEAR_MISSES = 5;
|
|
6
|
+
/**
|
|
7
|
+
* A bijection between the selectors of a loaded `ThymianFormat` and its
|
|
8
|
+
* transactions.
|
|
9
|
+
*
|
|
10
|
+
* Built once per format load and thrown away with the format — it is cheap, and
|
|
11
|
+
* caching it on `format.toHash()` would reintroduce exactly the staleness the
|
|
12
|
+
* selector exists to remove.
|
|
13
|
+
*/
|
|
14
|
+
export class TransactionCatalog {
|
|
15
|
+
bySelector;
|
|
16
|
+
orderedEntries;
|
|
17
|
+
selectorByTransactionId;
|
|
18
|
+
distinctPaths;
|
|
19
|
+
byOperation;
|
|
20
|
+
constructor(bySelector, orderedEntries, selectorByTransactionId, distinctPaths, byOperation) {
|
|
21
|
+
this.bySelector = bySelector;
|
|
22
|
+
this.orderedEntries = orderedEntries;
|
|
23
|
+
this.selectorByTransactionId = selectorByTransactionId;
|
|
24
|
+
this.distinctPaths = distinctPaths;
|
|
25
|
+
this.byOperation = byOperation;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* One pass over `format.getThymianHttpTransactions()`, then a sort.
|
|
29
|
+
*
|
|
30
|
+
* @throws `SelectorCollisionError` as soon as two transactions render the same
|
|
31
|
+
* selector. That is the only hard error here. Rendering is total and
|
|
32
|
+
* injective, so no description can make catalog construction impossible and no
|
|
33
|
+
* two *distinct* transactions can collide by accident of encoding: a collision
|
|
34
|
+
* means two sources describe the same method, path, status and media types,
|
|
35
|
+
* and a selector is host-stripped, so nothing distinguishes them. Silently
|
|
36
|
+
* picking one would make a hook target whichever load order won.
|
|
37
|
+
*/
|
|
38
|
+
static fromThymianFormat(format) {
|
|
39
|
+
const bySelector = new Map();
|
|
40
|
+
for (const transaction of format.getThymianHttpTransactions()) {
|
|
41
|
+
const selector = selectorForTransaction(transaction);
|
|
42
|
+
const existing = bySelector.get(selector);
|
|
43
|
+
if (existing) {
|
|
44
|
+
throw selectorCollisionError(selector, existing, transaction);
|
|
45
|
+
}
|
|
46
|
+
bySelector.set(selector, transaction);
|
|
47
|
+
}
|
|
48
|
+
const orderedEntries = [...bySelector.entries()]
|
|
49
|
+
.sort(([a], [b]) => compareSelectors(a, b))
|
|
50
|
+
.map(([selector, transaction]) => [selector, transaction]);
|
|
51
|
+
const byOperation = new Map();
|
|
52
|
+
for (const entry of orderedEntries) {
|
|
53
|
+
const operation = formatRequestSelector(entry[1].thymianReq);
|
|
54
|
+
byOperation.set(operation, [
|
|
55
|
+
...(byOperation.get(operation) ?? []),
|
|
56
|
+
entry,
|
|
57
|
+
]);
|
|
58
|
+
}
|
|
59
|
+
return new TransactionCatalog(bySelector, orderedEntries, new Map(orderedEntries.map(([selector, transaction]) => [
|
|
60
|
+
transaction.transactionId,
|
|
61
|
+
selector,
|
|
62
|
+
])), [
|
|
63
|
+
...new Set(orderedEntries.map(([, transaction]) => pathOf(transaction))),
|
|
64
|
+
].sort(), byOperation);
|
|
65
|
+
}
|
|
66
|
+
get size() {
|
|
67
|
+
return this.bySelector.size;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Selectors sorted by selector.
|
|
71
|
+
*
|
|
72
|
+
* The order is a decision, not an accident: it is the order the generated type
|
|
73
|
+
* surface is emitted in, so sorting is what makes reordering paths or schemas
|
|
74
|
+
* in the source document a drift non-event. Correctness never depends on it.
|
|
75
|
+
*/
|
|
76
|
+
selectors() {
|
|
77
|
+
return this.orderedEntries.map(([selector]) => selector);
|
|
78
|
+
}
|
|
79
|
+
entries() {
|
|
80
|
+
return this.orderedEntries;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Every distinct path the catalog holds, sorted — the universe a path glob is
|
|
84
|
+
* matched against, and the set a vacuous glob fails against.
|
|
85
|
+
*
|
|
86
|
+
* Derived once at construction, like the selector index: both are read once
|
|
87
|
+
* per hook that targets by filter, and the catalog is rebuilt per format load
|
|
88
|
+
* anyway.
|
|
89
|
+
*/
|
|
90
|
+
paths() {
|
|
91
|
+
return this.distinctPaths;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Every Transaction the same operation declares — the responses a call to
|
|
95
|
+
* `transaction` may legitimately be answered with.
|
|
96
|
+
*
|
|
97
|
+
* Grouped by the **request half of the selector**, which is what the
|
|
98
|
+
* generated `Responses` map is keyed by, so the union the types promise and
|
|
99
|
+
* the set the runtime checks against are built by one rule. Two sources
|
|
100
|
+
* describing the same operation contribute to one group; that is a superset,
|
|
101
|
+
* and a superset is the safe direction — it never calls a declared response
|
|
102
|
+
* undeclared.
|
|
103
|
+
*/
|
|
104
|
+
responsesOf(transaction) {
|
|
105
|
+
return (this.byOperation.get(formatRequestSelector(transaction.thymianReq)) ?? []);
|
|
106
|
+
}
|
|
107
|
+
/** The selector one transaction renders as, for a diagnostic that has the id. */
|
|
108
|
+
selectorFor(transactionId) {
|
|
109
|
+
return this.selectorByTransactionId.get(transactionId);
|
|
110
|
+
}
|
|
111
|
+
/** Every Transaction, in catalog order. */
|
|
112
|
+
transactions() {
|
|
113
|
+
return this.orderedEntries.map(([, transaction]) => transaction);
|
|
114
|
+
}
|
|
115
|
+
/** Never throws. Use where a miss is an expected outcome. */
|
|
116
|
+
tryResolve(selector) {
|
|
117
|
+
return this.bySelector.get(selector);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* A plain map lookup. Parsing happens only after a miss, to tell the caller
|
|
121
|
+
* whether the selector was malformed or merely unknown — never on the happy
|
|
122
|
+
* path.
|
|
123
|
+
*
|
|
124
|
+
* @throws `MalformedSelectorError` when the input is not a selector,
|
|
125
|
+
* `UnknownSelectorError` when it is well-formed but names nothing loaded.
|
|
126
|
+
*/
|
|
127
|
+
resolve(selector) {
|
|
128
|
+
const transaction = this.bySelector.get(selector);
|
|
129
|
+
if (transaction) {
|
|
130
|
+
return transaction;
|
|
131
|
+
}
|
|
132
|
+
throw unknownSelectorError(selector, this.nearMissSuggestions(parseSelector(selector)));
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* What to say to someone who named a selector nothing answers to.
|
|
136
|
+
*
|
|
137
|
+
* Public because the hook loader needs the same sentences without wanting the
|
|
138
|
+
* throw: it has already missed through {@link tryResolve}, and asking for the
|
|
139
|
+
* diagnostic by catching a second, deliberately failing lookup would make the
|
|
140
|
+
* error channel do the work of a query.
|
|
141
|
+
*/
|
|
142
|
+
nearMissSuggestions(parts) {
|
|
143
|
+
// An empty catalog is a state core explicitly warns about ("No nodes found
|
|
144
|
+
// in Thymian format"). Sending the user after a path typo would be wrong
|
|
145
|
+
// advice: no path would have resolved.
|
|
146
|
+
if (this.size === 0) {
|
|
147
|
+
return [
|
|
148
|
+
'No transactions are loaded, so no selector can resolve. Check that your configured specifications were found and describe at least one operation.',
|
|
149
|
+
];
|
|
150
|
+
}
|
|
151
|
+
const candidates = this.nearMisses(parts);
|
|
152
|
+
if (candidates.length > 0) {
|
|
153
|
+
return [
|
|
154
|
+
'Did you mean one of these selectors?',
|
|
155
|
+
...candidates.map((candidate) => `"${candidate}"`),
|
|
156
|
+
];
|
|
157
|
+
}
|
|
158
|
+
// No transaction shares this exact path under any method, so the typo is
|
|
159
|
+
// most likely in the path itself. Falls back to the same prefix walk a
|
|
160
|
+
// vacuous filter path value gets, so a path typo in a Selector is
|
|
161
|
+
// diagnosed the same way one in a filter is — one near-miss story, not
|
|
162
|
+
// two that could disagree.
|
|
163
|
+
// `canonicalPath`, matching how `distinctPaths` is spelled (`pathOf`).
|
|
164
|
+
// `encodePath` adds selector quoting for a path carrying whitespace or
|
|
165
|
+
// `>`, and a quoted needle never prefix-matches an unquoted haystack — so
|
|
166
|
+
// exactly the paths whose spelling is hardest to guess got no suggestion
|
|
167
|
+
// and fell through to the bare "no path begins with" line.
|
|
168
|
+
return nearestPathHints(canonicalPath(parts.path), this.distinctPaths);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Deterministic rank buckets, in catalog order: same method and path first,
|
|
172
|
+
* then the same path under another method. No fuzzy matching — it would add a
|
|
173
|
+
* dependency and make the ordering unexplainable.
|
|
174
|
+
*/
|
|
175
|
+
nearMisses(parts) {
|
|
176
|
+
const sameMethod = [];
|
|
177
|
+
const otherMethod = [];
|
|
178
|
+
const path = encodePath(parts.path);
|
|
179
|
+
for (const [selector, transaction] of this.orderedEntries) {
|
|
180
|
+
if (encodePath(transaction.thymianReq.path) !== path) {
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
if (transaction.thymianReq.method.toUpperCase() === parts.method) {
|
|
184
|
+
sameMethod.push(selector);
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
otherMethod.push(selector);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return [...sameMethod, ...otherMethod].slice(0, MAX_NEAR_MISSES);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=transaction-catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction-catalog.js","sourceRoot":"","sources":["../../src/selectors/transaction-catalog.ts"],"names":[],"mappings":"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"}
|