@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 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-targeting.d.ts","sourceRoot":"","sources":["../../src/hooks/resolve-targeting.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAU5D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAS9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAsBlE;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,OAAO,EACf,KAAK,EAAE,qBAAqB,EAC5B,OAAO,EAAE,kBAAkB,EAC3B,WAAW,EAAE,cAAc,EAAE,GAC5B,SAAS,sBAAsB,EAAE,CAkBnC"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { nearestPathHints } from '../selectors/nearest-paths.js';
|
|
2
|
+
import { hasWildcard, matchesPathGlob } from '../selectors/path-glob.js';
|
|
3
|
+
import { isSelector, malformedSelectorHints, parseSelector, } from '../selectors/selector.js';
|
|
4
|
+
import { emptyValueFields, filterProblems, isTransactionFilter, matchesTransactionFilter, pathValuesOf, } from '../selectors/transaction-filter.js';
|
|
5
|
+
/**
|
|
6
|
+
* The selectors a target names, or `undefined` when it is not a selector form.
|
|
7
|
+
*
|
|
8
|
+
* Takes `unknown` rather than a target type: a `.js` hook file is legal input
|
|
9
|
+
* and is not type-checked, so the value here is whatever the user passed.
|
|
10
|
+
*/
|
|
11
|
+
function selectorsOf(target) {
|
|
12
|
+
if (typeof target === 'string') {
|
|
13
|
+
return [target];
|
|
14
|
+
}
|
|
15
|
+
if (Array.isArray(target) && target.every((v) => typeof v === 'string')) {
|
|
16
|
+
return target;
|
|
17
|
+
}
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The Transactions a target covers, reporting whatever stops it covering any.
|
|
22
|
+
*
|
|
23
|
+
* A target that resolves to nothing is a diagnostic, never an empty result that
|
|
24
|
+
* runs quietly. There are four ways a hook can silently stop doing its job — a
|
|
25
|
+
* dangling Selector, a value that is not a legal filter value, a path or glob
|
|
26
|
+
* that names nothing, and a filter whose legal values intersect nothing — and
|
|
27
|
+
* each one gets its own sentence, because "this matched nothing" is true and
|
|
28
|
+
* useless when the cause is one typo.
|
|
29
|
+
*/
|
|
30
|
+
export function resolveTargeting(kind, target, entry, catalog, diagnostics) {
|
|
31
|
+
const where = { file: entry.file, exportName: entry.exportName };
|
|
32
|
+
const selectors = selectorsOf(target);
|
|
33
|
+
if (selectors) {
|
|
34
|
+
return resolveSelectors(kind, selectors, where, catalog, diagnostics);
|
|
35
|
+
}
|
|
36
|
+
if (isTransactionFilter(target)) {
|
|
37
|
+
return resolveFilter(kind, target, where, catalog, diagnostics);
|
|
38
|
+
}
|
|
39
|
+
diagnostics.push({
|
|
40
|
+
...where,
|
|
41
|
+
reason: `${kind} was given a target that is neither a selector, a list of selectors, nor a transaction filter`,
|
|
42
|
+
});
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
function resolveSelectors(kind, selectors, where, catalog, diagnostics) {
|
|
46
|
+
if (selectors.length === 0) {
|
|
47
|
+
diagnostics.push({
|
|
48
|
+
...where,
|
|
49
|
+
reason: `${kind} was given an empty list of selectors, so it targets nothing`,
|
|
50
|
+
});
|
|
51
|
+
return [];
|
|
52
|
+
}
|
|
53
|
+
const resolved = [];
|
|
54
|
+
// Naming one transaction twice targets it once.
|
|
55
|
+
//
|
|
56
|
+
// Composing lists is the ordinary way to build a target —
|
|
57
|
+
// `beforeEach([...PUBLIC, ...ADMIN], fn)` — and one transaction in both
|
|
58
|
+
// halves is a duplicate the author cannot see. Bound twice, the hook runs
|
|
59
|
+
// twice per request, and a `defineSample` written that way reports a
|
|
60
|
+
// conflict against itself.
|
|
61
|
+
const bound = new Set();
|
|
62
|
+
for (const selector of selectors) {
|
|
63
|
+
const transaction = catalog.tryResolve(selector);
|
|
64
|
+
if (transaction) {
|
|
65
|
+
if (!bound.has(transaction.transactionId)) {
|
|
66
|
+
bound.add(transaction.transactionId);
|
|
67
|
+
resolved.push(transaction);
|
|
68
|
+
}
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
// A target is user input like any other, and a hand-authored selector can
|
|
72
|
+
// fail to even parse — never thrown from here, or a single typo'd target
|
|
73
|
+
// would crash `validate`, `show` and `sync` instead of being recorded
|
|
74
|
+
// against the hook that carries it. `isSelector` is what tells "malformed"
|
|
75
|
+
// apart from "well-formed but unknown", which decides whether a grammar
|
|
76
|
+
// hint or a near-miss is the useful thing to say.
|
|
77
|
+
if (!isSelector(selector)) {
|
|
78
|
+
diagnostics.push({
|
|
79
|
+
...where,
|
|
80
|
+
reason: `${kind} targets "${selector}", which is not a valid transaction selector`,
|
|
81
|
+
suggestions: malformedSelectorHints(selector),
|
|
82
|
+
});
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
diagnostics.push({
|
|
86
|
+
...where,
|
|
87
|
+
reason: `${kind} targets the selector "${selector}", which names no transaction in the loaded API description`,
|
|
88
|
+
suggestions: catalog.nearMissSuggestions(parseSelector(selector)),
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
return resolved;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* The Transactions a filter covers.
|
|
95
|
+
*
|
|
96
|
+
* Faults are reported in the order they stop mattering: a filter whose text
|
|
97
|
+
* cannot mean anything is not asked what it matches, an empty value array is
|
|
98
|
+
* named before the catalog is even consulted, and a vacuous path value is
|
|
99
|
+
* named individually before the filter as a whole is called empty.
|
|
100
|
+
*/
|
|
101
|
+
function resolveFilter(kind, filter, where, catalog, diagnostics) {
|
|
102
|
+
const problems = filterProblems(filter);
|
|
103
|
+
if (problems.length > 0) {
|
|
104
|
+
diagnostics.push({
|
|
105
|
+
...where,
|
|
106
|
+
reason: `${kind} was given a filter that cannot mean anything: ${problems.join('; ')}`,
|
|
107
|
+
});
|
|
108
|
+
return [];
|
|
109
|
+
}
|
|
110
|
+
// A field given an explicit, empty value array is a shape the grammar
|
|
111
|
+
// accepts — it is not a "cannot mean anything" fault — but it is a
|
|
112
|
+
// disjunction of zero alternatives, which matches nothing by construction.
|
|
113
|
+
// Named here, the same way an empty list of selectors is: a hook must never
|
|
114
|
+
// silently apply to every Transaction because a computed array came back
|
|
115
|
+
// empty.
|
|
116
|
+
const emptyFields = emptyValueFields(filter);
|
|
117
|
+
if (emptyFields.length > 0) {
|
|
118
|
+
const plural = emptyFields.length > 1;
|
|
119
|
+
const names = emptyFields.map((name) => `"${name}"`).join(', ');
|
|
120
|
+
diagnostics.push({
|
|
121
|
+
...where,
|
|
122
|
+
reason: `${kind} targets a filter whose ${plural ? 'fields' : 'field'} ${names} ${plural ? 'were' : 'was'} given an empty list of values, so it targets nothing`,
|
|
123
|
+
});
|
|
124
|
+
return [];
|
|
125
|
+
}
|
|
126
|
+
const paths = catalog.paths();
|
|
127
|
+
if (paths.length === 0) {
|
|
128
|
+
diagnostics.push({
|
|
129
|
+
...where,
|
|
130
|
+
reason: `${kind} targets a filter, but no transactions are loaded, so no filter can match`,
|
|
131
|
+
suggestions: [
|
|
132
|
+
'Check that your configured specifications were found and describe at least one operation.',
|
|
133
|
+
],
|
|
134
|
+
});
|
|
135
|
+
return [];
|
|
136
|
+
}
|
|
137
|
+
let vacuous = false;
|
|
138
|
+
for (const value of pathValuesOf(filter)) {
|
|
139
|
+
if (paths.some((path) => matchesPathGlob(value, path))) {
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
vacuous = true;
|
|
143
|
+
diagnostics.push({
|
|
144
|
+
...where,
|
|
145
|
+
reason: hasWildcard(value)
|
|
146
|
+
? `${kind} targets the path glob "${value}", which matches no path in the loaded API description`
|
|
147
|
+
: `${kind} targets the path "${value}", which no path in the loaded API description is spelled as`,
|
|
148
|
+
suggestions: nearestPathHints(value, paths),
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
if (vacuous) {
|
|
152
|
+
return [];
|
|
153
|
+
}
|
|
154
|
+
const matched = catalog
|
|
155
|
+
.transactions()
|
|
156
|
+
.filter((transaction) => matchesTransactionFilter(filter, transaction));
|
|
157
|
+
if (matched.length === 0) {
|
|
158
|
+
diagnostics.push({
|
|
159
|
+
...where,
|
|
160
|
+
reason: `${kind} targets a filter whose values are all valid but intersect no transaction in the loaded API description`,
|
|
161
|
+
suggestions: [
|
|
162
|
+
'Every field of a filter must hold at the same time, so check whether the combination can exist — a method and a status that never occur together, for example.',
|
|
163
|
+
],
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
return matched;
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=resolve-targeting.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-targeting.js","sourceRoot":"","sources":["../../src/hooks/resolve-targeting.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { Logger } from '@thymian/core';
|
|
2
|
+
import type { HookUtilsFactory } from './hook-utils-factory.js';
|
|
3
|
+
import type { CollectedRegistration } from './load-user-hooks.js';
|
|
4
|
+
/**
|
|
5
|
+
* The run-scoped half of the lifecycle: `beforeAll` on a first-touch latch, and
|
|
6
|
+
* `afterAll` plus any cleanups `beforeAll` returned, on close.
|
|
7
|
+
*
|
|
8
|
+
* "Once before the run" has no meaning until something decides when the run
|
|
9
|
+
* starts, and the sampler's first observation of a run is the first request. So
|
|
10
|
+
* the latch is armed by the first `beforeRequest`, and it is also what gates
|
|
11
|
+
* teardown: a command that never sends a request — `sampler show`, `sampler
|
|
12
|
+
* init` — must not run somebody's teardown.
|
|
13
|
+
*/
|
|
14
|
+
export declare class RunScopedHooks {
|
|
15
|
+
private readonly logger;
|
|
16
|
+
private readonly makeUtils;
|
|
17
|
+
private beforeAll;
|
|
18
|
+
private teardown;
|
|
19
|
+
/**
|
|
20
|
+
* The latch itself: `undefined` until the first `beforeRequest` arms it,
|
|
21
|
+
* then the one setup run every caller — sequential or concurrent — awaits.
|
|
22
|
+
*
|
|
23
|
+
* A memoized promise rather than a boolean, because a boolean only answers
|
|
24
|
+
* "has setup started", and under concurrent dispatch a second caller can
|
|
25
|
+
* observe that answer before the first caller's `beforeAll` has finished (or
|
|
26
|
+
* failed). Memoizing the promise itself means every caller awaits the same
|
|
27
|
+
* settlement: nobody's request proceeds until setup resolves, and if it
|
|
28
|
+
* rejects, every caller — however many raced in — rejects with it.
|
|
29
|
+
*/
|
|
30
|
+
private startPromise;
|
|
31
|
+
constructor(logger: Logger, makeUtils: HookUtilsFactory);
|
|
32
|
+
/**
|
|
33
|
+
* Adopt newly loaded hooks.
|
|
34
|
+
*
|
|
35
|
+
* A reload drops teardown that the previous load's `beforeAll` registered. It
|
|
36
|
+
* has to: those closures were built against a format that is no longer
|
|
37
|
+
* loaded, and running them later would tear down a fixture whose description
|
|
38
|
+
* has changed underneath. A reload mid-run is not a shape the CLI produces.
|
|
39
|
+
*/
|
|
40
|
+
load(hooks: {
|
|
41
|
+
beforeAll: readonly CollectedRegistration[];
|
|
42
|
+
afterAll: readonly CollectedRegistration[];
|
|
43
|
+
}): void;
|
|
44
|
+
/**
|
|
45
|
+
* Arm the latch and run `beforeAll` in registration order, once — memoized as
|
|
46
|
+
* a promise, so every caller (sequential or concurrent) awaits the very same
|
|
47
|
+
* setup run instead of each independently checking whether one already
|
|
48
|
+
* started.
|
|
49
|
+
*
|
|
50
|
+
* The assignment happens synchronously, before {@link runBeforeAll}'s body
|
|
51
|
+
* gets its first chance to `await` anything: a second, concurrent caller
|
|
52
|
+
* reaching this method — however soon after the first — always finds
|
|
53
|
+
* {@link startPromise} already set and receives *that* promise rather than
|
|
54
|
+
* starting a second run. That is what makes concurrent dispatch safe: no
|
|
55
|
+
* caller's request proceeds until this promise settles, and if it rejects,
|
|
56
|
+
* every caller who awaited it rejects with it — none of their requests were
|
|
57
|
+
* ever sent.
|
|
58
|
+
*
|
|
59
|
+
* The latch is armed **before** the callbacks run, so a `beforeAll` that
|
|
60
|
+
* threw still gets its teardown — and so a later request cannot re-run setup
|
|
61
|
+
* that already failed.
|
|
62
|
+
*/
|
|
63
|
+
start(): Promise<void>;
|
|
64
|
+
/**
|
|
65
|
+
* The setup run itself. Failure goes through the same attribution wrapper
|
|
66
|
+
* every other hook kind does — there is no `beforeAll`-specific copy of it
|
|
67
|
+
* here any more — and propagates out of the memoized promise so every
|
|
68
|
+
* awaiter sees it.
|
|
69
|
+
*/
|
|
70
|
+
private runBeforeAll;
|
|
71
|
+
/**
|
|
72
|
+
* Run teardown in reverse order of the run: one list holding both the
|
|
73
|
+
* cleanups `beforeAll` returned and the `afterAll` hooks, reversed.
|
|
74
|
+
*
|
|
75
|
+
* Best-effort, because `core.close` is not a place a failure can be acted on —
|
|
76
|
+
* the report is already written. A teardown error is logged as a warning and
|
|
77
|
+
* the rest still runs, so one leaking fixture cannot strand the others.
|
|
78
|
+
*
|
|
79
|
+
* Latch-gated: nothing runs if no request was ever sent.
|
|
80
|
+
*/
|
|
81
|
+
close(): Promise<void>;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=run-scoped-hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-scoped-hooks.d.ts","sourceRoot":"","sources":["../../src/hooks/run-scoped-hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAYlE;;;;;;;;;GASG;AACH,qBAAa,cAAc;IAkBvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAlB5B,OAAO,CAAC,SAAS,CAAwC;IACzD,OAAO,CAAC,QAAQ,CAAsB;IAEtC;;;;;;;;;;OAUG;IACH,OAAO,CAAC,YAAY,CAA4B;gBAG7B,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,gBAAgB;IAG9C;;;;;;;OAOG;IACH,IAAI,CAAC,KAAK,EAAE;QACV,SAAS,EAAE,SAAS,qBAAqB,EAAE,CAAC;QAC5C,QAAQ,EAAE,SAAS,qBAAqB,EAAE,CAAC;KAC5C,GAAG,IAAI;IAsBR;;;;;;;;;;;;;;;;;;OAkBG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAMtB;;;;;OAKG;YACW,YAAY;IAyB1B;;;;;;;;;OASG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAiC7B"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { invokeOrThrow, reportHookResults } from './invoke-hook.js';
|
|
2
|
+
/**
|
|
3
|
+
* The run-scoped half of the lifecycle: `beforeAll` on a first-touch latch, and
|
|
4
|
+
* `afterAll` plus any cleanups `beforeAll` returned, on close.
|
|
5
|
+
*
|
|
6
|
+
* "Once before the run" has no meaning until something decides when the run
|
|
7
|
+
* starts, and the sampler's first observation of a run is the first request. So
|
|
8
|
+
* the latch is armed by the first `beforeRequest`, and it is also what gates
|
|
9
|
+
* teardown: a command that never sends a request — `sampler show`, `sampler
|
|
10
|
+
* init` — must not run somebody's teardown.
|
|
11
|
+
*/
|
|
12
|
+
export class RunScopedHooks {
|
|
13
|
+
logger;
|
|
14
|
+
makeUtils;
|
|
15
|
+
beforeAll = [];
|
|
16
|
+
teardown = [];
|
|
17
|
+
/**
|
|
18
|
+
* The latch itself: `undefined` until the first `beforeRequest` arms it,
|
|
19
|
+
* then the one setup run every caller — sequential or concurrent — awaits.
|
|
20
|
+
*
|
|
21
|
+
* A memoized promise rather than a boolean, because a boolean only answers
|
|
22
|
+
* "has setup started", and under concurrent dispatch a second caller can
|
|
23
|
+
* observe that answer before the first caller's `beforeAll` has finished (or
|
|
24
|
+
* failed). Memoizing the promise itself means every caller awaits the same
|
|
25
|
+
* settlement: nobody's request proceeds until setup resolves, and if it
|
|
26
|
+
* rejects, every caller — however many raced in — rejects with it.
|
|
27
|
+
*/
|
|
28
|
+
startPromise;
|
|
29
|
+
constructor(logger, makeUtils) {
|
|
30
|
+
this.logger = logger;
|
|
31
|
+
this.makeUtils = makeUtils;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Adopt newly loaded hooks.
|
|
35
|
+
*
|
|
36
|
+
* A reload drops teardown that the previous load's `beforeAll` registered. It
|
|
37
|
+
* has to: those closures were built against a format that is no longer
|
|
38
|
+
* loaded, and running them later would tear down a fixture whose description
|
|
39
|
+
* has changed underneath. A reload mid-run is not a shape the CLI produces.
|
|
40
|
+
*/
|
|
41
|
+
load(hooks) {
|
|
42
|
+
this.beforeAll = hooks.beforeAll;
|
|
43
|
+
this.startPromise = undefined;
|
|
44
|
+
// `afterAll` hooks are teardown from the start; cleanups join as their
|
|
45
|
+
// `beforeAll` returns them. One list, one order — so an `afterAll`
|
|
46
|
+
// registered after a `beforeAll` runs *before* that `beforeAll`'s cleanup
|
|
47
|
+
// when the list is reversed.
|
|
48
|
+
this.teardown = hooks.afterAll.map((entry) => ({
|
|
49
|
+
sequence: entry.sequence,
|
|
50
|
+
describe: `the afterAll hook exported as "${entry.exportName}" from "${entry.file}"`,
|
|
51
|
+
run: async () => {
|
|
52
|
+
const { utils, results } = this.makeUtils(entry);
|
|
53
|
+
try {
|
|
54
|
+
await invokeOrThrow('afterAll', entry, [utils]);
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
reportHookResults(this.logger, results);
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
}));
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Arm the latch and run `beforeAll` in registration order, once — memoized as
|
|
64
|
+
* a promise, so every caller (sequential or concurrent) awaits the very same
|
|
65
|
+
* setup run instead of each independently checking whether one already
|
|
66
|
+
* started.
|
|
67
|
+
*
|
|
68
|
+
* The assignment happens synchronously, before {@link runBeforeAll}'s body
|
|
69
|
+
* gets its first chance to `await` anything: a second, concurrent caller
|
|
70
|
+
* reaching this method — however soon after the first — always finds
|
|
71
|
+
* {@link startPromise} already set and receives *that* promise rather than
|
|
72
|
+
* starting a second run. That is what makes concurrent dispatch safe: no
|
|
73
|
+
* caller's request proceeds until this promise settles, and if it rejects,
|
|
74
|
+
* every caller who awaited it rejects with it — none of their requests were
|
|
75
|
+
* ever sent.
|
|
76
|
+
*
|
|
77
|
+
* The latch is armed **before** the callbacks run, so a `beforeAll` that
|
|
78
|
+
* threw still gets its teardown — and so a later request cannot re-run setup
|
|
79
|
+
* that already failed.
|
|
80
|
+
*/
|
|
81
|
+
start() {
|
|
82
|
+
this.startPromise ??= this.runBeforeAll();
|
|
83
|
+
return this.startPromise;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* The setup run itself. Failure goes through the same attribution wrapper
|
|
87
|
+
* every other hook kind does — there is no `beforeAll`-specific copy of it
|
|
88
|
+
* here any more — and propagates out of the memoized promise so every
|
|
89
|
+
* awaiter sees it.
|
|
90
|
+
*/
|
|
91
|
+
async runBeforeAll() {
|
|
92
|
+
for (const entry of this.beforeAll) {
|
|
93
|
+
const { utils, results } = this.makeUtils(entry);
|
|
94
|
+
let returned;
|
|
95
|
+
try {
|
|
96
|
+
returned = await invokeOrThrow('beforeAll', entry, [utils]);
|
|
97
|
+
}
|
|
98
|
+
finally {
|
|
99
|
+
reportHookResults(this.logger, results);
|
|
100
|
+
}
|
|
101
|
+
if (typeof returned === 'function') {
|
|
102
|
+
const cleanup = returned;
|
|
103
|
+
this.teardown.push({
|
|
104
|
+
sequence: entry.sequence,
|
|
105
|
+
describe: `the cleanup returned by the beforeAll hook exported as "${entry.exportName}" from "${entry.file}"`,
|
|
106
|
+
run: async () => {
|
|
107
|
+
await cleanup();
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Run teardown in reverse order of the run: one list holding both the
|
|
115
|
+
* cleanups `beforeAll` returned and the `afterAll` hooks, reversed.
|
|
116
|
+
*
|
|
117
|
+
* Best-effort, because `core.close` is not a place a failure can be acted on —
|
|
118
|
+
* the report is already written. A teardown error is logged as a warning and
|
|
119
|
+
* the rest still runs, so one leaking fixture cannot strand the others.
|
|
120
|
+
*
|
|
121
|
+
* Latch-gated: nothing runs if no request was ever sent.
|
|
122
|
+
*/
|
|
123
|
+
async close() {
|
|
124
|
+
if (!this.startPromise) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
// Setup may still be in flight, or may have rejected, by the time close
|
|
128
|
+
// runs. Either way, teardown waits for it to settle first: racing ahead
|
|
129
|
+
// would read {@link teardown} while `runBeforeAll` is still pushing
|
|
130
|
+
// cleanups onto it, and a rejection here is not this method's to report —
|
|
131
|
+
// whoever awaited `start()` already saw it. Best-effort teardown still
|
|
132
|
+
// runs for whatever succeeded before the rejection.
|
|
133
|
+
await this.startPromise.catch(() => {
|
|
134
|
+
// Ignored here: whoever awaited `start()` already saw this rejection.
|
|
135
|
+
});
|
|
136
|
+
const items = this.teardown
|
|
137
|
+
.splice(0)
|
|
138
|
+
// A stable sort, so two items registered in the same position keep the
|
|
139
|
+
// order they joined the list in.
|
|
140
|
+
.map((item, index) => ({ item, index }))
|
|
141
|
+
.sort((a, b) => b.item.sequence - a.item.sequence || b.index - a.index)
|
|
142
|
+
.map(({ item }) => item);
|
|
143
|
+
for (const item of items) {
|
|
144
|
+
try {
|
|
145
|
+
await item.run();
|
|
146
|
+
}
|
|
147
|
+
catch (e) {
|
|
148
|
+
this.logger.warn(`Teardown continued after ${item.describe} threw: ${e instanceof Error ? e.message : String(e)}`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=run-scoped-hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-scoped-hooks.js","sourceRoot":"","sources":["../../src/hooks/run-scoped-hooks.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,21 +1,7 @@
|
|
|
1
|
-
import { type HttpRequestTemplate, type
|
|
2
|
-
import { type SamplerValidationReport } from './validation/validate-sampler
|
|
1
|
+
import { type HttpRequestTemplate, type ThymianHttpTransaction, type ThymianPlugin, type ThymianSchema } from '@thymian/core';
|
|
2
|
+
import { type ValidationReport as SamplerValidationReport } from './validation/validate-sampler.js';
|
|
3
3
|
declare module '@thymian/core' {
|
|
4
4
|
interface ThymianActions {
|
|
5
|
-
'sampler.init': {
|
|
6
|
-
event: {
|
|
7
|
-
format: SerializedThymianFormat;
|
|
8
|
-
overwrite?: boolean;
|
|
9
|
-
};
|
|
10
|
-
response: void;
|
|
11
|
-
};
|
|
12
|
-
'sampler.validate': {
|
|
13
|
-
event: {
|
|
14
|
-
format: SerializedThymianFormat;
|
|
15
|
-
forPath?: string;
|
|
16
|
-
};
|
|
17
|
-
response: SamplerValidationReport;
|
|
18
|
-
};
|
|
19
5
|
'core.request.sample': {
|
|
20
6
|
event: {
|
|
21
7
|
transaction: ThymianHttpTransaction;
|
|
@@ -33,11 +19,48 @@ declare module '@thymian/core' {
|
|
|
33
19
|
$encoding?: string;
|
|
34
20
|
};
|
|
35
21
|
};
|
|
36
|
-
'sampler.
|
|
22
|
+
'sampler.show': {
|
|
37
23
|
event: {
|
|
38
|
-
|
|
24
|
+
selector: string;
|
|
25
|
+
};
|
|
26
|
+
response: {
|
|
27
|
+
selector: string;
|
|
28
|
+
request: HttpRequestTemplate;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
'sampler.sync': {
|
|
32
|
+
event: {
|
|
33
|
+
/** Report what would change and write nothing. The CI gate. */
|
|
34
|
+
check?: boolean;
|
|
35
|
+
};
|
|
36
|
+
response: {
|
|
37
|
+
/** Generated files whose **types** would change, or did. */
|
|
38
|
+
changed: string[];
|
|
39
|
+
/** Whether anything was written. */
|
|
40
|
+
wrote: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Generated files whose **bytes** changed. A superset of `changed`: a
|
|
43
|
+
* description edit rewrites a JSDoc comment without moving a type.
|
|
44
|
+
*/
|
|
45
|
+
rewritten?: string[];
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
'sampler.validate': {
|
|
49
|
+
event: Record<string, never>;
|
|
50
|
+
response: SamplerValidationReport;
|
|
51
|
+
};
|
|
52
|
+
'sampler.init': {
|
|
53
|
+
event: Record<string, never>;
|
|
54
|
+
response: {
|
|
55
|
+
/** The sampler root, absolute. */
|
|
56
|
+
root: string;
|
|
57
|
+
/** Generated files written, relative to the root. */
|
|
58
|
+
generated: string[];
|
|
59
|
+
/** Whether a tsconfig was scaffolded, or one was already there. */
|
|
60
|
+
tsconfig: 'written' | 'kept';
|
|
61
|
+
/** What the user has to do to their own tsconfig, in their own words. */
|
|
62
|
+
rootExcludeNote: string[];
|
|
39
63
|
};
|
|
40
|
-
response: string | undefined;
|
|
41
64
|
};
|
|
42
65
|
}
|
|
43
66
|
}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,mBAAmB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,mBAAmB,EAExB,KAAK,sBAAsB,EAC3B,KAAK,aAAa,EAClB,KAAK,aAAa,EACnB,MAAM,eAAe,CAAC;AA0BvB,OAAO,EAGL,KAAK,gBAAgB,IAAI,uBAAuB,EACjD,MAAM,kCAAkC,CAAC;AAE1C,OAAO,QAAQ,eAAe,CAAC;IAC7B,UAAU,cAAc;QACtB,qBAAqB,EAAE;YACrB,KAAK,EAAE;gBACL,WAAW,EAAE,sBAAsB,CAAC;gBACpC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;aACnC,CAAC;YACF,QAAQ,EAAE,mBAAmB,CAAC;SAC/B,CAAC;QAEF,sBAAsB,EAAE;YACtB,KAAK,EAAE;gBACL,WAAW,EAAE,MAAM,CAAC;gBACpB,MAAM,EAAE,aAAa,CAAC;aACvB,CAAC;YACF,QAAQ,EAAE;gBAAE,QAAQ,EAAE,OAAO,CAAC;gBAAC,SAAS,CAAC,EAAE,MAAM,CAAA;aAAE,CAAC;SACrD,CAAC;QAEF,cAAc,EAAE;YACd,KAAK,EAAE;gBACL,QAAQ,EAAE,MAAM,CAAC;aAClB,CAAC;YACF,QAAQ,EAAE;gBACR,QAAQ,EAAE,MAAM,CAAC;gBACjB,OAAO,EAAE,mBAAmB,CAAC;aAC9B,CAAC;SACH,CAAC;QAEF,cAAc,EAAE;YACd,KAAK,EAAE;gBACL,+DAA+D;gBAC/D,KAAK,CAAC,EAAE,OAAO,CAAC;aACjB,CAAC;YACF,QAAQ,EAAE;gBACR,4DAA4D;gBAC5D,OAAO,EAAE,MAAM,EAAE,CAAC;gBAClB,oCAAoC;gBACpC,KAAK,EAAE,OAAO,CAAC;gBACf;;;mBAGG;gBACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;aACtB,CAAC;SACH,CAAC;QAEF,kBAAkB,EAAE;YAClB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAC7B,QAAQ,EAAE,uBAAuB,CAAC;SACnC,CAAC;QAEF,cAAc,EAAE;YACd,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAC7B,QAAQ,EAAE;gBACR,kCAAkC;gBAClC,IAAI,EAAE,MAAM,CAAC;gBACb,qDAAqD;gBACrD,SAAS,EAAE,MAAM,EAAE,CAAC;gBACpB,mEAAmE;gBACnE,QAAQ,EAAE,SAAS,GAAG,MAAM,CAAC;gBAC7B,yEAAyE;gBACzE,eAAe,EAAE,MAAM,EAAE,CAAC;aAC3B,CAAC;SACH,CAAC;KACH;CACF;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,aAAa,CAAC,OAAO,CAAC,oBAAoB,CAAC,CA+OrE,CAAC;AAEF,eAAe,YAAY,CAAC"}
|