@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
|
@@ -1,20 +1,79 @@
|
|
|
1
1
|
export type ParameterType = string | number | null | boolean;
|
|
2
2
|
export type EndpointRequest = {
|
|
3
|
-
body
|
|
3
|
+
body?: unknown;
|
|
4
4
|
headers?: Record<PropertyKey, string | string[] | undefined>;
|
|
5
5
|
query?: Record<PropertyKey, ParameterType>;
|
|
6
6
|
cookies?: Record<PropertyKey, ParameterType>;
|
|
7
7
|
path?: Record<PropertyKey, ParameterType | ParameterType[] | Record<string, ParameterType | ParameterType[]>>;
|
|
8
8
|
};
|
|
9
|
+
/**
|
|
10
|
+
* One declared response, as a cross-endpoint caller sees it.
|
|
11
|
+
*
|
|
12
|
+
* The same four fields the generated `TransactionResponse<T>` carries, so the
|
|
13
|
+
* internal signature and the one an author's editor shows are one contract.
|
|
14
|
+
* `mediaType` is the essence the response actually arrived with.
|
|
15
|
+
*/
|
|
16
|
+
export type EndpointResponse = {
|
|
17
|
+
body: unknown;
|
|
18
|
+
mediaType: string;
|
|
19
|
+
statusCode: number;
|
|
20
|
+
headers: Record<string, unknown>;
|
|
21
|
+
};
|
|
9
22
|
export type Endpoints = Record<string, {
|
|
10
23
|
req: EndpointRequest;
|
|
11
|
-
res:
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
24
|
+
res: EndpointResponse;
|
|
25
|
+
/**
|
|
26
|
+
* Every response the Transaction's operation declares. Generated as a
|
|
27
|
+
* discriminated union; here it is the untyped stand-in, because the
|
|
28
|
+
* internal surface is only ever instantiated with `Record<string, never>`.
|
|
29
|
+
*/
|
|
30
|
+
responses: EndpointResponse;
|
|
16
31
|
}>;
|
|
17
|
-
|
|
32
|
+
/** Options for a cross-endpoint request. */
|
|
33
|
+
export type RequestOptions = {
|
|
34
|
+
/**
|
|
35
|
+
* Run the target's own `beforeEach` → `authorize` → `afterEach` pipeline, so
|
|
36
|
+
* a seeding call behaves like the real run. Default `true`; `false` is the
|
|
37
|
+
* raw-seeding escape, and the way out of a cycle.
|
|
38
|
+
*/
|
|
39
|
+
runHooks?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Force authorization on or off for this call, overriding the target's own
|
|
42
|
+
* `authorize` flag. Authorization still needs a registered authorize hook.
|
|
43
|
+
*/
|
|
44
|
+
authorize?: boolean;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* The typed setters.
|
|
48
|
+
*
|
|
49
|
+
* They coexist with direct mutation and do exactly the same thing: a setter is
|
|
50
|
+
* a place for the compiler to know the name and the value type, not a different
|
|
51
|
+
* mechanism. Both write into the same request object.
|
|
52
|
+
*
|
|
53
|
+
* In an `afterEach` hook the request has already been sent, so a setter there
|
|
54
|
+
* changes nothing observable — the surface stays uniform rather than throwing.
|
|
55
|
+
*/
|
|
56
|
+
export interface HookSetters {
|
|
57
|
+
setHeader(name: string, value: string | string[] | undefined): void;
|
|
58
|
+
setQuery(name: string, value: unknown): void;
|
|
59
|
+
setPathParam(name: string, value: unknown): void;
|
|
60
|
+
setCookie(name: string, value: unknown): void;
|
|
61
|
+
setBody(body: unknown): void;
|
|
62
|
+
setAuthorize(authorize: boolean): void;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Reads a file next to the hook that asks for it.
|
|
66
|
+
*
|
|
67
|
+
* A relative path resolves against the **hook file's own directory**, not the
|
|
68
|
+
* working directory: a fixture lives beside the hook that uses it, and a hook
|
|
69
|
+
* must keep working when the run starts somewhere else.
|
|
70
|
+
*/
|
|
71
|
+
export interface HookFileHelpers {
|
|
72
|
+
readFile(path: string): Buffer;
|
|
73
|
+
readText(path: string, encoding?: BufferEncoding): string;
|
|
74
|
+
readJson<T = unknown>(path: string): T;
|
|
75
|
+
}
|
|
76
|
+
export interface HookUtils<E extends Endpoints = Record<string, never>> extends HookSetters, HookFileHelpers {
|
|
18
77
|
skip(message: string): never;
|
|
19
78
|
fail(message: string): never;
|
|
20
79
|
info(message: string): void;
|
|
@@ -26,11 +85,20 @@ export interface HookUtils<E extends Endpoints = Record<string, never>> {
|
|
|
26
85
|
actual?: unknown;
|
|
27
86
|
}): void;
|
|
28
87
|
timeout(message: string, durationMs: number): void;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
88
|
+
/**
|
|
89
|
+
* Call another Transaction, addressed by its Selector.
|
|
90
|
+
*
|
|
91
|
+
* Keyed by Selector and resolved through the transaction catalog, so the keys
|
|
92
|
+
* the committed types carry and the strings resolved at run time are the same
|
|
93
|
+
* strings by construction. There is no `forStatusCode`: the Selector already
|
|
94
|
+
* carries the status you asked for.
|
|
95
|
+
*
|
|
96
|
+
* `args` **overlays** the generated request — parameter groups merge per key,
|
|
97
|
+
* the body deep-merges — and the answer is every response the operation
|
|
98
|
+
* declares, because initiating a Transaction is not the same as getting one.
|
|
99
|
+
* A status the description never declares throws `UndeclaredResponseError`.
|
|
100
|
+
*/
|
|
101
|
+
request<R extends keyof E>(selector: R, args?: E[R]['req'], options?: RequestOptions): Promise<E[R]['responses']>;
|
|
34
102
|
randomString(length?: number): string;
|
|
35
103
|
}
|
|
36
104
|
//# sourceMappingURL=hook-utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hook-utils.d.ts","sourceRoot":"","sources":["../../src/hooks/hook-utils.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC;AAE7D,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"hook-utils.d.ts","sourceRoot":"","sources":["../../src/hooks/hook-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { type HttpTestCaseResult, type Logger, ThymianBaseError } from '@thymian/core';
|
|
2
|
+
import type { HookKind } from './hook-registration.js';
|
|
3
|
+
import type { CollectedRegistration } from './load-user-hooks.js';
|
|
4
|
+
/**
|
|
5
|
+
* Calls one user callback with the arguments its kind is given.
|
|
6
|
+
*
|
|
7
|
+
* The cast lives here and nowhere else: a registration's `callback` is stored as
|
|
8
|
+
* an opaque function because each kind's precise signature is the runner's
|
|
9
|
+
* contract and the generated `.d.ts` is what types it for the author.
|
|
10
|
+
*
|
|
11
|
+
* The return value is discarded on purpose. A hook's contract is to mutate in
|
|
12
|
+
* place and return nothing, and honouring a return corrupts the value for the
|
|
13
|
+
* most ordinary shorthand there is: `(r) => (r.headers.x = 'y')` evaluates to
|
|
14
|
+
* `'y'`.
|
|
15
|
+
*/
|
|
16
|
+
export declare function invokeHook(entry: CollectedRegistration, args: readonly unknown[]): Promise<unknown>;
|
|
17
|
+
/**
|
|
18
|
+
* Where a hook's `utils` results go when there is no test case to attach them
|
|
19
|
+
* to — a run-scoped hook, or a `defineSample` that runs before any request
|
|
20
|
+
* exists. Logging them beats dropping them silently.
|
|
21
|
+
*/
|
|
22
|
+
export declare function reportHookResults(logger: Logger, results: readonly HttpTestCaseResult[]): void;
|
|
23
|
+
/**
|
|
24
|
+
* Names the hook a sampler diagnostic came out of, without burying the
|
|
25
|
+
* diagnostic.
|
|
26
|
+
*
|
|
27
|
+
* A cycle error's value is the chain it prints and a setter-misuse error's is
|
|
28
|
+
* the sentence explaining the misuse — both live in `suggestions`, so wrapping
|
|
29
|
+
* the error in a "hook X threw" envelope would throw away the part worth
|
|
30
|
+
* reading. The location joins the suggestions instead, at the front, where it
|
|
31
|
+
* answers "which line do I open" before the diagnostic answers "why".
|
|
32
|
+
*/
|
|
33
|
+
export declare function attributeToHook(error: ThymianBaseError, kind: string, entry: CollectedRegistration): ThymianBaseError;
|
|
34
|
+
/** What interpreting a hook's failure decided should happen next. */
|
|
35
|
+
export type HookFailure = {
|
|
36
|
+
rethrow?: ThymianBaseError;
|
|
37
|
+
report?: {
|
|
38
|
+
skip: string;
|
|
39
|
+
} | {
|
|
40
|
+
fail: string;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* The one interpretation every hook kind's failure goes through:
|
|
45
|
+
* `utils.skip`/`utils.fail` and an unhandled off-spec seed answer become a
|
|
46
|
+
* verdict for the kinds that have a Transaction to apply it to; a diagnostic
|
|
47
|
+
* the sampler itself raised keeps its own message and suggestions with the
|
|
48
|
+
* hook's location added; anything else is a defect in the hook and gets the
|
|
49
|
+
* envelope that names it.
|
|
50
|
+
*
|
|
51
|
+
* Every diagnostic that leaves here carries `severity: 'warn'`, and that is
|
|
52
|
+
* load-bearing rather than a judgement about how bad it is. An `error`-severity
|
|
53
|
+
* event closes the whole run through `Thymian.run`'s error subscription, which
|
|
54
|
+
* is precisely the behaviour the outcome model replaces: one broken hook used
|
|
55
|
+
* to end the command and hide every transaction after it.
|
|
56
|
+
*/
|
|
57
|
+
export declare function interpretHookFailure(e: unknown, kind: HookKind, entry: CollectedRegistration): HookFailure;
|
|
58
|
+
/**
|
|
59
|
+
* Runs one hook through the shared attribution pipeline and always throws on
|
|
60
|
+
* failure — for `defineSample`, `beforeAll` and `afterAll`, which have no
|
|
61
|
+
* Transaction to report a `skip`/`fail` verdict against. Callable only with a
|
|
62
|
+
* kind outside {@link TRANSACTION_SCOPED_KINDS}, which is what guarantees
|
|
63
|
+
* {@link interpretHookFailure} always hands back a `rethrow` here and never a
|
|
64
|
+
* `report` with nowhere to go.
|
|
65
|
+
*
|
|
66
|
+
* The raw return value is handed back rather than discarded: `beforeAll` is
|
|
67
|
+
* the one kind whose return is not mutate-and-ignore — a returned function is
|
|
68
|
+
* a cleanup to run at teardown.
|
|
69
|
+
*/
|
|
70
|
+
export declare function invokeOrThrow(kind: Exclude<HookKind, 'beforeEach' | 'afterEach' | 'authorize'>, entry: CollectedRegistration, args: readonly unknown[]): Promise<unknown>;
|
|
71
|
+
//# sourceMappingURL=invoke-hook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invoke-hook.d.ts","sourceRoot":"","sources":["../../src/hooks/invoke-hook.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,MAAM,EACX,gBAAgB,EACjB,MAAM,eAAe,CAAC;AAOvB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAElE;;;;;;;;;;;GAWG;AACH,wBAAsB,UAAU,CAC9B,KAAK,EAAE,qBAAqB,EAC5B,IAAI,EAAE,SAAS,OAAO,EAAE,GACvB,OAAO,CAAC,OAAO,CAAC,CAMlB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,SAAS,kBAAkB,EAAE,GACrC,IAAI,CAoBN;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,gBAAgB,EACvB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,qBAAqB,GAC3B,gBAAgB,CAkBlB;AAED,qEAAqE;AACrE,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9C,CAAC;AAgBF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAClC,CAAC,EAAE,OAAO,EACV,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,qBAAqB,GAC3B,WAAW,CAsCb;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,OAAO,CAAC,QAAQ,EAAE,YAAY,GAAG,WAAW,GAAG,WAAW,CAAC,EACjE,KAAK,EAAE,qBAAqB,EAC5B,IAAI,EAAE,SAAS,OAAO,EAAE,GACvB,OAAO,CAAC,OAAO,CAAC,CAkBlB"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { ThymianBaseError, } from '@thymian/core';
|
|
2
|
+
import { FailError, SkipError, UndeclaredResponseError, } from './hook-errors.js';
|
|
3
|
+
/**
|
|
4
|
+
* Calls one user callback with the arguments its kind is given.
|
|
5
|
+
*
|
|
6
|
+
* The cast lives here and nowhere else: a registration's `callback` is stored as
|
|
7
|
+
* an opaque function because each kind's precise signature is the runner's
|
|
8
|
+
* contract and the generated `.d.ts` is what types it for the author.
|
|
9
|
+
*
|
|
10
|
+
* The return value is discarded on purpose. A hook's contract is to mutate in
|
|
11
|
+
* place and return nothing, and honouring a return corrupts the value for the
|
|
12
|
+
* most ordinary shorthand there is: `(r) => (r.headers.x = 'y')` evaluates to
|
|
13
|
+
* `'y'`.
|
|
14
|
+
*/
|
|
15
|
+
export async function invokeHook(entry, args) {
|
|
16
|
+
const callback = entry.registration.callback;
|
|
17
|
+
return await callback(...args);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Where a hook's `utils` results go when there is no test case to attach them
|
|
21
|
+
* to — a run-scoped hook, or a `defineSample` that runs before any request
|
|
22
|
+
* exists. Logging them beats dropping them silently.
|
|
23
|
+
*/
|
|
24
|
+
export function reportHookResults(logger, results) {
|
|
25
|
+
for (const result of results) {
|
|
26
|
+
if (result.type === 'assertion-failure' || result.type === 'timeout') {
|
|
27
|
+
logger.error(result.message);
|
|
28
|
+
}
|
|
29
|
+
else if (result.type === 'warning' ||
|
|
30
|
+
// A nested request has no test case of its own, so these are the only
|
|
31
|
+
// place its failure is ever said out loud. At `info` a seed answered
|
|
32
|
+
// with a declared-but-different status was invisible at the default
|
|
33
|
+
// level, while every transaction that depended on it turned up
|
|
34
|
+
// `skipped` with nothing naming the cause — the reader saw the
|
|
35
|
+
// consequence and not the reason.
|
|
36
|
+
result.type === 'invalid-transaction' ||
|
|
37
|
+
result.type === 'execution-error') {
|
|
38
|
+
logger.warn(result.message);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
logger.info(result.message);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Names the hook a sampler diagnostic came out of, without burying the
|
|
47
|
+
* diagnostic.
|
|
48
|
+
*
|
|
49
|
+
* A cycle error's value is the chain it prints and a setter-misuse error's is
|
|
50
|
+
* the sentence explaining the misuse — both live in `suggestions`, so wrapping
|
|
51
|
+
* the error in a "hook X threw" envelope would throw away the part worth
|
|
52
|
+
* reading. The location joins the suggestions instead, at the front, where it
|
|
53
|
+
* answers "which line do I open" before the diagnostic answers "why".
|
|
54
|
+
*/
|
|
55
|
+
export function attributeToHook(error, kind, entry) {
|
|
56
|
+
return new ThymianBaseError(error.message, {
|
|
57
|
+
...error.options,
|
|
58
|
+
// After the spread, never before it. An `error` closes the run
|
|
59
|
+
// (`thymian.ts`), which is the mechanism ADR-0023 §2 names and the sentence
|
|
60
|
+
// above promises to prevent — and every sampler-raised error that reaches
|
|
61
|
+
// here defaults to `error` because none of them sets a severity of its own:
|
|
62
|
+
// `UnknownSelectorError` and `MalformedSelectorError` from `utils.request`,
|
|
63
|
+
// `RequestCycleError`, a seed's `RequestSerializationError`,
|
|
64
|
+
// `NoRequestToShapeError`, `NoNestedRequestError`. A typo in a seed's
|
|
65
|
+
// selector is the most ordinary hook fault there is, and it ended the run.
|
|
66
|
+
severity: 'warn',
|
|
67
|
+
suggestions: [
|
|
68
|
+
`Raised by the ${kind} hook exported as "${entry.exportName}" from "${entry.file}".`,
|
|
69
|
+
...(error.options.suggestions ?? []),
|
|
70
|
+
],
|
|
71
|
+
cause: error.cause,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The kinds that run against one Transaction, and so have somewhere for a
|
|
76
|
+
* `utils.skip`/`utils.fail` verdict — or an unhandled off-spec seed answer —
|
|
77
|
+
* to land. `defineSample` runs before any request exists and `beforeAll`/
|
|
78
|
+
* `afterAll` run once for the whole run rather than per Transaction, so a
|
|
79
|
+
* control-flow throw from one of those has no Transaction to apply to and is
|
|
80
|
+
* treated like any other defect in the hook.
|
|
81
|
+
*/
|
|
82
|
+
const TRANSACTION_SCOPED_KINDS = new Set([
|
|
83
|
+
'beforeEach',
|
|
84
|
+
'afterEach',
|
|
85
|
+
'authorize',
|
|
86
|
+
]);
|
|
87
|
+
/**
|
|
88
|
+
* The one interpretation every hook kind's failure goes through:
|
|
89
|
+
* `utils.skip`/`utils.fail` and an unhandled off-spec seed answer become a
|
|
90
|
+
* verdict for the kinds that have a Transaction to apply it to; a diagnostic
|
|
91
|
+
* the sampler itself raised keeps its own message and suggestions with the
|
|
92
|
+
* hook's location added; anything else is a defect in the hook and gets the
|
|
93
|
+
* envelope that names it.
|
|
94
|
+
*
|
|
95
|
+
* Every diagnostic that leaves here carries `severity: 'warn'`, and that is
|
|
96
|
+
* load-bearing rather than a judgement about how bad it is. An `error`-severity
|
|
97
|
+
* event closes the whole run through `Thymian.run`'s error subscription, which
|
|
98
|
+
* is precisely the behaviour the outcome model replaces: one broken hook used
|
|
99
|
+
* to end the command and hide every transaction after it.
|
|
100
|
+
*/
|
|
101
|
+
export function interpretHookFailure(e, kind, entry) {
|
|
102
|
+
const controlFlow = TRANSACTION_SCOPED_KINDS.has(kind);
|
|
103
|
+
if (controlFlow && e instanceof SkipError) {
|
|
104
|
+
return { report: { skip: e.message } };
|
|
105
|
+
}
|
|
106
|
+
if (controlFlow && e instanceof FailError) {
|
|
107
|
+
return { report: { fail: e.message } };
|
|
108
|
+
}
|
|
109
|
+
// An off-spec seed answer that nobody caught. Reacting to it is opt-in, so
|
|
110
|
+
// letting it escape is a legitimate way to write a hook: the transaction
|
|
111
|
+
// cannot be executed as described, which is a skip and not a defect, and the
|
|
112
|
+
// message already names the seed and what it was answered with.
|
|
113
|
+
if (controlFlow && e instanceof UndeclaredResponseError) {
|
|
114
|
+
return { report: { skip: e.message } };
|
|
115
|
+
}
|
|
116
|
+
if (e instanceof ThymianBaseError) {
|
|
117
|
+
return { rethrow: attributeToHook(e, kind, entry) };
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
rethrow: new ThymianBaseError(
|
|
121
|
+
// Deliberately without the Transaction: every surface that prints one
|
|
122
|
+
// already names it (ADR-0022), and repeating it under a header that says
|
|
123
|
+
// it is the noise this model removes. What only this sentence knows is
|
|
124
|
+
// which export in which file to open.
|
|
125
|
+
`The ${kind} hook exported as "${entry.exportName}" from "${entry.file}" threw.`, {
|
|
126
|
+
cause: e,
|
|
127
|
+
name: 'HookError',
|
|
128
|
+
ref: 'https://thymian.dev/references/errors/hook-error/',
|
|
129
|
+
severity: 'warn',
|
|
130
|
+
}),
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Runs one hook through the shared attribution pipeline and always throws on
|
|
135
|
+
* failure — for `defineSample`, `beforeAll` and `afterAll`, which have no
|
|
136
|
+
* Transaction to report a `skip`/`fail` verdict against. Callable only with a
|
|
137
|
+
* kind outside {@link TRANSACTION_SCOPED_KINDS}, which is what guarantees
|
|
138
|
+
* {@link interpretHookFailure} always hands back a `rethrow` here and never a
|
|
139
|
+
* `report` with nowhere to go.
|
|
140
|
+
*
|
|
141
|
+
* The raw return value is handed back rather than discarded: `beforeAll` is
|
|
142
|
+
* the one kind whose return is not mutate-and-ignore — a returned function is
|
|
143
|
+
* a cleanup to run at teardown.
|
|
144
|
+
*/
|
|
145
|
+
export async function invokeOrThrow(kind, entry, args) {
|
|
146
|
+
try {
|
|
147
|
+
return await invokeHook(entry, args);
|
|
148
|
+
}
|
|
149
|
+
catch (e) {
|
|
150
|
+
const { rethrow } = interpretHookFailure(e, kind, entry);
|
|
151
|
+
if (!rethrow) {
|
|
152
|
+
// Unreachable: `kind`'s type excludes every member of
|
|
153
|
+
// TRANSACTION_SCOPED_KINDS, and that is the only set
|
|
154
|
+
// interpretHookFailure ever produces a `report` — never a `rethrow` —
|
|
155
|
+
// for.
|
|
156
|
+
throw new Error(`invariant violated: interpretHookFailure produced no rethrow for hook kind "${kind}"`);
|
|
157
|
+
}
|
|
158
|
+
throw rethrow;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=invoke-hook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invoke-hook.js","sourceRoot":"","sources":["../../src/hooks/invoke-hook.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { TransactionCatalog } from '../selectors/transaction-catalog.js';
|
|
2
|
+
import type { HookDiagnostic } from './hook-diagnostics.js';
|
|
3
|
+
import { type HookRegistration } from './hook-registration.js';
|
|
4
|
+
/** The specifier a hook file writes. */
|
|
5
|
+
export declare const HOOKS_RUNTIME_SPECIFIER = "@thymian/hooks";
|
|
6
|
+
/**
|
|
7
|
+
* Keep a file iff its name ends in one of the six module extensions and is not a
|
|
8
|
+
* declaration file.
|
|
9
|
+
*
|
|
10
|
+
* `.tsx`/`.jsx` are not among them: JSX needs a transform pragma this jiti
|
|
11
|
+
* instance is not configured for, so such a file would be scanned only to fail
|
|
12
|
+
* on its own syntax.
|
|
13
|
+
*
|
|
14
|
+
* The declaration-file exclusion is case-insensitive while the keep pattern is
|
|
15
|
+
* not. `types.D.ts` ends in `.ts` and so matched the keep pattern, but missed a
|
|
16
|
+
* case-sensitive `\.d\.ts$` — and a hand-written declaration file handed to jiti
|
|
17
|
+
* fails on its own `declare module` syntax. Widening the exclusion can only ever
|
|
18
|
+
* skip a file that could not have executed; widening the keep pattern the same
|
|
19
|
+
* way would make the scan depend on filesystem case sensitivity.
|
|
20
|
+
*/
|
|
21
|
+
export declare function isHookFile(name: string): boolean;
|
|
22
|
+
/** The hooks that apply to one Transaction, each in registration order. */
|
|
23
|
+
export type TransactionHooks = {
|
|
24
|
+
readonly defineSample: readonly CollectedRegistration[];
|
|
25
|
+
readonly beforeEach: readonly CollectedRegistration[];
|
|
26
|
+
readonly afterEach: readonly CollectedRegistration[];
|
|
27
|
+
readonly authorize: readonly CollectedRegistration[];
|
|
28
|
+
};
|
|
29
|
+
/** A registration plus where it came from, which only the loader knows. */
|
|
30
|
+
export type CollectedRegistration = {
|
|
31
|
+
registration: HookRegistration;
|
|
32
|
+
/** Hooks-dir-relative path, `/`-normalized. */
|
|
33
|
+
file: string;
|
|
34
|
+
/** Absolute directory of the hook file, for the file helpers. */
|
|
35
|
+
dir: string;
|
|
36
|
+
exportName: string;
|
|
37
|
+
/**
|
|
38
|
+
* Position in the whole scan: file order on the outside, registration order
|
|
39
|
+
* inside each file.
|
|
40
|
+
*
|
|
41
|
+
* The registration's own `order` cannot serve: it is stamped when the hook
|
|
42
|
+
* is created, and a hook created in a shared module is created when the
|
|
43
|
+
* first file that imports it is evaluated, not when the file that exports
|
|
44
|
+
* it is. This is the one number that orders every hook in the run against
|
|
45
|
+
* every other, which is what run-scoped teardown needs to reverse.
|
|
46
|
+
*/
|
|
47
|
+
sequence: number;
|
|
48
|
+
};
|
|
49
|
+
export type LoadUserHooksResult = {
|
|
50
|
+
/** Hook files found, in load order. */
|
|
51
|
+
files: readonly string[];
|
|
52
|
+
/** Per-transaction bindings, keyed by transaction id. */
|
|
53
|
+
byTransactionId: ReadonlyMap<string, TransactionHooks>;
|
|
54
|
+
/** Run-scoped registrations, in registration order. */
|
|
55
|
+
runScoped: {
|
|
56
|
+
beforeAll: CollectedRegistration[];
|
|
57
|
+
afterAll: CollectedRegistration[];
|
|
58
|
+
};
|
|
59
|
+
/** The global `authorize(callback)` registrations, in registration order. */
|
|
60
|
+
globalAuthorize: CollectedRegistration[];
|
|
61
|
+
/** Every hook that does not resolve. A non-empty list must fail the run. */
|
|
62
|
+
diagnostics: readonly HookDiagnostic[];
|
|
63
|
+
/**
|
|
64
|
+
* Hooks that resolve but cannot both apply — today, two `defineSample` hooks
|
|
65
|
+
* on one Transaction. Kept apart from {@link diagnostics} because the fault is
|
|
66
|
+
* different and so is the sentence a reader needs: the selector is fine, the
|
|
67
|
+
* pair of hooks is not.
|
|
68
|
+
*/
|
|
69
|
+
conflicts: readonly HookDiagnostic[];
|
|
70
|
+
/**
|
|
71
|
+
* Hooks a file created and did not export, so nothing can reach them.
|
|
72
|
+
*
|
|
73
|
+
* Kept apart from {@link diagnostics} for the same reason {@link conflicts}
|
|
74
|
+
* is: the selector resolves and the file loaded, so a sentence about hooks
|
|
75
|
+
* that "do not resolve" would send the reader to the one thing that is fine.
|
|
76
|
+
*/
|
|
77
|
+
unexported: readonly HookDiagnostic[];
|
|
78
|
+
/**
|
|
79
|
+
* Things the scan could not do, which are not a hook failing to resolve.
|
|
80
|
+
*
|
|
81
|
+
* Kept apart from {@link diagnostics} on purpose: an unreadable subdirectory
|
|
82
|
+
* is why the walk goes a level at a time, and turning it into a fatal error
|
|
83
|
+
* would throw away every healthy hook in the tree — the outcome the level-wise
|
|
84
|
+
* walk exists to avoid. These are reported as warnings and the run continues.
|
|
85
|
+
*/
|
|
86
|
+
warnings: readonly string[];
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Scan the hooks directory and bind every registration it exports to the
|
|
90
|
+
* Transactions it names.
|
|
91
|
+
*
|
|
92
|
+
* A hooks directory that does not exist is not an error — `sampler init` is
|
|
93
|
+
* optional and a project may have no hooks at all — it is an empty result.
|
|
94
|
+
*/
|
|
95
|
+
export declare function loadUserHooks(hooksDir: string, catalog: TransactionCatalog): Promise<LoadUserHooksResult>;
|
|
96
|
+
//# sourceMappingURL=load-user-hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load-user-hooks.d.ts","sourceRoot":"","sources":["../../src/hooks/load-user-hooks.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAG9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EAEL,KAAK,gBAAgB,EAEtB,MAAM,wBAAwB,CAAC;AAwBhC,wCAAwC;AACxC,eAAO,MAAM,uBAAuB,mBAAmB,CAAC;AAExD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAMhD;AAED,2EAA2E;AAC3E,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,YAAY,EAAE,SAAS,qBAAqB,EAAE,CAAC;IACxD,QAAQ,CAAC,UAAU,EAAE,SAAS,qBAAqB,EAAE,CAAC;IACtD,QAAQ,CAAC,SAAS,EAAE,SAAS,qBAAqB,EAAE,CAAC;IACrD,QAAQ,CAAC,SAAS,EAAE,SAAS,qBAAqB,EAAE,CAAC;CACtD,CAAC;AAOF,2EAA2E;AAC3E,MAAM,MAAM,qBAAqB,GAAG;IAClC,YAAY,EAAE,gBAAgB,CAAC;IAC/B,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;;;;;OASG;IACH,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,uCAAuC;IACvC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,yDAAyD;IACzD,eAAe,EAAE,WAAW,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IACvD,uDAAuD;IACvD,SAAS,EAAE;QACT,SAAS,EAAE,qBAAqB,EAAE,CAAC;QACnC,QAAQ,EAAE,qBAAqB,EAAE,CAAC;KACnC,CAAC;IACF,6EAA6E;IAC7E,eAAe,EAAE,qBAAqB,EAAE,CAAC;IACzC,4EAA4E;IAC5E,WAAW,EAAE,SAAS,cAAc,EAAE,CAAC;IACvC;;;;;OAKG;IACH,SAAS,EAAE,SAAS,cAAc,EAAE,CAAC;IACrC;;;;;;OAMG;IACH,UAAU,EAAE,SAAS,cAAc,EAAE,CAAC;IACtC;;;;;;;OAOG;IACH,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B,CAAC;AAgPF;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,mBAAmB,CAAC,CAgO9B"}
|