@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
@@ -0,0 +1,432 @@
1
+ import { readdir, realpath } from 'node:fs/promises';
2
+ import { createRequire, Module } from 'node:module';
3
+ import { dirname, isAbsolute, join, relative, sep } from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { createJiti } from 'jiti';
6
+ import { toTypeScriptPath } from '../ts-path.js';
7
+ import { entryExists } from '../utils.js';
8
+ import { hookFileImportError } from './hook-diagnostics.js';
9
+ import { createdRegistrations, isHookRegistration, } from './hook-registration.js';
10
+ import { resolveTargeting } from './resolve-targeting.js';
11
+ /**
12
+ * `@thymian/hooks` is resolved by **this** alias — not by a tsconfig `paths`
13
+ * entry and not by a committed `.d.ts` — which is what lets a hook file import
14
+ * runtime values in a workspace with no generated directory, no generated
15
+ * tsconfig and `sampler init` never run.
16
+ *
17
+ * Two properties are load-bearing:
18
+ *
19
+ * - **An absolute path, never a bare specifier.** The package exports only `"."`
20
+ * and `"./package.json"`, so `'@thymian/plugin-sampler/hook-api'` would be
21
+ * blocked by the exports map in a published install, and adding a subpath
22
+ * export would put an internal module on the public surface. Deriving the path
23
+ * from `import.meta.url` sidesteps the exports map entirely.
24
+ * - **Extensionless.** jiti resolves `.js .mjs .cjs .ts .mts .cts` itself, so one
25
+ * target serves `dist/hooks/hook-api.js` in an installed CLI and
26
+ * `src/hooks/hook-api.ts` when running from source, identically.
27
+ */
28
+ const hooksRuntimeModule = fileURLToPath(new URL('./hook-api.js', import.meta.url)).replace(/\.[cm]?js$/, '');
29
+ /** The specifier a hook file writes. */
30
+ export const HOOKS_RUNTIME_SPECIFIER = '@thymian/hooks';
31
+ /**
32
+ * Keep a file iff its name ends in one of the six module extensions and is not a
33
+ * declaration file.
34
+ *
35
+ * `.tsx`/`.jsx` are not among them: JSX needs a transform pragma this jiti
36
+ * instance is not configured for, so such a file would be scanned only to fail
37
+ * on its own syntax.
38
+ *
39
+ * The declaration-file exclusion is case-insensitive while the keep pattern is
40
+ * not. `types.D.ts` ends in `.ts` and so matched the keep pattern, but missed a
41
+ * case-sensitive `\.d\.ts$` — and a hand-written declaration file handed to jiti
42
+ * fails on its own `declare module` syntax. Widening the exclusion can only ever
43
+ * skip a file that could not have executed; widening the keep pattern the same
44
+ * way would make the scan depend on filesystem case sensitivity.
45
+ */
46
+ export function isHookFile(name) {
47
+ if (/\.d\.[cm]?ts$/i.test(name)) {
48
+ return false;
49
+ }
50
+ return /\.[cm]?[jt]s$/.test(name);
51
+ }
52
+ /** Hooks-dir-relative, `/`-normalized — the sort key and the diagnostic label. */
53
+ function hooksDirRelative(hooksDir, full) {
54
+ return toTypeScriptPath(relative(hooksDir, full));
55
+ }
56
+ /**
57
+ * One directory level, then its subdirectories.
58
+ *
59
+ * Deliberately not `readdir({ recursive: true })`: that is a single call, so an
60
+ * `EACCES` on any nested directory rejects the *whole* walk and loses every
61
+ * healthy hook in the tree. Walking a level at a time costs one `readdir` per
62
+ * directory and confines a failure to the subtree that actually failed.
63
+ *
64
+ * Dot-directories are skipped, so an editor's or a tool's cache inside the hooks
65
+ * tree is not scanned.
66
+ */
67
+ async function walkHookDirectory(hooksDir, dir, isRoot, files, warnings) {
68
+ let entries;
69
+ try {
70
+ entries = await readdir(dir, { withFileTypes: true });
71
+ }
72
+ catch (error) {
73
+ if (isRoot) {
74
+ throw error;
75
+ }
76
+ warnings.push(`The hooks subdirectory "${hooksDirRelative(hooksDir, dir)}" could not be read (${error instanceof Error ? error.message : String(error)}), so any hooks inside it were not loaded.`);
77
+ return;
78
+ }
79
+ const directories = [];
80
+ for (const entry of entries) {
81
+ const full = join(dir, entry.name);
82
+ // `Dirent`'s type flags describe the entry itself, never the symlink's
83
+ // target — `isFile()`/`isDirectory()` are both false for a symlink, which
84
+ // already keeps one out of `files`/`directories` below. What was missing
85
+ // is the word: a hook that silently never runs because its file is a
86
+ // symlink looks exactly like a Thymian bug, so it is named rather than
87
+ // dropped.
88
+ if (entry.isSymbolicLink()) {
89
+ warnings.push(`The hooks entry "${hooksDirRelative(hooksDir, full)}" is a symlink and was skipped: symlinked hook files and directories are not followed.`);
90
+ continue;
91
+ }
92
+ if (entry.isDirectory()) {
93
+ // `node_modules` is never a source of hooks, however it got there —
94
+ // installed by the user's own tooling or vendored by hand — so it is
95
+ // excluded by name rather than relying on every install layout to
96
+ // happen to start with a dot.
97
+ if (!entry.name.startsWith('.') && entry.name !== 'node_modules') {
98
+ directories.push(full);
99
+ }
100
+ continue;
101
+ }
102
+ if (entry.isFile() && isHookFile(entry.name)) {
103
+ files.push(full);
104
+ }
105
+ }
106
+ for (const directory of directories) {
107
+ await walkHookDirectory(hooksDir, directory, false, files, warnings);
108
+ }
109
+ }
110
+ /**
111
+ * A stable load order: hooks-dir-relative key, by code unit.
112
+ *
113
+ * `readdir` order is filesystem-dependent, and composition order is observable,
114
+ * so the order hooks are loaded in is a decision rather than an accident.
115
+ */
116
+ function compareKeys(a, b) {
117
+ return a < b ? -1 : a > b ? 1 : 0;
118
+ }
119
+ /**
120
+ * Every registration exported by one module namespace, with its export name.
121
+ *
122
+ * Both a registration and an array of them count, at any export name including
123
+ * `default`. Nothing here calls a value to find out what it is: functions are
124
+ * rejected structurally by {@link isHookRegistration}.
125
+ */
126
+ function collectFromNamespace(namespace, file, dir) {
127
+ if (typeof namespace !== 'object' || namespace === null) {
128
+ return [];
129
+ }
130
+ const collected = [];
131
+ for (const exportName of Object.keys(namespace)) {
132
+ let value;
133
+ try {
134
+ value = namespace[exportName];
135
+ }
136
+ catch {
137
+ // A getter that throws is not a hook; the module's other exports stand.
138
+ continue;
139
+ }
140
+ if (isHookRegistration(value)) {
141
+ collected.push({
142
+ registration: value,
143
+ file,
144
+ dir,
145
+ exportName,
146
+ sequence: 0,
147
+ });
148
+ continue;
149
+ }
150
+ if (Array.isArray(value)) {
151
+ for (const element of value) {
152
+ if (isHookRegistration(element)) {
153
+ collected.push({
154
+ registration: element,
155
+ file,
156
+ dir,
157
+ exportName,
158
+ sequence: 0,
159
+ });
160
+ }
161
+ }
162
+ }
163
+ }
164
+ return collected;
165
+ }
166
+ /**
167
+ * jiti's module cache is Node's own `require.cache`, which is one object per
168
+ * process, so the loader can read it through any `require`.
169
+ */
170
+ function moduleCache() {
171
+ return createRequire(import.meta.url).cache;
172
+ }
173
+ /**
174
+ * Forget every module one scan evaluated, so the next scan evaluates the
175
+ * files as they are then.
176
+ *
177
+ * The module cache is on for the scan's sake, not the process's: a hook file
178
+ * may be edited between two scans of one long-lived process — `thymian serve`
179
+ * dispatching `validate` after every save — and so may a module a hook file
180
+ * imports. Evicting exactly what the scan added, rather than what lies under
181
+ * the hooks directory, is what covers that second case, and it keeps the
182
+ * cache from growing by one scan's worth of entries per call. A registration
183
+ * already collected is unaffected: it is held by reference, and the cache
184
+ * entry was only ever the way to reach it.
185
+ */
186
+ function evictScannedModules(cachedBefore) {
187
+ const cache = moduleCache();
188
+ for (const id of Object.keys(cache)) {
189
+ // An installed package is not edited between scans, and jiti's own
190
+ // transformer is among them: evicting it would re-load the transpiler
191
+ // on every scan for nothing.
192
+ if (!cachedBefore.has(id) && !/[\\/]node_modules[\\/]/.test(id)) {
193
+ delete cache[id];
194
+ }
195
+ }
196
+ }
197
+ /**
198
+ * Make every path jiti resolves under the hooks directory take ONE spelling,
199
+ * so a file is one module-cache entry however it was reached. Returns the
200
+ * function that undoes it.
201
+ *
202
+ * jiti keys its module cache by the path its resolver returns, and it has two
203
+ * resolvers that spell a path differently on Windows. A path that exists as
204
+ * written — every file the scan imports, `./shared.ts`, `./shared` — goes
205
+ * through exsolve and comes back with forward slashes. `./shared.js` naming a
206
+ * `.ts` file does not exist as written, so jiti rewrites it to `.ts` and asks
207
+ * Node's `require.resolve`, which answers with backslashes. `C:/…/shared.ts`
208
+ * and `C:\…\shared.ts` are two cache entries, so the file was evaluated twice:
209
+ * a re-exported hook was two objects, a re-exported `defineSample` a conflict
210
+ * with itself, and an import cycle re-entered its first file and created a
211
+ * hook nothing exported. On POSIX both spellings are the same string, which is
212
+ * why only Windows saw it.
213
+ *
214
+ * `Module._resolveFilename` is what `require.resolve` calls, so rewriting its
215
+ * answer to forward slashes aligns the second resolver with the first. It is
216
+ * scoped to the scan and to paths under `root`, so nothing else in the process
217
+ * resolves differently, and it is a no-op where the separator already is `/`.
218
+ */
219
+ function unifyResolvedPathSpelling(root) {
220
+ if (sep === '/') {
221
+ return () => undefined;
222
+ }
223
+ // Private Node API, absent from the type declarations.
224
+ const internals = Module;
225
+ const original = internals._resolveFilename;
226
+ internals._resolveFilename = function (request, ...rest) {
227
+ const resolved = original.call(this, request, ...rest);
228
+ const fromRoot = relative(root, resolved);
229
+ return fromRoot.startsWith('..') || isAbsolute(fromRoot)
230
+ ? resolved
231
+ : resolved.replaceAll('\\', '/');
232
+ };
233
+ return () => {
234
+ internals._resolveFilename = original;
235
+ };
236
+ }
237
+ function emptyTransactionHooks() {
238
+ return {
239
+ defineSample: [],
240
+ beforeEach: [],
241
+ afterEach: [],
242
+ authorize: [],
243
+ };
244
+ }
245
+ /**
246
+ * Scan the hooks directory and bind every registration it exports to the
247
+ * Transactions it names.
248
+ *
249
+ * A hooks directory that does not exist is not an error — `sampler init` is
250
+ * optional and a project may have no hooks at all — it is an empty result.
251
+ */
252
+ export async function loadUserHooks(hooksDir, catalog) {
253
+ const diagnostics = [];
254
+ const conflicts = [];
255
+ const unexported = [];
256
+ const warnings = [];
257
+ const byTransactionId = new Map();
258
+ const runScoped = {
259
+ beforeAll: [],
260
+ afterAll: [],
261
+ };
262
+ const globalAuthorize = [];
263
+ if (!(await entryExists(hooksDir))) {
264
+ return {
265
+ files: [],
266
+ byTransactionId,
267
+ runScoped,
268
+ globalAuthorize,
269
+ diagnostics,
270
+ conflicts,
271
+ unexported,
272
+ warnings,
273
+ };
274
+ }
275
+ // The REAL path, because the module cache is keyed by what jiti resolves an
276
+ // import to, and jiti resolves through symlinks. Handed a path with a
277
+ // symlink in it — macOS's `/var` is one onto `/private/var` — the file the
278
+ // scan imports and the same file reached through `./shared.js` were two
279
+ // cache entries, evaluated twice, and the re-export was two objects again.
280
+ const root = await realpath(hooksDir);
281
+ const found = [];
282
+ await walkHookDirectory(root, root, true, found, warnings);
283
+ const files = found
284
+ .map((full) => ({ full, key: hooksDirRelative(root, full) }))
285
+ .sort((a, b) => compareKeys(a.key, b.key));
286
+ const jiti = createJiti(hooksRuntimeModule, {
287
+ alias: { [HOOKS_RUNTIME_SPECIFIER]: hooksRuntimeModule },
288
+ // A hook file is user code that may have been edited between runs, and a
289
+ // run is short-lived: nothing is gained by caching its transpilation, and a
290
+ // stale entry would be served silently.
291
+ fsCache: false,
292
+ // Cached for the span of ONE scan — see `evictScannedModules`. With the
293
+ // cache off, a module two hook files import was evaluated once per
294
+ // importer, so a re-exported hook was a different object per exporting
295
+ // file: bound twice, and a re-exported `defineSample` a conflict with
296
+ // itself. A re-export is the same binding in ESM; caching for the scan
297
+ // makes it the same object here too, which is what lets `collected` be
298
+ // deduplicated by identity below without touching the conflict check
299
+ // — two genuinely distinct hooks remain two objects.
300
+ moduleCache: true,
301
+ });
302
+ const collected = [];
303
+ // Emptied per scan, so what it holds is this scan's registrations and the
304
+ // slice taken after each import is that file's.
305
+ const created = createdRegistrations();
306
+ const createdPerFile = [];
307
+ const exported = new Set();
308
+ const cachedBefore = new Set(Object.keys(moduleCache()));
309
+ created.length = 0;
310
+ const restoreResolution = unifyResolvedPathSpelling(root);
311
+ try {
312
+ for (const { full, key } of files) {
313
+ const createdBefore = created.length;
314
+ let namespace;
315
+ try {
316
+ namespace = await jiti.import(full);
317
+ }
318
+ catch (error) {
319
+ throw hookFileImportError(key, error);
320
+ }
321
+ // Registration order **within the file**, not export order: an ESM
322
+ // namespace exposes its keys sorted, so `order` is the only thing that
323
+ // knows which hook the file created first.
324
+ //
325
+ // Sorted per file rather than once at the end: `order` is stamped by the
326
+ // hooks runtime at creation, and a hook created in a shared module is
327
+ // created when the FIRST importer is evaluated, so a global sort by
328
+ // `order` would interleave the files. File order is the outer key and
329
+ // it is already deterministic; `order` only has to sequence what one
330
+ // file exports.
331
+ const fromFile = collectFromNamespace(namespace, key, dirname(full)).sort((a, b) => a.registration.order - b.registration.order);
332
+ createdPerFile.push({ file: key, created: created.slice(createdBefore) });
333
+ for (const entry of fromFile) {
334
+ // One hook, however many files re-export it. The first exporting file
335
+ // in load order is the one it is attributed to.
336
+ if (exported.has(entry.registration)) {
337
+ continue;
338
+ }
339
+ exported.add(entry.registration);
340
+ collected.push(entry);
341
+ }
342
+ }
343
+ }
344
+ finally {
345
+ restoreResolution();
346
+ evictScannedModules(cachedBefore);
347
+ }
348
+ // A hook created and never exported is unreachable: discovery is
349
+ // export-based, so it never fires, and a hook that never fires looks exactly
350
+ // like one with nothing to do. It was the only failure here that was silent.
351
+ //
352
+ // Checked only once every file has been scanned, because a hook created in a
353
+ // shared module is created when the first file that IMPORTS it is evaluated
354
+ // — accusing that file would fail a run over a hook that another file
355
+ // exports and that does fire.
356
+ for (const { file, created: createdHere } of createdPerFile) {
357
+ for (const registration of createdHere) {
358
+ if (exported.has(registration)) {
359
+ continue;
360
+ }
361
+ unexported.push({
362
+ file,
363
+ reason: `a ${registration.kind} hook was created here but never exported, so nothing can reach it`,
364
+ suggestions: [
365
+ `Assign it to an export, as in: export const shape = ${registration.kind}(...)`,
366
+ ],
367
+ });
368
+ }
369
+ }
370
+ // One number ordering every hook in the run against every other. Assigned
371
+ // here, once the file-then-registration order is settled, because that is the
372
+ // only place both halves are known.
373
+ collected.forEach((entry, index) => {
374
+ entry.sequence = index;
375
+ });
376
+ for (const entry of collected) {
377
+ const { registration } = entry;
378
+ if (registration.kind === 'beforeAll' || registration.kind === 'afterAll') {
379
+ runScoped[registration.kind].push(entry);
380
+ continue;
381
+ }
382
+ if (registration.kind === 'authorize' &&
383
+ registration.target === undefined) {
384
+ globalAuthorize.push(entry);
385
+ continue;
386
+ }
387
+ const targeted = resolveTargeting(registration.kind, registration.target, entry, catalog, diagnostics);
388
+ for (const transaction of targeted) {
389
+ let hooks = byTransactionId.get(transaction.transactionId);
390
+ if (!hooks) {
391
+ hooks = emptyTransactionHooks();
392
+ byTransactionId.set(transaction.transactionId, hooks);
393
+ }
394
+ // `defineSample` is set-once per Transaction. A second one is a conflict
395
+ // rather than a last-wins override, and it is reported at load time —
396
+ // not when that Transaction happens to be sampled — because the mistake
397
+ // exists whether or not the run reaches it.
398
+ const conflicting = hooks.defineSample[0];
399
+ if (registration.kind === 'defineSample' && conflicting) {
400
+ conflicts.push({
401
+ file: entry.file,
402
+ exportName: entry.exportName,
403
+ reason: `defineSample is already defined for the selector "${catalog.selectorFor(transaction.transactionId) ?? transaction.transactionId}" by "${conflicting.exportName}" in ${conflicting.file}; a Transaction can have only one`,
404
+ suggestions: [
405
+ 'Merge the two into one defineSample, or target a different selector.',
406
+ ],
407
+ });
408
+ continue;
409
+ }
410
+ // Two authorize hooks in the same tier on one Transaction: the later one
411
+ // wins, which is what lets a file override an earlier one — but silently
412
+ // dropping a set of credentials is worth a word, since a reader who just
413
+ // met the `defineSample` conflict will expect one.
414
+ const supersededAuthorize = registration.kind === 'authorize' ? hooks.authorize.at(-1) : undefined;
415
+ if (supersededAuthorize) {
416
+ warnings.push(`Two authorize hooks target the same transaction: "${entry.exportName}" in ${entry.file} supersedes "${supersededAuthorize.exportName}" in ${supersededAuthorize.file}. Only the last one runs.`);
417
+ }
418
+ hooks[registration.kind].push(entry);
419
+ }
420
+ }
421
+ return {
422
+ files: files.map(({ key }) => key),
423
+ byTransactionId,
424
+ runScoped,
425
+ globalAuthorize,
426
+ diagnostics,
427
+ conflicts,
428
+ unexported,
429
+ warnings,
430
+ };
431
+ }
432
+ //# sourceMappingURL=load-user-hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-user-hooks.js","sourceRoot":"","sources":["../../src/hooks/load-user-hooks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { ThymianBaseError } from '@thymian/core';
2
+ import type { Selector } from '../selectors/selector.js';
3
+ /**
4
+ * The Selectors whose pipelines are currently on the stack.
5
+ *
6
+ * Travels with the hook context rather than living in the runner, because that
7
+ * is what makes the guard reflect *this* call's ancestry instead of whatever
8
+ * the runner happened to be doing last.
9
+ */
10
+ export type SelectorChain = readonly Selector[];
11
+ /**
12
+ * A seeding call has re-entered a Transaction already on the stack.
13
+ *
14
+ * Printing the chain is the whole point: `A → B → A` is a mistake three files
15
+ * apart, and the middle of the cycle is where the fix goes. Without it the run
16
+ * would recurse until the stack gave out, and a stack overflow names nothing.
17
+ */
18
+ export declare function requestCycleError(chain: SelectorChain, selector: Selector): ThymianBaseError;
19
+ /** Whether `selector` is already on `chain`. */
20
+ export declare function isOnChain(chain: SelectorChain, selector: Selector): boolean;
21
+ //# sourceMappingURL=nested-request.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nested-request.d.ts","sourceRoot":"","sources":["../../src/hooks/nested-request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEzD;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GAAG,SAAS,QAAQ,EAAE,CAAC;AAEhD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,aAAa,EACpB,QAAQ,EAAE,QAAQ,GACjB,gBAAgB,CAclB;AAED,gDAAgD;AAChD,wBAAgB,SAAS,CAAC,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAE3E"}
@@ -0,0 +1,24 @@
1
+ import { ThymianBaseError } from '@thymian/core';
2
+ /**
3
+ * A seeding call has re-entered a Transaction already on the stack.
4
+ *
5
+ * Printing the chain is the whole point: `A → B → A` is a mistake three files
6
+ * apart, and the middle of the cycle is where the fix goes. Without it the run
7
+ * would recurse until the stack gave out, and a stack overflow names nothing.
8
+ */
9
+ export function requestCycleError(chain, selector) {
10
+ const path = [...chain, selector].map((entry) => `"${entry}"`).join('\n → ');
11
+ return new ThymianBaseError(`A cross-endpoint request would re-enter "${selector}", which is already running.`, {
12
+ name: 'RequestCycleError',
13
+ ref: 'https://thymian.dev/references/errors/request-cycle-error/',
14
+ suggestions: [
15
+ `The chain is:\n ${path}`,
16
+ 'Break the cycle, or pass `{ runHooks: false }` to seed from the raw request without running the target’s hooks.',
17
+ ],
18
+ });
19
+ }
20
+ /** Whether `selector` is already on `chain`. */
21
+ export function isOnChain(chain, selector) {
22
+ return chain.includes(selector);
23
+ }
24
+ //# sourceMappingURL=nested-request.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nested-request.js","sourceRoot":"","sources":["../../src/hooks/nested-request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAajD;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,KAAoB,EACpB,QAAkB;IAElB,MAAM,IAAI,GAAG,CAAC,GAAG,KAAK,EAAE,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAE9E,OAAO,IAAI,gBAAgB,CACzB,4CAA4C,QAAQ,8BAA8B,EAClF;QACE,IAAI,EAAE,mBAAmB;QACzB,GAAG,EAAE,4DAA4D;QACjE,WAAW,EAAE;YACX,oBAAoB,IAAI,EAAE;YAC1B,iHAAiH;SAClH;KACF,CACF,CAAC;AACJ,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,SAAS,CAAC,KAAoB,EAAE,QAAkB;IAChE,OAAO,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAClC,CAAC"}
@@ -0,0 +1,40 @@
1
+ import type { HttpRequestTemplate } from '@thymian/core';
2
+ import type { EndpointRequest } from './hook-utils.js';
3
+ /**
4
+ * Overlays a caller's arguments onto a generated request.
5
+ *
6
+ * The generated sample plus the target's own hooks already produce a complete,
7
+ * schema-satisfying request. Arguments are therefore an **overlay**, not a
8
+ * replacement: a seeding call states the one field that has to differ — a name
9
+ * it will assert on later, an id it just created — and inherits everything
10
+ * else. Requiring the whole request instead made the caller re-state a body
11
+ * the description had already described.
12
+ *
13
+ * Parameter groups merge per key. The body deep-merges (see
14
+ * {@link deepMergeBody}).
15
+ */
16
+ export declare function applyArgs(template: HttpRequestTemplate, args: EndpointRequest): HttpRequestTemplate;
17
+ /**
18
+ * Merges an overlay body onto the generated one: **objects recurse, arrays and
19
+ * primitives replace, `null` overrides.**
20
+ *
21
+ * Arrays replace rather than merge because a positional merge needs an index
22
+ * the caller cannot know is stable, and a per-element merge would produce
23
+ * elements the schema never described. `null` overrides for the same reason it
24
+ * is not "absent": a description that allows `null` means it, and merging
25
+ * around it would make the one value you cannot express the one you meant.
26
+ *
27
+ * Written here rather than taken from a library so that the rule the generated
28
+ * `DeepPartial` types promise and the rule the runtime applies are the same
29
+ * three sentences, in one place.
30
+ *
31
+ * Every key is handled as an **own property**, never through `in` or a bare
32
+ * `[key] =` assignment. `key in base` is true for `'toString'` on a base that
33
+ * never declared it — it walks the prototype chain — and `merged[key] = …`
34
+ * for `key === '__proto__'` does not create a data property at all: it
35
+ * invokes the inherited setter and repoints `merged`'s own prototype. Neither
36
+ * is a filter field's schema value; a body field named `__proto__` is exactly
37
+ * as ordinary as one named anything else, and this is what makes it one.
38
+ */
39
+ export declare function deepMergeBody(base: unknown, overlay: unknown): unknown;
40
+ //# sourceMappingURL=overlay-args.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overlay-args.d.ts","sourceRoot":"","sources":["../../src/hooks/overlay-args.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEvD;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CACvB,QAAQ,EAAE,mBAAmB,EAC7B,IAAI,EAAE,eAAe,GACpB,mBAAmB,CAerB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAsBtE"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Overlays a caller's arguments onto a generated request.
3
+ *
4
+ * The generated sample plus the target's own hooks already produce a complete,
5
+ * schema-satisfying request. Arguments are therefore an **overlay**, not a
6
+ * replacement: a seeding call states the one field that has to differ — a name
7
+ * it will assert on later, an id it just created — and inherits everything
8
+ * else. Requiring the whole request instead made the caller re-state a body
9
+ * the description had already described.
10
+ *
11
+ * Parameter groups merge per key. The body deep-merges (see
12
+ * {@link deepMergeBody}).
13
+ */
14
+ export function applyArgs(template, args) {
15
+ return {
16
+ ...template,
17
+ headers: { ...template.headers, ...args.headers },
18
+ query: { ...template.query, ...args.query },
19
+ cookies: { ...template.cookies, ...args.cookies },
20
+ pathParameters: { ...template.pathParameters, ...args.path },
21
+ // `Object.hasOwn`, never `in`: `in` walks the prototype chain, so an args
22
+ // object inheriting a `body` — from `Object.prototype` being polluted, or
23
+ // from a caller's own base object — would overlay a body the caller never
24
+ // passed.
25
+ ...(Object.hasOwn(args, 'body')
26
+ ? { body: deepMergeBody(template.body, args.body) }
27
+ : {}),
28
+ };
29
+ }
30
+ /**
31
+ * Merges an overlay body onto the generated one: **objects recurse, arrays and
32
+ * primitives replace, `null` overrides.**
33
+ *
34
+ * Arrays replace rather than merge because a positional merge needs an index
35
+ * the caller cannot know is stable, and a per-element merge would produce
36
+ * elements the schema never described. `null` overrides for the same reason it
37
+ * is not "absent": a description that allows `null` means it, and merging
38
+ * around it would make the one value you cannot express the one you meant.
39
+ *
40
+ * Written here rather than taken from a library so that the rule the generated
41
+ * `DeepPartial` types promise and the rule the runtime applies are the same
42
+ * three sentences, in one place.
43
+ *
44
+ * Every key is handled as an **own property**, never through `in` or a bare
45
+ * `[key] =` assignment. `key in base` is true for `'toString'` on a base that
46
+ * never declared it — it walks the prototype chain — and `merged[key] = …`
47
+ * for `key === '__proto__'` does not create a data property at all: it
48
+ * invokes the inherited setter and repoints `merged`'s own prototype. Neither
49
+ * is a filter field's schema value; a body field named `__proto__` is exactly
50
+ * as ordinary as one named anything else, and this is what makes it one.
51
+ */
52
+ export function deepMergeBody(base, overlay) {
53
+ if (!isPlainObject(base) || !isPlainObject(overlay)) {
54
+ return overlay;
55
+ }
56
+ const merged = { ...base };
57
+ for (const key of Object.keys(overlay)) {
58
+ const value = overlay[key];
59
+ const next = Object.prototype.hasOwnProperty.call(base, key)
60
+ ? deepMergeBody(base[key], value)
61
+ : value;
62
+ Object.defineProperty(merged, key, {
63
+ value: next,
64
+ writable: true,
65
+ enumerable: true,
66
+ configurable: true,
67
+ });
68
+ }
69
+ return merged;
70
+ }
71
+ /**
72
+ * A JSON object, and nothing that merely looks like one.
73
+ *
74
+ * `null`, arrays, `Buffer`s and dates all answer `'object'` to `typeof`, and
75
+ * every one of them is a value the caller means to replace whole.
76
+ */
77
+ function isPlainObject(value) {
78
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
79
+ return false;
80
+ }
81
+ const prototype = Object.getPrototypeOf(value);
82
+ return prototype === Object.prototype || prototype === null;
83
+ }
84
+ //# sourceMappingURL=overlay-args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overlay-args.js","sourceRoot":"","sources":["../../src/hooks/overlay-args.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,SAAS,CACvB,QAA6B,EAC7B,IAAqB;IAErB,OAAO;QACL,GAAG,QAAQ;QACX,OAAO,EAAE,EAAE,GAAG,QAAQ,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE;QACjD,KAAK,EAAE,EAAE,GAAG,QAAQ,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE;QAC3C,OAAO,EAAE,EAAE,GAAG,QAAQ,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE;QACjD,cAAc,EAAE,EAAE,GAAG,QAAQ,CAAC,cAAc,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE;QAC5D,0EAA0E;QAC1E,0EAA0E;QAC1E,0EAA0E;QAC1E,UAAU;QACV,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC;YAC7B,CAAC,CAAC,EAAE,IAAI,EAAE,aAAa,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE;YACnD,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,aAAa,CAAC,IAAa,EAAE,OAAgB;IAC3D,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;QACpD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,MAAM,GAA4B,EAAE,GAAG,IAAI,EAAE,CAAC;IAEpD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC3B,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC;YAC1D,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC;YACjC,CAAC,CAAC,KAAK,CAAC;QAEV,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,GAAG,EAAE;YACjC,KAAK,EAAE,IAAI;YACX,QAAQ,EAAE,IAAI;YACd,UAAU,EAAE,IAAI;YAChB,YAAY,EAAE,IAAI;SACnB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,SAAS,aAAa,CAAC,KAAc;IACnC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACxE,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,CAAC,cAAc,CAAC,KAAK,CAAY,CAAC;IAE1D,OAAO,SAAS,KAAK,MAAM,CAAC,SAAS,IAAI,SAAS,KAAK,IAAI,CAAC;AAC9D,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { ThymianHttpTransaction } from '@thymian/core';
2
+ import type { TransactionCatalog } from '../selectors/transaction-catalog.js';
3
+ import type { HookDiagnostic } from './hook-diagnostics.js';
4
+ import type { CollectedRegistration } from './load-user-hooks.js';
5
+ /**
6
+ * The Transactions a target covers, reporting whatever stops it covering any.
7
+ *
8
+ * A target that resolves to nothing is a diagnostic, never an empty result that
9
+ * runs quietly. There are four ways a hook can silently stop doing its job — a
10
+ * dangling Selector, a value that is not a legal filter value, a path or glob
11
+ * that names nothing, and a filter whose legal values intersect nothing — and
12
+ * each one gets its own sentence, because "this matched nothing" is true and
13
+ * useless when the cause is one typo.
14
+ */
15
+ export declare function resolveTargeting(kind: string, target: unknown, entry: CollectedRegistration, catalog: TransactionCatalog, diagnostics: HookDiagnostic[]): readonly ThymianHttpTransaction[];
16
+ //# sourceMappingURL=resolve-targeting.d.ts.map