@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
package/dist/index.js
CHANGED
|
@@ -1,61 +1,37 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { mkdir, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { ThymianFormat, } from '@thymian/core';
|
|
3
|
+
import { generateTypeSurface } from './generation/types/generate-type-surface.js';
|
|
4
|
+
import { selfCheckSurface } from './generation/types/self-check-surface.js';
|
|
5
|
+
import { readGenerated, rootExcludeNote, scaffoldTsconfig, surfaceAsFiles, writeGenerated, } from './generation/types/write-type-surface.js';
|
|
6
|
+
import { hookConflictError, unexportedHooksError, unresolvedHooksError, } from './hooks/hook-diagnostics.js';
|
|
5
7
|
import { HookRunner } from './hooks/hook-runner.js';
|
|
6
|
-
import {
|
|
8
|
+
import { loadUserHooks, } from './hooks/load-user-hooks.js';
|
|
7
9
|
import { RequestSampler } from './request-sampler.js';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { writeSamplesToDir } from './samples-structure/write-samples-to-dir.js';
|
|
10
|
+
import { resolveSamplerPaths } from './sampler-paths.js';
|
|
11
|
+
import { TransactionCatalog } from './selectors/transaction-catalog.js';
|
|
11
12
|
import { entryExists } from './utils.js';
|
|
12
|
-
import {
|
|
13
|
-
const samplerValidateActionSchema = {
|
|
14
|
-
event: {
|
|
15
|
-
type: 'object',
|
|
16
|
-
required: ['format'],
|
|
17
|
-
properties: {
|
|
18
|
-
format: {},
|
|
19
|
-
forPath: { type: 'string' },
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
|
-
response: {
|
|
23
|
-
type: 'object',
|
|
24
|
-
required: ['samplePath', 'checkedArtifacts', 'failures'],
|
|
25
|
-
properties: {
|
|
26
|
-
samplePath: { type: 'string' },
|
|
27
|
-
checkedArtifacts: { type: 'integer' },
|
|
28
|
-
failures: {
|
|
29
|
-
type: 'array',
|
|
30
|
-
items: {
|
|
31
|
-
type: 'object',
|
|
32
|
-
required: ['type', 'path', 'message'],
|
|
33
|
-
properties: {
|
|
34
|
-
type: {
|
|
35
|
-
type: 'string',
|
|
36
|
-
enum: [
|
|
37
|
-
'missing-artifact',
|
|
38
|
-
'changed-artifact',
|
|
39
|
-
'stale-root-metadata',
|
|
40
|
-
'metadata-out-of-sync',
|
|
41
|
-
'unexpected-artifact',
|
|
42
|
-
'invalid-json',
|
|
43
|
-
],
|
|
44
|
-
},
|
|
45
|
-
path: { type: 'string' },
|
|
46
|
-
message: { type: 'string' },
|
|
47
|
-
expected: { type: 'string' },
|
|
48
|
-
actual: { type: 'string' },
|
|
49
|
-
changes: { type: 'array' },
|
|
50
|
-
},
|
|
51
|
-
},
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
},
|
|
55
|
-
};
|
|
13
|
+
import { changedFiles, validateSampler, } from './validation/validate-sampler.js';
|
|
56
14
|
export const samplePlugin = {
|
|
57
15
|
name: '@thymian/plugin-sampler',
|
|
58
16
|
version: '0.x',
|
|
17
|
+
actions: {
|
|
18
|
+
// What this plugin answers, what it asks for, and what it hands off. Kept
|
|
19
|
+
// in step with the `onAction` calls below; `provides` stays empty because
|
|
20
|
+
// the payload schemas would be hand-written duplicates of the types.
|
|
21
|
+
listensOn: [
|
|
22
|
+
'core.format',
|
|
23
|
+
'core.close',
|
|
24
|
+
'core.request.sample',
|
|
25
|
+
'http-testing.beforeRequest',
|
|
26
|
+
'http-testing.afterResponse',
|
|
27
|
+
'http-testing.authorize',
|
|
28
|
+
'sampler.show',
|
|
29
|
+
'sampler.init',
|
|
30
|
+
'sampler.sync',
|
|
31
|
+
'sampler.validate',
|
|
32
|
+
],
|
|
33
|
+
emits: ['sampler.unknown-type'],
|
|
34
|
+
},
|
|
59
35
|
options: {
|
|
60
36
|
// ### for reference documentation ###
|
|
61
37
|
title: 'Plugin Options',
|
|
@@ -69,130 +45,137 @@ export const samplePlugin = {
|
|
|
69
45
|
},
|
|
70
46
|
},
|
|
71
47
|
},
|
|
72
|
-
actions: {
|
|
73
|
-
provides: {
|
|
74
|
-
'sampler.init': {
|
|
75
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
76
|
-
// @ts-expect-error
|
|
77
|
-
event: {
|
|
78
|
-
type: 'object',
|
|
79
|
-
required: ['contentType', 'schema'],
|
|
80
|
-
properties: {
|
|
81
|
-
contentType: { type: 'string' },
|
|
82
|
-
schema: {},
|
|
83
|
-
},
|
|
84
|
-
},
|
|
85
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
86
|
-
// @ts-expect-error
|
|
87
|
-
response: {
|
|
88
|
-
type: 'object',
|
|
89
|
-
required: ['contentType', 'schema'],
|
|
90
|
-
properties: {
|
|
91
|
-
contentType: { type: 'string' },
|
|
92
|
-
schema: {},
|
|
93
|
-
},
|
|
94
|
-
},
|
|
95
|
-
},
|
|
96
|
-
// The strict `JSONSchemaType<T>` target can't be satisfied by this
|
|
97
|
-
// hand-written `as const` schema (readonly literals + a deliberately
|
|
98
|
-
// loose `format: {}`, which ajv validates at runtime). Suppress the
|
|
99
|
-
// structural check the same way `sampler.init` does above, for parity.
|
|
100
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
101
|
-
// @ts-expect-error
|
|
102
|
-
'sampler.validate': samplerValidateActionSchema,
|
|
103
|
-
},
|
|
104
|
-
},
|
|
105
48
|
plugin: async (emitter, logger, options) => {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
let
|
|
113
|
-
let
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
49
|
+
const paths = resolveSamplerPaths(options.cwd, options.path);
|
|
50
|
+
const requestSampler = new RequestSampler();
|
|
51
|
+
const hookRunner = new HookRunner(logger, {
|
|
52
|
+
sampleRequest: async (transaction) => await requestSampler.sampleForTransaction(transaction, emitter),
|
|
53
|
+
dispatch: async (request) => await emitter.emitAction('core.request.dispatch', { request }, { strategy: 'first' }),
|
|
54
|
+
});
|
|
55
|
+
let catalog = TransactionCatalog.fromThymianFormat(new ThymianFormat());
|
|
56
|
+
let unresolvedHooks;
|
|
57
|
+
/**
|
|
58
|
+
* Refuse to start a run while a hook does not resolve.
|
|
59
|
+
*
|
|
60
|
+
* Checked here rather than when the format arrives, because a dangling
|
|
61
|
+
* Selector must stop a *run* and not every command: `sampler validate` has
|
|
62
|
+
* to survive long enough to report all of them, and `sampler show` and
|
|
63
|
+
* `sampler sync` are not runs. This is the earliest run-only point — the
|
|
64
|
+
* first request the tester asks the sampler to generate — so nothing is
|
|
65
|
+
* sent before the diagnostic.
|
|
66
|
+
*/
|
|
67
|
+
function assertHooksResolve() {
|
|
68
|
+
if (!unresolvedHooks) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (unresolvedHooks.diagnostics.length > 0) {
|
|
72
|
+
throw unresolvedHooksError(unresolvedHooks.diagnostics);
|
|
73
|
+
}
|
|
74
|
+
if (unresolvedHooks.conflicts.length > 0) {
|
|
75
|
+
throw hookConflictError(unresolvedHooks.conflicts);
|
|
76
|
+
}
|
|
77
|
+
if (unresolvedHooks.unexported.length > 0) {
|
|
78
|
+
throw unexportedHooksError(unresolvedHooks.unexported);
|
|
79
|
+
}
|
|
128
80
|
}
|
|
129
|
-
emitter.onAction('core.format', async (
|
|
130
|
-
format = ThymianFormat.import(
|
|
131
|
-
|
|
81
|
+
emitter.onAction('core.format', async (serialized, ctx) => {
|
|
82
|
+
const format = ThymianFormat.import(serialized);
|
|
83
|
+
// Before the projection, so an ambiguous description fails at catalog
|
|
84
|
+
// build rather than after generating samples nobody can address.
|
|
85
|
+
catalog = TransactionCatalog.fromThymianFormat(format);
|
|
86
|
+
const hooks = await loadUserHooks(paths.hooksDir, catalog);
|
|
87
|
+
// Recorded, not thrown. A hook that does not resolve must fail the *run*
|
|
88
|
+
// — see `assertHooksResolve` — but `sampler validate` exists to report
|
|
89
|
+
// every such hook at once, and it cannot report anything if publishing
|
|
90
|
+
// the format is what kills it.
|
|
91
|
+
unresolvedHooks = hooks;
|
|
92
|
+
for (const warning of hooks.warnings) {
|
|
93
|
+
logger.warn(warning);
|
|
94
|
+
}
|
|
95
|
+
// The same non-breaking signal `validate` gives, at the point a run would
|
|
96
|
+
// otherwise proceed silently against types that no longer describe the
|
|
97
|
+
// API. Only when something is committed: with no `generated/` there is
|
|
98
|
+
// nothing to be behind.
|
|
99
|
+
// Gated on the level that would print it. Answering "are the committed
|
|
100
|
+
// types behind?" means regenerating the whole surface —
|
|
101
|
+
// json-schema-to-typescript plus prettier, per schema per transaction —
|
|
102
|
+
// and that ran before the first request of every `test`, `lint` and
|
|
103
|
+
// `sampler check`, to decide whether to emit one line nobody sees at the
|
|
104
|
+
// default level. `validate` and `sync --check` are the gates that report
|
|
105
|
+
// drift; this is only a breadcrumb for someone already reading debug
|
|
106
|
+
// output, so it costs nothing when nobody is.
|
|
107
|
+
if (logger.level === 'debug' || logger.level === 'trace') {
|
|
108
|
+
const committed = await readGenerated(paths);
|
|
109
|
+
if (Object.keys(committed).length > 0) {
|
|
110
|
+
const stale = changedFiles(committed, await generateTypeSurface(catalog));
|
|
111
|
+
if (stale.length > 0) {
|
|
112
|
+
logger.debug(`The committed sampler types are behind this API description (${stale.join(', ')}).`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
hookRunner.load(format, catalog, hooks);
|
|
117
|
+
// After the hooks, because the sampler asks the runner to shape each
|
|
118
|
+
// draft with its `defineSample` hook.
|
|
119
|
+
await requestSampler.load(format, emitter, hookRunner.shapeSample);
|
|
120
|
+
logger.debug(`Catalogued ${catalog.size} transactions, projected their request samples and loaded ${hooks.files.length} hook file(s) from ${paths.hooksDir}.`);
|
|
132
121
|
ctx.reply();
|
|
133
122
|
});
|
|
134
|
-
emitter.onAction('sampler.
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
123
|
+
emitter.onAction('sampler.init', async (_event, ctx) => {
|
|
124
|
+
await mkdir(paths.hooksDir, { recursive: true });
|
|
125
|
+
const surface = await generateTypeSurface(catalog);
|
|
126
|
+
// Refuse to write a surface that does not compile on its own — the
|
|
127
|
+
// self-check gate, before anything lands on disk.
|
|
128
|
+
await selfCheckSurface(surface);
|
|
129
|
+
await writeGenerated(paths, surface);
|
|
130
|
+
// Scaffolded once and user-owned from then on: an existing one is kept
|
|
131
|
+
// even if it no longer matches what this version would write.
|
|
132
|
+
const hadTsconfig = await entryExists(paths.tsconfigPath);
|
|
133
|
+
if (!hadTsconfig) {
|
|
134
|
+
await writeFile(paths.tsconfigPath, scaffoldTsconfig(), 'utf-8');
|
|
140
135
|
}
|
|
141
|
-
ctx.reply(
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
logger.debug('Generated samples for thymian format.');
|
|
147
|
-
const generatedTypes = await generateTypesForThymianFormat(parsedFormat);
|
|
148
|
-
logger.debug('Generated types for thymian format.');
|
|
149
|
-
await writeSamplesToDir(samples, generatedTypes.keyToTransactionId, {
|
|
150
|
-
path: basePath,
|
|
151
|
-
mode: typeof overwrite === 'boolean' ? 'overwrite' : 'failIfExist',
|
|
152
|
-
typeArtifacts: {
|
|
153
|
-
typesContent: generatedTypesToString(generatedTypes),
|
|
154
|
-
},
|
|
136
|
+
ctx.reply({
|
|
137
|
+
root: paths.root,
|
|
138
|
+
generated: Object.keys(surfaceAsFiles(surface)).sort(),
|
|
139
|
+
tsconfig: hadTsconfig ? 'kept' : 'written',
|
|
140
|
+
rootExcludeNote: rootExcludeNote(paths, options.cwd),
|
|
155
141
|
});
|
|
156
|
-
logger.debug(`Wrote samples at ${basePath}`);
|
|
157
|
-
ctx.reply();
|
|
158
142
|
});
|
|
159
|
-
emitter.onAction('sampler.
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
143
|
+
emitter.onAction('sampler.sync', async ({ check }, ctx) => {
|
|
144
|
+
const surface = await generateTypeSurface(catalog);
|
|
145
|
+
// The self-check gate, ahead of both the `--check` report and the
|
|
146
|
+
// write: a fresh surface is produced either way.
|
|
147
|
+
await selfCheckSurface(surface);
|
|
148
|
+
const changed = changedFiles(await readGenerated(paths), surface);
|
|
149
|
+
if (check) {
|
|
150
|
+
// Writes nothing, by contract: a CI gate that fixed the thing it was
|
|
151
|
+
// checking would pass on the second run for the wrong reason.
|
|
152
|
+
ctx.reply({ changed, wrote: false });
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
await mkdir(paths.hooksDir, { recursive: true });
|
|
156
|
+
// Never the tsconfig: it is scaffolded once by `init` and the author's
|
|
157
|
+
// from then on.
|
|
158
|
+
const rewritten = await writeGenerated(paths, surface);
|
|
159
|
+
ctx.reply({ changed, wrote: true, rewritten });
|
|
160
|
+
});
|
|
161
|
+
emitter.onAction('sampler.validate', async (_event, ctx) => {
|
|
162
|
+
// The hooks this run already loaded, so `validate` does not evaluate
|
|
163
|
+
// every hook file a second time.
|
|
164
|
+
ctx.reply(await validateSampler(paths, catalog, unresolvedHooks));
|
|
165
|
+
});
|
|
166
|
+
emitter.onAction('sampler.show', async ({ selector }, ctx) => {
|
|
167
|
+
const transaction = catalog.resolve(selector);
|
|
168
|
+
ctx.reply({
|
|
169
|
+
selector,
|
|
170
|
+
request: await requestSampler.sampleForTransaction(transaction, emitter),
|
|
171
|
+
});
|
|
167
172
|
});
|
|
168
173
|
emitter.onAction('core.request.sample', async ({ transaction }, ctx) => {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
name: 'FormatNotLoadedError',
|
|
172
|
-
ref: 'https://thymian.dev/references/errors/format-not-loaded-error/',
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
const sample = requestSampler.sampleForTransaction(transaction.transactionId);
|
|
176
|
-
if (!sample) {
|
|
177
|
-
const currentFormatVersion = format.toHash();
|
|
178
|
-
if (currentFormatVersion !== requestSampler.version()) {
|
|
179
|
-
throw new ThymianBaseError(`Cannot sample for transaction "${thymianHttpTransactionToString(transaction.thymianReq, transaction.thymianRes)}", because it based on version "${currentFormatVersion}" but the loaded samples are based on version "${requestSampler.version()}".`, {
|
|
180
|
-
name: 'VersionMismatchError',
|
|
181
|
-
suggestions: [
|
|
182
|
-
`The loaded samples were generated at ${requestSampler.timestamp()}. Did you forget to regenerate the samples?`,
|
|
183
|
-
'$ thymian sampler init',
|
|
184
|
-
],
|
|
185
|
-
ref: 'https://thymian.dev/guides/samples/update-samples',
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
throw new ThymianBaseError(`Cannot sample for transaction ${thymianHttpTransactionToString(transaction.thymianReq, transaction.thymianRes)} with transaction ID ${transaction.transactionId}`, {
|
|
189
|
-
name: 'TransactionSampleNotFoundError',
|
|
190
|
-
ref: 'https://thymian.dev/references/errors/transaction-sample-not-found-error/',
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
ctx.reply(requestSampleToRequestTemplate(sample));
|
|
174
|
+
assertHooksResolve();
|
|
175
|
+
ctx.reply(await requestSampler.sampleForTransaction(transaction, emitter));
|
|
194
176
|
});
|
|
195
177
|
emitter.onAction('http-testing.beforeRequest', async (hook, ctx) => {
|
|
178
|
+
assertHooksResolve();
|
|
196
179
|
ctx.reply(await hookRunner.beforeEachRequest(hook));
|
|
197
180
|
});
|
|
198
181
|
emitter.onAction('http-testing.afterResponse', async (hook, ctx) => {
|
|
@@ -201,6 +184,10 @@ export const samplePlugin = {
|
|
|
201
184
|
emitter.onAction('http-testing.authorize', async (hook, ctx) => {
|
|
202
185
|
ctx.reply(await hookRunner.authorize(hook));
|
|
203
186
|
});
|
|
187
|
+
emitter.onAction('core.close', async (_event, ctx) => {
|
|
188
|
+
await hookRunner.close();
|
|
189
|
+
ctx.reply();
|
|
190
|
+
});
|
|
204
191
|
},
|
|
205
192
|
};
|
|
206
193
|
export default samplePlugin;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,15 +1,44 @@
|
|
|
1
|
-
import type
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { type HttpRequestTemplate, type ThymianEmitter, ThymianFormat, type ThymianHttpTransaction } from '@thymian/core';
|
|
2
|
+
/**
|
|
3
|
+
* Shapes the request a Transaction will send, at generation time. The
|
|
4
|
+
* `defineSample` hook, seen from here.
|
|
5
|
+
*/
|
|
6
|
+
export type SampleShaper = (draft: HttpRequestTemplate, transactionId: string) => Promise<void>;
|
|
7
|
+
/**
|
|
8
|
+
* The sampler's answer to "what request should this transaction send?".
|
|
9
|
+
*
|
|
10
|
+
* Holds the in-memory projection of the currently loaded format and nothing
|
|
11
|
+
* else. There is no version, no timestamp and no baseline to compare against,
|
|
12
|
+
* because there is no artifact that could disagree with the format: {@link load}
|
|
13
|
+
* throws the previous projection away and rebuilds it.
|
|
14
|
+
*/
|
|
4
15
|
export declare class RequestSampler {
|
|
5
|
-
private readonly basePath;
|
|
6
|
-
constructor(basePath: string, samples?: SamplesStructure);
|
|
7
16
|
private samples;
|
|
8
|
-
private
|
|
9
|
-
private
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
17
|
+
private format;
|
|
18
|
+
private shape;
|
|
19
|
+
/**
|
|
20
|
+
* Project `format` in full, replacing any previous projection.
|
|
21
|
+
*
|
|
22
|
+
* `shape` is applied per reply rather than baked into the projection, which is
|
|
23
|
+
* where the pipeline puts it — "generate base sample, then `defineSample`" —
|
|
24
|
+
* and it is also what keeps a `defineSample` hook from running for
|
|
25
|
+
* Transactions nobody asks about.
|
|
26
|
+
*/
|
|
27
|
+
load(format: ThymianFormat, emitter: ThymianEmitter, shape?: SampleShaper): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* The request for one transaction, as a value the caller owns.
|
|
30
|
+
*
|
|
31
|
+
* Every reply is a fresh deep copy. Hooks mutate the request in place, and an
|
|
32
|
+
* inline content source hands its value out by reference, so returning the
|
|
33
|
+
* projection itself let a `beforeEach` header land in what `sampler show`
|
|
34
|
+
* printed afterwards — the projection is a projection of the description, and
|
|
35
|
+
* nothing a run does may write back into it.
|
|
36
|
+
*
|
|
37
|
+
* A transaction the projection has not seen is generated on the spot rather
|
|
38
|
+
* than reported as missing: generation is a pure function of the transaction,
|
|
39
|
+
* so an unprojected transaction is one nobody has asked for yet, not evidence
|
|
40
|
+
* that something on disk is out of date.
|
|
41
|
+
*/
|
|
42
|
+
sampleForTransaction(transaction: ThymianHttpTransaction, emitter: ThymianEmitter): Promise<HttpRequestTemplate>;
|
|
14
43
|
}
|
|
15
44
|
//# sourceMappingURL=request-sampler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-sampler.d.ts","sourceRoot":"","sources":["../src/request-sampler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"request-sampler.d.ts","sourceRoot":"","sources":["../src/request-sampler.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,aAAa,EACb,KAAK,sBAAsB,EAC5B,MAAM,eAAe,CAAC;AAMvB;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,CACzB,KAAK,EAAE,mBAAmB,EAC1B,aAAa,EAAE,MAAM,KAClB,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnB;;;;;;;GAOG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAA6C;IAC5D,OAAO,CAAC,MAAM,CAAsC;IACpD,OAAO,CAAC,KAAK,CAA2B;IAExC;;;;;;;OAOG;IACG,IAAI,CACR,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,cAAc,EACvB,KAAK,CAAC,EAAE,YAAY,GACnB,OAAO,CAAC,IAAI,CAAC;IAahB;;;;;;;;;;;;;OAaG;IACG,oBAAoB,CACxB,WAAW,EAAE,sBAAsB,EACnC,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,mBAAmB,CAAC;CAmBhC"}
|
package/dist/request-sampler.js
CHANGED
|
@@ -1,82 +1,57 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
return ctx;
|
|
13
|
-
});
|
|
14
|
-
return result;
|
|
15
|
-
}
|
|
1
|
+
import { ThymianFormat, } from '@thymian/core';
|
|
2
|
+
import { generateRequestSampleForTransaction } from './generation/generate-request-sample.js';
|
|
3
|
+
import { requestSampleToRequestTemplate } from './request-sample-to-request-template.js';
|
|
4
|
+
/**
|
|
5
|
+
* The sampler's answer to "what request should this transaction send?".
|
|
6
|
+
*
|
|
7
|
+
* Holds the in-memory projection of the currently loaded format and nothing
|
|
8
|
+
* else. There is no version, no timestamp and no baseline to compare against,
|
|
9
|
+
* because there is no artifact that could disagree with the format: {@link load}
|
|
10
|
+
* throws the previous projection away and rebuilds it.
|
|
11
|
+
*/
|
|
16
12
|
export class RequestSampler {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
return new Date(this.samples.meta.timestamp).toISOString();
|
|
35
|
-
}
|
|
36
|
-
catch (e) {
|
|
37
|
-
throw new ThymianBaseError(`Invalid timestamp in samples meta: ${this.samples.meta.timestamp}`, {
|
|
38
|
-
name: 'InvalidSampleTimestampError',
|
|
39
|
-
ref: 'https://thymian.dev/references/errors/invalid-sample-timestamp-error/',
|
|
40
|
-
cause: e,
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
async init(samples) {
|
|
45
|
-
if (this.initialized) {
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
if (!(await entryExists(this.basePath))) {
|
|
49
|
-
return;
|
|
13
|
+
samples = new Map();
|
|
14
|
+
format = new ThymianFormat();
|
|
15
|
+
shape;
|
|
16
|
+
/**
|
|
17
|
+
* Project `format` in full, replacing any previous projection.
|
|
18
|
+
*
|
|
19
|
+
* `shape` is applied per reply rather than baked into the projection, which is
|
|
20
|
+
* where the pipeline puts it — "generate base sample, then `defineSample`" —
|
|
21
|
+
* and it is also what keeps a `defineSample` hook from running for
|
|
22
|
+
* Transactions nobody asks about.
|
|
23
|
+
*/
|
|
24
|
+
async load(format, emitter, shape) {
|
|
25
|
+
this.format = format;
|
|
26
|
+
this.shape = shape;
|
|
27
|
+
this.samples = new Map();
|
|
28
|
+
for (const transaction of format.getThymianHttpTransactions()) {
|
|
29
|
+
this.samples.set(transaction.transactionId, await generateRequestSampleForTransaction(format, transaction, emitter));
|
|
50
30
|
}
|
|
51
|
-
this.samples = samples ?? (await readSamplesFromDir(this.basePath));
|
|
52
|
-
this.sampleNodes = readSamplesNodesFromTree(this.samples);
|
|
53
|
-
this.initialized = true;
|
|
54
31
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
throw new Error(`Unsupported sampling strategy ${samplingStrategy}`);
|
|
79
|
-
}
|
|
32
|
+
/**
|
|
33
|
+
* The request for one transaction, as a value the caller owns.
|
|
34
|
+
*
|
|
35
|
+
* Every reply is a fresh deep copy. Hooks mutate the request in place, and an
|
|
36
|
+
* inline content source hands its value out by reference, so returning the
|
|
37
|
+
* projection itself let a `beforeEach` header land in what `sampler show`
|
|
38
|
+
* printed afterwards — the projection is a projection of the description, and
|
|
39
|
+
* nothing a run does may write back into it.
|
|
40
|
+
*
|
|
41
|
+
* A transaction the projection has not seen is generated on the spot rather
|
|
42
|
+
* than reported as missing: generation is a pure function of the transaction,
|
|
43
|
+
* so an unprojected transaction is one nobody has asked for yet, not evidence
|
|
44
|
+
* that something on disk is out of date.
|
|
45
|
+
*/
|
|
46
|
+
async sampleForTransaction(transaction, emitter) {
|
|
47
|
+
let sample = this.samples.get(transaction.transactionId);
|
|
48
|
+
if (!sample) {
|
|
49
|
+
sample = await generateRequestSampleForTransaction(this.format, transaction, emitter);
|
|
50
|
+
this.samples.set(transaction.transactionId, sample);
|
|
51
|
+
}
|
|
52
|
+
const draft = structuredClone(requestSampleToRequestTemplate(sample));
|
|
53
|
+
await this.shape?.(draft, transaction.transactionId);
|
|
54
|
+
return draft;
|
|
80
55
|
}
|
|
81
56
|
}
|
|
82
57
|
//# sourceMappingURL=request-sampler.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-sampler.js","sourceRoot":"","sources":["../src/request-sampler.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"request-sampler.js","sourceRoot":"","sources":["../src/request-sampler.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,aAAa,GAEd,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,mCAAmC,EAAE,MAAM,yCAAyC,CAAC;AAE9F,OAAO,EAAE,8BAA8B,EAAE,MAAM,yCAAyC,CAAC;AAWzF;;;;;;;GAOG;AACH,MAAM,OAAO,cAAc;IACjB,OAAO,GAAmC,IAAI,GAAG,EAAE,CAAC;IACpD,MAAM,GAAkB,IAAI,aAAa,EAAE,CAAC;IAC5C,KAAK,CAA2B;IAExC;;;;;;;OAOG;IACH,KAAK,CAAC,IAAI,CACR,MAAqB,EACrB,OAAuB,EACvB,KAAoB;QAEpB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,OAAO,GAAG,IAAI,GAAG,EAAE,CAAC;QAEzB,KAAK,MAAM,WAAW,IAAI,MAAM,CAAC,0BAA0B,EAAE,EAAE,CAAC;YAC9D,IAAI,CAAC,OAAO,CAAC,GAAG,CACd,WAAW,CAAC,aAAa,EACzB,MAAM,mCAAmC,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,CAAC,CACxE,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,oBAAoB,CACxB,WAAmC,EACnC,OAAuB;QAEvB,IAAI,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;QAEzD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,GAAG,MAAM,mCAAmC,CAChD,IAAI,CAAC,MAAM,EACX,WAAW,EACX,OAAO,CACR,CAAC;YAEF,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;QACtD,CAAC;QAED,MAAM,KAAK,GAAG,eAAe,CAAC,8BAA8B,CAAC,MAAM,CAAC,CAAC,CAAC;QAEtE,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,aAAa,CAAC,CAAC;QAErD,OAAO,KAAK,CAAC;IACf,CAAC;CACF"}
|