@lovrozagar/oat 0.9.1 → 0.11.0

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 (283) hide show
  1. package/README.md +26 -1936
  2. package/dist/cli.js +326 -60
  3. package/dist/config/define-config.d.ts +15 -1
  4. package/dist/config/define-config.d.ts.map +1 -1
  5. package/dist/config/define-config.js.map +1 -1
  6. package/dist/config/validate.d.ts +12 -0
  7. package/dist/config/validate.d.ts.map +1 -0
  8. package/dist/config/validate.js +86 -0
  9. package/dist/config/validate.js.map +1 -0
  10. package/dist/conformance/effects.d.ts +9 -0
  11. package/dist/conformance/effects.d.ts.map +1 -0
  12. package/dist/conformance/effects.js +276 -0
  13. package/dist/conformance/effects.js.map +1 -0
  14. package/dist/conformance/expected-failures.d.ts +18 -0
  15. package/dist/conformance/expected-failures.d.ts.map +1 -0
  16. package/dist/conformance/expected-failures.js +48 -0
  17. package/dist/conformance/expected-failures.js.map +1 -0
  18. package/dist/conformance/feature-gate.d.ts +7 -0
  19. package/dist/conformance/feature-gate.d.ts.map +1 -0
  20. package/dist/conformance/feature-gate.js +428 -0
  21. package/dist/conformance/feature-gate.js.map +1 -0
  22. package/dist/conformance/fuzz.d.ts +108 -0
  23. package/dist/conformance/fuzz.d.ts.map +1 -0
  24. package/dist/conformance/fuzz.js +246 -0
  25. package/dist/conformance/fuzz.js.map +1 -0
  26. package/dist/conformance/leaks.d.ts +10 -0
  27. package/dist/conformance/leaks.d.ts.map +1 -0
  28. package/dist/conformance/leaks.js +23 -0
  29. package/dist/conformance/leaks.js.map +1 -0
  30. package/dist/conformance/pool.d.ts +49 -0
  31. package/dist/conformance/pool.d.ts.map +1 -0
  32. package/dist/conformance/pool.js +75 -0
  33. package/dist/conformance/pool.js.map +1 -0
  34. package/dist/conformance/rate-limit.d.ts +7 -0
  35. package/dist/conformance/rate-limit.d.ts.map +1 -0
  36. package/dist/conformance/rate-limit.js +372 -0
  37. package/dist/conformance/rate-limit.js.map +1 -0
  38. package/dist/conformance/scope.d.ts +15 -0
  39. package/dist/conformance/scope.d.ts.map +1 -0
  40. package/dist/conformance/scope.js +78 -0
  41. package/dist/conformance/scope.js.map +1 -0
  42. package/dist/conformance/seed-contract.d.ts +11 -0
  43. package/dist/conformance/seed-contract.d.ts.map +1 -0
  44. package/dist/conformance/seed-contract.js +680 -0
  45. package/dist/conformance/seed-contract.js.map +1 -0
  46. package/dist/conformance/shapes.d.ts +35 -0
  47. package/dist/conformance/shapes.d.ts.map +1 -0
  48. package/dist/conformance/shapes.js +162 -0
  49. package/dist/conformance/shapes.js.map +1 -0
  50. package/dist/conformance/specs.d.ts +21 -0
  51. package/dist/conformance/specs.d.ts.map +1 -0
  52. package/dist/conformance/specs.js +306 -0
  53. package/dist/conformance/specs.js.map +1 -0
  54. package/dist/conformance/suite.d.ts +209 -0
  55. package/dist/conformance/suite.d.ts.map +1 -0
  56. package/dist/conformance/suite.js +1538 -0
  57. package/dist/conformance/suite.js.map +1 -0
  58. package/dist/conformance/unique.d.ts +7 -0
  59. package/dist/conformance/unique.d.ts.map +1 -0
  60. package/dist/conformance/unique.js +586 -0
  61. package/dist/conformance/unique.js.map +1 -0
  62. package/dist/conformance/worker.d.ts +3 -0
  63. package/dist/conformance/worker.d.ts.map +1 -0
  64. package/dist/conformance/worker.js +27 -0
  65. package/dist/conformance/worker.js.map +1 -0
  66. package/dist/index.d.ts +10 -3
  67. package/dist/index.js +6 -2
  68. package/dist/reference/defects.d.ts +71 -1
  69. package/dist/reference/defects.d.ts.map +1 -1
  70. package/dist/reference/defects.js +74 -8
  71. package/dist/reference/defects.js.map +1 -1
  72. package/dist/reference/dialect.d.ts +6 -4
  73. package/dist/reference/dialect.d.ts.map +1 -1
  74. package/dist/reference/dialect.js +1 -0
  75. package/dist/reference/dialect.js.map +1 -1
  76. package/dist/reference/http.d.ts +17 -25
  77. package/dist/reference/http.d.ts.map +1 -1
  78. package/dist/reference/http.js +574 -224
  79. package/dist/reference/http.js.map +1 -1
  80. package/dist/reference/listing.d.ts +51 -0
  81. package/dist/reference/listing.d.ts.map +1 -0
  82. package/dist/reference/listing.js +256 -0
  83. package/dist/reference/listing.js.map +1 -0
  84. package/dist/reference/model.d.ts +35 -1
  85. package/dist/reference/model.d.ts.map +1 -1
  86. package/dist/reference/model.js +42 -0
  87. package/dist/reference/model.js.map +1 -1
  88. package/dist/reference/query.d.ts +132 -43
  89. package/dist/reference/query.d.ts.map +1 -1
  90. package/dist/reference/query.js +397 -315
  91. package/dist/reference/query.js.map +1 -1
  92. package/dist/reference/shapes.d.ts +60 -0
  93. package/dist/reference/shapes.d.ts.map +1 -0
  94. package/dist/reference/shapes.js +142 -0
  95. package/dist/reference/shapes.js.map +1 -0
  96. package/dist/reference/spec.d.ts +9 -2
  97. package/dist/reference/spec.d.ts.map +1 -1
  98. package/dist/reference/spec.js +291 -71
  99. package/dist/reference/spec.js.map +1 -1
  100. package/dist/reference/store-api.d.ts +14 -43
  101. package/dist/reference/store-api.d.ts.map +1 -1
  102. package/dist/reference/store-api.js +8 -58
  103. package/dist/reference/store-api.js.map +1 -1
  104. package/dist/reference/stores/memory.d.ts +12 -15
  105. package/dist/reference/stores/memory.d.ts.map +1 -1
  106. package/dist/reference/stores/memory.js +22 -70
  107. package/dist/reference/stores/memory.js.map +1 -1
  108. package/dist/reference/stores/postgres.d.ts +11 -23
  109. package/dist/reference/stores/postgres.d.ts.map +1 -1
  110. package/dist/reference/stores/postgres.js +53 -334
  111. package/dist/reference/stores/postgres.js.map +1 -1
  112. package/dist/reference/stores/sql-compile.d.ts +36 -0
  113. package/dist/reference/stores/sql-compile.d.ts.map +1 -0
  114. package/dist/reference/stores/sql-compile.js +95 -0
  115. package/dist/reference/stores/sql-compile.js.map +1 -0
  116. package/dist/reference/stores/sqlite.d.ts +12 -27
  117. package/dist/reference/stores/sqlite.d.ts.map +1 -1
  118. package/dist/reference/stores/sqlite.js +54 -355
  119. package/dist/reference/stores/sqlite.js.map +1 -1
  120. package/dist/report/console.d.ts +2 -1
  121. package/dist/report/console.d.ts.map +1 -1
  122. package/dist/report/console.js +56 -10
  123. package/dist/report/console.js.map +1 -1
  124. package/dist/report/matrix.d.ts +10 -13
  125. package/dist/report/matrix.d.ts.map +1 -1
  126. package/dist/report/matrix.js +82 -18
  127. package/dist/report/matrix.js.map +1 -1
  128. package/dist/report/render.d.ts +18 -1
  129. package/dist/report/render.d.ts.map +1 -1
  130. package/dist/report/render.js +169 -14
  131. package/dist/report/render.js.map +1 -1
  132. package/dist/runtime/async.d.ts +16 -3
  133. package/dist/runtime/async.d.ts.map +1 -1
  134. package/dist/runtime/async.js +24 -19
  135. package/dist/runtime/async.js.map +1 -1
  136. package/dist/runtime/auth.d.ts +2 -9
  137. package/dist/runtime/auth.d.ts.map +1 -1
  138. package/dist/runtime/auth.js +38 -62
  139. package/dist/runtime/auth.js.map +1 -1
  140. package/dist/runtime/body.d.ts +15 -3
  141. package/dist/runtime/body.d.ts.map +1 -1
  142. package/dist/runtime/body.js +61 -12
  143. package/dist/runtime/body.js.map +1 -1
  144. package/dist/runtime/check-costs.d.ts +15 -0
  145. package/dist/runtime/check-costs.d.ts.map +1 -0
  146. package/dist/runtime/check-costs.js +114 -0
  147. package/dist/runtime/check-costs.js.map +1 -0
  148. package/dist/runtime/check-ids.d.ts +15 -0
  149. package/dist/runtime/check-ids.d.ts.map +1 -0
  150. package/dist/runtime/check-ids.js +140 -0
  151. package/dist/runtime/check-ids.js.map +1 -0
  152. package/dist/runtime/checks.d.ts +122 -18
  153. package/dist/runtime/checks.d.ts.map +1 -1
  154. package/dist/runtime/checks.js +3437 -1933
  155. package/dist/runtime/checks.js.map +1 -1
  156. package/dist/runtime/client.d.ts +112 -0
  157. package/dist/runtime/client.d.ts.map +1 -1
  158. package/dist/runtime/client.js +271 -39
  159. package/dist/runtime/client.js.map +1 -1
  160. package/dist/runtime/cookies.d.ts +16 -2
  161. package/dist/runtime/cookies.d.ts.map +1 -1
  162. package/dist/runtime/cookies.js +83 -22
  163. package/dist/runtime/cookies.js.map +1 -1
  164. package/dist/runtime/exchanges.d.ts +4 -5
  165. package/dist/runtime/exchanges.d.ts.map +1 -1
  166. package/dist/runtime/exchanges.js +33 -55
  167. package/dist/runtime/exchanges.js.map +1 -1
  168. package/dist/runtime/exit.d.ts +40 -0
  169. package/dist/runtime/exit.d.ts.map +1 -0
  170. package/dist/runtime/exit.js +48 -0
  171. package/dist/runtime/exit.js.map +1 -0
  172. package/dist/runtime/feature-gate.d.ts +0 -9
  173. package/dist/runtime/feature-gate.d.ts.map +1 -1
  174. package/dist/runtime/feature-gate.js +0 -21
  175. package/dist/runtime/feature-gate.js.map +1 -1
  176. package/dist/runtime/finding.d.ts +61 -7
  177. package/dist/runtime/finding.d.ts.map +1 -1
  178. package/dist/runtime/finding.js +74 -12
  179. package/dist/runtime/finding.js.map +1 -1
  180. package/dist/runtime/fixture.d.ts +35 -28
  181. package/dist/runtime/fixture.d.ts.map +1 -1
  182. package/dist/runtime/fixture.js +92 -731
  183. package/dist/runtime/fixture.js.map +1 -1
  184. package/dist/runtime/generate.d.ts +63 -0
  185. package/dist/runtime/generate.d.ts.map +1 -0
  186. package/dist/runtime/generate.js +635 -0
  187. package/dist/runtime/generate.js.map +1 -0
  188. package/dist/runtime/headers.d.ts +6 -0
  189. package/dist/runtime/headers.d.ts.map +1 -0
  190. package/dist/runtime/headers.js +16 -0
  191. package/dist/runtime/headers.js.map +1 -0
  192. package/dist/runtime/path.d.ts +7 -0
  193. package/dist/runtime/path.d.ts.map +1 -0
  194. package/dist/runtime/path.js +44 -0
  195. package/dist/runtime/path.js.map +1 -0
  196. package/dist/runtime/payloads.d.ts +2 -0
  197. package/dist/runtime/payloads.d.ts.map +1 -1
  198. package/dist/runtime/payloads.js +2 -1
  199. package/dist/runtime/payloads.js.map +1 -1
  200. package/dist/runtime/rate-limit.d.ts +6 -4
  201. package/dist/runtime/rate-limit.d.ts.map +1 -1
  202. package/dist/runtime/rate-limit.js +22 -33
  203. package/dist/runtime/rate-limit.js.map +1 -1
  204. package/dist/runtime/redact.d.ts +24 -0
  205. package/dist/runtime/redact.d.ts.map +1 -0
  206. package/dist/runtime/redact.js +98 -0
  207. package/dist/runtime/redact.js.map +1 -0
  208. package/dist/runtime/run.d.ts +51 -2
  209. package/dist/runtime/run.d.ts.map +1 -1
  210. package/dist/runtime/run.js +463 -195
  211. package/dist/runtime/run.js.map +1 -1
  212. package/dist/runtime/runs.d.ts +5 -0
  213. package/dist/runtime/runs.d.ts.map +1 -1
  214. package/dist/runtime/runs.js +7 -1
  215. package/dist/runtime/runs.js.map +1 -1
  216. package/dist/runtime/scope.d.ts +163 -0
  217. package/dist/runtime/scope.d.ts.map +1 -0
  218. package/dist/runtime/scope.js +423 -0
  219. package/dist/runtime/scope.js.map +1 -0
  220. package/dist/runtime/teardown.d.ts +17 -4
  221. package/dist/runtime/teardown.d.ts.map +1 -1
  222. package/dist/runtime/teardown.js +49 -16
  223. package/dist/runtime/teardown.js.map +1 -1
  224. package/dist/runtime/transcript.d.ts +34 -2
  225. package/dist/runtime/transcript.d.ts.map +1 -1
  226. package/dist/runtime/transcript.js +119 -24
  227. package/dist/runtime/transcript.js.map +1 -1
  228. package/dist/runtime/unique.d.ts +2 -11
  229. package/dist/runtime/unique.d.ts.map +1 -1
  230. package/dist/runtime/unique.js +27 -53
  231. package/dist/runtime/unique.js.map +1 -1
  232. package/dist/runtime/validate.d.ts +13 -2
  233. package/dist/runtime/validate.d.ts.map +1 -1
  234. package/dist/runtime/validate.js +51 -31
  235. package/dist/runtime/validate.js.map +1 -1
  236. package/dist/runtime/wait.d.ts +2 -1
  237. package/dist/runtime/wait.d.ts.map +1 -1
  238. package/dist/runtime/wait.js +2 -36
  239. package/dist/runtime/wait.js.map +1 -1
  240. package/dist/runtime/world.d.ts +31 -3
  241. package/dist/runtime/world.d.ts.map +1 -1
  242. package/dist/runtime/world.js +113 -32
  243. package/dist/runtime/world.js.map +1 -1
  244. package/dist/spec/collection.d.ts +8 -2
  245. package/dist/spec/collection.d.ts.map +1 -1
  246. package/dist/spec/collection.js +47 -7
  247. package/dist/spec/collection.js.map +1 -1
  248. package/dist/spec/extensions.d.ts +5 -1
  249. package/dist/spec/extensions.d.ts.map +1 -1
  250. package/dist/spec/extensions.js +9 -2
  251. package/dist/spec/extensions.js.map +1 -1
  252. package/dist/spec/graph.d.ts +46 -0
  253. package/dist/spec/graph.d.ts.map +1 -1
  254. package/dist/spec/graph.js +175 -11
  255. package/dist/spec/graph.js.map +1 -1
  256. package/dist/spec/load.d.ts +25 -5
  257. package/dist/spec/load.d.ts.map +1 -1
  258. package/dist/spec/load.js +160 -59
  259. package/dist/spec/load.js.map +1 -1
  260. package/dist/spec/query-capabilities.d.ts +4 -0
  261. package/dist/spec/query-capabilities.d.ts.map +1 -1
  262. package/dist/spec/query-capabilities.js +6 -0
  263. package/dist/spec/query-capabilities.js.map +1 -1
  264. package/dist/spec/schema.d.ts +20 -0
  265. package/dist/spec/schema.d.ts.map +1 -0
  266. package/dist/spec/schema.js +118 -0
  267. package/dist/spec/schema.js.map +1 -0
  268. package/dist/spec/tag-schema.d.ts +12 -0
  269. package/dist/spec/tag-schema.d.ts.map +1 -0
  270. package/dist/spec/tag-schema.js +143 -0
  271. package/dist/spec/tag-schema.js.map +1 -0
  272. package/dist/spec/types.js +17 -1
  273. package/dist/spec/types.js.map +1 -1
  274. package/docs/api.md +59 -0
  275. package/docs/assumptions.md +99 -0
  276. package/docs/checks.md +183 -0
  277. package/docs/commands.md +214 -0
  278. package/docs/configuration.md +650 -0
  279. package/docs/model.md +184 -0
  280. package/docs/reference-defects.md +94 -0
  281. package/docs/reports.md +211 -0
  282. package/docs/tags.md +400 -0
  283. package/package.json +3 -1
@@ -7,6 +7,8 @@
7
7
  */
8
8
  import ajvModule from "ajv/dist/2020.js";
9
9
  import formatsModule from "ajv-formats";
10
+ import { DEFS_ID } from "../spec/load.js";
11
+ import { normalizeSchema } from "../spec/schema.js";
10
12
  const OK = { errors: [], ok: true };
11
13
  /* Both packages ship CJS with an interop default, so the callable lives on `.default` under
12
14
  * NodeNext resolution — but only at runtime, hence the cast. */
@@ -15,7 +17,8 @@ const addFormats = (formatsModule.default ?? formatsModule);
15
17
  export class SchemaValidator {
16
18
  ajv;
17
19
  cache = new Map();
18
- constructor() {
20
+ /** `defs`: the recursive schemas a dereferenced document refers to (see `dereference`). */
21
+ constructor(defs = {}) {
19
22
  this.ajv = new Ajv2020({
20
23
  allErrors: true,
21
24
  /* Specs in the wild carry annotations AJV does not know; refusing to compile over a
@@ -24,6 +27,12 @@ export class SchemaValidator {
24
27
  validateFormats: true,
25
28
  });
26
29
  addFormats(this.ajv);
30
+ /* Recursive schemas are referenced as `oat-defs#/$defs/<name>`, so they are registered
31
+ * once under that id and every compiled schema can reach them. */
32
+ const $defs = {};
33
+ for (const [name, def] of Object.entries(defs))
34
+ $defs[name] = normalizeSchema(def, { direction: "response" });
35
+ this.ajv.addSchema({ $defs, $id: DEFS_ID });
27
36
  }
28
37
  /** Compiles the schema documented for this operation and status, if there is one. */
29
38
  compile(op, key, status) {
@@ -36,21 +45,24 @@ export class SchemaValidator {
36
45
  return null;
37
46
  }
38
47
  try {
39
- const validate = this.ajv.compile(sanitise(schema));
48
+ const validate = this.ajv.compile(normalizeSchema(schema, { direction: "response" }));
40
49
  this.cache.set(key, validate);
41
50
  return validate;
42
51
  }
43
- catch {
52
+ catch (error) {
44
53
  /* An uncompilable schema is a spec defect, surfaced by the caller as a gap rather than
45
- * crashing the run. */
46
- this.cache.set(key, null);
47
- return null;
54
+ * crashing the run — and never as a pass. */
55
+ const failed = { failed: error instanceof Error ? error.message : String(error) };
56
+ this.cache.set(key, failed);
57
+ return failed;
48
58
  }
49
59
  }
50
60
  validate(operationId, op, status, body) {
51
61
  const validate = this.compile(op, `${operationId}:${status}`, status);
52
62
  if (validate === null)
53
63
  return OK;
64
+ if ("failed" in validate)
65
+ return { errors: [], ok: true, unchecked: validate.failed };
54
66
  if (validate(body) === true)
55
67
  return OK;
56
68
  const errors = (validate.errors ?? []).map((error) => {
@@ -78,34 +90,42 @@ function schemaFor(op, status) {
78
90
  }
79
91
  return null;
80
92
  }
93
+ /* One AJV per set of definitions: each registers them under `oat-defs`, as the document names them. */
94
+ const instanceAjvs = new WeakMap();
95
+ const NO_DEFS = {};
96
+ const instanceCache = new WeakMap();
97
+ function ajvFor(defs) {
98
+ const existing = instanceAjvs.get(defs);
99
+ if (existing !== undefined)
100
+ return existing;
101
+ const ajv = new Ajv2020({ allErrors: true, strict: false, validateFormats: true });
102
+ addFormats(ajv);
103
+ const $defs = {};
104
+ for (const [name, def] of Object.entries(defs))
105
+ $defs[name] = normalizeSchema(def, { direction: "request" });
106
+ ajv.addSchema({ $defs, $id: DEFS_ID });
107
+ instanceAjvs.set(defs, ajv);
108
+ return ajv;
109
+ }
81
110
  /**
82
- * Strips constructs that break AJV but carry no validation meaning here: OpenAPI's `nullable`
83
- * without a sibling `type` (invalid JSON Schema, emitted by several generators), and `example`
84
- * keys that collide with the `examples` keyword in draft 2020-12.
111
+ * Whether `value` satisfies an already-normalized `schema` — the self-check every generated body
112
+ * passes before it is sent. Returns AJV's complaints, or `[]`.
85
113
  */
86
- function sanitise(schema) {
87
- const walk = (node) => {
88
- if (Array.isArray(node))
89
- return node.map(walk);
90
- if (node === null || typeof node !== "object")
91
- return node;
92
- const out = {};
93
- for (const [key, value] of Object.entries(node)) {
94
- if (key === "nullable")
95
- continue;
96
- if (key === "example")
97
- continue;
98
- if (key === "discriminator")
99
- continue;
100
- out[key] = walk(value);
114
+ export function instanceErrors(schema, value, defs = NO_DEFS) {
115
+ let compiled = instanceCache.get(schema);
116
+ if (compiled === undefined) {
117
+ try {
118
+ compiled = ajvFor(defs).compile(schema);
101
119
  }
102
- /* `nullable: true` with a concrete type widens the type rather than being dropped. */
103
- const original = node;
104
- if (original.nullable === true && typeof original.type === "string") {
105
- out.type = [original.type, "null"];
120
+ catch (error) {
121
+ compiled = { failed: error instanceof Error ? error.message : String(error) };
106
122
  }
107
- return out;
108
- };
109
- return walk(schema);
123
+ instanceCache.set(schema, compiled);
124
+ }
125
+ if ("failed" in compiled)
126
+ return [`schema cannot be compiled: ${compiled.failed}`];
127
+ if (compiled(value) === true)
128
+ return [];
129
+ return (compiled.errors ?? []).map((error) => `${error.instancePath || "(root)"} ${error.message ?? "is invalid"}`);
110
130
  }
111
131
  //# sourceMappingURL=validate.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/runtime/validate.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,SAAS,MAAM,kBAAkB,CAAA;AACxC,OAAO,aAAa,MAAM,aAAa,CAAA;AAoBvC,MAAM,EAAE,GAAqB,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,CAAA;AAErD;gEACgE;AAChE,MAAM,OAAO,GAAG,CAAE,SAAmC,CAAC,OAAO,IAAI,SAAS,CAAmB,CAAA;AAC7F,MAAM,UAAU,GAAG,CAAE,aAAuC,CAAC,OAAO,IAAI,aAAa,CAA2B,CAAA;AAEhH,MAAM,OAAO,eAAe;IACV,GAAG,CAAS;IACZ,KAAK,GAAG,IAAI,GAAG,EAAmC,CAAA;IAEnE;QACC,IAAI,CAAC,GAAG,GAAG,IAAI,OAAO,CAAC;YACtB,SAAS,EAAE,IAAI;YACf;8EACkE;YAClE,MAAM,EAAE,KAAK;YACb,eAAe,EAAE,IAAI;SACrB,CAAC,CAAA;QACF,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACrB,CAAC;IAED,qFAAqF;IAC7E,OAAO,CAAC,EAAmB,EAAE,GAAW,EAAE,MAAc;QAC/D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAClC,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,MAAM,CAAA;QAEvC,MAAM,MAAM,GAAG,SAAS,CAAC,EAAE,EAAE,MAAM,CAAC,CAAA;QACpC,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YACrB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;YACzB,OAAO,IAAI,CAAA;QACZ,CAAC;QACD,IAAI,CAAC;YACJ,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAA;YACnD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;YAC7B,OAAO,QAAQ,CAAA;QAChB,CAAC;QAAC,MAAM,CAAC;YACR;mCACuB;YACvB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;YACzB,OAAO,IAAI,CAAA;QACZ,CAAC;IACF,CAAC;IAED,QAAQ,CAAC,WAAmB,EAAE,EAAmB,EAAE,MAAc,EAAE,IAAa;QAC/E,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,WAAW,IAAI,MAAM,EAAE,EAAE,MAAM,CAAC,CAAA;QACrE,IAAI,QAAQ,KAAK,IAAI;YAAE,OAAO,EAAE,CAAA;QAChC,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,IAAI;YAAE,OAAO,EAAE,CAAA;QACtC,MAAM,MAAM,GAAG,CAAC,QAAQ,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;YACpD,MAAM,EAAE,GAAG,KAAK,CAAC,YAAY,KAAK,SAAS,IAAI,KAAK,CAAC,YAAY,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAA;YACxG,OAAO,GAAG,EAAE,IAAI,KAAK,CAAC,OAAO,IAAI,YAAY,EAAE,CAAA;QAChD,CAAC,CAAC,CAAA;QACF,OAAO,EAAE,MAAM,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAA;IAChE,CAAC;IAED,gFAAgF;IAChF,SAAS,CAAC,EAAmB,EAAE,MAAc;QAC5C,OAAO,SAAS,CAAC,EAAE,EAAE,MAAM,CAAC,KAAK,IAAI,CAAA;IACtC,CAAC;CACD;AAED,SAAS,SAAS,CAAC,EAAmB,EAAE,MAAc;IACrD,MAAM,SAAS,GAAG,EAAE,CAAC,SAAS,IAAI,EAAE,CAAA;IACpC,MAAM,UAAU,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;IAC/E,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,CAAA;QACxC,IAAI,OAAO,KAAK,SAAS;YAAE,SAAQ;QACnC,KAAK,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YAC1D,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS;gBAAE,OAAO,KAAK,CAAC,MAAM,CAAA;QAClF,CAAC;IACF,CAAC;IACD,OAAO,IAAI,CAAA;AACZ,CAAC;AAED;;;;GAIG;AACH,SAAS,QAAQ,CAAC,MAAoB;IACrC,MAAM,IAAI,GAAG,CAAC,IAAa,EAAW,EAAE;QACvC,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QAC9C,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAA;QAC1D,MAAM,GAAG,GAA4B,EAAE,CAAA;QACvC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAA+B,CAAC,EAAE,CAAC;YAC5E,IAAI,GAAG,KAAK,UAAU;gBAAE,SAAQ;YAChC,IAAI,GAAG,KAAK,SAAS;gBAAE,SAAQ;YAC/B,IAAI,GAAG,KAAK,eAAe;gBAAE,SAAQ;YACrC,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAA;QACvB,CAAC;QACD,sFAAsF;QACtF,MAAM,QAAQ,GAAG,IAA+B,CAAA;QAChD,IAAI,QAAQ,CAAC,QAAQ,KAAK,IAAI,IAAI,OAAO,QAAQ,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACrE,GAAG,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QACnC,CAAC;QACD,OAAO,GAAG,CAAA;IACX,CAAC,CAAA;IACD,OAAO,IAAI,CAAC,MAAM,CAAiB,CAAA;AACpC,CAAC"}
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/runtime/validate.ts"],"names":[],"mappings":"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"}
@@ -8,7 +8,7 @@ import type { Hooks } from "../config/define-config.ts";
8
8
  import type { WaitSpec } from "../spec/extensions.ts";
9
9
  import type { OperationModel } from "../spec/graph.ts";
10
10
  import type { Client, Exchange } from "./client.ts";
11
- export declare function readPointer(body: unknown, pointer: string): unknown;
11
+ import { readPath as readPointer } from "./path.ts";
12
12
  /** Present enough to stop polling: not null, not "", not []. */
13
13
  export declare function pointerIsOccupied(value: unknown): boolean;
14
14
  export interface WaitOutcome {
@@ -29,4 +29,5 @@ export declare function driveWait(options: {
29
29
  awaitSideEffect?: Hooks["awaitSideEffect"];
30
30
  refreshIfStale?: (force?: boolean) => Promise<void>;
31
31
  }): Promise<WaitOutcome>;
32
+ export { readPointer };
32
33
  //# sourceMappingURL=wait.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"wait.d.ts","sourceRoot":"","sources":["../../src/runtime/wait.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAA;AACvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACtD,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAInD,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAgBnE;AAkBD,gEAAgE;AAChE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAIzD;AAED,MAAM,WAAW,WAAW;IAC3B,QAAQ,EAAE,OAAO,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,QAAQ,EAAE,CAAA;IACrB,OAAO,EAAE,OAAO,CAAA;CAChB;AAED,wBAAsB,SAAS,CAAC,OAAO,EAAE;IACxC,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,cAAc,CAAA;IACtB,IAAI,EAAE,QAAQ,CAAA;IACd,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B,OAAO,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACrC,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,OAAO,CAAA;IACf,eAAe,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,CAAA;IAC1C,cAAc,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACnD,GAAG,OAAO,CAAC,WAAW,CAAC,CAuEvB"}
1
+ {"version":3,"file":"wait.d.ts","sourceRoot":"","sources":["../../src/runtime/wait.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAA;AACvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACtD,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACnD,OAAO,EAAE,QAAQ,IAAI,WAAW,EAAE,MAAM,WAAW,CAAA;AAInD,gEAAgE;AAChE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAIzD;AAED,MAAM,WAAW,WAAW;IAC3B,QAAQ,EAAE,OAAO,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,QAAQ,EAAE,CAAA;IACrB,OAAO,EAAE,OAAO,CAAA;CAChB;AAED,wBAAsB,SAAS,CAAC,OAAO,EAAE;IACxC,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,cAAc,CAAA;IACtB,IAAI,EAAE,QAAQ,CAAA;IACd,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B,OAAO,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACrC,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,OAAO,CAAA;IACf,eAAe,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,CAAA;IAC1C,cAAc,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACnD,GAAG,OAAO,CAAC,WAAW,CAAC,CAuEvB;AAED,OAAO,EAAE,WAAW,EAAE,CAAA"}
@@ -4,44 +4,9 @@
4
4
  * Queue consumers and webhook inboxes are not the same request. Timeout is a finding, not a
5
5
  * coverage gap — the document claimed the side effect would appear.
6
6
  */
7
+ import { readPath as readPointer } from "./path.js";
7
8
  import { sleep } from "./poll.js";
8
9
  import { fillPath } from "./world.js";
9
- export function readPointer(body, pointer) {
10
- if (pointer.startsWith("/"))
11
- return readJsonPointer(body, pointer);
12
- let node = body;
13
- for (const segment of pointer
14
- .replace(/^\$\.?/, "")
15
- .split(".")
16
- .filter(Boolean)) {
17
- if (node === null || typeof node !== "object")
18
- return undefined;
19
- const index = Number.parseInt(segment, 10);
20
- node = Array.isArray(node)
21
- ? Number.isNaN(index)
22
- ? undefined
23
- : node[index]
24
- : node[segment];
25
- }
26
- return node;
27
- }
28
- function readJsonPointer(body, pointer) {
29
- if (pointer === "/")
30
- return body;
31
- let node = body;
32
- for (const raw of pointer.slice(1).split("/")) {
33
- const segment = raw.replace(/~1/g, "/").replace(/~0/g, "~");
34
- if (node === null || typeof node !== "object")
35
- return undefined;
36
- const index = Number.parseInt(segment, 10);
37
- node = Array.isArray(node)
38
- ? Number.isNaN(index)
39
- ? undefined
40
- : node[index]
41
- : node[segment];
42
- }
43
- return node;
44
- }
45
10
  /** Present enough to stop polling: not null, not "", not []. */
46
11
  export function pointerIsOccupied(value) {
47
12
  if (value === undefined || value === null || value === "")
@@ -122,4 +87,5 @@ export async function driveWait(options) {
122
87
  timedOut: true,
123
88
  };
124
89
  }
90
+ export { readPointer };
125
91
  //# sourceMappingURL=wait.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"wait.js","sourceRoot":"","sources":["../../src/runtime/wait.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"wait.js","sourceRoot":"","sources":["../../src/runtime/wait.ts"],"names":[],"mappings":"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"}
@@ -24,9 +24,14 @@ export declare class SeedError extends Error {
24
24
  readonly cause_: string;
25
25
  /** Status the failing request returned, when the failure was an HTTP response. */
26
26
  readonly status?: number | undefined;
27
+ /** The create that failed, when the failure was one — a parent's, not always the entity's own. */
28
+ readonly operationId?: string | undefined;
29
+ readonly exchange?: Exchange | undefined;
27
30
  constructor(cause_: string, message: string,
28
31
  /** Status the failing request returned, when the failure was an HTTP response. */
29
- status?: number | undefined);
32
+ status?: number | undefined,
33
+ /** The create that failed, when the failure was one — a parent's, not always the entity's own. */
34
+ operationId?: string | undefined, exchange?: Exchange | undefined);
30
35
  }
31
36
  export declare function fillPath(template: string, values: Record<string, string>): string;
32
37
  /**
@@ -39,19 +44,33 @@ export declare function isPlanLimitResponse(status: number, body: unknown): bool
39
44
  /** Pulls the collection out of a list body the same way seed fallback and effect checks do. */
40
45
  export declare function recordsFromList(body: unknown, collectionKey: string | null): Record_[];
41
46
  /** Same-tenant records the list route already returns. Empty when the route cannot be resolved. */
42
- export declare function listExisting(listOp: OperationModel, client: Client, headers: Record<string, string> | (() => Record<string, string>), values: Record<string, string>): Promise<Record_[]>;
47
+ export declare function listExisting(listOp: OperationModel, model: SpecModel, client: Client, headers: Record<string, string> | (() => Record<string, string>), values: Record<string, string>): Promise<Record_[]>;
43
48
  export interface WorldOptions {
44
49
  roots: Record<string, string>;
45
50
  seed: number;
51
+ /**
52
+ * Per-run token mixed into every value that must not collide with an earlier run's records —
53
+ * unique columns, above all. A seed alone repeats exactly, which is its job.
54
+ */
55
+ nonce?: string;
46
56
  cohortSize?: number;
47
57
  authHeaders: () => Record<string, string>;
48
58
  uploads?: UploadContext;
59
+ /**
60
+ * Called the moment a record exists, before anything else can fail. A record learned about
61
+ * only after the step that made it returns is dropped whenever a later step throws.
62
+ */
63
+ onCreate?: (entity: string, id: string, scope: Record<string, string>) => void;
64
+ /** Who is creating — keys the ancestor cache, since one principal's parent is not another's. */
65
+ principal?: string;
66
+ /** Ancestors already made in this run, by principal, operation and parent path. */
67
+ ancestors?: Map<string, string>;
49
68
  }
50
69
  /**
51
70
  * Resolves every path parameter an operation needs. Roots come from config; everything else is
52
71
  * created through the owning entity's create operation, depth-first.
53
72
  */
54
- export declare function resolveScope(op: OperationModel, model: SpecModel, client: Client, options: WorldOptions, scope?: Scope): Promise<Scope>;
73
+ export declare function resolvePathScope(op: OperationModel, model: SpecModel, client: Client, options: WorldOptions, scope?: Scope): Promise<Scope>;
55
74
  export declare function requestSchemaOf(op: OperationModel, model: SpecModel): Record<string, unknown> | null;
56
75
  export interface SeededCohort {
57
76
  members: CohortMember[];
@@ -80,6 +99,15 @@ export interface SeededCohort {
80
99
  uniqueAdopted?: boolean;
81
100
  /** Set when extra cohort variants were dropped because unique values could not differ. */
82
101
  uniqueGap?: string;
102
+ /**
103
+ * Variants after the first whose create failed. The cohort carries on without them, and the
104
+ * run reports each: a 5xx is the backend's failure, a 4xx a variant the document permits and
105
+ * the backend refused.
106
+ */
107
+ failedVariants?: Array<{
108
+ variant: string;
109
+ exchange: Exchange;
110
+ }>;
83
111
  }
84
112
  /** Creates the cohort and returns the server's view of each instance. */
85
113
  export declare function seedCohort(createOp: OperationModel, model: SpecModel, client: Client, options: WorldOptions, scope: Scope): Promise<SeededCohort>;
@@ -1 +1 @@
1
- {"version":3,"file":"world.d.ts","sourceRoot":"","sources":["../../src/runtime/world.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"world.d.ts","sourceRoot":"","sources":["../../src/runtime/world.ts"],"names":[],"mappings":"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"}
@@ -7,7 +7,7 @@
7
7
  * reported as BLOCKED against that single cause.
8
8
  */
9
9
  import { requestContent } from "../spec/collection.js";
10
- import { owningEntityName } from "../spec/graph.js";
10
+ import { largestPageQuery, owningEntityName } from "../spec/graph.js";
11
11
  import { encodeForOperation } from "./body.js";
12
12
  import { forEachInvocation } from "./upload-each.js";
13
13
  import { buildCohort, ensureDistinctUniqueValues, isOverflowError, overflowFrom } from "./fixture.js";
@@ -16,12 +16,18 @@ import { describeFeatureGate, isDocumentedFeatureGateDenial } from "./feature-ga
16
16
  export class SeedError extends Error {
17
17
  cause_;
18
18
  status;
19
+ operationId;
20
+ exchange;
19
21
  constructor(cause_, message,
20
22
  /** Status the failing request returned, when the failure was an HTTP response. */
21
- status) {
23
+ status,
24
+ /** The create that failed, when the failure was one — a parent's, not always the entity's own. */
25
+ operationId, exchange) {
22
26
  super(message);
23
27
  this.cause_ = cause_;
24
28
  this.status = status;
29
+ this.operationId = operationId;
30
+ this.exchange = exchange;
25
31
  }
26
32
  }
27
33
  export function fillPath(template, values) {
@@ -76,13 +82,16 @@ export function recordsFromList(body, collectionKey) {
76
82
  return [];
77
83
  }
78
84
  /** Same-tenant records the list route already returns. Empty when the route cannot be resolved. */
79
- export async function listExisting(listOp, client, headers, values) {
85
+ export async function listExisting(listOp, model, client, headers, values) {
80
86
  for (const param of listOp.pathParams) {
81
87
  if (values[param] === undefined)
82
88
  return [];
83
89
  }
84
90
  try {
85
- const exchange = await client.get(fillPath(listOp.path, values), { headers, query: { limit: 50 } });
91
+ const exchange = await client.get(fillPath(listOp.path, values), {
92
+ headers,
93
+ query: largestPageQuery(model, listOp),
94
+ });
86
95
  if (exchange.status >= 300)
87
96
  return [];
88
97
  return recordsFromList(exchange.responseBody, listOp.collection?.key ?? null);
@@ -95,7 +104,7 @@ export async function listExisting(listOp, client, headers, values) {
95
104
  * Resolves every path parameter an operation needs. Roots come from config; everything else is
96
105
  * created through the owning entity's create operation, depth-first.
97
106
  */
98
- export async function resolveScope(op, model, client, options, scope = { created: [], values: {} }) {
107
+ export async function resolvePathScope(op, model, client, options, scope = { created: [], values: {} }) {
99
108
  for (const param of op.pathParams) {
100
109
  if (scope.values[param] !== undefined)
101
110
  continue;
@@ -115,28 +124,72 @@ export async function resolveScope(op, model, client, options, scope = { created
115
124
  const createOp = model.byOperationId.get(entity.create);
116
125
  if (createOp === undefined)
117
126
  throw new SeedError(param, `missing operation ${entity.create}`);
118
- await resolveScope(createOp, model, client, options, scope);
119
- const created = await createOne(createOp, model, client, options, scope);
120
- const identity = entity.identity ?? "id";
121
- const id = created[identity];
122
- if (typeof id !== "string" && typeof id !== "number") {
123
- throw new SeedError(param, `create for "${owner}" returned no usable "${identity}"`);
127
+ await resolvePathScope(createOp, model, client, options, scope);
128
+ /* One ancestor per principal and parent path: a row and its siblings share the table oat
129
+ * made for the first of them, instead of each leaving another table behind. */
130
+ const cacheKey = `${options.principal ?? ""}\u0000${createOp.operationId}\u0000${fillPath(createOp.path, scope.values)}`;
131
+ const cached = options.ancestors?.get(cacheKey);
132
+ if (cached !== undefined) {
133
+ scope.values[param] = cached;
134
+ continue;
135
+ }
136
+ /* Entities in parallel lanes can reach the same missing ancestor at once; the second
137
+ * waits for the first's create rather than making a twin. */
138
+ const pending = options.ancestors === undefined ? undefined : inflightAncestors(options.ancestors).get(cacheKey);
139
+ if (pending !== undefined) {
140
+ scope.values[param] = await pending;
141
+ continue;
142
+ }
143
+ const creating = (async () => {
144
+ const { record: created, adopted } = await createOne(createOp, model, client, options, scope);
145
+ const identity = entity.identity ?? "id";
146
+ const id = created[identity];
147
+ if (typeof id !== "string" && typeof id !== "number") {
148
+ throw new SeedError(param, `create for "${owner}" returned no usable "${identity}"`);
149
+ }
150
+ /* Adopted, not created: somebody else's record, never oat's to remove. */
151
+ if (!adopted)
152
+ options.onCreate?.(owner, String(id), { ...scope.values });
153
+ options.ancestors?.set(cacheKey, String(id));
154
+ return String(id);
155
+ })();
156
+ if (options.ancestors !== undefined)
157
+ inflightAncestors(options.ancestors).set(cacheKey, creating);
158
+ try {
159
+ scope.values[param] = await creating;
160
+ }
161
+ finally {
162
+ if (options.ancestors !== undefined)
163
+ inflightAncestors(options.ancestors).delete(cacheKey);
124
164
  }
125
- scope.values[param] = String(id);
126
165
  scope.created.push({
127
166
  entity: owner,
128
- id: String(id),
167
+ id: scope.values[param],
129
168
  path: fillPath(createOp.path, scope.values),
130
169
  });
131
170
  }
132
171
  return scope;
133
172
  }
173
+ /** Ancestor creates under way, per ancestor cache. */
174
+ const INFLIGHT = new WeakMap();
175
+ function inflightAncestors(cache) {
176
+ let pending = INFLIGHT.get(cache);
177
+ if (pending === undefined) {
178
+ pending = new Map();
179
+ INFLIGHT.set(cache, pending);
180
+ }
181
+ return pending;
182
+ }
134
183
  async function createOne(createOp, model, client, options, scope) {
135
184
  const schema = requestSchemaOf(createOp, model);
136
185
  let member;
137
186
  try {
138
187
  ;
139
- [member] = buildCohort(schema ?? {}, options.seed, ["baseline"], createOp.operationId);
188
+ [member] = buildCohort(schema ?? {}, options.seed, ["baseline"], createOp.operationId, {
189
+ defs: model.defs,
190
+ distinct: new Set((createOp.unique ?? []).flat()),
191
+ ...(options.nonce === undefined ? {} : { nonce: options.nonce }),
192
+ });
140
193
  }
141
194
  catch (error) {
142
195
  if (isOverflowError(error))
@@ -147,7 +200,7 @@ async function createOne(createOp, model, client, options, scope) {
147
200
  if ((createOp.unique?.length ?? 0) > 0) {
148
201
  /* Ancestor creates share the entity seed with the entity's own cohort; unique columns
149
202
  * must not collide with a later seed of the same collection. */
150
- body = uniquifyProbeBody(body, createOp.unique ?? [], schema, `anc${options.seed}`);
203
+ body = uniquifyProbeBody(body, createOp.unique ?? [], schema, `anc${options.seed}-${options.nonce ?? ""}`);
151
204
  }
152
205
  const encoded = await encodeForOperation(createOp, model, body, uploadContext(options), member?.variant ?? "baseline", 0);
153
206
  const exchange = await client.request("POST", fillPath(createOp.path, scope.values), {
@@ -162,16 +215,16 @@ async function createOne(createOp, model, client, options, scope) {
162
215
  if (isPlanLimitResponse(exchange.status, exchange.responseBody)) {
163
216
  const reused = await adoptExisting(createOp, model, client, options, scope);
164
217
  if (reused !== null)
165
- return reused;
218
+ return { adopted: true, record: reused };
166
219
  }
167
220
  if (isUniqueConflictResponse(createOp, exchange.status)) {
168
221
  const reused = await adoptExisting(createOp, model, client, options, scope);
169
222
  if (reused !== null)
170
- return reused;
223
+ return { adopted: true, record: reused };
171
224
  }
172
- throw new SeedError(createOp.operationId, `${createOp.operationId} returned ${exchange.status}: ${JSON.stringify(exchange.responseBody).slice(0, 300)}`, exchange.status);
225
+ throw new SeedError(createOp.operationId, `${createOp.operationId} returned ${exchange.status}: ${JSON.stringify(exchange.responseBody).slice(0, 300)}`, exchange.status, createOp.operationId, exchange);
173
226
  }
174
- return (exchange.responseBody ?? {});
227
+ return { adopted: false, record: (exchange.responseBody ?? {}) };
175
228
  }
176
229
  /** First listed record with a usable identity, or null — never synthesises a row. */
177
230
  async function adoptExisting(createOp, model, client, options, scope) {
@@ -184,7 +237,7 @@ async function adoptExisting(createOp, model, client, options, scope) {
184
237
  const listOp = model.byOperationId.get(entity.list);
185
238
  if (listOp === undefined)
186
239
  return null;
187
- const records = await listExisting(listOp, client, options.authHeaders, { ...options.roots, ...scope.values });
240
+ const records = await listExisting(listOp, model, client, options.authHeaders, { ...options.roots, ...scope.values });
188
241
  const identity = entity.identity ?? "id";
189
242
  return (records.find((record) => {
190
243
  const id = record[identity];
@@ -205,8 +258,16 @@ export async function seedCohort(createOp, model, client, options, scope) {
205
258
  let members;
206
259
  let uniqueGap;
207
260
  try {
208
- const generated = buildCohort(schema, options.seed, undefined, createOp.operationId).slice(0, options.cohortSize ?? 7);
209
- const distinct = ensureDistinctUniqueValues(generated, createOp.unique ?? [], schema);
261
+ const generated = buildCohort(schema, options.seed, undefined, createOp.operationId, {
262
+ defs: model.defs,
263
+ distinct: new Set((createOp.unique ?? []).flat()),
264
+ ...(options.nonce === undefined ? {} : { nonce: options.nonce }),
265
+ }).slice(0, options.cohortSize ?? 7);
266
+ const distinct = ensureDistinctUniqueValues(generated, createOp.unique ?? [], schema, {
267
+ defs: model.defs,
268
+ distinct: new Set((createOp.unique ?? []).flat()),
269
+ ...(options.nonce === undefined ? {} : { nonce: options.nonce }),
270
+ });
210
271
  members = distinct.members;
211
272
  if (distinct.gap !== null)
212
273
  uniqueGap = distinct.gap;
@@ -214,12 +275,12 @@ export async function seedCohort(createOp, model, client, options, scope) {
214
275
  const listOp = entity?.list === undefined ? undefined : model.byOperationId.get(entity.list);
215
276
  const existing = listOp === undefined
216
277
  ? []
217
- : await listExisting(listOp, client, options.authHeaders, { ...options.roots, ...scope.values });
278
+ : await listExisting(listOp, model, client, options.authHeaders, { ...options.roots, ...scope.values });
218
279
  if (existing.length > 0 && (createOp.unique?.length ?? 0) > 0) {
219
280
  members = members.map((member, index) => {
220
281
  let body = member.body;
221
282
  for (let token = 0; token < 8 && uniqueTupleCollides(body, createOp.unique ?? [], existing); token++) {
222
- body = uniquifyProbeBody(body, createOp.unique ?? [], schema, `ex${index}${token}`);
283
+ body = uniquifyProbeBody(body, createOp.unique ?? [], schema, `ex${index}${token}-${options.nonce ?? ""}`);
223
284
  }
224
285
  return { ...member, body };
225
286
  });
@@ -234,6 +295,15 @@ export async function seedCohort(createOp, model, client, options, scope) {
234
295
  const path = fillPath(createOp.path, scope.values);
235
296
  const uploads = uploadContext(options);
236
297
  const seededMembers = [];
298
+ const identity = (createOp.entity === null ? undefined : model.entities.get(createOp.entity))?.identity ?? "id";
299
+ const created = (exchange) => {
300
+ const record = (exchange.responseBody ?? {});
301
+ const id = record[identity];
302
+ if (createOp.entity !== null && (typeof id === "string" || typeof id === "number")) {
303
+ options.onCreate?.(createOp.entity, String(id), { ...scope.values });
304
+ }
305
+ return record;
306
+ };
237
307
  const postMember = async (member, nextUploads) => {
238
308
  const encoded = await encodeForOperation(createOp, model, member.body, nextUploads, member.variant, records.length);
239
309
  return client.request("POST", path, {
@@ -244,7 +314,12 @@ export async function seedCohort(createOp, model, client, options, scope) {
244
314
  ...(nextUploads.fixture === undefined ? {} : { fixture: nextUploads.fixture.filename }),
245
315
  });
246
316
  };
247
- const withGap = (cohort) => (uniqueGap === undefined ? cohort : { ...cohort, uniqueGap });
317
+ const failedVariants = [];
318
+ const withGap = (cohort) => ({
319
+ ...cohort,
320
+ ...(uniqueGap === undefined ? {} : { uniqueGap }),
321
+ ...(failedVariants.length === 0 ? {} : { failedVariants }),
322
+ });
248
323
  const failOrAdopt = async (member, exchange) => {
249
324
  if (records.length > 0)
250
325
  return withGap({ featureGate: null, members: seededMembers, records });
@@ -270,14 +345,14 @@ export async function seedCohort(createOp, model, client, options, scope) {
270
345
  });
271
346
  }
272
347
  throw new SeedError(createOp.operationId, `seeding "${member.variant}" returned ${exchange.status}: ` +
273
- JSON.stringify(exchange.responseBody).slice(0, 300), exchange.status);
348
+ JSON.stringify(exchange.responseBody).slice(0, 300), exchange.status, createOp.operationId, exchange);
274
349
  }
275
350
  if (isPlanLimitResponse(exchange.status, exchange.responseBody)) {
276
351
  const adopted = await adoptExisting(createOp, model, client, options, scope);
277
352
  if (adopted !== null)
278
353
  return withGap({ adopted: true, featureGate: null, members: seededMembers, records: [adopted] });
279
354
  }
280
- throw new SeedError(createOp.operationId, `seeding "${member.variant}" returned ${exchange.status}: ` + JSON.stringify(exchange.responseBody).slice(0, 300), exchange.status);
355
+ throw new SeedError(createOp.operationId, `seeding "${member.variant}" returned ${exchange.status}: ` + JSON.stringify(exchange.responseBody).slice(0, 300), exchange.status, createOp.operationId, exchange);
281
356
  };
282
357
  let lastFail;
283
358
  const outcomes = await forEachInvocation(createOp.operationId, uploads, async (nextUploads, slot) => {
@@ -290,15 +365,21 @@ export async function seedCohort(createOp, model, client, options, scope) {
290
365
  return null;
291
366
  }
292
367
  seededMembers.push(member);
293
- records.push((exchange.responseBody ?? {}));
368
+ records.push(created(exchange));
294
369
  return null;
295
370
  }
296
371
  for (const member of members) {
297
372
  const exchange = await postMember(member, nextUploads);
298
- if (exchange.status >= 300)
299
- return failOrAdopt(member, exchange);
373
+ if (exchange.status >= 300) {
374
+ /* The first create decides whether there is a cohort at all; a later one failing
375
+ * is a variant lost, reported rather than ending the cohort in silence. */
376
+ if (records.length === 0)
377
+ return failOrAdopt(member, exchange);
378
+ failedVariants.push({ exchange, variant: member.variant });
379
+ continue;
380
+ }
300
381
  seededMembers.push(member);
301
- records.push((exchange.responseBody ?? {}));
382
+ records.push(created(exchange));
302
383
  }
303
384
  return null;
304
385
  });
@@ -325,7 +406,7 @@ export function probeCreateFixtures(model) {
325
406
  continue;
326
407
  const schema = requestSchemaOf(op, model) ?? {};
327
408
  try {
328
- buildCohort(schema, 1, ["baseline"], op.operationId);
409
+ buildCohort(schema, 1, ["baseline"], op.operationId, { defs: model.defs });
329
410
  }
330
411
  catch (error) {
331
412
  if (isOverflowError(error)) {