@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.
Files changed (264) hide show
  1. package/dist/cli/check-result.d.ts +88 -0
  2. package/dist/cli/check-result.d.ts.map +1 -0
  3. package/dist/cli/check-result.js +160 -0
  4. package/dist/cli/check-result.js.map +1 -0
  5. package/dist/cli/commands/sampler/check.d.ts +32 -4
  6. package/dist/cli/commands/sampler/check.d.ts.map +1 -1
  7. package/dist/cli/commands/sampler/check.js +126 -88
  8. package/dist/cli/commands/sampler/check.js.map +1 -1
  9. package/dist/cli/commands/sampler/init.d.ts +4 -6
  10. package/dist/cli/commands/sampler/init.d.ts.map +1 -1
  11. package/dist/cli/commands/sampler/init.js +33 -49
  12. package/dist/cli/commands/sampler/init.js.map +1 -1
  13. package/dist/cli/commands/sampler/show.d.ts +11 -0
  14. package/dist/cli/commands/sampler/show.d.ts.map +1 -0
  15. package/dist/cli/commands/sampler/show.js +36 -0
  16. package/dist/cli/commands/sampler/show.js.map +1 -0
  17. package/dist/cli/commands/sampler/sync.d.ts +11 -0
  18. package/dist/cli/commands/sampler/sync.d.ts.map +1 -0
  19. package/dist/cli/commands/sampler/sync.js +65 -0
  20. package/dist/cli/commands/sampler/sync.js.map +1 -0
  21. package/dist/cli/commands/sampler/validate.d.ts +3 -10
  22. package/dist/cli/commands/sampler/validate.d.ts.map +1 -1
  23. package/dist/cli/commands/sampler/validate.js +57 -126
  24. package/dist/cli/commands/sampler/validate.js.map +1 -1
  25. package/dist/generation/closed-schema.d.ts +22 -0
  26. package/dist/generation/closed-schema.d.ts.map +1 -0
  27. package/dist/generation/closed-schema.js +45 -0
  28. package/dist/generation/closed-schema.js.map +1 -0
  29. package/dist/generation/content-type-strategies/json.content-type-strategy.d.ts.map +1 -1
  30. package/dist/generation/content-type-strategies/json.content-type-strategy.js +3 -1
  31. package/dist/generation/content-type-strategies/json.content-type-strategy.js.map +1 -1
  32. package/dist/generation/content-type-strategies/xml.content-type-strategy.d.ts.map +1 -1
  33. package/dist/generation/content-type-strategies/xml.content-type-strategy.js +3 -1
  34. package/dist/generation/content-type-strategies/xml.content-type-strategy.js.map +1 -1
  35. package/dist/generation/generate-request-sample.d.ts +12 -0
  36. package/dist/generation/generate-request-sample.d.ts.map +1 -0
  37. package/dist/generation/{generate-samples.js → generate-request-sample.js} +11 -4
  38. package/dist/generation/generate-request-sample.js.map +1 -0
  39. package/dist/generation/request-generators/default-request-generator.d.ts +14 -0
  40. package/dist/generation/request-generators/default-request-generator.d.ts.map +1 -1
  41. package/dist/generation/request-generators/default-request-generator.js +18 -1
  42. package/dist/generation/request-generators/default-request-generator.js.map +1 -1
  43. package/dist/generation/types/declaration-set.d.ts +124 -0
  44. package/dist/generation/types/declaration-set.d.ts.map +1 -0
  45. package/dist/generation/types/declaration-set.js +389 -0
  46. package/dist/generation/types/declaration-set.js.map +1 -0
  47. package/dist/generation/types/example-reflection.d.ts +21 -0
  48. package/dist/generation/types/example-reflection.d.ts.map +1 -0
  49. package/dist/generation/types/example-reflection.js +135 -0
  50. package/dist/generation/types/example-reflection.js.map +1 -0
  51. package/dist/generation/types/generate-type-surface.d.ts +23 -0
  52. package/dist/generation/types/generate-type-surface.d.ts.map +1 -0
  53. package/dist/generation/types/generate-type-surface.js +671 -0
  54. package/dist/generation/types/generate-type-surface.js.map +1 -0
  55. package/dist/generation/types/schema-type.d.ts +20 -0
  56. package/dist/generation/types/schema-type.d.ts.map +1 -0
  57. package/dist/generation/types/schema-type.js +203 -0
  58. package/dist/generation/types/schema-type.js.map +1 -0
  59. package/dist/generation/types/self-check-surface.d.ts +32 -0
  60. package/dist/generation/types/self-check-surface.d.ts.map +1 -0
  61. package/dist/generation/types/self-check-surface.js +92 -0
  62. package/dist/generation/types/self-check-surface.js.map +1 -0
  63. package/dist/generation/types/type-names.d.ts +135 -0
  64. package/dist/generation/types/type-names.d.ts.map +1 -0
  65. package/dist/generation/types/type-names.js +213 -0
  66. package/dist/generation/types/type-names.js.map +1 -0
  67. package/dist/generation/types/write-type-surface.d.ts +58 -0
  68. package/dist/generation/types/write-type-surface.d.ts.map +1 -0
  69. package/dist/generation/types/write-type-surface.js +119 -0
  70. package/dist/generation/types/write-type-surface.js.map +1 -0
  71. package/dist/hooks/create-hook-utils.d.ts +22 -6
  72. package/dist/hooks/create-hook-utils.d.ts.map +1 -1
  73. package/dist/hooks/create-hook-utils.js +74 -96
  74. package/dist/hooks/create-hook-utils.js.map +1 -1
  75. package/dist/hooks/hook-api.d.ts +49 -0
  76. package/dist/hooks/hook-api.d.ts.map +1 -0
  77. package/dist/hooks/hook-api.js +105 -0
  78. package/dist/hooks/hook-api.js.map +1 -0
  79. package/dist/hooks/hook-diagnostics.d.ts +45 -0
  80. package/dist/hooks/hook-diagnostics.d.ts.map +1 -0
  81. package/dist/hooks/hook-diagnostics.js +80 -0
  82. package/dist/hooks/hook-diagnostics.js.map +1 -0
  83. package/dist/hooks/hook-errors.d.ts +33 -0
  84. package/dist/hooks/hook-errors.d.ts.map +1 -1
  85. package/dist/hooks/hook-errors.js +46 -0
  86. package/dist/hooks/hook-errors.js.map +1 -1
  87. package/dist/hooks/hook-registration.d.ts +108 -0
  88. package/dist/hooks/hook-registration.d.ts.map +1 -0
  89. package/dist/hooks/hook-registration.js +69 -0
  90. package/dist/hooks/hook-registration.js.map +1 -0
  91. package/dist/hooks/hook-runner.d.ts +111 -11
  92. package/dist/hooks/hook-runner.d.ts.map +1 -1
  93. package/dist/hooks/hook-runner.js +309 -142
  94. package/dist/hooks/hook-runner.js.map +1 -1
  95. package/dist/hooks/hook-utils-factory.d.ts +19 -0
  96. package/dist/hooks/hook-utils-factory.d.ts.map +1 -0
  97. package/dist/hooks/hook-utils-factory.js +2 -0
  98. package/dist/hooks/hook-utils-factory.js.map +1 -0
  99. package/dist/hooks/hook-utils.d.ts +80 -12
  100. package/dist/hooks/hook-utils.d.ts.map +1 -1
  101. package/dist/hooks/invoke-hook.d.ts +71 -0
  102. package/dist/hooks/invoke-hook.d.ts.map +1 -0
  103. package/dist/hooks/invoke-hook.js +161 -0
  104. package/dist/hooks/invoke-hook.js.map +1 -0
  105. package/dist/hooks/load-user-hooks.d.ts +96 -0
  106. package/dist/hooks/load-user-hooks.d.ts.map +1 -0
  107. package/dist/hooks/load-user-hooks.js +432 -0
  108. package/dist/hooks/load-user-hooks.js.map +1 -0
  109. package/dist/hooks/nested-request.d.ts +21 -0
  110. package/dist/hooks/nested-request.d.ts.map +1 -0
  111. package/dist/hooks/nested-request.js +24 -0
  112. package/dist/hooks/nested-request.js.map +1 -0
  113. package/dist/hooks/overlay-args.d.ts +40 -0
  114. package/dist/hooks/overlay-args.d.ts.map +1 -0
  115. package/dist/hooks/overlay-args.js +84 -0
  116. package/dist/hooks/overlay-args.js.map +1 -0
  117. package/dist/hooks/resolve-targeting.d.ts +16 -0
  118. package/dist/hooks/resolve-targeting.d.ts.map +1 -0
  119. package/dist/hooks/resolve-targeting.js +168 -0
  120. package/dist/hooks/resolve-targeting.js.map +1 -0
  121. package/dist/hooks/run-scoped-hooks.d.ts +83 -0
  122. package/dist/hooks/run-scoped-hooks.d.ts.map +1 -0
  123. package/dist/hooks/run-scoped-hooks.js +153 -0
  124. package/dist/hooks/run-scoped-hooks.js.map +1 -0
  125. package/dist/index.d.ts +42 -19
  126. package/dist/index.d.ts.map +1 -1
  127. package/dist/index.js +152 -165
  128. package/dist/index.js.map +1 -1
  129. package/dist/request-sampler.d.ts +40 -11
  130. package/dist/request-sampler.d.ts.map +1 -1
  131. package/dist/request-sampler.js +51 -76
  132. package/dist/request-sampler.js.map +1 -1
  133. package/dist/sampler-paths.d.ts +19 -0
  134. package/dist/sampler-paths.d.ts.map +1 -0
  135. package/dist/sampler-paths.js +22 -0
  136. package/dist/sampler-paths.js.map +1 -0
  137. package/dist/selectors/nearest-paths.d.ts +14 -0
  138. package/dist/selectors/nearest-paths.d.ts.map +1 -0
  139. package/dist/selectors/nearest-paths.js +32 -0
  140. package/dist/selectors/nearest-paths.js.map +1 -0
  141. package/dist/selectors/path-glob.d.ts +94 -0
  142. package/dist/selectors/path-glob.d.ts.map +1 -0
  143. package/dist/selectors/path-glob.js +136 -0
  144. package/dist/selectors/path-glob.js.map +1 -0
  145. package/dist/selectors/selector-errors.d.ts +17 -0
  146. package/dist/selectors/selector-errors.d.ts.map +1 -0
  147. package/dist/selectors/selector-errors.js +139 -0
  148. package/dist/selectors/selector-errors.js.map +1 -0
  149. package/dist/selectors/selector.d.ts +55 -0
  150. package/dist/selectors/selector.d.ts.map +1 -0
  151. package/dist/selectors/selector.js +305 -0
  152. package/dist/selectors/selector.js.map +1 -0
  153. package/dist/selectors/transaction-catalog.d.ts +96 -0
  154. package/dist/selectors/transaction-catalog.d.ts.map +1 -0
  155. package/dist/selectors/transaction-catalog.js +193 -0
  156. package/dist/selectors/transaction-catalog.js.map +1 -0
  157. package/dist/selectors/transaction-filter.d.ts +119 -0
  158. package/dist/selectors/transaction-filter.d.ts.map +1 -0
  159. package/dist/selectors/transaction-filter.js +191 -0
  160. package/dist/selectors/transaction-filter.js.map +1 -0
  161. package/dist/ts-path.d.ts +36 -0
  162. package/dist/ts-path.d.ts.map +1 -0
  163. package/dist/ts-path.js +46 -0
  164. package/dist/ts-path.js.map +1 -0
  165. package/dist/utils.d.ts +1 -2
  166. package/dist/utils.d.ts.map +1 -1
  167. package/dist/utils.js +2 -20
  168. package/dist/utils.js.map +1 -1
  169. package/dist/validation/canonicalize.d.ts +17 -0
  170. package/dist/validation/canonicalize.d.ts.map +1 -0
  171. package/dist/validation/canonicalize.js +29 -0
  172. package/dist/validation/canonicalize.js.map +1 -0
  173. package/dist/validation/shared-compiler-host.d.ts +17 -0
  174. package/dist/validation/shared-compiler-host.d.ts.map +1 -0
  175. package/dist/validation/shared-compiler-host.js +58 -0
  176. package/dist/validation/shared-compiler-host.js.map +1 -0
  177. package/dist/validation/typecheck-hooks.d.ts +37 -0
  178. package/dist/validation/typecheck-hooks.d.ts.map +1 -0
  179. package/dist/validation/typecheck-hooks.js +169 -0
  180. package/dist/validation/typecheck-hooks.js.map +1 -0
  181. package/dist/validation/validate-sampler.d.ts +79 -0
  182. package/dist/validation/validate-sampler.d.ts.map +1 -0
  183. package/dist/validation/validate-sampler.js +89 -0
  184. package/dist/validation/validate-sampler.js.map +1 -0
  185. package/package.json +7 -11
  186. package/dist/cli/commands/sampler/generate/hook.d.ts +0 -10
  187. package/dist/cli/commands/sampler/generate/hook.d.ts.map +0 -1
  188. package/dist/cli/commands/sampler/generate/hook.js +0 -19
  189. package/dist/cli/commands/sampler/generate/hook.js.map +0 -1
  190. package/dist/cli/generate-hook.d.ts +0 -4
  191. package/dist/cli/generate-hook.d.ts.map +0 -1
  192. package/dist/cli/generate-hook.js +0 -96
  193. package/dist/cli/generate-hook.js.map +0 -1
  194. package/dist/cli/templates.d.ts +0 -4
  195. package/dist/cli/templates.d.ts.map +0 -1
  196. package/dist/cli/templates.js +0 -28
  197. package/dist/cli/templates.js.map +0 -1
  198. package/dist/constants.d.ts +0 -12
  199. package/dist/constants.d.ts.map +0 -1
  200. package/dist/constants.js +0 -16
  201. package/dist/constants.js.map +0 -1
  202. package/dist/generation/generate-samples-for-thymian-format.d.ts +0 -4
  203. package/dist/generation/generate-samples-for-thymian-format.d.ts.map +0 -1
  204. package/dist/generation/generate-samples-for-thymian-format.js +0 -18
  205. package/dist/generation/generate-samples-for-thymian-format.js.map +0 -1
  206. package/dist/generation/generate-samples.d.ts +0 -4
  207. package/dist/generation/generate-samples.d.ts.map +0 -1
  208. package/dist/generation/generate-samples.js.map +0 -1
  209. package/dist/hooks/generate-request-types.d.ts +0 -34
  210. package/dist/hooks/generate-request-types.d.ts.map +0 -1
  211. package/dist/hooks/generate-request-types.js +0 -458
  212. package/dist/hooks/generate-request-types.js.map +0 -1
  213. package/dist/hooks/hook-types.d.ts +0 -7
  214. package/dist/hooks/hook-types.d.ts.map +0 -1
  215. package/dist/hooks/hook-types.js +0 -2
  216. package/dist/hooks/hook-types.js.map +0 -1
  217. package/dist/hooks/load-hooks-from-samples.d.ts +0 -3
  218. package/dist/hooks/load-hooks-from-samples.d.ts.map +0 -1
  219. package/dist/hooks/load-hooks-from-samples.js +0 -22
  220. package/dist/hooks/load-hooks-from-samples.js.map +0 -1
  221. package/dist/hooks/ts-config.d.ts +0 -10
  222. package/dist/hooks/ts-config.d.ts.map +0 -1
  223. package/dist/hooks/ts-config.js +0 -10
  224. package/dist/hooks/ts-config.js.map +0 -1
  225. package/dist/samples-structure/file-request-sample.d.ts +0 -20
  226. package/dist/samples-structure/file-request-sample.d.ts.map +0 -1
  227. package/dist/samples-structure/file-request-sample.js +0 -5
  228. package/dist/samples-structure/file-request-sample.js.map +0 -1
  229. package/dist/samples-structure/get-path-transaction-id.d.ts +0 -3
  230. package/dist/samples-structure/get-path-transaction-id.d.ts.map +0 -1
  231. package/dist/samples-structure/get-path-transaction-id.js +0 -22
  232. package/dist/samples-structure/get-path-transaction-id.js.map +0 -1
  233. package/dist/samples-structure/merge-tree.d.ts +0 -5
  234. package/dist/samples-structure/merge-tree.d.ts.map +0 -1
  235. package/dist/samples-structure/merge-tree.js +0 -118
  236. package/dist/samples-structure/merge-tree.js.map +0 -1
  237. package/dist/samples-structure/read-samples-from-dir.d.ts +0 -13
  238. package/dist/samples-structure/read-samples-from-dir.d.ts.map +0 -1
  239. package/dist/samples-structure/read-samples-from-dir.js +0 -205
  240. package/dist/samples-structure/read-samples-from-dir.js.map +0 -1
  241. package/dist/samples-structure/samples-from-transactions.d.ts +0 -5
  242. package/dist/samples-structure/samples-from-transactions.d.ts.map +0 -1
  243. package/dist/samples-structure/samples-from-transactions.js +0 -120
  244. package/dist/samples-structure/samples-from-transactions.js.map +0 -1
  245. package/dist/samples-structure/samples-tree-structure.d.ts +0 -106
  246. package/dist/samples-structure/samples-tree-structure.d.ts.map +0 -1
  247. package/dist/samples-structure/samples-tree-structure.js +0 -26
  248. package/dist/samples-structure/samples-tree-structure.js.map +0 -1
  249. package/dist/samples-structure/structure-meta-on-disc.d.ts +0 -11
  250. package/dist/samples-structure/structure-meta-on-disc.d.ts.map +0 -1
  251. package/dist/samples-structure/structure-meta-on-disc.js +0 -2
  252. package/dist/samples-structure/structure-meta-on-disc.js.map +0 -1
  253. package/dist/samples-structure/traverse.d.ts +0 -4
  254. package/dist/samples-structure/traverse.d.ts.map +0 -1
  255. package/dist/samples-structure/traverse.js +0 -13
  256. package/dist/samples-structure/traverse.js.map +0 -1
  257. package/dist/samples-structure/write-samples-to-dir.d.ts +0 -37
  258. package/dist/samples-structure/write-samples-to-dir.d.ts.map +0 -1
  259. package/dist/samples-structure/write-samples-to-dir.js +0 -183
  260. package/dist/samples-structure/write-samples-to-dir.js.map +0 -1
  261. package/dist/validation/validate-sampler-output.d.ts +0 -38
  262. package/dist/validation/validate-sampler-output.d.ts.map +0 -1
  263. package/dist/validation/validate-sampler-output.js +0 -288
  264. package/dist/validation/validate-sampler-output.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,61 +1,37 @@
1
- import { isAbsolute, join } from 'node:path';
2
- import { ThymianBaseError, ThymianFormat, thymianHttpTransactionToString, } from '@thymian/core';
3
- import { generateSamplesForThymianFormat } from './generation/generate-samples-for-thymian-format.js';
4
- import { generatedTypesToString, generateTypesForThymianFormat, } from './hooks/generate-request-types.js';
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 { requestSampleToRequestTemplate } from './request-sample-to-request-template.js';
8
+ import { loadUserHooks, } from './hooks/load-user-hooks.js';
7
9
  import { RequestSampler } from './request-sampler.js';
8
- import { getPathTransactionId } from './samples-structure/get-path-transaction-id.js';
9
- import { readSamplesFromDir } from './samples-structure/read-samples-from-dir.js';
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 { validateSamplerOutput, } from './validation/validate-sampler-output.js';
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
- let basePath = join(options.cwd, '.thymian', 'samples');
107
- if (options.path) {
108
- basePath = isAbsolute(options.path)
109
- ? options.path
110
- : join(options.cwd, options.path);
111
- }
112
- let format;
113
- let samples;
114
- const requestSampler = new RequestSampler(basePath);
115
- const hookRunner = new HookRunner(basePath, async (request) => {
116
- return await emitter.emitAction('core.request.dispatch', {
117
- request,
118
- }, {
119
- strategy: 'first',
120
- });
121
- }, logger);
122
- async function initializeSamplerAndHookRunner(format) {
123
- samples = (await entryExists(basePath))
124
- ? await readSamplesFromDir(basePath)
125
- : undefined;
126
- await requestSampler.init(samples);
127
- await hookRunner.init(format, samples);
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 (f, ctx) => {
130
- format = ThymianFormat.import(f);
131
- await initializeSamplerAndHookRunner(format);
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.path-from-transaction', ({ transactionId }, ctx) => {
135
- if (!samples) {
136
- throw new ThymianBaseError('No samples are loaded.', {
137
- name: 'SamplesNotLoadedError',
138
- ref: 'https://thymian.dev/references/errors/samples-not-loaded-error/',
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(getPathTransactionId(transactionId, basePath, samples));
142
- });
143
- emitter.onAction('sampler.init', async ({ format, overwrite }, ctx) => {
144
- const parsedFormat = ThymianFormat.import(format);
145
- const samples = await generateSamplesForThymianFormat(parsedFormat, emitter);
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.validate', async ({ format, forPath }, ctx) => {
160
- const parsedFormat = ThymianFormat.import(format);
161
- ctx.reply(await validateSamplerOutput({
162
- format: parsedFormat,
163
- emitter,
164
- samplePath: basePath,
165
- forPath,
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
- if (!format) {
170
- throw new ThymianBaseError('Format is not loaded.', {
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":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -1,15 +1,44 @@
1
- import type { HttpRequestSample } from './http-request-sample.js';
2
- import { type SamplesNode, type SamplesStructure } from './samples-structure/samples-tree-structure.js';
3
- export declare function readSamplesNodesFromTree(tree: SamplesStructure): Map<string, SamplesNode>;
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 initialized;
9
- private sampleNodes;
10
- version(): string;
11
- timestamp(): string;
12
- init(samples?: SamplesStructure): Promise<void>;
13
- sampleForTransaction(transactionId: string): HttpRequestSample | undefined;
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":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElE,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACtB,MAAM,+CAA+C,CAAC;AAIvD,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,gBAAgB,GACrB,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAY1B;AAED,qBAAa,cAAc;IAEvB,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,MAAM,EACjC,OAAO,CAAC,EAAE,gBAAgB;IAS5B,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAuC;IAE1D,OAAO,IAAI,MAAM;IAIjB,SAAS,IAAI,MAAM;IAeb,IAAI,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBrD,oBAAoB,CAAC,aAAa,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS;CA+B3E"}
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"}
@@ -1,82 +1,57 @@
1
- import { ThymianBaseError } from '@thymian/core';
2
- import { readSamplesFromDir } from './samples-structure/read-samples-from-dir.js';
3
- import { nodeIsType, } from './samples-structure/samples-tree-structure.js';
4
- import { traverse } from './samples-structure/traverse.js';
5
- import { entryExists } from './utils.js';
6
- export function readSamplesNodesFromTree(tree) {
7
- const result = new Map();
8
- traverse(tree, null, (node, ctx) => {
9
- if (nodeIsType(node, 'samples')) {
10
- result.set(node.meta.sourceTransaction, node);
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
- basePath;
18
- constructor(basePath, samples) {
19
- this.basePath = basePath;
20
- if (samples) {
21
- this.sampleNodes = readSamplesNodesFromTree(samples);
22
- this.samples = samples;
23
- this.initialized = true;
24
- }
25
- }
26
- samples;
27
- initialized = false;
28
- sampleNodes = new Map();
29
- version() {
30
- return this.samples.meta.version;
31
- }
32
- timestamp() {
33
- try {
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
- sampleForTransaction(transactionId) {
56
- if (!this.initialized) {
57
- throw new ThymianBaseError('Cannot sample for transaction before @thymian/plugin-sampler was initialized.', {
58
- suggestions: ['Did you run "thymian sampler init"?'],
59
- name: 'SamplerNotInitializedError',
60
- });
61
- }
62
- const node = this.sampleNodes.get(transactionId);
63
- if (!node) {
64
- return;
65
- }
66
- const { samplingStrategy } = node.meta;
67
- const samples = node.children
68
- .filter((child) => nodeIsType(child, 'requests'))
69
- .flatMap((child) => child.value);
70
- if (samplingStrategy.type === 'random') {
71
- const randomIndex = Math.floor(Math.random() * samples.length);
72
- return samples[randomIndex];
73
- }
74
- else if (samplingStrategy.type === 'fixed') {
75
- return samples[0];
76
- }
77
- else {
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":"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"}
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"}