@datakable/core 1.0.1 → 2.0.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 (280) hide show
  1. package/README.md +5 -3
  2. package/dist/catalog/codes.cjs +12 -8
  3. package/dist/catalog/codes.cjs.map +1 -1
  4. package/dist/catalog/codes.js +12 -8
  5. package/dist/catalog/codes.js.map +1 -1
  6. package/dist/catalog/slots.cjs +10 -6
  7. package/dist/catalog/slots.cjs.map +1 -1
  8. package/dist/catalog/slots.js +10 -6
  9. package/dist/catalog/slots.js.map +1 -1
  10. package/dist/{codes-OsjAR3Wz.d.cts → codes-B9bCK73-.d.cts} +30 -4
  11. package/dist/{codes-OsjAR3Wz.d.ts → codes-B9bCK73-.d.ts} +30 -4
  12. package/dist/column/column-def.cjs.map +1 -1
  13. package/dist/column/get-value.cjs +6 -1
  14. package/dist/column/get-value.cjs.map +1 -1
  15. package/dist/column/get-value.js +6 -1
  16. package/dist/column/get-value.js.map +1 -1
  17. package/dist/column-filters.d.cts +2 -2
  18. package/dist/column-filters.d.ts +2 -2
  19. package/dist/diagnostics/build.cjs +4 -1
  20. package/dist/diagnostics/build.cjs.map +1 -1
  21. package/dist/diagnostics/build.js +4 -1
  22. package/dist/diagnostics/build.js.map +1 -1
  23. package/dist/diagnostics/catalog.cjs +11 -5
  24. package/dist/diagnostics/catalog.cjs.map +1 -1
  25. package/dist/diagnostics/catalog.js +10 -5
  26. package/dist/diagnostics/catalog.js.map +1 -1
  27. package/dist/diagnostics/codes.cjs +12 -8
  28. package/dist/diagnostics/codes.cjs.map +1 -1
  29. package/dist/diagnostics/codes.js +12 -8
  30. package/dist/diagnostics/codes.js.map +1 -1
  31. package/dist/diagnostics/console.cjs +13 -6
  32. package/dist/diagnostics/console.cjs.map +1 -1
  33. package/dist/diagnostics/console.js +13 -6
  34. package/dist/diagnostics/console.js.map +1 -1
  35. package/dist/diagnostics/env.cjs +1 -0
  36. package/dist/diagnostics/env.cjs.map +1 -1
  37. package/dist/diagnostics/env.js +1 -0
  38. package/dist/diagnostics/env.js.map +1 -1
  39. package/dist/diagnostics/explain-text.cjs +2 -1
  40. package/dist/diagnostics/explain-text.cjs.map +1 -1
  41. package/dist/diagnostics/explain-text.js +2 -1
  42. package/dist/diagnostics/explain-text.js.map +1 -1
  43. package/dist/diagnostics/explain.cjs +3 -2
  44. package/dist/diagnostics/explain.cjs.map +1 -1
  45. package/dist/diagnostics/explain.js +3 -2
  46. package/dist/diagnostics/explain.js.map +1 -1
  47. package/dist/diagnostics/hub.cjs +5 -4
  48. package/dist/diagnostics/hub.cjs.map +1 -1
  49. package/dist/diagnostics/hub.js +5 -4
  50. package/dist/diagnostics/hub.js.map +1 -1
  51. package/dist/diagnostics/process-guard.cjs +26 -0
  52. package/dist/diagnostics/process-guard.cjs.map +1 -0
  53. package/dist/diagnostics/process-guard.js +9 -0
  54. package/dist/diagnostics/process-guard.js.map +1 -0
  55. package/dist/diagnostics/prose.cjs +120 -0
  56. package/dist/diagnostics/prose.cjs.map +1 -0
  57. package/dist/diagnostics/prose.js +93 -0
  58. package/dist/diagnostics/prose.js.map +1 -0
  59. package/dist/diagnostics/redact.cjs +7 -4
  60. package/dist/diagnostics/redact.cjs.map +1 -1
  61. package/dist/diagnostics/redact.js +6 -4
  62. package/dist/diagnostics/redact.js.map +1 -1
  63. package/dist/diagnostics/trace-store.cjs +6 -0
  64. package/dist/diagnostics/trace-store.cjs.map +1 -1
  65. package/dist/diagnostics/trace-store.js +4 -0
  66. package/dist/diagnostics/trace-store.js.map +1 -1
  67. package/dist/diagnostics/tracer.cjs +74 -13
  68. package/dist/diagnostics/tracer.cjs.map +1 -1
  69. package/dist/diagnostics/tracer.js +75 -14
  70. package/dist/diagnostics/tracer.js.map +1 -1
  71. package/dist/diagnostics/types.cjs.map +1 -1
  72. package/dist/{explain-vkD2cewE.d.cts → explain-Q8Cg0cZy.d.cts} +13 -4
  73. package/dist/{explain-Dn99IQt0.d.ts → explain-i0OATi_W.d.ts} +13 -4
  74. package/dist/feature/codes.cjs +1 -0
  75. package/dist/feature/codes.cjs.map +1 -1
  76. package/dist/feature/codes.js +1 -0
  77. package/dist/feature/codes.js.map +1 -1
  78. package/dist/feature/install.cjs +4 -3
  79. package/dist/feature/install.cjs.map +1 -1
  80. package/dist/feature/install.js +4 -3
  81. package/dist/feature/install.js.map +1 -1
  82. package/dist/features/column-filters/codes.cjs +1 -0
  83. package/dist/features/column-filters/codes.cjs.map +1 -1
  84. package/dist/features/column-filters/codes.js +1 -0
  85. package/dist/features/column-filters/codes.js.map +1 -1
  86. package/dist/features/column-filters/column-filters.cjs +4 -2
  87. package/dist/features/column-filters/column-filters.cjs.map +1 -1
  88. package/dist/features/column-filters/column-filters.js +4 -2
  89. package/dist/features/column-filters/column-filters.js.map +1 -1
  90. package/dist/features/column-filters/match.cjs +5 -5
  91. package/dist/features/column-filters/match.cjs.map +1 -1
  92. package/dist/features/column-filters/match.js +5 -5
  93. package/dist/features/column-filters/match.js.map +1 -1
  94. package/dist/features/pagination/codes.cjs +1 -0
  95. package/dist/features/pagination/codes.cjs.map +1 -1
  96. package/dist/features/pagination/codes.js +1 -0
  97. package/dist/features/pagination/codes.js.map +1 -1
  98. package/dist/features/pagination/pagination.cjs +16 -13
  99. package/dist/features/pagination/pagination.cjs.map +1 -1
  100. package/dist/features/pagination/pagination.js +16 -13
  101. package/dist/features/pagination/pagination.js.map +1 -1
  102. package/dist/features/search/codes.cjs +1 -0
  103. package/dist/features/search/codes.cjs.map +1 -1
  104. package/dist/features/search/codes.js +1 -0
  105. package/dist/features/search/codes.js.map +1 -1
  106. package/dist/features/search/search-index.cjs +68 -15
  107. package/dist/features/search/search-index.cjs.map +1 -1
  108. package/dist/features/search/search-index.js +68 -15
  109. package/dist/features/search/search-index.js.map +1 -1
  110. package/dist/features/search/search.cjs +41 -9
  111. package/dist/features/search/search.cjs.map +1 -1
  112. package/dist/features/search/search.js +41 -9
  113. package/dist/features/search/search.js.map +1 -1
  114. package/dist/features/search/skipped-codes.cjs +45 -0
  115. package/dist/features/search/skipped-codes.cjs.map +1 -0
  116. package/dist/features/search/skipped-codes.js +20 -0
  117. package/dist/features/search/skipped-codes.js.map +1 -0
  118. package/dist/features/sorting/codes.cjs +1 -0
  119. package/dist/features/sorting/codes.cjs.map +1 -1
  120. package/dist/features/sorting/codes.js +1 -0
  121. package/dist/features/sorting/codes.js.map +1 -1
  122. package/dist/features/sorting/sorting.cjs +16 -20
  123. package/dist/features/sorting/sorting.cjs.map +1 -1
  124. package/dist/features/sorting/sorting.js +16 -20
  125. package/dist/features/sorting/sorting.js.map +1 -1
  126. package/dist/features/sorting/strategy.cjs +4 -4
  127. package/dist/features/sorting/strategy.cjs.map +1 -1
  128. package/dist/features/sorting/strategy.js +4 -4
  129. package/dist/features/sorting/strategy.js.map +1 -1
  130. package/dist/features/validity/codes.cjs +1 -0
  131. package/dist/features/validity/codes.cjs.map +1 -1
  132. package/dist/features/validity/codes.js +1 -0
  133. package/dist/features/validity/codes.js.map +1 -1
  134. package/dist/features/validity/validity.cjs +3 -3
  135. package/dist/features/validity/validity.cjs.map +1 -1
  136. package/dist/features/validity/validity.js +3 -3
  137. package/dist/features/validity/validity.js.map +1 -1
  138. package/dist/index.d.cts +13 -10
  139. package/dist/index.d.ts +13 -10
  140. package/dist/ingest/data-check-codes.cjs +4 -2
  141. package/dist/ingest/data-check-codes.cjs.map +1 -1
  142. package/dist/ingest/data-check-codes.js +4 -2
  143. package/dist/ingest/data-check-codes.js.map +1 -1
  144. package/dist/ingest/data-checks.cjs +1 -1
  145. package/dist/ingest/data-checks.cjs.map +1 -1
  146. package/dist/ingest/data-checks.js +1 -1
  147. package/dist/ingest/data-checks.js.map +1 -1
  148. package/dist/ingest/row-key-codes.cjs +1 -0
  149. package/dist/ingest/row-key-codes.cjs.map +1 -1
  150. package/dist/ingest/row-key-codes.js +1 -0
  151. package/dist/ingest/row-key-codes.js.map +1 -1
  152. package/dist/ingest/row-key.cjs +23 -20
  153. package/dist/ingest/row-key.cjs.map +1 -1
  154. package/dist/ingest/row-key.js +23 -20
  155. package/dist/ingest/row-key.js.map +1 -1
  156. package/dist/ingest/schema-codes.cjs +1 -0
  157. package/dist/ingest/schema-codes.cjs.map +1 -1
  158. package/dist/ingest/schema-codes.js +1 -0
  159. package/dist/ingest/schema-codes.js.map +1 -1
  160. package/dist/ingest/unique-fields.cjs +2 -2
  161. package/dist/ingest/unique-fields.cjs.map +1 -1
  162. package/dist/ingest/unique-fields.js +2 -2
  163. package/dist/ingest/unique-fields.js.map +1 -1
  164. package/dist/intercept/boundary.cjs +4 -2
  165. package/dist/intercept/boundary.cjs.map +1 -1
  166. package/dist/intercept/boundary.js +4 -2
  167. package/dist/intercept/boundary.js.map +1 -1
  168. package/dist/intercept/cell-batch.cjs +4 -4
  169. package/dist/intercept/cell-batch.cjs.map +1 -1
  170. package/dist/intercept/cell-batch.js +4 -4
  171. package/dist/intercept/cell-batch.js.map +1 -1
  172. package/dist/intercept/codes.cjs +1 -0
  173. package/dist/intercept/codes.cjs.map +1 -1
  174. package/dist/intercept/codes.js +1 -0
  175. package/dist/intercept/codes.js.map +1 -1
  176. package/dist/intercept/fallbacks.cjs +12 -20
  177. package/dist/intercept/fallbacks.cjs.map +1 -1
  178. package/dist/intercept/fallbacks.js +12 -20
  179. package/dist/intercept/fallbacks.js.map +1 -1
  180. package/dist/intercept/runtime.cjs +7 -9
  181. package/dist/intercept/runtime.cjs.map +1 -1
  182. package/dist/intercept/runtime.js +7 -9
  183. package/dist/intercept/runtime.js.map +1 -1
  184. package/dist/messages/index.cjs +4 -1
  185. package/dist/messages/index.cjs.map +1 -1
  186. package/dist/messages/index.js +4 -1
  187. package/dist/messages/index.js.map +1 -1
  188. package/dist/pagination.d.cts +2 -2
  189. package/dist/pagination.d.ts +2 -2
  190. package/dist/pipeline/codes.cjs +1 -0
  191. package/dist/pipeline/codes.cjs.map +1 -1
  192. package/dist/pipeline/codes.js +1 -0
  193. package/dist/pipeline/codes.js.map +1 -1
  194. package/dist/pipeline/column-cache.cjs +94 -76
  195. package/dist/pipeline/column-cache.cjs.map +1 -1
  196. package/dist/pipeline/column-cache.js +92 -75
  197. package/dist/pipeline/column-cache.js.map +1 -1
  198. package/dist/pipeline/dev-checks.cjs +1 -0
  199. package/dist/pipeline/dev-checks.cjs.map +1 -1
  200. package/dist/pipeline/dev-checks.js +1 -0
  201. package/dist/pipeline/dev-checks.js.map +1 -1
  202. package/dist/pipeline/env-codes.cjs +3 -2
  203. package/dist/pipeline/env-codes.cjs.map +1 -1
  204. package/dist/pipeline/env-codes.js +3 -2
  205. package/dist/pipeline/env-codes.js.map +1 -1
  206. package/dist/pipeline/perf-codes.cjs +1 -0
  207. package/dist/pipeline/perf-codes.cjs.map +1 -1
  208. package/dist/pipeline/perf-codes.js +1 -0
  209. package/dist/pipeline/perf-codes.js.map +1 -1
  210. package/dist/pipeline/runner.cjs +17 -9
  211. package/dist/pipeline/runner.cjs.map +1 -1
  212. package/dist/pipeline/runner.js +17 -9
  213. package/dist/pipeline/runner.js.map +1 -1
  214. package/dist/pipeline/slice.cjs +3 -1
  215. package/dist/pipeline/slice.cjs.map +1 -1
  216. package/dist/pipeline/slice.js +3 -1
  217. package/dist/pipeline/slice.js.map +1 -1
  218. package/dist/schema.d.cts +2 -2
  219. package/dist/schema.d.ts +2 -2
  220. package/dist/{search-async-entry-v5JdEk5Y.d.cts → search-async-entry-CuLYPfY_.d.cts} +2 -2
  221. package/dist/{search-async-entry-DGSw2pDL.d.ts → search-async-entry-Cx7xpuVZ.d.ts} +2 -2
  222. package/dist/search-async.d.cts +3 -3
  223. package/dist/search-async.d.ts +3 -3
  224. package/dist/search.d.cts +8 -6
  225. package/dist/search.d.ts +8 -6
  226. package/dist/server.d.cts +3 -3
  227. package/dist/server.d.ts +3 -3
  228. package/dist/sorting.d.cts +2 -2
  229. package/dist/sorting.d.ts +2 -2
  230. package/dist/source/codes.cjs +1 -0
  231. package/dist/source/codes.cjs.map +1 -1
  232. package/dist/source/codes.js +1 -0
  233. package/dist/source/codes.js.map +1 -1
  234. package/dist/source/fetch-codes.cjs +1 -0
  235. package/dist/source/fetch-codes.cjs.map +1 -1
  236. package/dist/source/fetch-codes.js +1 -0
  237. package/dist/source/fetch-codes.js.map +1 -1
  238. package/dist/table/codes.cjs +1 -0
  239. package/dist/table/codes.cjs.map +1 -1
  240. package/dist/table/codes.js +1 -0
  241. package/dist/table/codes.js.map +1 -1
  242. package/dist/table/create-table.cjs +39 -9
  243. package/dist/table/create-table.cjs.map +1 -1
  244. package/dist/table/create-table.js +39 -9
  245. package/dist/table/create-table.js.map +1 -1
  246. package/dist/table/data-mutation.cjs +1 -0
  247. package/dist/table/data-mutation.cjs.map +1 -1
  248. package/dist/table/data-mutation.js +1 -0
  249. package/dist/table/data-mutation.js.map +1 -1
  250. package/dist/table/internals.cjs.map +1 -1
  251. package/dist/table/internals.js.map +1 -1
  252. package/dist/table/ssr-codes.cjs +1 -0
  253. package/dist/table/ssr-codes.cjs.map +1 -1
  254. package/dist/table/ssr-codes.js +1 -0
  255. package/dist/table/ssr-codes.js.map +1 -1
  256. package/dist/table/ssr.cjs +4 -1
  257. package/dist/table/ssr.cjs.map +1 -1
  258. package/dist/table/ssr.js +4 -1
  259. package/dist/table/ssr.js.map +1 -1
  260. package/dist/table/state-feedback.cjs +19 -0
  261. package/dist/table/state-feedback.cjs.map +1 -1
  262. package/dist/table/state-feedback.js +19 -0
  263. package/dist/table/state-feedback.js.map +1 -1
  264. package/dist/table/types.cjs.map +1 -1
  265. package/dist/table/types.js.map +1 -1
  266. package/dist/validity.d.cts +2 -2
  267. package/dist/validity.d.ts +2 -2
  268. package/dist/version.cjs +1 -1
  269. package/dist/version.cjs.map +1 -1
  270. package/dist/version.js +1 -1
  271. package/dist/version.js.map +1 -1
  272. package/dist/versioning/codes.cjs +18 -0
  273. package/dist/versioning/codes.cjs.map +1 -1
  274. package/dist/versioning/codes.js +18 -0
  275. package/dist/versioning/codes.js.map +1 -1
  276. package/dist/versioning/registry.cjs +4 -2
  277. package/dist/versioning/registry.cjs.map +1 -1
  278. package/dist/versioning/registry.js +4 -2
  279. package/dist/versioning/registry.js.map +1 -1
  280. package/package.json +39 -3
@@ -36,10 +36,10 @@ var CELL_FALLBACK = {
36
36
  sortBy: void 0
37
37
  };
38
38
  var CELL_FALLBACK_TEXT = {
39
- accessor: "the failed cells read as undefined",
40
- format: "the failed cells render ''",
41
- filterFn: "the failed rows are treated as non-matching",
42
- sortBy: "the failed rows sort as missing values (last)"
39
+ accessor: "cells-undefined",
40
+ format: "cells-empty",
41
+ filterFn: "rows-unmatched",
42
+ sortBy: "rows-last"
43
43
  };
44
44
  var CellFailures = class {
45
45
  constructor(sample = 5) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/intercept/cell-batch.ts"],"sourcesContent":["import { keepDiagnostics } from '../diagnostics/catalog'\nimport type { Emit, EmitOptions } from '../diagnostics/types'\nimport { errorName } from './classify'\nimport { boundaryDiagnostics } from './codes'\n\n// CellFailures emits DK_CALLBACK_FAILED: keep its definition wherever this module is bundled (a\n// feature entry alone brings the feature runtime, and with it the column cache, #5).\nkeepDiagnostics(boundaryDiagnostics)\n\n/** The cell slots of `column:batch`. */\nexport type CellSlot = 'accessor' | 'format' | 'filterFn' | 'sortBy'\n\n/**\n * Per failed cell (§3.4): `''` (format) / `undefined` (accessor) / non-matching (filter fn) /\n * `undefined`, sorted last as a missing value (sortBy).\n */\nexport const CELL_FALLBACK = {\n accessor: undefined,\n format: '',\n filterFn: false,\n sortBy: undefined,\n} as const\n\nconst CELL_FALLBACK_TEXT: Record<CellSlot, string> = {\n accessor: 'the failed cells read as undefined',\n format: \"the failed cells render ''\",\n filterFn: 'the failed rows are treated as non-matching',\n sortBy: 'the failed rows sort as missing values (last)',\n}\n\n/**\n * Failures of one column's cells in one pipeline run, recorded as numbers (§3.4): a count, the\n * first `sample` row indices and the first error. No per-cell allocation; `where` and text are\n * built only in {@link CellFailures.report}. Reuse one instance per column across runs.\n */\nexport class CellFailures {\n count = 0\n private first: unknown\n private readonly rows: Uint32Array\n\n constructor(sample = 5) {\n this.rows = new Uint32Array(sample)\n }\n\n add(row: number, error: unknown): void {\n if (this.count === 0) this.first = error\n if (this.count < this.rows.length) this.rows[this.count] = row\n this.count++\n }\n\n /** The recorded sample of failing row indices (a view; valid until the next reset). */\n sample(): Uint32Array {\n return this.rows.subarray(0, Math.min(this.count, this.rows.length))\n }\n\n reset(): void {\n this.count = 0\n this.first = undefined\n }\n\n /**\n * Emits one `DK_CALLBACK_FAILED` for this column (if any cell failed), then resets. `where` is the\n * slot path `columns[<index>].<slot>`; `field` replaces the slot name in that path when the\n * failing column field differs (`key` for a key column whose getter threw).\n */\n report(\n emit: Emit,\n columnIndex: number,\n columnId: string,\n slot: CellSlot,\n options?: EmitOptions,\n field: string = slot,\n ): void {\n if (this.count === 0) return\n const name = errorName(this.first)\n emit(\n 'DK_CALLBACK_FAILED',\n {\n slot: `columns[${columnIndex}].${field}`,\n column: columnId,\n rows: Array.from(this.sample()),\n count: this.count,\n fallback: CELL_FALLBACK_TEXT[slot],\n ...(name === undefined ? {} : { errorName: name }),\n },\n { ...options, cause: this.first },\n )\n this.reset()\n }\n}\n\n/**\n * The body of a `column:batch`: runs `cell` for each row in `rows` and writes `out[row]`. A throwing\n * cell gets `fallback` and is recorded in `failures` — the loop never throws per cell and never\n * dispatches an interceptor per cell. Call `failures.report(...)` once after the loop.\n */\nexport function runCells<R>(\n rows: Uint32Array,\n cell: (row: number) => R,\n out: { [row: number]: R },\n fallback: R,\n failures: CellFailures,\n): void {\n for (let i = 0; i < rows.length; i++) {\n const row = rows[i] as number\n try {\n out[row] = cell(row)\n } catch (e) {\n out[row] = fallback\n failures.add(row, e)\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAAgC;AAEhC,sBAA0B;AAC1B,mBAAoC;AAAA,IAIpC,gCAAgB,gCAAmB;AAS5B,IAAM,gBAAgB;AAAA,EAC3B,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,QAAQ;AACV;AAEA,IAAM,qBAA+C;AAAA,EACnD,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,QAAQ;AACV;AAOO,IAAM,eAAN,MAAmB;AAAA,EAKxB,YAAY,SAAS,GAAG;AAJxB,iBAAQ;AAKN,SAAK,OAAO,IAAI,YAAY,MAAM;AAAA,EACpC;AAAA,EAEA,IAAI,KAAa,OAAsB;AACrC,QAAI,KAAK,UAAU,EAAG,MAAK,QAAQ;AACnC,QAAI,KAAK,QAAQ,KAAK,KAAK,OAAQ,MAAK,KAAK,KAAK,KAAK,IAAI;AAC3D,SAAK;AAAA,EACP;AAAA;AAAA,EAGA,SAAsB;AACpB,WAAO,KAAK,KAAK,SAAS,GAAG,KAAK,IAAI,KAAK,OAAO,KAAK,KAAK,MAAM,CAAC;AAAA,EACrE;AAAA,EAEA,QAAc;AACZ,SAAK,QAAQ;AACb,SAAK,QAAQ;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OACE,MACA,aACA,UACA,MACA,SACA,QAAgB,MACV;AACN,QAAI,KAAK,UAAU,EAAG;AACtB,UAAM,WAAO,2BAAU,KAAK,KAAK;AACjC;AAAA,MACE;AAAA,MACA;AAAA,QACE,MAAM,WAAW,WAAW,KAAK,KAAK;AAAA,QACtC,QAAQ;AAAA,QACR,MAAM,MAAM,KAAK,KAAK,OAAO,CAAC;AAAA,QAC9B,OAAO,KAAK;AAAA,QACZ,UAAU,mBAAmB,IAAI;AAAA,QACjC,GAAI,SAAS,SAAY,CAAC,IAAI,EAAE,WAAW,KAAK;AAAA,MAClD;AAAA,MACA,EAAE,GAAG,SAAS,OAAO,KAAK,MAAM;AAAA,IAClC;AACA,SAAK,MAAM;AAAA,EACb;AACF;AAOO,SAAS,SACd,MACA,MACA,KACA,UACA,UACM;AACN,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,MAAM,KAAK,CAAC;AAClB,QAAI;AACF,UAAI,GAAG,IAAI,KAAK,GAAG;AAAA,IACrB,SAAS,GAAG;AACV,UAAI,GAAG,IAAI;AACX,eAAS,IAAI,KAAK,CAAC;AAAA,IACrB;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/intercept/cell-batch.ts"],"sourcesContent":["import { keepDiagnostics } from '../diagnostics/catalog'\nimport type { Emit, EmitOptions } from '../diagnostics/types'\nimport { errorName } from './classify'\nimport { boundaryDiagnostics } from './codes'\n\n// CellFailures emits DK_CALLBACK_FAILED: keep its definition wherever this module is bundled (a\n// feature entry alone brings the feature runtime, and with it the column cache, #5).\nkeepDiagnostics(boundaryDiagnostics)\n\n/** The cell slots of `column:batch`. */\nexport type CellSlot = 'accessor' | 'format' | 'filterFn' | 'sortBy'\n\n/**\n * Per failed cell (§3.4): `''` (format) / `undefined` (accessor) / non-matching (filter fn) /\n * `undefined`, sorted last as a missing value (sortBy).\n */\nexport const CELL_FALLBACK = {\n accessor: undefined,\n format: '',\n filterFn: false,\n sortBy: undefined,\n} as const\n\n/** Prose keys (diagnostics/prose.ts) of each slot's fallback. */\nconst CELL_FALLBACK_TEXT: Record<CellSlot, string> = {\n accessor: 'cells-undefined',\n format: 'cells-empty',\n filterFn: 'rows-unmatched',\n sortBy: 'rows-last',\n}\n\n/**\n * Failures of one column's cells in one pipeline run, recorded as numbers (§3.4): a count, the\n * first `sample` row indices and the first error. No per-cell allocation; `where` and text are\n * built only in {@link CellFailures.report}. Reuse one instance per column across runs.\n */\nexport class CellFailures {\n count = 0\n private first: unknown\n private readonly rows: Uint32Array\n\n constructor(sample = 5) {\n this.rows = new Uint32Array(sample)\n }\n\n add(row: number, error: unknown): void {\n if (this.count === 0) this.first = error\n if (this.count < this.rows.length) this.rows[this.count] = row\n this.count++\n }\n\n /** The recorded sample of failing row indices (a view; valid until the next reset). */\n sample(): Uint32Array {\n return this.rows.subarray(0, Math.min(this.count, this.rows.length))\n }\n\n reset(): void {\n this.count = 0\n this.first = undefined\n }\n\n /**\n * Emits one `DK_CALLBACK_FAILED` for this column (if any cell failed), then resets. `where` is the\n * slot path `columns[<index>].<slot>`; `field` replaces the slot name in that path when the\n * failing column field differs (`key` for a key column whose getter threw).\n */\n report(\n emit: Emit,\n columnIndex: number,\n columnId: string,\n slot: CellSlot,\n options?: EmitOptions,\n field: string = slot,\n ): void {\n if (this.count === 0) return\n const name = errorName(this.first)\n emit(\n 'DK_CALLBACK_FAILED',\n {\n slot: `columns[${columnIndex}].${field}`,\n column: columnId,\n rows: Array.from(this.sample()),\n count: this.count,\n fallback: CELL_FALLBACK_TEXT[slot],\n ...(name === undefined ? {} : { errorName: name }),\n },\n { ...options, cause: this.first },\n )\n this.reset()\n }\n}\n\n/**\n * The body of a `column:batch`: runs `cell` for each row in `rows` and writes `out[row]`. A throwing\n * cell gets `fallback` and is recorded in `failures` — the loop never throws per cell and never\n * dispatches an interceptor per cell. Call `failures.report(...)` once after the loop.\n */\nexport function runCells<R>(\n rows: Uint32Array,\n cell: (row: number) => R,\n out: { [row: number]: R },\n fallback: R,\n failures: CellFailures,\n): void {\n for (let i = 0; i < rows.length; i++) {\n const row = rows[i] as number\n try {\n out[row] = cell(row)\n } catch (e) {\n out[row] = fallback\n failures.add(row, e)\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAAgC;AAEhC,sBAA0B;AAC1B,mBAAoC;AAAA,IAIpC,gCAAgB,gCAAmB;AAS5B,IAAM,gBAAgB;AAAA,EAC3B,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,QAAQ;AACV;AAGA,IAAM,qBAA+C;AAAA,EACnD,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,QAAQ;AACV;AAOO,IAAM,eAAN,MAAmB;AAAA,EAKxB,YAAY,SAAS,GAAG;AAJxB,iBAAQ;AAKN,SAAK,OAAO,IAAI,YAAY,MAAM;AAAA,EACpC;AAAA,EAEA,IAAI,KAAa,OAAsB;AACrC,QAAI,KAAK,UAAU,EAAG,MAAK,QAAQ;AACnC,QAAI,KAAK,QAAQ,KAAK,KAAK,OAAQ,MAAK,KAAK,KAAK,KAAK,IAAI;AAC3D,SAAK;AAAA,EACP;AAAA;AAAA,EAGA,SAAsB;AACpB,WAAO,KAAK,KAAK,SAAS,GAAG,KAAK,IAAI,KAAK,OAAO,KAAK,KAAK,MAAM,CAAC;AAAA,EACrE;AAAA,EAEA,QAAc;AACZ,SAAK,QAAQ;AACb,SAAK,QAAQ;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OACE,MACA,aACA,UACA,MACA,SACA,QAAgB,MACV;AACN,QAAI,KAAK,UAAU,EAAG;AACtB,UAAM,WAAO,2BAAU,KAAK,KAAK;AACjC;AAAA,MACE;AAAA,MACA;AAAA,QACE,MAAM,WAAW,WAAW,KAAK,KAAK;AAAA,QACtC,QAAQ;AAAA,QACR,MAAM,MAAM,KAAK,KAAK,OAAO,CAAC;AAAA,QAC9B,OAAO,KAAK;AAAA,QACZ,UAAU,mBAAmB,IAAI;AAAA,QACjC,GAAI,SAAS,SAAY,CAAC,IAAI,EAAE,WAAW,KAAK;AAAA,MAClD;AAAA,MACA,EAAE,GAAG,SAAS,OAAO,KAAK,MAAM;AAAA,IAClC;AACA,SAAK,MAAM;AAAA,EACb;AACF;AAOO,SAAS,SACd,MACA,MACA,KACA,UACA,UACM;AACN,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,MAAM,KAAK,CAAC;AAClB,QAAI;AACF,UAAI,GAAG,IAAI,KAAK,GAAG;AAAA,IACrB,SAAS,GAAG;AACV,UAAI,GAAG,IAAI;AACX,eAAS,IAAI,KAAK,CAAC;AAAA,IACrB;AAAA,EACF;AACF;","names":[]}
@@ -10,10 +10,10 @@ var CELL_FALLBACK = {
10
10
  sortBy: void 0
11
11
  };
12
12
  var CELL_FALLBACK_TEXT = {
13
- accessor: "the failed cells read as undefined",
14
- format: "the failed cells render ''",
15
- filterFn: "the failed rows are treated as non-matching",
16
- sortBy: "the failed rows sort as missing values (last)"
13
+ accessor: "cells-undefined",
14
+ format: "cells-empty",
15
+ filterFn: "rows-unmatched",
16
+ sortBy: "rows-last"
17
17
  };
18
18
  var CellFailures = class {
19
19
  constructor(sample = 5) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/intercept/cell-batch.ts"],"sourcesContent":["import { keepDiagnostics } from '../diagnostics/catalog'\nimport type { Emit, EmitOptions } from '../diagnostics/types'\nimport { errorName } from './classify'\nimport { boundaryDiagnostics } from './codes'\n\n// CellFailures emits DK_CALLBACK_FAILED: keep its definition wherever this module is bundled (a\n// feature entry alone brings the feature runtime, and with it the column cache, #5).\nkeepDiagnostics(boundaryDiagnostics)\n\n/** The cell slots of `column:batch`. */\nexport type CellSlot = 'accessor' | 'format' | 'filterFn' | 'sortBy'\n\n/**\n * Per failed cell (§3.4): `''` (format) / `undefined` (accessor) / non-matching (filter fn) /\n * `undefined`, sorted last as a missing value (sortBy).\n */\nexport const CELL_FALLBACK = {\n accessor: undefined,\n format: '',\n filterFn: false,\n sortBy: undefined,\n} as const\n\nconst CELL_FALLBACK_TEXT: Record<CellSlot, string> = {\n accessor: 'the failed cells read as undefined',\n format: \"the failed cells render ''\",\n filterFn: 'the failed rows are treated as non-matching',\n sortBy: 'the failed rows sort as missing values (last)',\n}\n\n/**\n * Failures of one column's cells in one pipeline run, recorded as numbers (§3.4): a count, the\n * first `sample` row indices and the first error. No per-cell allocation; `where` and text are\n * built only in {@link CellFailures.report}. Reuse one instance per column across runs.\n */\nexport class CellFailures {\n count = 0\n private first: unknown\n private readonly rows: Uint32Array\n\n constructor(sample = 5) {\n this.rows = new Uint32Array(sample)\n }\n\n add(row: number, error: unknown): void {\n if (this.count === 0) this.first = error\n if (this.count < this.rows.length) this.rows[this.count] = row\n this.count++\n }\n\n /** The recorded sample of failing row indices (a view; valid until the next reset). */\n sample(): Uint32Array {\n return this.rows.subarray(0, Math.min(this.count, this.rows.length))\n }\n\n reset(): void {\n this.count = 0\n this.first = undefined\n }\n\n /**\n * Emits one `DK_CALLBACK_FAILED` for this column (if any cell failed), then resets. `where` is the\n * slot path `columns[<index>].<slot>`; `field` replaces the slot name in that path when the\n * failing column field differs (`key` for a key column whose getter threw).\n */\n report(\n emit: Emit,\n columnIndex: number,\n columnId: string,\n slot: CellSlot,\n options?: EmitOptions,\n field: string = slot,\n ): void {\n if (this.count === 0) return\n const name = errorName(this.first)\n emit(\n 'DK_CALLBACK_FAILED',\n {\n slot: `columns[${columnIndex}].${field}`,\n column: columnId,\n rows: Array.from(this.sample()),\n count: this.count,\n fallback: CELL_FALLBACK_TEXT[slot],\n ...(name === undefined ? {} : { errorName: name }),\n },\n { ...options, cause: this.first },\n )\n this.reset()\n }\n}\n\n/**\n * The body of a `column:batch`: runs `cell` for each row in `rows` and writes `out[row]`. A throwing\n * cell gets `fallback` and is recorded in `failures` — the loop never throws per cell and never\n * dispatches an interceptor per cell. Call `failures.report(...)` once after the loop.\n */\nexport function runCells<R>(\n rows: Uint32Array,\n cell: (row: number) => R,\n out: { [row: number]: R },\n fallback: R,\n failures: CellFailures,\n): void {\n for (let i = 0; i < rows.length; i++) {\n const row = rows[i] as number\n try {\n out[row] = cell(row)\n } catch (e) {\n out[row] = fallback\n failures.add(row, e)\n }\n }\n}\n"],"mappings":";AAAA,SAAS,uBAAuB;AAEhC,SAAS,iBAAiB;AAC1B,SAAS,2BAA2B;AAIpC,gBAAgB,mBAAmB;AAS5B,IAAM,gBAAgB;AAAA,EAC3B,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,QAAQ;AACV;AAEA,IAAM,qBAA+C;AAAA,EACnD,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,QAAQ;AACV;AAOO,IAAM,eAAN,MAAmB;AAAA,EAKxB,YAAY,SAAS,GAAG;AAJxB,iBAAQ;AAKN,SAAK,OAAO,IAAI,YAAY,MAAM;AAAA,EACpC;AAAA,EAEA,IAAI,KAAa,OAAsB;AACrC,QAAI,KAAK,UAAU,EAAG,MAAK,QAAQ;AACnC,QAAI,KAAK,QAAQ,KAAK,KAAK,OAAQ,MAAK,KAAK,KAAK,KAAK,IAAI;AAC3D,SAAK;AAAA,EACP;AAAA;AAAA,EAGA,SAAsB;AACpB,WAAO,KAAK,KAAK,SAAS,GAAG,KAAK,IAAI,KAAK,OAAO,KAAK,KAAK,MAAM,CAAC;AAAA,EACrE;AAAA,EAEA,QAAc;AACZ,SAAK,QAAQ;AACb,SAAK,QAAQ;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OACE,MACA,aACA,UACA,MACA,SACA,QAAgB,MACV;AACN,QAAI,KAAK,UAAU,EAAG;AACtB,UAAM,OAAO,UAAU,KAAK,KAAK;AACjC;AAAA,MACE;AAAA,MACA;AAAA,QACE,MAAM,WAAW,WAAW,KAAK,KAAK;AAAA,QACtC,QAAQ;AAAA,QACR,MAAM,MAAM,KAAK,KAAK,OAAO,CAAC;AAAA,QAC9B,OAAO,KAAK;AAAA,QACZ,UAAU,mBAAmB,IAAI;AAAA,QACjC,GAAI,SAAS,SAAY,CAAC,IAAI,EAAE,WAAW,KAAK;AAAA,MAClD;AAAA,MACA,EAAE,GAAG,SAAS,OAAO,KAAK,MAAM;AAAA,IAClC;AACA,SAAK,MAAM;AAAA,EACb;AACF;AAOO,SAAS,SACd,MACA,MACA,KACA,UACA,UACM;AACN,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,MAAM,KAAK,CAAC;AAClB,QAAI;AACF,UAAI,GAAG,IAAI,KAAK,GAAG;AAAA,IACrB,SAAS,GAAG;AACV,UAAI,GAAG,IAAI;AACX,eAAS,IAAI,KAAK,CAAC;AAAA,IACrB;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/intercept/cell-batch.ts"],"sourcesContent":["import { keepDiagnostics } from '../diagnostics/catalog'\nimport type { Emit, EmitOptions } from '../diagnostics/types'\nimport { errorName } from './classify'\nimport { boundaryDiagnostics } from './codes'\n\n// CellFailures emits DK_CALLBACK_FAILED: keep its definition wherever this module is bundled (a\n// feature entry alone brings the feature runtime, and with it the column cache, #5).\nkeepDiagnostics(boundaryDiagnostics)\n\n/** The cell slots of `column:batch`. */\nexport type CellSlot = 'accessor' | 'format' | 'filterFn' | 'sortBy'\n\n/**\n * Per failed cell (§3.4): `''` (format) / `undefined` (accessor) / non-matching (filter fn) /\n * `undefined`, sorted last as a missing value (sortBy).\n */\nexport const CELL_FALLBACK = {\n accessor: undefined,\n format: '',\n filterFn: false,\n sortBy: undefined,\n} as const\n\n/** Prose keys (diagnostics/prose.ts) of each slot's fallback. */\nconst CELL_FALLBACK_TEXT: Record<CellSlot, string> = {\n accessor: 'cells-undefined',\n format: 'cells-empty',\n filterFn: 'rows-unmatched',\n sortBy: 'rows-last',\n}\n\n/**\n * Failures of one column's cells in one pipeline run, recorded as numbers (§3.4): a count, the\n * first `sample` row indices and the first error. No per-cell allocation; `where` and text are\n * built only in {@link CellFailures.report}. Reuse one instance per column across runs.\n */\nexport class CellFailures {\n count = 0\n private first: unknown\n private readonly rows: Uint32Array\n\n constructor(sample = 5) {\n this.rows = new Uint32Array(sample)\n }\n\n add(row: number, error: unknown): void {\n if (this.count === 0) this.first = error\n if (this.count < this.rows.length) this.rows[this.count] = row\n this.count++\n }\n\n /** The recorded sample of failing row indices (a view; valid until the next reset). */\n sample(): Uint32Array {\n return this.rows.subarray(0, Math.min(this.count, this.rows.length))\n }\n\n reset(): void {\n this.count = 0\n this.first = undefined\n }\n\n /**\n * Emits one `DK_CALLBACK_FAILED` for this column (if any cell failed), then resets. `where` is the\n * slot path `columns[<index>].<slot>`; `field` replaces the slot name in that path when the\n * failing column field differs (`key` for a key column whose getter threw).\n */\n report(\n emit: Emit,\n columnIndex: number,\n columnId: string,\n slot: CellSlot,\n options?: EmitOptions,\n field: string = slot,\n ): void {\n if (this.count === 0) return\n const name = errorName(this.first)\n emit(\n 'DK_CALLBACK_FAILED',\n {\n slot: `columns[${columnIndex}].${field}`,\n column: columnId,\n rows: Array.from(this.sample()),\n count: this.count,\n fallback: CELL_FALLBACK_TEXT[slot],\n ...(name === undefined ? {} : { errorName: name }),\n },\n { ...options, cause: this.first },\n )\n this.reset()\n }\n}\n\n/**\n * The body of a `column:batch`: runs `cell` for each row in `rows` and writes `out[row]`. A throwing\n * cell gets `fallback` and is recorded in `failures` — the loop never throws per cell and never\n * dispatches an interceptor per cell. Call `failures.report(...)` once after the loop.\n */\nexport function runCells<R>(\n rows: Uint32Array,\n cell: (row: number) => R,\n out: { [row: number]: R },\n fallback: R,\n failures: CellFailures,\n): void {\n for (let i = 0; i < rows.length; i++) {\n const row = rows[i] as number\n try {\n out[row] = cell(row)\n } catch (e) {\n out[row] = fallback\n failures.add(row, e)\n }\n }\n}\n"],"mappings":";AAAA,SAAS,uBAAuB;AAEhC,SAAS,iBAAiB;AAC1B,SAAS,2BAA2B;AAIpC,gBAAgB,mBAAmB;AAS5B,IAAM,gBAAgB;AAAA,EAC3B,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,QAAQ;AACV;AAGA,IAAM,qBAA+C;AAAA,EACnD,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,QAAQ;AACV;AAOO,IAAM,eAAN,MAAmB;AAAA,EAKxB,YAAY,SAAS,GAAG;AAJxB,iBAAQ;AAKN,SAAK,OAAO,IAAI,YAAY,MAAM;AAAA,EACpC;AAAA,EAEA,IAAI,KAAa,OAAsB;AACrC,QAAI,KAAK,UAAU,EAAG,MAAK,QAAQ;AACnC,QAAI,KAAK,QAAQ,KAAK,KAAK,OAAQ,MAAK,KAAK,KAAK,KAAK,IAAI;AAC3D,SAAK;AAAA,EACP;AAAA;AAAA,EAGA,SAAsB;AACpB,WAAO,KAAK,KAAK,SAAS,GAAG,KAAK,IAAI,KAAK,OAAO,KAAK,KAAK,MAAM,CAAC;AAAA,EACrE;AAAA,EAEA,QAAc;AACZ,SAAK,QAAQ;AACb,SAAK,QAAQ;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OACE,MACA,aACA,UACA,MACA,SACA,QAAgB,MACV;AACN,QAAI,KAAK,UAAU,EAAG;AACtB,UAAM,OAAO,UAAU,KAAK,KAAK;AACjC;AAAA,MACE;AAAA,MACA;AAAA,QACE,MAAM,WAAW,WAAW,KAAK,KAAK;AAAA,QACtC,QAAQ;AAAA,QACR,MAAM,MAAM,KAAK,KAAK,OAAO,CAAC;AAAA,QAC9B,OAAO,KAAK;AAAA,QACZ,UAAU,mBAAmB,IAAI;AAAA,QACjC,GAAI,SAAS,SAAY,CAAC,IAAI,EAAE,WAAW,KAAK;AAAA,MAClD;AAAA,MACA,EAAE,GAAG,SAAS,OAAO,KAAK,MAAM;AAAA,IAClC;AACA,SAAK,MAAM;AAAA,EACb;AACF;AAOO,SAAS,SACd,MACA,MACA,KACA,UACA,UACM;AACN,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,MAAM,KAAK,CAAC;AAClB,QAAI;AACF,UAAI,GAAG,IAAI,KAAK,GAAG;AAAA,IACrB,SAAS,GAAG;AACV,UAAI,GAAG,IAAI;AACX,eAAS,IAAI,KAAK,CAAC;AAAA,IACrB;AAAA,EACF;AACF;","names":[]}
@@ -25,6 +25,7 @@ __export(codes_exports, {
25
25
  });
26
26
  module.exports = __toCommonJS(codes_exports);
27
27
  var import_catalog = require("../diagnostics/catalog.cjs");
28
+ var import_process_guard = require("../diagnostics/process-guard.cjs");
28
29
  var rowList = (rows, count) => {
29
30
  if (!rows || rows.length === 0) return "";
30
31
  const list = rows.map((r) => `#${r}`).join(", ");
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/intercept/codes.ts"],"sourcesContent":["import { type DiagnosticMessages, defineDiagnostic } from '../diagnostics/catalog'\n\ndeclare module '../diagnostics/catalog' {\n interface DiagnosticCatalog {\n DK_CALLBACK_FAILED: {\n /** The callback's option path, e.g. `columns[2].format`, `fetcher`, `searchFn`. */\n slot: string\n /**\n * A callback passed to a method rather than set as an option: the method (`table.setState`);\n * `slot` is then the argument (`updater`).\n */\n op?: string\n /** Column id, for cell slots. */\n column?: string\n /** A sample of the failing row indices (first few, in order). */\n rows?: readonly number[]\n /** How many calls failed (cells in a column batch; 1 for a single call). */\n count: number\n /** The slot fallback that was applied. */\n fallback: string\n /** `error.name` only; the full error is `context.cause`. */\n errorName?: string\n }\n DK_UNKNOWN: {\n op: string\n slot?: string\n errorName?: string\n fallback: string\n }\n }\n}\n\nconst rowList = (rows: readonly number[] | undefined, count: number) => {\n if (!rows || rows.length === 0) return ''\n const list = rows.map((r) => `#${r}`).join(', ')\n return ` (${count > rows.length ? `first: ${list}, …` : `rows ${list}`})`\n}\n\n/** Message text (§8.2): development builds, or production via `@datakable/core/messages`. */\nexport const boundaryMessages: DiagnosticMessages<'DK_CALLBACK_FAILED' | 'DK_UNKNOWN'> = {\n DK_CALLBACK_FAILED: {\n problem: (d) =>\n `${d.op === undefined ? '' : `${d.op}() `}${d.slot}${d.column === undefined ? '' : ` (column \"${d.column}\")`} threw` +\n `${d.errorName ? ` ${d.errorName}` : ''} for ` +\n `${d.count === 1 ? '1 row' : `${d.count} rows`}${rowList(d.rows, d.count)}`,\n impact: (d) => `${d.fallback}; the rest of the table is unaffected`,\n fix: (d) => [\n `make ${d.op === undefined ? d.slot : `the ${d.slot} passed to ${d.op}()`} total: guard null / undefined / unexpected types and return a fallback ` +\n 'instead of throwing',\n d.rows && d.rows.length > 0\n ? `reproduce with table.explainRow() on row #${d.rows[0]}; the original error is context.cause`\n : 'the original error is context.cause (passed to onDiagnostic)',\n ],\n },\n DK_UNKNOWN: {\n problem: (d) =>\n `${d.errorName ?? 'a non-Error value'} was thrown during ${d.op}` +\n `${d.slot ? ` at ${d.slot}` : ''} from code DataKable could not classify`,\n impact: (d) => `${d.fallback}; the table keeps working`,\n fix: (d) => [\n 'inspect context.cause (passed to onDiagnostic) for the original error and its stack',\n `if your code runs inside ${d.op} (a callback, interceptor or plugin), catch errors there ` +\n 'and return a fallback',\n 'if the stack points into DataKable, report it as a bug',\n ],\n },\n}\n\n/** Codes owned by the errorBoundary (spec §3.4, §8.3, §8.6). `DK_INTERNAL` lives in diagnostics/codes.ts. */\nexport const boundaryDiagnostics = [\n defineDiagnostic(\n {\n code: 'DK_CALLBACK_FAILED',\n level: 'error',\n where: (d) =>\n d.op === undefined\n ? { kind: 'option', path: d.slot }\n : { kind: 'operation', op: d.op, slot: d.slot },\n },\n (process.env.NODE_ENV !== \"production\") && boundaryMessages.DK_CALLBACK_FAILED,\n ),\n defineDiagnostic(\n {\n code: 'DK_UNKNOWN',\n level: 'error',\n where: (d) =>\n d.slot ? { kind: 'operation', op: d.op, slot: d.slot } : { kind: 'operation', op: d.op },\n },\n (process.env.NODE_ENV !== \"production\") && boundaryMessages.DK_UNKNOWN,\n ),\n]\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAA0D;AAgC1D,IAAM,UAAU,CAAC,MAAqC,UAAkB;AACtE,MAAI,CAAC,QAAQ,KAAK,WAAW,EAAG,QAAO;AACvC,QAAM,OAAO,KAAK,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,EAAE,KAAK,IAAI;AAC/C,SAAO,KAAK,QAAQ,KAAK,SAAS,UAAU,IAAI,aAAQ,QAAQ,IAAI,EAAE;AACxE;AAGO,IAAM,mBAA4E;AAAA,EACvF,oBAAoB;AAAA,IAClB,SAAS,CAAC,MACR,GAAG,EAAE,OAAO,SAAY,KAAK,GAAG,EAAE,EAAE,KAAK,GAAG,EAAE,IAAI,GAAG,EAAE,WAAW,SAAY,KAAK,aAAa,EAAE,MAAM,IAAI,SACzG,EAAE,YAAY,IAAI,EAAE,SAAS,KAAK,EAAE,QACpC,EAAE,UAAU,IAAI,UAAU,GAAG,EAAE,KAAK,OAAO,GAAG,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC;AAAA,IAC3E,QAAQ,CAAC,MAAM,GAAG,EAAE,QAAQ;AAAA,IAC5B,KAAK,CAAC,MAAM;AAAA,MACV,QAAQ,EAAE,OAAO,SAAY,EAAE,OAAO,OAAO,EAAE,IAAI,cAAc,EAAE,EAAE,IAAI;AAAA,MAEzE,EAAE,QAAQ,EAAE,KAAK,SAAS,IACtB,6CAA6C,EAAE,KAAK,CAAC,CAAC,0CACtD;AAAA,IACN;AAAA,EACF;AAAA,EACA,YAAY;AAAA,IACV,SAAS,CAAC,MACR,GAAG,EAAE,aAAa,mBAAmB,sBAAsB,EAAE,EAAE,GAC5D,EAAE,OAAO,OAAO,EAAE,IAAI,KAAK,EAAE;AAAA,IAClC,QAAQ,CAAC,MAAM,GAAG,EAAE,QAAQ;AAAA,IAC5B,KAAK,CAAC,MAAM;AAAA,MACV;AAAA,MACA,4BAA4B,EAAE,EAAE;AAAA,MAEhC;AAAA,IACF;AAAA,EACF;AACF;AAGO,IAAM,sBAAsB;AAAA,MACjC;AAAA,IACE;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MACP,OAAO,CAAC,MACN,EAAE,OAAO,SACL,EAAE,MAAM,UAAU,MAAM,EAAE,KAAK,IAC/B,EAAE,MAAM,aAAa,IAAI,EAAE,IAAI,MAAM,EAAE,KAAK;AAAA,IACpD;AAAA,IACC,QAAQ,IAAI,aAAa,gBAAiB,iBAAiB;AAAA,EAC9D;AAAA,MACA;AAAA,IACE;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MACP,OAAO,CAAC,MACN,EAAE,OAAO,EAAE,MAAM,aAAa,IAAI,EAAE,IAAI,MAAM,EAAE,KAAK,IAAI,EAAE,MAAM,aAAa,IAAI,EAAE,GAAG;AAAA,IAC3F;AAAA,IACC,QAAQ,IAAI,aAAa,gBAAiB,iBAAiB;AAAA,EAC9D;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/intercept/codes.ts"],"sourcesContent":["import { type DiagnosticMessages, defineDiagnostic } from '../diagnostics/catalog'\nimport '../diagnostics/process-guard'\n\ndeclare module '../diagnostics/catalog' {\n interface DiagnosticCatalog {\n DK_CALLBACK_FAILED: {\n /** The callback's option path, e.g. `columns[2].format`, `fetcher`, `searchFn`. */\n slot: string\n /**\n * A callback passed to a method rather than set as an option: the method (`table.setState`);\n * `slot` is then the argument (`updater`).\n */\n op?: string\n /** Column id, for cell slots. */\n column?: string\n /** A sample of the failing row indices (first few, in order). */\n rows?: readonly number[]\n /** How many calls failed (cells in a column batch; 1 for a single call). */\n count: number\n /** The slot fallback that was applied. */\n fallback: string\n /** `error.name` only; the full error is `context.cause`. */\n errorName?: string\n }\n DK_UNKNOWN: {\n op: string\n slot?: string\n errorName?: string\n fallback: string\n }\n }\n}\n\nconst rowList = (rows: readonly number[] | undefined, count: number) => {\n if (!rows || rows.length === 0) return ''\n const list = rows.map((r) => `#${r}`).join(', ')\n return ` (${count > rows.length ? `first: ${list}, …` : `rows ${list}`})`\n}\n\n/** Message text (§8.2): development builds, or production via `@datakable/core/messages`. */\nexport const boundaryMessages: DiagnosticMessages<'DK_CALLBACK_FAILED' | 'DK_UNKNOWN'> = {\n DK_CALLBACK_FAILED: {\n problem: (d) =>\n `${d.op === undefined ? '' : `${d.op}() `}${d.slot}${d.column === undefined ? '' : ` (column \"${d.column}\")`} threw` +\n `${d.errorName ? ` ${d.errorName}` : ''} for ` +\n `${d.count === 1 ? '1 row' : `${d.count} rows`}${rowList(d.rows, d.count)}`,\n impact: (d) => `${d.fallback}; the rest of the table is unaffected`,\n fix: (d) => [\n `make ${d.op === undefined ? d.slot : `the ${d.slot} passed to ${d.op}()`} total: guard null / undefined / unexpected types and return a fallback ` +\n 'instead of throwing',\n d.rows && d.rows.length > 0\n ? `reproduce with table.explainRow() on row #${d.rows[0]}; the original error is context.cause`\n : 'the original error is context.cause (passed to onDiagnostic)',\n ],\n },\n DK_UNKNOWN: {\n problem: (d) =>\n `${d.errorName ?? 'a non-Error value'} was thrown during ${d.op}` +\n `${d.slot ? ` at ${d.slot}` : ''} from code DataKable could not classify`,\n impact: (d) => `${d.fallback}; the table keeps working`,\n fix: (d) => [\n 'inspect context.cause (passed to onDiagnostic) for the original error and its stack',\n `if your code runs inside ${d.op} (a callback, interceptor or plugin), catch errors there ` +\n 'and return a fallback',\n 'if the stack points into DataKable, report it as a bug',\n ],\n },\n}\n\n/** Codes owned by the errorBoundary (spec §3.4, §8.3, §8.6). `DK_INTERNAL` lives in diagnostics/codes.ts. */\nexport const boundaryDiagnostics = [\n defineDiagnostic(\n {\n code: 'DK_CALLBACK_FAILED',\n level: 'error',\n where: (d) =>\n d.op === undefined\n ? { kind: 'option', path: d.slot }\n : { kind: 'operation', op: d.op, slot: d.slot },\n },\n (process.env.NODE_ENV !== \"production\") && boundaryMessages.DK_CALLBACK_FAILED,\n ),\n defineDiagnostic(\n {\n code: 'DK_UNKNOWN',\n level: 'error',\n where: (d) =>\n d.slot ? { kind: 'operation', op: d.op, slot: d.slot } : { kind: 'operation', op: d.op },\n },\n (process.env.NODE_ENV !== \"production\") && boundaryMessages.DK_UNKNOWN,\n ),\n]\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAA0D;AAC1D,2BAAO;AAgCP,IAAM,UAAU,CAAC,MAAqC,UAAkB;AACtE,MAAI,CAAC,QAAQ,KAAK,WAAW,EAAG,QAAO;AACvC,QAAM,OAAO,KAAK,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,EAAE,KAAK,IAAI;AAC/C,SAAO,KAAK,QAAQ,KAAK,SAAS,UAAU,IAAI,aAAQ,QAAQ,IAAI,EAAE;AACxE;AAGO,IAAM,mBAA4E;AAAA,EACvF,oBAAoB;AAAA,IAClB,SAAS,CAAC,MACR,GAAG,EAAE,OAAO,SAAY,KAAK,GAAG,EAAE,EAAE,KAAK,GAAG,EAAE,IAAI,GAAG,EAAE,WAAW,SAAY,KAAK,aAAa,EAAE,MAAM,IAAI,SACzG,EAAE,YAAY,IAAI,EAAE,SAAS,KAAK,EAAE,QACpC,EAAE,UAAU,IAAI,UAAU,GAAG,EAAE,KAAK,OAAO,GAAG,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC;AAAA,IAC3E,QAAQ,CAAC,MAAM,GAAG,EAAE,QAAQ;AAAA,IAC5B,KAAK,CAAC,MAAM;AAAA,MACV,QAAQ,EAAE,OAAO,SAAY,EAAE,OAAO,OAAO,EAAE,IAAI,cAAc,EAAE,EAAE,IAAI;AAAA,MAEzE,EAAE,QAAQ,EAAE,KAAK,SAAS,IACtB,6CAA6C,EAAE,KAAK,CAAC,CAAC,0CACtD;AAAA,IACN;AAAA,EACF;AAAA,EACA,YAAY;AAAA,IACV,SAAS,CAAC,MACR,GAAG,EAAE,aAAa,mBAAmB,sBAAsB,EAAE,EAAE,GAC5D,EAAE,OAAO,OAAO,EAAE,IAAI,KAAK,EAAE;AAAA,IAClC,QAAQ,CAAC,MAAM,GAAG,EAAE,QAAQ;AAAA,IAC5B,KAAK,CAAC,MAAM;AAAA,MACV;AAAA,MACA,4BAA4B,EAAE,EAAE;AAAA,MAEhC;AAAA,IACF;AAAA,EACF;AACF;AAGO,IAAM,sBAAsB;AAAA,MACjC;AAAA,IACE;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MACP,OAAO,CAAC,MACN,EAAE,OAAO,SACL,EAAE,MAAM,UAAU,MAAM,EAAE,KAAK,IAC/B,EAAE,MAAM,aAAa,IAAI,EAAE,IAAI,MAAM,EAAE,KAAK;AAAA,IACpD;AAAA,IACC,QAAQ,IAAI,aAAa,gBAAiB,iBAAiB;AAAA,EAC9D;AAAA,MACA;AAAA,IACE;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MACP,OAAO,CAAC,MACN,EAAE,OAAO,EAAE,MAAM,aAAa,IAAI,EAAE,IAAI,MAAM,EAAE,KAAK,IAAI,EAAE,MAAM,aAAa,IAAI,EAAE,GAAG;AAAA,IAC3F;AAAA,IACC,QAAQ,IAAI,aAAa,gBAAiB,iBAAiB;AAAA,EAC9D;AACF;","names":[]}
@@ -1,5 +1,6 @@
1
1
  // src/intercept/codes.ts
2
2
  import { defineDiagnostic } from "../diagnostics/catalog.js";
3
+ import "../diagnostics/process-guard.js";
3
4
  var rowList = (rows, count) => {
4
5
  if (!rows || rows.length === 0) return "";
5
6
  const list = rows.map((r) => `#${r}`).join(", ");
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/intercept/codes.ts"],"sourcesContent":["import { type DiagnosticMessages, defineDiagnostic } from '../diagnostics/catalog'\n\ndeclare module '../diagnostics/catalog' {\n interface DiagnosticCatalog {\n DK_CALLBACK_FAILED: {\n /** The callback's option path, e.g. `columns[2].format`, `fetcher`, `searchFn`. */\n slot: string\n /**\n * A callback passed to a method rather than set as an option: the method (`table.setState`);\n * `slot` is then the argument (`updater`).\n */\n op?: string\n /** Column id, for cell slots. */\n column?: string\n /** A sample of the failing row indices (first few, in order). */\n rows?: readonly number[]\n /** How many calls failed (cells in a column batch; 1 for a single call). */\n count: number\n /** The slot fallback that was applied. */\n fallback: string\n /** `error.name` only; the full error is `context.cause`. */\n errorName?: string\n }\n DK_UNKNOWN: {\n op: string\n slot?: string\n errorName?: string\n fallback: string\n }\n }\n}\n\nconst rowList = (rows: readonly number[] | undefined, count: number) => {\n if (!rows || rows.length === 0) return ''\n const list = rows.map((r) => `#${r}`).join(', ')\n return ` (${count > rows.length ? `first: ${list}, …` : `rows ${list}`})`\n}\n\n/** Message text (§8.2): development builds, or production via `@datakable/core/messages`. */\nexport const boundaryMessages: DiagnosticMessages<'DK_CALLBACK_FAILED' | 'DK_UNKNOWN'> = {\n DK_CALLBACK_FAILED: {\n problem: (d) =>\n `${d.op === undefined ? '' : `${d.op}() `}${d.slot}${d.column === undefined ? '' : ` (column \"${d.column}\")`} threw` +\n `${d.errorName ? ` ${d.errorName}` : ''} for ` +\n `${d.count === 1 ? '1 row' : `${d.count} rows`}${rowList(d.rows, d.count)}`,\n impact: (d) => `${d.fallback}; the rest of the table is unaffected`,\n fix: (d) => [\n `make ${d.op === undefined ? d.slot : `the ${d.slot} passed to ${d.op}()`} total: guard null / undefined / unexpected types and return a fallback ` +\n 'instead of throwing',\n d.rows && d.rows.length > 0\n ? `reproduce with table.explainRow() on row #${d.rows[0]}; the original error is context.cause`\n : 'the original error is context.cause (passed to onDiagnostic)',\n ],\n },\n DK_UNKNOWN: {\n problem: (d) =>\n `${d.errorName ?? 'a non-Error value'} was thrown during ${d.op}` +\n `${d.slot ? ` at ${d.slot}` : ''} from code DataKable could not classify`,\n impact: (d) => `${d.fallback}; the table keeps working`,\n fix: (d) => [\n 'inspect context.cause (passed to onDiagnostic) for the original error and its stack',\n `if your code runs inside ${d.op} (a callback, interceptor or plugin), catch errors there ` +\n 'and return a fallback',\n 'if the stack points into DataKable, report it as a bug',\n ],\n },\n}\n\n/** Codes owned by the errorBoundary (spec §3.4, §8.3, §8.6). `DK_INTERNAL` lives in diagnostics/codes.ts. */\nexport const boundaryDiagnostics = [\n defineDiagnostic(\n {\n code: 'DK_CALLBACK_FAILED',\n level: 'error',\n where: (d) =>\n d.op === undefined\n ? { kind: 'option', path: d.slot }\n : { kind: 'operation', op: d.op, slot: d.slot },\n },\n (process.env.NODE_ENV !== \"production\") && boundaryMessages.DK_CALLBACK_FAILED,\n ),\n defineDiagnostic(\n {\n code: 'DK_UNKNOWN',\n level: 'error',\n where: (d) =>\n d.slot ? { kind: 'operation', op: d.op, slot: d.slot } : { kind: 'operation', op: d.op },\n },\n (process.env.NODE_ENV !== \"production\") && boundaryMessages.DK_UNKNOWN,\n ),\n]\n"],"mappings":";AAAA,SAAkC,wBAAwB;AAgC1D,IAAM,UAAU,CAAC,MAAqC,UAAkB;AACtE,MAAI,CAAC,QAAQ,KAAK,WAAW,EAAG,QAAO;AACvC,QAAM,OAAO,KAAK,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,EAAE,KAAK,IAAI;AAC/C,SAAO,KAAK,QAAQ,KAAK,SAAS,UAAU,IAAI,aAAQ,QAAQ,IAAI,EAAE;AACxE;AAGO,IAAM,mBAA4E;AAAA,EACvF,oBAAoB;AAAA,IAClB,SAAS,CAAC,MACR,GAAG,EAAE,OAAO,SAAY,KAAK,GAAG,EAAE,EAAE,KAAK,GAAG,EAAE,IAAI,GAAG,EAAE,WAAW,SAAY,KAAK,aAAa,EAAE,MAAM,IAAI,SACzG,EAAE,YAAY,IAAI,EAAE,SAAS,KAAK,EAAE,QACpC,EAAE,UAAU,IAAI,UAAU,GAAG,EAAE,KAAK,OAAO,GAAG,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC;AAAA,IAC3E,QAAQ,CAAC,MAAM,GAAG,EAAE,QAAQ;AAAA,IAC5B,KAAK,CAAC,MAAM;AAAA,MACV,QAAQ,EAAE,OAAO,SAAY,EAAE,OAAO,OAAO,EAAE,IAAI,cAAc,EAAE,EAAE,IAAI;AAAA,MAEzE,EAAE,QAAQ,EAAE,KAAK,SAAS,IACtB,6CAA6C,EAAE,KAAK,CAAC,CAAC,0CACtD;AAAA,IACN;AAAA,EACF;AAAA,EACA,YAAY;AAAA,IACV,SAAS,CAAC,MACR,GAAG,EAAE,aAAa,mBAAmB,sBAAsB,EAAE,EAAE,GAC5D,EAAE,OAAO,OAAO,EAAE,IAAI,KAAK,EAAE;AAAA,IAClC,QAAQ,CAAC,MAAM,GAAG,EAAE,QAAQ;AAAA,IAC5B,KAAK,CAAC,MAAM;AAAA,MACV;AAAA,MACA,4BAA4B,EAAE,EAAE;AAAA,MAEhC;AAAA,IACF;AAAA,EACF;AACF;AAGO,IAAM,sBAAsB;AAAA,EACjC;AAAA,IACE;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MACP,OAAO,CAAC,MACN,EAAE,OAAO,SACL,EAAE,MAAM,UAAU,MAAM,EAAE,KAAK,IAC/B,EAAE,MAAM,aAAa,IAAI,EAAE,IAAI,MAAM,EAAE,KAAK;AAAA,IACpD;AAAA,IACC,QAAQ,IAAI,aAAa,gBAAiB,iBAAiB;AAAA,EAC9D;AAAA,EACA;AAAA,IACE;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MACP,OAAO,CAAC,MACN,EAAE,OAAO,EAAE,MAAM,aAAa,IAAI,EAAE,IAAI,MAAM,EAAE,KAAK,IAAI,EAAE,MAAM,aAAa,IAAI,EAAE,GAAG;AAAA,IAC3F;AAAA,IACC,QAAQ,IAAI,aAAa,gBAAiB,iBAAiB;AAAA,EAC9D;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/intercept/codes.ts"],"sourcesContent":["import { type DiagnosticMessages, defineDiagnostic } from '../diagnostics/catalog'\nimport '../diagnostics/process-guard'\n\ndeclare module '../diagnostics/catalog' {\n interface DiagnosticCatalog {\n DK_CALLBACK_FAILED: {\n /** The callback's option path, e.g. `columns[2].format`, `fetcher`, `searchFn`. */\n slot: string\n /**\n * A callback passed to a method rather than set as an option: the method (`table.setState`);\n * `slot` is then the argument (`updater`).\n */\n op?: string\n /** Column id, for cell slots. */\n column?: string\n /** A sample of the failing row indices (first few, in order). */\n rows?: readonly number[]\n /** How many calls failed (cells in a column batch; 1 for a single call). */\n count: number\n /** The slot fallback that was applied. */\n fallback: string\n /** `error.name` only; the full error is `context.cause`. */\n errorName?: string\n }\n DK_UNKNOWN: {\n op: string\n slot?: string\n errorName?: string\n fallback: string\n }\n }\n}\n\nconst rowList = (rows: readonly number[] | undefined, count: number) => {\n if (!rows || rows.length === 0) return ''\n const list = rows.map((r) => `#${r}`).join(', ')\n return ` (${count > rows.length ? `first: ${list}, …` : `rows ${list}`})`\n}\n\n/** Message text (§8.2): development builds, or production via `@datakable/core/messages`. */\nexport const boundaryMessages: DiagnosticMessages<'DK_CALLBACK_FAILED' | 'DK_UNKNOWN'> = {\n DK_CALLBACK_FAILED: {\n problem: (d) =>\n `${d.op === undefined ? '' : `${d.op}() `}${d.slot}${d.column === undefined ? '' : ` (column \"${d.column}\")`} threw` +\n `${d.errorName ? ` ${d.errorName}` : ''} for ` +\n `${d.count === 1 ? '1 row' : `${d.count} rows`}${rowList(d.rows, d.count)}`,\n impact: (d) => `${d.fallback}; the rest of the table is unaffected`,\n fix: (d) => [\n `make ${d.op === undefined ? d.slot : `the ${d.slot} passed to ${d.op}()`} total: guard null / undefined / unexpected types and return a fallback ` +\n 'instead of throwing',\n d.rows && d.rows.length > 0\n ? `reproduce with table.explainRow() on row #${d.rows[0]}; the original error is context.cause`\n : 'the original error is context.cause (passed to onDiagnostic)',\n ],\n },\n DK_UNKNOWN: {\n problem: (d) =>\n `${d.errorName ?? 'a non-Error value'} was thrown during ${d.op}` +\n `${d.slot ? ` at ${d.slot}` : ''} from code DataKable could not classify`,\n impact: (d) => `${d.fallback}; the table keeps working`,\n fix: (d) => [\n 'inspect context.cause (passed to onDiagnostic) for the original error and its stack',\n `if your code runs inside ${d.op} (a callback, interceptor or plugin), catch errors there ` +\n 'and return a fallback',\n 'if the stack points into DataKable, report it as a bug',\n ],\n },\n}\n\n/** Codes owned by the errorBoundary (spec §3.4, §8.3, §8.6). `DK_INTERNAL` lives in diagnostics/codes.ts. */\nexport const boundaryDiagnostics = [\n defineDiagnostic(\n {\n code: 'DK_CALLBACK_FAILED',\n level: 'error',\n where: (d) =>\n d.op === undefined\n ? { kind: 'option', path: d.slot }\n : { kind: 'operation', op: d.op, slot: d.slot },\n },\n (process.env.NODE_ENV !== \"production\") && boundaryMessages.DK_CALLBACK_FAILED,\n ),\n defineDiagnostic(\n {\n code: 'DK_UNKNOWN',\n level: 'error',\n where: (d) =>\n d.slot ? { kind: 'operation', op: d.op, slot: d.slot } : { kind: 'operation', op: d.op },\n },\n (process.env.NODE_ENV !== \"production\") && boundaryMessages.DK_UNKNOWN,\n ),\n]\n"],"mappings":";AAAA,SAAkC,wBAAwB;AAC1D,OAAO;AAgCP,IAAM,UAAU,CAAC,MAAqC,UAAkB;AACtE,MAAI,CAAC,QAAQ,KAAK,WAAW,EAAG,QAAO;AACvC,QAAM,OAAO,KAAK,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,EAAE,KAAK,IAAI;AAC/C,SAAO,KAAK,QAAQ,KAAK,SAAS,UAAU,IAAI,aAAQ,QAAQ,IAAI,EAAE;AACxE;AAGO,IAAM,mBAA4E;AAAA,EACvF,oBAAoB;AAAA,IAClB,SAAS,CAAC,MACR,GAAG,EAAE,OAAO,SAAY,KAAK,GAAG,EAAE,EAAE,KAAK,GAAG,EAAE,IAAI,GAAG,EAAE,WAAW,SAAY,KAAK,aAAa,EAAE,MAAM,IAAI,SACzG,EAAE,YAAY,IAAI,EAAE,SAAS,KAAK,EAAE,QACpC,EAAE,UAAU,IAAI,UAAU,GAAG,EAAE,KAAK,OAAO,GAAG,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC;AAAA,IAC3E,QAAQ,CAAC,MAAM,GAAG,EAAE,QAAQ;AAAA,IAC5B,KAAK,CAAC,MAAM;AAAA,MACV,QAAQ,EAAE,OAAO,SAAY,EAAE,OAAO,OAAO,EAAE,IAAI,cAAc,EAAE,EAAE,IAAI;AAAA,MAEzE,EAAE,QAAQ,EAAE,KAAK,SAAS,IACtB,6CAA6C,EAAE,KAAK,CAAC,CAAC,0CACtD;AAAA,IACN;AAAA,EACF;AAAA,EACA,YAAY;AAAA,IACV,SAAS,CAAC,MACR,GAAG,EAAE,aAAa,mBAAmB,sBAAsB,EAAE,EAAE,GAC5D,EAAE,OAAO,OAAO,EAAE,IAAI,KAAK,EAAE;AAAA,IAClC,QAAQ,CAAC,MAAM,GAAG,EAAE,QAAQ;AAAA,IAC5B,KAAK,CAAC,MAAM;AAAA,MACV;AAAA,MACA,4BAA4B,EAAE,EAAE;AAAA,MAEhC;AAAA,IACF;AAAA,EACF;AACF;AAGO,IAAM,sBAAsB;AAAA,EACjC;AAAA,IACE;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MACP,OAAO,CAAC,MACN,EAAE,OAAO,SACL,EAAE,MAAM,UAAU,MAAM,EAAE,KAAK,IAC/B,EAAE,MAAM,aAAa,IAAI,EAAE,IAAI,MAAM,EAAE,KAAK;AAAA,IACpD;AAAA,IACC,QAAQ,IAAI,aAAa,gBAAiB,iBAAiB;AAAA,EAC9D;AAAA,EACA;AAAA,IACE;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MACP,OAAO,CAAC,MACN,EAAE,OAAO,EAAE,MAAM,aAAa,IAAI,EAAE,IAAI,MAAM,EAAE,KAAK,IAAI,EAAE,MAAM,aAAa,IAAI,EAAE,GAAG;AAAA,IAC3F;AAAA,IACC,QAAQ,IAAI,aAAa,gBAAiB,iBAAiB;AAAA,EAC9D;AACF;","names":[]}
@@ -34,46 +34,38 @@ function allRows(n) {
34
34
  return out;
35
35
  }
36
36
  var builtins = {
37
- "table:init": {
38
- describe: "table creation continued without the failed step",
39
- value: () => void 0
40
- },
41
- "table:setOptions": { describe: "the previous options were kept", value: () => void 0 },
42
- "table:destroy": {
43
- describe: "teardown continued; the table is destroyed",
44
- value: () => void 0
45
- },
46
- "state:dispatch": {
47
- describe: "the update was dropped (state unchanged)",
48
- value: () => void 0
49
- },
37
+ // `describe`: prose keys (diagnostics/prose.ts); a plugin's own fallback may use plain text.
38
+ "table:init": { describe: "init-continued", value: () => void 0 },
39
+ "table:setOptions": { describe: "options-kept", value: () => void 0 },
40
+ "table:destroy": { describe: "destroy-continued", value: () => void 0 },
41
+ "state:dispatch": { describe: "update-dropped", value: () => void 0 },
50
42
  "data:ingest": {
51
- describe: "the previous data was kept",
43
+ describe: "data-kept",
52
44
  value: (ctx) => ctx.meta.get(FALLBACK) ?? []
53
45
  },
54
46
  "pipeline:run": {
55
- describe: "the last good row model was kept",
47
+ describe: "row-model-kept",
56
48
  value: (ctx) => ctx.meta.get(FALLBACK) ?? allRows(ctx.input.rowCount)
57
49
  },
58
50
  "pipeline:step": {
59
- describe: "the step passed its input through",
51
+ describe: "step-passthrough",
60
52
  value: (ctx) => ctx.input.indices
61
53
  },
62
54
  "column:batch": {
63
- describe: "the column's cells use the slot fallback ('' for format, undefined for accessor, non-matching for filterFn, missing (sorted last) for sortBy)",
55
+ describe: "batch-fallback",
64
56
  value: () => void 0
65
57
  },
66
58
  "async:request": {
67
- describe: "the previous results were kept (status: 'error')",
59
+ describe: "results-kept",
68
60
  value: (ctx) => Promise.resolve(ctx.meta.get(FALLBACK))
69
61
  },
70
62
  "diagnostic:emit": {
71
- describe: "the diagnostic was dropped (the logger never kills the table)",
63
+ describe: "diagnostic-dropped",
72
64
  silent: true,
73
65
  value: () => void 0
74
66
  }
75
67
  };
76
- var NONE = { describe: "the operation returned undefined", value: () => void 0 };
68
+ var NONE = { describe: "returned-undefined", value: () => void 0 };
77
69
  var registry = new Map(Object.entries(builtins));
78
70
  function registerFallback(op, fallback) {
79
71
  registry.set(op, fallback);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/intercept/fallbacks.ts"],"sourcesContent":["import type { InterceptorContext } from './context'\nimport type { BuiltinOperations, OpName, OpResult } from './operations'\n\n/**\n * What the errorBoundary returns when an op fails (§3.4 registry table). `describe` becomes the\n * diagnostic's `impact`.\n */\nexport interface Fallback<O extends OpName = OpName> {\n readonly describe: string\n /**\n * Report without the diagnostics pipeline: one `console.error` per table. Used by\n * `diagnostic:emit`, where reporting through the pipeline could recurse.\n */\n readonly silent?: boolean\n value(ctx: InterceptorContext<O>): OpResult<O>\n}\n\n/**\n * `ctx.meta` key for a caller-supplied fallback value: the previous data (`data:ingest`), the last\n * good row model (`pipeline:run`), the previous results (`async:request`). Set it before `run`.\n */\nexport const FALLBACK = 'datakable:fallback'\n\n/**\n * `ctx.meta` key the errorBoundary sets (to the error) when it replaced the op's result with the\n * fallback, so the caller can tell a fallback from a real result (e.g. a failed `data:ingest` sets\n * `status: 'error'`, §6.6).\n */\nexport const FAILED = 'datakable:failed'\n\nfunction allRows(n: number): Uint32Array {\n const out = new Uint32Array(n)\n for (let i = 0; i < n; i++) out[i] = i\n return out\n}\n\nconst builtins: { [K in keyof BuiltinOperations]: Fallback<K> } = {\n 'table:init': {\n describe: 'table creation continued without the failed step',\n value: () => undefined,\n },\n 'table:setOptions': { describe: 'the previous options were kept', value: () => undefined },\n 'table:destroy': {\n describe: 'teardown continued; the table is destroyed',\n value: () => undefined,\n },\n 'state:dispatch': {\n describe: 'the update was dropped (state unchanged)',\n value: () => undefined,\n },\n 'data:ingest': {\n describe: 'the previous data was kept',\n value: (ctx) => (ctx.meta.get(FALLBACK) as readonly unknown[] | undefined) ?? [],\n },\n 'pipeline:run': {\n describe: 'the last good row model was kept',\n value: (ctx) =>\n (ctx.meta.get(FALLBACK) as Uint32Array | undefined) ?? allRows(ctx.input.rowCount),\n },\n 'pipeline:step': {\n describe: 'the step passed its input through',\n value: (ctx) => ctx.input.indices,\n },\n 'column:batch': {\n describe:\n \"the column's cells use the slot fallback ('' for format, undefined for accessor, \" +\n 'non-matching for filterFn, missing (sorted last) for sortBy)',\n value: () => undefined,\n },\n 'async:request': {\n describe: \"the previous results were kept (status: 'error')\",\n value: (ctx) => Promise.resolve(ctx.meta.get(FALLBACK)),\n },\n 'diagnostic:emit': {\n describe: 'the diagnostic was dropped (the logger never kills the table)',\n silent: true,\n value: () => undefined,\n },\n}\n\nconst NONE: Fallback = { describe: 'the operation returned undefined', value: () => undefined }\n\nconst registry = new Map<string, Fallback>(Object.entries(builtins) as [string, Fallback][])\n\n/**\n * Sets the fallback of an op (ops registered by plugins / `@datakable/react`). Process-wide like\n * the op registry; the last registration wins.\n */\nexport function registerFallback<O extends OpName>(op: O, fallback: Fallback<O>): void {\n registry.set(op, fallback as unknown as Fallback)\n}\n\n/** The registered fallback, or one that returns `undefined` for ops without an entry. */\nexport function getFallback(op: string): Fallback {\n return registry.get(op) ?? NONE\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAqBO,IAAM,WAAW;AAOjB,IAAM,SAAS;AAEtB,SAAS,QAAQ,GAAwB;AACvC,QAAM,MAAM,IAAI,YAAY,CAAC;AAC7B,WAAS,IAAI,GAAG,IAAI,GAAG,IAAK,KAAI,CAAC,IAAI;AACrC,SAAO;AACT;AAEA,IAAM,WAA4D;AAAA,EAChE,cAAc;AAAA,IACZ,UAAU;AAAA,IACV,OAAO,MAAM;AAAA,EACf;AAAA,EACA,oBAAoB,EAAE,UAAU,kCAAkC,OAAO,MAAM,OAAU;AAAA,EACzF,iBAAiB;AAAA,IACf,UAAU;AAAA,IACV,OAAO,MAAM;AAAA,EACf;AAAA,EACA,kBAAkB;AAAA,IAChB,UAAU;AAAA,IACV,OAAO,MAAM;AAAA,EACf;AAAA,EACA,eAAe;AAAA,IACb,UAAU;AAAA,IACV,OAAO,CAAC,QAAS,IAAI,KAAK,IAAI,QAAQ,KAAwC,CAAC;AAAA,EACjF;AAAA,EACA,gBAAgB;AAAA,IACd,UAAU;AAAA,IACV,OAAO,CAAC,QACL,IAAI,KAAK,IAAI,QAAQ,KAAiC,QAAQ,IAAI,MAAM,QAAQ;AAAA,EACrF;AAAA,EACA,iBAAiB;AAAA,IACf,UAAU;AAAA,IACV,OAAO,CAAC,QAAQ,IAAI,MAAM;AAAA,EAC5B;AAAA,EACA,gBAAgB;AAAA,IACd,UACE;AAAA,IAEF,OAAO,MAAM;AAAA,EACf;AAAA,EACA,iBAAiB;AAAA,IACf,UAAU;AAAA,IACV,OAAO,CAAC,QAAQ,QAAQ,QAAQ,IAAI,KAAK,IAAI,QAAQ,CAAC;AAAA,EACxD;AAAA,EACA,mBAAmB;AAAA,IACjB,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,OAAO,MAAM;AAAA,EACf;AACF;AAEA,IAAM,OAAiB,EAAE,UAAU,oCAAoC,OAAO,MAAM,OAAU;AAE9F,IAAM,WAAW,IAAI,IAAsB,OAAO,QAAQ,QAAQ,CAAyB;AAMpF,SAAS,iBAAmC,IAAO,UAA6B;AACrF,WAAS,IAAI,IAAI,QAA+B;AAClD;AAGO,SAAS,YAAY,IAAsB;AAChD,SAAO,SAAS,IAAI,EAAE,KAAK;AAC7B;","names":[]}
1
+ {"version":3,"sources":["../../src/intercept/fallbacks.ts"],"sourcesContent":["import type { InterceptorContext } from './context'\nimport type { BuiltinOperations, OpName, OpResult } from './operations'\n\n/**\n * What the errorBoundary returns when an op fails (§3.4 registry table). `describe` becomes the\n * diagnostic's `impact`.\n */\nexport interface Fallback<O extends OpName = OpName> {\n readonly describe: string\n /**\n * Report without the diagnostics pipeline: one `console.error` per table. Used by\n * `diagnostic:emit`, where reporting through the pipeline could recurse.\n */\n readonly silent?: boolean\n value(ctx: InterceptorContext<O>): OpResult<O>\n}\n\n/**\n * `ctx.meta` key for a caller-supplied fallback value: the previous data (`data:ingest`), the last\n * good row model (`pipeline:run`), the previous results (`async:request`). Set it before `run`.\n */\nexport const FALLBACK = 'datakable:fallback'\n\n/**\n * `ctx.meta` key the errorBoundary sets (to the error) when it replaced the op's result with the\n * fallback, so the caller can tell a fallback from a real result (e.g. a failed `data:ingest` sets\n * `status: 'error'`, §6.6).\n */\nexport const FAILED = 'datakable:failed'\n\nfunction allRows(n: number): Uint32Array {\n const out = new Uint32Array(n)\n for (let i = 0; i < n; i++) out[i] = i\n return out\n}\n\nconst builtins: { [K in keyof BuiltinOperations]: Fallback<K> } = {\n // `describe`: prose keys (diagnostics/prose.ts); a plugin's own fallback may use plain text.\n 'table:init': { describe: 'init-continued', value: () => undefined },\n 'table:setOptions': { describe: 'options-kept', value: () => undefined },\n 'table:destroy': { describe: 'destroy-continued', value: () => undefined },\n 'state:dispatch': { describe: 'update-dropped', value: () => undefined },\n 'data:ingest': {\n describe: 'data-kept',\n value: (ctx) => (ctx.meta.get(FALLBACK) as readonly unknown[] | undefined) ?? [],\n },\n 'pipeline:run': {\n describe: 'row-model-kept',\n value: (ctx) =>\n (ctx.meta.get(FALLBACK) as Uint32Array | undefined) ?? allRows(ctx.input.rowCount),\n },\n 'pipeline:step': {\n describe: 'step-passthrough',\n value: (ctx) => ctx.input.indices,\n },\n 'column:batch': {\n describe: 'batch-fallback',\n value: () => undefined,\n },\n 'async:request': {\n describe: 'results-kept',\n value: (ctx) => Promise.resolve(ctx.meta.get(FALLBACK)),\n },\n 'diagnostic:emit': {\n describe: 'diagnostic-dropped',\n silent: true,\n value: () => undefined,\n },\n}\n\nconst NONE: Fallback = { describe: 'returned-undefined', value: () => undefined }\n\nconst registry = new Map<string, Fallback>(Object.entries(builtins) as [string, Fallback][])\n\n/**\n * Sets the fallback of an op (ops registered by plugins / `@datakable/react`). Process-wide like\n * the op registry; the last registration wins.\n */\nexport function registerFallback<O extends OpName>(op: O, fallback: Fallback<O>): void {\n registry.set(op, fallback as unknown as Fallback)\n}\n\n/** The registered fallback, or one that returns `undefined` for ops without an entry. */\nexport function getFallback(op: string): Fallback {\n return registry.get(op) ?? NONE\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAqBO,IAAM,WAAW;AAOjB,IAAM,SAAS;AAEtB,SAAS,QAAQ,GAAwB;AACvC,QAAM,MAAM,IAAI,YAAY,CAAC;AAC7B,WAAS,IAAI,GAAG,IAAI,GAAG,IAAK,KAAI,CAAC,IAAI;AACrC,SAAO;AACT;AAEA,IAAM,WAA4D;AAAA;AAAA,EAEhE,cAAc,EAAE,UAAU,kBAAkB,OAAO,MAAM,OAAU;AAAA,EACnE,oBAAoB,EAAE,UAAU,gBAAgB,OAAO,MAAM,OAAU;AAAA,EACvE,iBAAiB,EAAE,UAAU,qBAAqB,OAAO,MAAM,OAAU;AAAA,EACzE,kBAAkB,EAAE,UAAU,kBAAkB,OAAO,MAAM,OAAU;AAAA,EACvE,eAAe;AAAA,IACb,UAAU;AAAA,IACV,OAAO,CAAC,QAAS,IAAI,KAAK,IAAI,QAAQ,KAAwC,CAAC;AAAA,EACjF;AAAA,EACA,gBAAgB;AAAA,IACd,UAAU;AAAA,IACV,OAAO,CAAC,QACL,IAAI,KAAK,IAAI,QAAQ,KAAiC,QAAQ,IAAI,MAAM,QAAQ;AAAA,EACrF;AAAA,EACA,iBAAiB;AAAA,IACf,UAAU;AAAA,IACV,OAAO,CAAC,QAAQ,IAAI,MAAM;AAAA,EAC5B;AAAA,EACA,gBAAgB;AAAA,IACd,UAAU;AAAA,IACV,OAAO,MAAM;AAAA,EACf;AAAA,EACA,iBAAiB;AAAA,IACf,UAAU;AAAA,IACV,OAAO,CAAC,QAAQ,QAAQ,QAAQ,IAAI,KAAK,IAAI,QAAQ,CAAC;AAAA,EACxD;AAAA,EACA,mBAAmB;AAAA,IACjB,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,OAAO,MAAM;AAAA,EACf;AACF;AAEA,IAAM,OAAiB,EAAE,UAAU,sBAAsB,OAAO,MAAM,OAAU;AAEhF,IAAM,WAAW,IAAI,IAAsB,OAAO,QAAQ,QAAQ,CAAyB;AAMpF,SAAS,iBAAmC,IAAO,UAA6B;AACrF,WAAS,IAAI,IAAI,QAA+B;AAClD;AAGO,SAAS,YAAY,IAAsB;AAChD,SAAO,SAAS,IAAI,EAAE,KAAK;AAC7B;","names":[]}
@@ -7,46 +7,38 @@ function allRows(n) {
7
7
  return out;
8
8
  }
9
9
  var builtins = {
10
- "table:init": {
11
- describe: "table creation continued without the failed step",
12
- value: () => void 0
13
- },
14
- "table:setOptions": { describe: "the previous options were kept", value: () => void 0 },
15
- "table:destroy": {
16
- describe: "teardown continued; the table is destroyed",
17
- value: () => void 0
18
- },
19
- "state:dispatch": {
20
- describe: "the update was dropped (state unchanged)",
21
- value: () => void 0
22
- },
10
+ // `describe`: prose keys (diagnostics/prose.ts); a plugin's own fallback may use plain text.
11
+ "table:init": { describe: "init-continued", value: () => void 0 },
12
+ "table:setOptions": { describe: "options-kept", value: () => void 0 },
13
+ "table:destroy": { describe: "destroy-continued", value: () => void 0 },
14
+ "state:dispatch": { describe: "update-dropped", value: () => void 0 },
23
15
  "data:ingest": {
24
- describe: "the previous data was kept",
16
+ describe: "data-kept",
25
17
  value: (ctx) => ctx.meta.get(FALLBACK) ?? []
26
18
  },
27
19
  "pipeline:run": {
28
- describe: "the last good row model was kept",
20
+ describe: "row-model-kept",
29
21
  value: (ctx) => ctx.meta.get(FALLBACK) ?? allRows(ctx.input.rowCount)
30
22
  },
31
23
  "pipeline:step": {
32
- describe: "the step passed its input through",
24
+ describe: "step-passthrough",
33
25
  value: (ctx) => ctx.input.indices
34
26
  },
35
27
  "column:batch": {
36
- describe: "the column's cells use the slot fallback ('' for format, undefined for accessor, non-matching for filterFn, missing (sorted last) for sortBy)",
28
+ describe: "batch-fallback",
37
29
  value: () => void 0
38
30
  },
39
31
  "async:request": {
40
- describe: "the previous results were kept (status: 'error')",
32
+ describe: "results-kept",
41
33
  value: (ctx) => Promise.resolve(ctx.meta.get(FALLBACK))
42
34
  },
43
35
  "diagnostic:emit": {
44
- describe: "the diagnostic was dropped (the logger never kills the table)",
36
+ describe: "diagnostic-dropped",
45
37
  silent: true,
46
38
  value: () => void 0
47
39
  }
48
40
  };
49
- var NONE = { describe: "the operation returned undefined", value: () => void 0 };
41
+ var NONE = { describe: "returned-undefined", value: () => void 0 };
50
42
  var registry = new Map(Object.entries(builtins));
51
43
  function registerFallback(op, fallback) {
52
44
  registry.set(op, fallback);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/intercept/fallbacks.ts"],"sourcesContent":["import type { InterceptorContext } from './context'\nimport type { BuiltinOperations, OpName, OpResult } from './operations'\n\n/**\n * What the errorBoundary returns when an op fails (§3.4 registry table). `describe` becomes the\n * diagnostic's `impact`.\n */\nexport interface Fallback<O extends OpName = OpName> {\n readonly describe: string\n /**\n * Report without the diagnostics pipeline: one `console.error` per table. Used by\n * `diagnostic:emit`, where reporting through the pipeline could recurse.\n */\n readonly silent?: boolean\n value(ctx: InterceptorContext<O>): OpResult<O>\n}\n\n/**\n * `ctx.meta` key for a caller-supplied fallback value: the previous data (`data:ingest`), the last\n * good row model (`pipeline:run`), the previous results (`async:request`). Set it before `run`.\n */\nexport const FALLBACK = 'datakable:fallback'\n\n/**\n * `ctx.meta` key the errorBoundary sets (to the error) when it replaced the op's result with the\n * fallback, so the caller can tell a fallback from a real result (e.g. a failed `data:ingest` sets\n * `status: 'error'`, §6.6).\n */\nexport const FAILED = 'datakable:failed'\n\nfunction allRows(n: number): Uint32Array {\n const out = new Uint32Array(n)\n for (let i = 0; i < n; i++) out[i] = i\n return out\n}\n\nconst builtins: { [K in keyof BuiltinOperations]: Fallback<K> } = {\n 'table:init': {\n describe: 'table creation continued without the failed step',\n value: () => undefined,\n },\n 'table:setOptions': { describe: 'the previous options were kept', value: () => undefined },\n 'table:destroy': {\n describe: 'teardown continued; the table is destroyed',\n value: () => undefined,\n },\n 'state:dispatch': {\n describe: 'the update was dropped (state unchanged)',\n value: () => undefined,\n },\n 'data:ingest': {\n describe: 'the previous data was kept',\n value: (ctx) => (ctx.meta.get(FALLBACK) as readonly unknown[] | undefined) ?? [],\n },\n 'pipeline:run': {\n describe: 'the last good row model was kept',\n value: (ctx) =>\n (ctx.meta.get(FALLBACK) as Uint32Array | undefined) ?? allRows(ctx.input.rowCount),\n },\n 'pipeline:step': {\n describe: 'the step passed its input through',\n value: (ctx) => ctx.input.indices,\n },\n 'column:batch': {\n describe:\n \"the column's cells use the slot fallback ('' for format, undefined for accessor, \" +\n 'non-matching for filterFn, missing (sorted last) for sortBy)',\n value: () => undefined,\n },\n 'async:request': {\n describe: \"the previous results were kept (status: 'error')\",\n value: (ctx) => Promise.resolve(ctx.meta.get(FALLBACK)),\n },\n 'diagnostic:emit': {\n describe: 'the diagnostic was dropped (the logger never kills the table)',\n silent: true,\n value: () => undefined,\n },\n}\n\nconst NONE: Fallback = { describe: 'the operation returned undefined', value: () => undefined }\n\nconst registry = new Map<string, Fallback>(Object.entries(builtins) as [string, Fallback][])\n\n/**\n * Sets the fallback of an op (ops registered by plugins / `@datakable/react`). Process-wide like\n * the op registry; the last registration wins.\n */\nexport function registerFallback<O extends OpName>(op: O, fallback: Fallback<O>): void {\n registry.set(op, fallback as unknown as Fallback)\n}\n\n/** The registered fallback, or one that returns `undefined` for ops without an entry. */\nexport function getFallback(op: string): Fallback {\n return registry.get(op) ?? NONE\n}\n"],"mappings":";AAqBO,IAAM,WAAW;AAOjB,IAAM,SAAS;AAEtB,SAAS,QAAQ,GAAwB;AACvC,QAAM,MAAM,IAAI,YAAY,CAAC;AAC7B,WAAS,IAAI,GAAG,IAAI,GAAG,IAAK,KAAI,CAAC,IAAI;AACrC,SAAO;AACT;AAEA,IAAM,WAA4D;AAAA,EAChE,cAAc;AAAA,IACZ,UAAU;AAAA,IACV,OAAO,MAAM;AAAA,EACf;AAAA,EACA,oBAAoB,EAAE,UAAU,kCAAkC,OAAO,MAAM,OAAU;AAAA,EACzF,iBAAiB;AAAA,IACf,UAAU;AAAA,IACV,OAAO,MAAM;AAAA,EACf;AAAA,EACA,kBAAkB;AAAA,IAChB,UAAU;AAAA,IACV,OAAO,MAAM;AAAA,EACf;AAAA,EACA,eAAe;AAAA,IACb,UAAU;AAAA,IACV,OAAO,CAAC,QAAS,IAAI,KAAK,IAAI,QAAQ,KAAwC,CAAC;AAAA,EACjF;AAAA,EACA,gBAAgB;AAAA,IACd,UAAU;AAAA,IACV,OAAO,CAAC,QACL,IAAI,KAAK,IAAI,QAAQ,KAAiC,QAAQ,IAAI,MAAM,QAAQ;AAAA,EACrF;AAAA,EACA,iBAAiB;AAAA,IACf,UAAU;AAAA,IACV,OAAO,CAAC,QAAQ,IAAI,MAAM;AAAA,EAC5B;AAAA,EACA,gBAAgB;AAAA,IACd,UACE;AAAA,IAEF,OAAO,MAAM;AAAA,EACf;AAAA,EACA,iBAAiB;AAAA,IACf,UAAU;AAAA,IACV,OAAO,CAAC,QAAQ,QAAQ,QAAQ,IAAI,KAAK,IAAI,QAAQ,CAAC;AAAA,EACxD;AAAA,EACA,mBAAmB;AAAA,IACjB,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,OAAO,MAAM;AAAA,EACf;AACF;AAEA,IAAM,OAAiB,EAAE,UAAU,oCAAoC,OAAO,MAAM,OAAU;AAE9F,IAAM,WAAW,IAAI,IAAsB,OAAO,QAAQ,QAAQ,CAAyB;AAMpF,SAAS,iBAAmC,IAAO,UAA6B;AACrF,WAAS,IAAI,IAAI,QAA+B;AAClD;AAGO,SAAS,YAAY,IAAsB;AAChD,SAAO,SAAS,IAAI,EAAE,KAAK;AAC7B;","names":[]}
1
+ {"version":3,"sources":["../../src/intercept/fallbacks.ts"],"sourcesContent":["import type { InterceptorContext } from './context'\nimport type { BuiltinOperations, OpName, OpResult } from './operations'\n\n/**\n * What the errorBoundary returns when an op fails (§3.4 registry table). `describe` becomes the\n * diagnostic's `impact`.\n */\nexport interface Fallback<O extends OpName = OpName> {\n readonly describe: string\n /**\n * Report without the diagnostics pipeline: one `console.error` per table. Used by\n * `diagnostic:emit`, where reporting through the pipeline could recurse.\n */\n readonly silent?: boolean\n value(ctx: InterceptorContext<O>): OpResult<O>\n}\n\n/**\n * `ctx.meta` key for a caller-supplied fallback value: the previous data (`data:ingest`), the last\n * good row model (`pipeline:run`), the previous results (`async:request`). Set it before `run`.\n */\nexport const FALLBACK = 'datakable:fallback'\n\n/**\n * `ctx.meta` key the errorBoundary sets (to the error) when it replaced the op's result with the\n * fallback, so the caller can tell a fallback from a real result (e.g. a failed `data:ingest` sets\n * `status: 'error'`, §6.6).\n */\nexport const FAILED = 'datakable:failed'\n\nfunction allRows(n: number): Uint32Array {\n const out = new Uint32Array(n)\n for (let i = 0; i < n; i++) out[i] = i\n return out\n}\n\nconst builtins: { [K in keyof BuiltinOperations]: Fallback<K> } = {\n // `describe`: prose keys (diagnostics/prose.ts); a plugin's own fallback may use plain text.\n 'table:init': { describe: 'init-continued', value: () => undefined },\n 'table:setOptions': { describe: 'options-kept', value: () => undefined },\n 'table:destroy': { describe: 'destroy-continued', value: () => undefined },\n 'state:dispatch': { describe: 'update-dropped', value: () => undefined },\n 'data:ingest': {\n describe: 'data-kept',\n value: (ctx) => (ctx.meta.get(FALLBACK) as readonly unknown[] | undefined) ?? [],\n },\n 'pipeline:run': {\n describe: 'row-model-kept',\n value: (ctx) =>\n (ctx.meta.get(FALLBACK) as Uint32Array | undefined) ?? allRows(ctx.input.rowCount),\n },\n 'pipeline:step': {\n describe: 'step-passthrough',\n value: (ctx) => ctx.input.indices,\n },\n 'column:batch': {\n describe: 'batch-fallback',\n value: () => undefined,\n },\n 'async:request': {\n describe: 'results-kept',\n value: (ctx) => Promise.resolve(ctx.meta.get(FALLBACK)),\n },\n 'diagnostic:emit': {\n describe: 'diagnostic-dropped',\n silent: true,\n value: () => undefined,\n },\n}\n\nconst NONE: Fallback = { describe: 'returned-undefined', value: () => undefined }\n\nconst registry = new Map<string, Fallback>(Object.entries(builtins) as [string, Fallback][])\n\n/**\n * Sets the fallback of an op (ops registered by plugins / `@datakable/react`). Process-wide like\n * the op registry; the last registration wins.\n */\nexport function registerFallback<O extends OpName>(op: O, fallback: Fallback<O>): void {\n registry.set(op, fallback as unknown as Fallback)\n}\n\n/** The registered fallback, or one that returns `undefined` for ops without an entry. */\nexport function getFallback(op: string): Fallback {\n return registry.get(op) ?? NONE\n}\n"],"mappings":";AAqBO,IAAM,WAAW;AAOjB,IAAM,SAAS;AAEtB,SAAS,QAAQ,GAAwB;AACvC,QAAM,MAAM,IAAI,YAAY,CAAC;AAC7B,WAAS,IAAI,GAAG,IAAI,GAAG,IAAK,KAAI,CAAC,IAAI;AACrC,SAAO;AACT;AAEA,IAAM,WAA4D;AAAA;AAAA,EAEhE,cAAc,EAAE,UAAU,kBAAkB,OAAO,MAAM,OAAU;AAAA,EACnE,oBAAoB,EAAE,UAAU,gBAAgB,OAAO,MAAM,OAAU;AAAA,EACvE,iBAAiB,EAAE,UAAU,qBAAqB,OAAO,MAAM,OAAU;AAAA,EACzE,kBAAkB,EAAE,UAAU,kBAAkB,OAAO,MAAM,OAAU;AAAA,EACvE,eAAe;AAAA,IACb,UAAU;AAAA,IACV,OAAO,CAAC,QAAS,IAAI,KAAK,IAAI,QAAQ,KAAwC,CAAC;AAAA,EACjF;AAAA,EACA,gBAAgB;AAAA,IACd,UAAU;AAAA,IACV,OAAO,CAAC,QACL,IAAI,KAAK,IAAI,QAAQ,KAAiC,QAAQ,IAAI,MAAM,QAAQ;AAAA,EACrF;AAAA,EACA,iBAAiB;AAAA,IACf,UAAU;AAAA,IACV,OAAO,CAAC,QAAQ,IAAI,MAAM;AAAA,EAC5B;AAAA,EACA,gBAAgB;AAAA,IACd,UAAU;AAAA,IACV,OAAO,MAAM;AAAA,EACf;AAAA,EACA,iBAAiB;AAAA,IACf,UAAU;AAAA,IACV,OAAO,CAAC,QAAQ,QAAQ,QAAQ,IAAI,KAAK,IAAI,QAAQ,CAAC;AAAA,EACxD;AAAA,EACA,mBAAmB;AAAA,IACjB,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,OAAO,MAAM;AAAA,EACf;AACF;AAEA,IAAM,OAAiB,EAAE,UAAU,sBAAsB,OAAO,MAAM,OAAU;AAEhF,IAAM,WAAW,IAAI,IAAsB,OAAO,QAAQ,QAAQ,CAAyB;AAMpF,SAAS,iBAAmC,IAAO,UAA6B;AACrF,WAAS,IAAI,IAAI,QAA+B;AAClD;AAGO,SAAS,YAAY,IAAsB;AAChD,SAAO,SAAS,IAAI,EAAE,KAAK;AAC7B;","names":[]}
@@ -24,6 +24,7 @@ __export(runtime_exports, {
24
24
  });
25
25
  module.exports = __toCommonJS(runtime_exports);
26
26
  var import_build = require("../diagnostics/build.cjs");
27
+ var import_process_guard = require("../diagnostics/process-guard.cjs");
27
28
  var import_operations = require("./operations.cjs");
28
29
  var NOT_CALLED = 0;
29
30
  var CALLED = 1;
@@ -85,10 +86,10 @@ function createInterceptorRuntime(options = {}) {
85
86
  );
86
87
  }
87
88
  });
88
- const onHotWarning = options.onHotWarning ?? ((w) => {
89
+ const onHotWarning = process.env.NODE_ENV !== "production" ? options.onHotWarning ?? ((w) => {
89
90
  if (emit) emit("DK_HOT_INTERCEPTOR", { interceptor: w.interceptor.name, op: w.op });
90
91
  else console.warn(`[DataKable] ${w.message}`);
91
- });
92
+ }) : void 0;
92
93
  const report = (error, i, ctx) => {
93
94
  try {
94
95
  onError(error, i, ctx);
@@ -99,9 +100,9 @@ function createInterceptorRuntime(options = {}) {
99
100
  let list = [];
100
101
  let boundary;
101
102
  const chains = /* @__PURE__ */ new Map();
102
- const warned = /* @__PURE__ */ new WeakMap();
103
+ const warned = process.env.NODE_ENV !== "production" ? /* @__PURE__ */ new WeakMap() : void 0;
103
104
  function warnHot(i, op) {
104
- if (!(process.env.NODE_ENV !== "production")) return;
105
+ if (!(process.env.NODE_ENV !== "production") || !warned || !onHotWarning) return;
105
106
  let ops = warned.get(i);
106
107
  if (ops?.has(op)) return;
107
108
  if (!ops) {
@@ -121,7 +122,7 @@ function createInterceptorRuntime(options = {}) {
121
122
  function compile(op) {
122
123
  const info = (0, import_operations.getOperation)(op);
123
124
  if (!info) {
124
- throw (0, import_build.internalError)(op, `Unknown operation "${op}": register it with registerOperation()`);
125
+ throw (0, import_build.internalError)(op, `unknown-op|${op}`);
125
126
  }
126
127
  const mine = list.filter((i) => attaches(i, op));
127
128
  if (boundary && attaches(boundary, op)) mine.unshift(boundary);
@@ -151,10 +152,7 @@ function createInterceptorRuntime(options = {}) {
151
152
  setInterceptors,
152
153
  installBoundary(b) {
153
154
  if (boundary) {
154
- throw (0, import_build.internalError)(
155
- "*",
156
- `A boundary interceptor is already installed ("${boundary.name}"); "${b.name}" was rejected`
157
- );
155
+ throw (0, import_build.internalError)("*", `boundary-twice|${boundary.name}|${b.name}`);
158
156
  }
159
157
  boundary = b;
160
158
  compileAll();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/intercept/runtime.ts"],"sourcesContent":["import { DatakableError, internalError } from '../diagnostics/build'\nimport type { Emit } from '../diagnostics/types'\nimport type { InterceptorContext } from './context'\nimport type { Interceptor } from './define'\nimport { getOperation, listOperations, type OpName, type OpResult } from './operations'\n\nexport type Core<O extends OpName> = (ctx: InterceptorContext<O>) => OpResult<O>\n\nexport interface HotOpWarning {\n interceptor: Interceptor<OpName>\n op: string\n message: string\n}\n\nexport interface InterceptorRuntimeOptions {\n interceptors?: readonly Interceptor<OpName>[]\n /**\n * The table's diagnostic emitter. When given, the default hooks below report through it:\n * `DK_INTERCEPTOR_FAILED` and (dev only) `DK_HOT_INTERCEPTOR`. Without it they use the console.\n */\n emit?: Emit\n /**\n * An interceptor threw (or its promise rejected); it was skipped. Overrides the default report\n * (`DK_INTERCEPTOR_FAILED` via `emit`, else console.error).\n */\n onInterceptorError?: (\n error: unknown,\n interceptor: Interceptor<OpName>,\n ctx: InterceptorContext,\n ) => void\n /**\n * An interceptor is attached to a hot op without `hot: true` (checked when the op's chain is\n * compiled, once per interceptor + op). Overrides the default (`DK_HOT_INTERCEPTOR` via `emit`).\n */\n onHotWarning?: (warning: HotOpWarning) => void\n /** Called each time a chain is compiled (tracing / tests). `length` counts the boundary too. */\n onCompile?: (op: string, length: number) => void\n}\n\nexport interface InterceptorRuntime {\n /** Runs `core` for `op` through the compiled chain. */\n run<O extends OpName>(op: O, ctx: InterceptorContext<O>, core: NoInfer<Core<O>>): OpResult<O>\n /** Replaces the user / feature interceptors and recompiles. The boundary slot is kept. */\n setInterceptors(interceptors: readonly Interceptor<OpName>[]): void\n /** Installs the outermost, non-removable interceptor (errorBoundary, T06). Once only. */\n installBoundary(boundary: Interceptor<OpName>): void\n}\n\ntype AnyCtx = InterceptorContext\ntype AnyCore = (ctx: AnyCtx) => unknown\ntype Chain = (ctx: AnyCtx, core: AnyCore) => unknown\n\nconst NOT_CALLED = 0\nconst CALLED = 1\nconst FAILED_INSIDE = 2\n\nconst direct: Chain = (ctx, core) => core(ctx)\n\nconst isThenable = (v: unknown): v is PromiseLike<unknown> =>\n v != null && typeof (v as { then?: unknown }).then === 'function'\n\nconst attaches = (i: Interceptor<OpName>, op: string) =>\n i.on === '*' || (i.on as readonly string[]).includes(op)\n\n/**\n * Wraps one interceptor around `inner`. Skip semantics (§3.4): if the interceptor throws before\n * calling `next`, `next` runs directly; if it throws after, the result `next` produced is kept so\n * the core never runs twice. An error that came out of `next` belongs to an inner layer and is\n * rethrown untouched. Async results get the same rules on rejection.\n */\nfunction wrap(\n i: Interceptor<OpName>,\n inner: Chain,\n mayBeAsync: boolean,\n report: (error: unknown, i: Interceptor<OpName>, ctx: AnyCtx) => void,\n): Chain {\n const intercept = i.intercept as (ctx: AnyCtx, next: () => unknown) => unknown\n return (ctx, core) => {\n let state = NOT_CALLED\n let out: unknown\n const next = () => {\n state = CALLED\n try {\n out = inner(ctx, core)\n } catch (e) {\n state = FAILED_INSIDE\n throw e\n }\n if (mayBeAsync && isThenable(out)) {\n const p = Promise.resolve(out).then(undefined, (e: unknown) => {\n state = FAILED_INSIDE\n throw e\n })\n // Handled here so an interceptor that drops `next()` never causes an unhandled rejection;\n // whoever awaits `p` still sees the rejection.\n p.catch(() => {})\n out = p\n }\n return out\n }\n const recover = (e: unknown) => {\n if (state === FAILED_INSIDE) throw e\n report(e, i, ctx)\n return state === CALLED ? out : inner(ctx, core)\n }\n let r: unknown\n try {\n r = intercept(ctx, next)\n } catch (e) {\n return recover(e)\n }\n return mayBeAsync && isThenable(r) ? Promise.resolve(r).then(undefined, recover) : r\n }\n}\n\nexport function createInterceptorRuntime(\n options: InterceptorRuntimeOptions = {},\n): InterceptorRuntime {\n const { emit, onCompile } = options\n const onError =\n options.onInterceptorError ??\n ((error: unknown, i: Interceptor<OpName>, ctx: AnyCtx) => {\n if (emit) {\n emit(\n 'DK_INTERCEPTOR_FAILED',\n { interceptor: i.name, op: ctx.op, slot: ctx.where },\n { cause: error, run: ctx.run, trigger: ctx.trigger, phase: ctx.phase },\n )\n } else {\n console.error(\n `[DataKable] interceptor \"${i.name}\" failed on ${ctx.op} and was skipped`,\n error,\n )\n }\n })\n const onHotWarning =\n options.onHotWarning ??\n ((w: HotOpWarning) => {\n if (emit) emit('DK_HOT_INTERCEPTOR', { interceptor: w.interceptor.name, op: w.op })\n else console.warn(`[DataKable] ${w.message}`)\n })\n const report = (error: unknown, i: Interceptor<OpName>, ctx: AnyCtx) => {\n try {\n onError(error, i, ctx)\n } catch (e) {\n // The reporter must never break the operation it reports on — except `strict: true`, whose\n // DatakableError is the requested behaviour.\n if (e instanceof DatakableError) throw e\n }\n }\n\n let list: readonly Interceptor<OpName>[] = []\n let boundary: Interceptor<OpName> | undefined\n const chains = new Map<string, Chain>()\n /** (interceptor, op) pairs already warned about, so recompiles do not repeat the warning. */\n const warned = new WeakMap<Interceptor<OpName>, Set<string>>()\n\n function warnHot(i: Interceptor<OpName>, op: string) {\n if (!(process.env.NODE_ENV !== \"production\")) return // dev-only warning: drops the text below from production bundles\n let ops = warned.get(i)\n if (ops?.has(op)) return\n if (!ops) {\n ops = new Set()\n warned.set(i, ops)\n }\n ops.add(op)\n try {\n onHotWarning({\n interceptor: i,\n op,\n message:\n `Interceptor \"${i.name}\" is attached to hot op \"${op}\" without hot: true. ` +\n // Measured by intercept/chain.bench.ts (Apple M4 Pro, Node 25.2.1). Inline here, inside\n // the (process.env.NODE_ENV !== \"production\")-only function, so production bundles carry none of it.\n 'It runs once per column per pipeline run; measured cost: ~10 ns per call per ' +\n 'interceptor (+15% on a per-cell format call, spec §9.2) on top of the interceptor ' +\n 'body, which runs columns × pipeline runs times. ' +\n 'Never loop per cell inside it. Set hot: true to accept the cost, ' +\n 'or attach it to a cold op.',\n })\n } catch {\n // A warning must never break compilation.\n }\n }\n\n function compile(op: string): Chain {\n const info = getOperation(op)\n if (!info) {\n throw internalError(op, `Unknown operation \"${op}\": register it with registerOperation()`)\n }\n const mine = list.filter((i) => attaches(i, op))\n if (boundary && attaches(boundary, op)) mine.unshift(boundary)\n // Checked here, not when the list is set, so ops registered after creation are covered too.\n if ((process.env.NODE_ENV !== \"production\") && info.hot) for (const i of mine) if (!i.hot) warnHot(i, op)\n const mayBeAsync = info.kind !== 'sync'\n const chain = mine.reduceRight<Chain>((inner, i) => wrap(i, inner, mayBeAsync, report), direct)\n chains.set(op, chain)\n onCompile?.(op, mine.length)\n return chain\n }\n\n function compileAll() {\n chains.clear()\n for (const op of listOperations()) compile(op)\n }\n\n function setInterceptors(next: readonly Interceptor<OpName>[]) {\n list = [...next]\n compileAll()\n }\n\n setInterceptors(options.interceptors ?? [])\n\n return {\n run(op, ctx, core) {\n const chain = chains.get(op) ?? compile(op)\n return chain(ctx, core as AnyCore) as OpResult<typeof op>\n },\n setInterceptors,\n installBoundary(b) {\n if (boundary) {\n throw internalError(\n '*',\n `A boundary interceptor is already installed (\"${boundary.name}\"); ` +\n `\"${b.name}\" was rejected`,\n )\n }\n boundary = b\n compileAll()\n },\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/intercept/runtime.ts"],"sourcesContent":["import { DatakableError, internalError } from '../diagnostics/build'\nimport '../diagnostics/process-guard'\nimport type { Emit } from '../diagnostics/types'\nimport type { InterceptorContext } from './context'\nimport type { Interceptor } from './define'\nimport { getOperation, listOperations, type OpName, type OpResult } from './operations'\n\nexport type Core<O extends OpName> = (ctx: InterceptorContext<O>) => OpResult<O>\n\nexport interface HotOpWarning {\n interceptor: Interceptor<OpName>\n op: string\n message: string\n}\n\nexport interface InterceptorRuntimeOptions {\n interceptors?: readonly Interceptor<OpName>[]\n /**\n * The table's diagnostic emitter. When given, the default hooks below report through it:\n * `DK_INTERCEPTOR_FAILED` and (dev only) `DK_HOT_INTERCEPTOR`. Without it they use the console.\n */\n emit?: Emit\n /**\n * An interceptor threw (or its promise rejected); it was skipped. Overrides the default report\n * (`DK_INTERCEPTOR_FAILED` via `emit`, else console.error).\n */\n onInterceptorError?: (\n error: unknown,\n interceptor: Interceptor<OpName>,\n ctx: InterceptorContext,\n ) => void\n /**\n * An interceptor is attached to a hot op without `hot: true` (checked when the op's chain is\n * compiled, once per interceptor + op). Overrides the default (`DK_HOT_INTERCEPTOR` via `emit`).\n */\n onHotWarning?: (warning: HotOpWarning) => void\n /** Called each time a chain is compiled (tracing / tests). `length` counts the boundary too. */\n onCompile?: (op: string, length: number) => void\n}\n\nexport interface InterceptorRuntime {\n /** Runs `core` for `op` through the compiled chain. */\n run<O extends OpName>(op: O, ctx: InterceptorContext<O>, core: NoInfer<Core<O>>): OpResult<O>\n /** Replaces the user / feature interceptors and recompiles. The boundary slot is kept. */\n setInterceptors(interceptors: readonly Interceptor<OpName>[]): void\n /** Installs the outermost, non-removable interceptor (errorBoundary, T06). Once only. */\n installBoundary(boundary: Interceptor<OpName>): void\n}\n\ntype AnyCtx = InterceptorContext\ntype AnyCore = (ctx: AnyCtx) => unknown\ntype Chain = (ctx: AnyCtx, core: AnyCore) => unknown\n\nconst NOT_CALLED = 0\nconst CALLED = 1\nconst FAILED_INSIDE = 2\n\nconst direct: Chain = (ctx, core) => core(ctx)\n\nconst isThenable = (v: unknown): v is PromiseLike<unknown> =>\n v != null && typeof (v as { then?: unknown }).then === 'function'\n\nconst attaches = (i: Interceptor<OpName>, op: string) =>\n i.on === '*' || (i.on as readonly string[]).includes(op)\n\n/**\n * Wraps one interceptor around `inner`. Skip semantics (§3.4): if the interceptor throws before\n * calling `next`, `next` runs directly; if it throws after, the result `next` produced is kept so\n * the core never runs twice. An error that came out of `next` belongs to an inner layer and is\n * rethrown untouched. Async results get the same rules on rejection.\n */\nfunction wrap(\n i: Interceptor<OpName>,\n inner: Chain,\n mayBeAsync: boolean,\n report: (error: unknown, i: Interceptor<OpName>, ctx: AnyCtx) => void,\n): Chain {\n const intercept = i.intercept as (ctx: AnyCtx, next: () => unknown) => unknown\n return (ctx, core) => {\n let state = NOT_CALLED\n let out: unknown\n const next = () => {\n state = CALLED\n try {\n out = inner(ctx, core)\n } catch (e) {\n state = FAILED_INSIDE\n throw e\n }\n if (mayBeAsync && isThenable(out)) {\n const p = Promise.resolve(out).then(undefined, (e: unknown) => {\n state = FAILED_INSIDE\n throw e\n })\n // Handled here so an interceptor that drops `next()` never causes an unhandled rejection;\n // whoever awaits `p` still sees the rejection.\n p.catch(() => {})\n out = p\n }\n return out\n }\n const recover = (e: unknown) => {\n if (state === FAILED_INSIDE) throw e\n report(e, i, ctx)\n return state === CALLED ? out : inner(ctx, core)\n }\n let r: unknown\n try {\n r = intercept(ctx, next)\n } catch (e) {\n return recover(e)\n }\n return mayBeAsync && isThenable(r) ? Promise.resolve(r).then(undefined, recover) : r\n }\n}\n\nexport function createInterceptorRuntime(\n options: InterceptorRuntimeOptions = {},\n): InterceptorRuntime {\n const { emit, onCompile } = options\n const onError =\n options.onInterceptorError ??\n ((error: unknown, i: Interceptor<OpName>, ctx: AnyCtx) => {\n if (emit) {\n emit(\n 'DK_INTERCEPTOR_FAILED',\n { interceptor: i.name, op: ctx.op, slot: ctx.where },\n { cause: error, run: ctx.run, trigger: ctx.trigger, phase: ctx.phase },\n )\n } else {\n console.error(\n `[DataKable] interceptor \"${i.name}\" failed on ${ctx.op} and was skipped`,\n error,\n )\n }\n })\n // Dev-only (DK_HOT_INTERCEPTOR): `undefined` in production, with the code and its text.\n const onHotWarning = (process.env.NODE_ENV !== \"production\")\n ? (options.onHotWarning ??\n ((w: HotOpWarning) => {\n if (emit) emit('DK_HOT_INTERCEPTOR', { interceptor: w.interceptor.name, op: w.op })\n else console.warn(`[DataKable] ${w.message}`)\n }))\n : undefined\n const report = (error: unknown, i: Interceptor<OpName>, ctx: AnyCtx) => {\n try {\n onError(error, i, ctx)\n } catch (e) {\n // The reporter must never break the operation it reports on — except `strict: true`, whose\n // DatakableError is the requested behaviour.\n if (e instanceof DatakableError) throw e\n }\n }\n\n let list: readonly Interceptor<OpName>[] = []\n let boundary: Interceptor<OpName> | undefined\n const chains = new Map<string, Chain>()\n /** (interceptor, op) pairs already warned about, so recompiles do not repeat the warning. */\n const warned = (process.env.NODE_ENV !== \"production\") ? new WeakMap<Interceptor<OpName>, Set<string>>() : undefined\n\n function warnHot(i: Interceptor<OpName>, op: string) {\n if (!(process.env.NODE_ENV !== \"production\") || !warned || !onHotWarning) return // dev-only: production bundles drop the text below\n let ops = warned.get(i)\n if (ops?.has(op)) return\n if (!ops) {\n ops = new Set()\n warned.set(i, ops)\n }\n ops.add(op)\n try {\n onHotWarning({\n interceptor: i,\n op,\n message:\n `Interceptor \"${i.name}\" is attached to hot op \"${op}\" without hot: true. ` +\n // Measured by intercept/chain.bench.ts (Apple M4 Pro, Node 25.2.1). Inline here, inside\n // the (process.env.NODE_ENV !== \"production\")-only function, so production bundles carry none of it.\n 'It runs once per column per pipeline run; measured cost: ~10 ns per call per ' +\n 'interceptor (+15% on a per-cell format call, spec §9.2) on top of the interceptor ' +\n 'body, which runs columns × pipeline runs times. ' +\n 'Never loop per cell inside it. Set hot: true to accept the cost, ' +\n 'or attach it to a cold op.',\n })\n } catch {\n // A warning must never break compilation.\n }\n }\n\n function compile(op: string): Chain {\n const info = getOperation(op)\n if (!info) {\n throw internalError(op, `unknown-op|${op}`)\n }\n const mine = list.filter((i) => attaches(i, op))\n if (boundary && attaches(boundary, op)) mine.unshift(boundary)\n // Checked here, not when the list is set, so ops registered after creation are covered too.\n if ((process.env.NODE_ENV !== \"production\") && info.hot) for (const i of mine) if (!i.hot) warnHot(i, op)\n const mayBeAsync = info.kind !== 'sync'\n const chain = mine.reduceRight<Chain>((inner, i) => wrap(i, inner, mayBeAsync, report), direct)\n chains.set(op, chain)\n onCompile?.(op, mine.length)\n return chain\n }\n\n function compileAll() {\n chains.clear()\n for (const op of listOperations()) compile(op)\n }\n\n function setInterceptors(next: readonly Interceptor<OpName>[]) {\n list = [...next]\n compileAll()\n }\n\n setInterceptors(options.interceptors ?? [])\n\n return {\n run(op, ctx, core) {\n const chain = chains.get(op) ?? compile(op)\n return chain(ctx, core as AnyCore) as OpResult<typeof op>\n },\n setInterceptors,\n installBoundary(b) {\n if (boundary) {\n throw internalError('*', `boundary-twice|${boundary.name}|${b.name}`)\n }\n boundary = b\n compileAll()\n },\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,5 +1,6 @@
1
1
  // src/intercept/runtime.ts
2
2
  import { DatakableError, internalError } from "../diagnostics/build.js";
3
+ import "../diagnostics/process-guard.js";
3
4
  import { getOperation, listOperations } from "./operations.js";
4
5
  var NOT_CALLED = 0;
5
6
  var CALLED = 1;
@@ -61,10 +62,10 @@ function createInterceptorRuntime(options = {}) {
61
62
  );
62
63
  }
63
64
  });
64
- const onHotWarning = options.onHotWarning ?? ((w) => {
65
+ const onHotWarning = process.env.NODE_ENV !== "production" ? options.onHotWarning ?? ((w) => {
65
66
  if (emit) emit("DK_HOT_INTERCEPTOR", { interceptor: w.interceptor.name, op: w.op });
66
67
  else console.warn(`[DataKable] ${w.message}`);
67
- });
68
+ }) : void 0;
68
69
  const report = (error, i, ctx) => {
69
70
  try {
70
71
  onError(error, i, ctx);
@@ -75,9 +76,9 @@ function createInterceptorRuntime(options = {}) {
75
76
  let list = [];
76
77
  let boundary;
77
78
  const chains = /* @__PURE__ */ new Map();
78
- const warned = /* @__PURE__ */ new WeakMap();
79
+ const warned = process.env.NODE_ENV !== "production" ? /* @__PURE__ */ new WeakMap() : void 0;
79
80
  function warnHot(i, op) {
80
- if (!(process.env.NODE_ENV !== "production")) return;
81
+ if (!(process.env.NODE_ENV !== "production") || !warned || !onHotWarning) return;
81
82
  let ops = warned.get(i);
82
83
  if (ops?.has(op)) return;
83
84
  if (!ops) {
@@ -97,7 +98,7 @@ function createInterceptorRuntime(options = {}) {
97
98
  function compile(op) {
98
99
  const info = getOperation(op);
99
100
  if (!info) {
100
- throw internalError(op, `Unknown operation "${op}": register it with registerOperation()`);
101
+ throw internalError(op, `unknown-op|${op}`);
101
102
  }
102
103
  const mine = list.filter((i) => attaches(i, op));
103
104
  if (boundary && attaches(boundary, op)) mine.unshift(boundary);
@@ -127,10 +128,7 @@ function createInterceptorRuntime(options = {}) {
127
128
  setInterceptors,
128
129
  installBoundary(b) {
129
130
  if (boundary) {
130
- throw internalError(
131
- "*",
132
- `A boundary interceptor is already installed ("${boundary.name}"); "${b.name}" was rejected`
133
- );
131
+ throw internalError("*", `boundary-twice|${boundary.name}|${b.name}`);
134
132
  }
135
133
  boundary = b;
136
134
  compileAll();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/intercept/runtime.ts"],"sourcesContent":["import { DatakableError, internalError } from '../diagnostics/build'\nimport type { Emit } from '../diagnostics/types'\nimport type { InterceptorContext } from './context'\nimport type { Interceptor } from './define'\nimport { getOperation, listOperations, type OpName, type OpResult } from './operations'\n\nexport type Core<O extends OpName> = (ctx: InterceptorContext<O>) => OpResult<O>\n\nexport interface HotOpWarning {\n interceptor: Interceptor<OpName>\n op: string\n message: string\n}\n\nexport interface InterceptorRuntimeOptions {\n interceptors?: readonly Interceptor<OpName>[]\n /**\n * The table's diagnostic emitter. When given, the default hooks below report through it:\n * `DK_INTERCEPTOR_FAILED` and (dev only) `DK_HOT_INTERCEPTOR`. Without it they use the console.\n */\n emit?: Emit\n /**\n * An interceptor threw (or its promise rejected); it was skipped. Overrides the default report\n * (`DK_INTERCEPTOR_FAILED` via `emit`, else console.error).\n */\n onInterceptorError?: (\n error: unknown,\n interceptor: Interceptor<OpName>,\n ctx: InterceptorContext,\n ) => void\n /**\n * An interceptor is attached to a hot op without `hot: true` (checked when the op's chain is\n * compiled, once per interceptor + op). Overrides the default (`DK_HOT_INTERCEPTOR` via `emit`).\n */\n onHotWarning?: (warning: HotOpWarning) => void\n /** Called each time a chain is compiled (tracing / tests). `length` counts the boundary too. */\n onCompile?: (op: string, length: number) => void\n}\n\nexport interface InterceptorRuntime {\n /** Runs `core` for `op` through the compiled chain. */\n run<O extends OpName>(op: O, ctx: InterceptorContext<O>, core: NoInfer<Core<O>>): OpResult<O>\n /** Replaces the user / feature interceptors and recompiles. The boundary slot is kept. */\n setInterceptors(interceptors: readonly Interceptor<OpName>[]): void\n /** Installs the outermost, non-removable interceptor (errorBoundary, T06). Once only. */\n installBoundary(boundary: Interceptor<OpName>): void\n}\n\ntype AnyCtx = InterceptorContext\ntype AnyCore = (ctx: AnyCtx) => unknown\ntype Chain = (ctx: AnyCtx, core: AnyCore) => unknown\n\nconst NOT_CALLED = 0\nconst CALLED = 1\nconst FAILED_INSIDE = 2\n\nconst direct: Chain = (ctx, core) => core(ctx)\n\nconst isThenable = (v: unknown): v is PromiseLike<unknown> =>\n v != null && typeof (v as { then?: unknown }).then === 'function'\n\nconst attaches = (i: Interceptor<OpName>, op: string) =>\n i.on === '*' || (i.on as readonly string[]).includes(op)\n\n/**\n * Wraps one interceptor around `inner`. Skip semantics (§3.4): if the interceptor throws before\n * calling `next`, `next` runs directly; if it throws after, the result `next` produced is kept so\n * the core never runs twice. An error that came out of `next` belongs to an inner layer and is\n * rethrown untouched. Async results get the same rules on rejection.\n */\nfunction wrap(\n i: Interceptor<OpName>,\n inner: Chain,\n mayBeAsync: boolean,\n report: (error: unknown, i: Interceptor<OpName>, ctx: AnyCtx) => void,\n): Chain {\n const intercept = i.intercept as (ctx: AnyCtx, next: () => unknown) => unknown\n return (ctx, core) => {\n let state = NOT_CALLED\n let out: unknown\n const next = () => {\n state = CALLED\n try {\n out = inner(ctx, core)\n } catch (e) {\n state = FAILED_INSIDE\n throw e\n }\n if (mayBeAsync && isThenable(out)) {\n const p = Promise.resolve(out).then(undefined, (e: unknown) => {\n state = FAILED_INSIDE\n throw e\n })\n // Handled here so an interceptor that drops `next()` never causes an unhandled rejection;\n // whoever awaits `p` still sees the rejection.\n p.catch(() => {})\n out = p\n }\n return out\n }\n const recover = (e: unknown) => {\n if (state === FAILED_INSIDE) throw e\n report(e, i, ctx)\n return state === CALLED ? out : inner(ctx, core)\n }\n let r: unknown\n try {\n r = intercept(ctx, next)\n } catch (e) {\n return recover(e)\n }\n return mayBeAsync && isThenable(r) ? Promise.resolve(r).then(undefined, recover) : r\n }\n}\n\nexport function createInterceptorRuntime(\n options: InterceptorRuntimeOptions = {},\n): InterceptorRuntime {\n const { emit, onCompile } = options\n const onError =\n options.onInterceptorError ??\n ((error: unknown, i: Interceptor<OpName>, ctx: AnyCtx) => {\n if (emit) {\n emit(\n 'DK_INTERCEPTOR_FAILED',\n { interceptor: i.name, op: ctx.op, slot: ctx.where },\n { cause: error, run: ctx.run, trigger: ctx.trigger, phase: ctx.phase },\n )\n } else {\n console.error(\n `[DataKable] interceptor \"${i.name}\" failed on ${ctx.op} and was skipped`,\n error,\n )\n }\n })\n const onHotWarning =\n options.onHotWarning ??\n ((w: HotOpWarning) => {\n if (emit) emit('DK_HOT_INTERCEPTOR', { interceptor: w.interceptor.name, op: w.op })\n else console.warn(`[DataKable] ${w.message}`)\n })\n const report = (error: unknown, i: Interceptor<OpName>, ctx: AnyCtx) => {\n try {\n onError(error, i, ctx)\n } catch (e) {\n // The reporter must never break the operation it reports on — except `strict: true`, whose\n // DatakableError is the requested behaviour.\n if (e instanceof DatakableError) throw e\n }\n }\n\n let list: readonly Interceptor<OpName>[] = []\n let boundary: Interceptor<OpName> | undefined\n const chains = new Map<string, Chain>()\n /** (interceptor, op) pairs already warned about, so recompiles do not repeat the warning. */\n const warned = new WeakMap<Interceptor<OpName>, Set<string>>()\n\n function warnHot(i: Interceptor<OpName>, op: string) {\n if (!(process.env.NODE_ENV !== \"production\")) return // dev-only warning: drops the text below from production bundles\n let ops = warned.get(i)\n if (ops?.has(op)) return\n if (!ops) {\n ops = new Set()\n warned.set(i, ops)\n }\n ops.add(op)\n try {\n onHotWarning({\n interceptor: i,\n op,\n message:\n `Interceptor \"${i.name}\" is attached to hot op \"${op}\" without hot: true. ` +\n // Measured by intercept/chain.bench.ts (Apple M4 Pro, Node 25.2.1). Inline here, inside\n // the (process.env.NODE_ENV !== \"production\")-only function, so production bundles carry none of it.\n 'It runs once per column per pipeline run; measured cost: ~10 ns per call per ' +\n 'interceptor (+15% on a per-cell format call, spec §9.2) on top of the interceptor ' +\n 'body, which runs columns × pipeline runs times. ' +\n 'Never loop per cell inside it. Set hot: true to accept the cost, ' +\n 'or attach it to a cold op.',\n })\n } catch {\n // A warning must never break compilation.\n }\n }\n\n function compile(op: string): Chain {\n const info = getOperation(op)\n if (!info) {\n throw internalError(op, `Unknown operation \"${op}\": register it with registerOperation()`)\n }\n const mine = list.filter((i) => attaches(i, op))\n if (boundary && attaches(boundary, op)) mine.unshift(boundary)\n // Checked here, not when the list is set, so ops registered after creation are covered too.\n if ((process.env.NODE_ENV !== \"production\") && info.hot) for (const i of mine) if (!i.hot) warnHot(i, op)\n const mayBeAsync = info.kind !== 'sync'\n const chain = mine.reduceRight<Chain>((inner, i) => wrap(i, inner, mayBeAsync, report), direct)\n chains.set(op, chain)\n onCompile?.(op, mine.length)\n return chain\n }\n\n function compileAll() {\n chains.clear()\n for (const op of listOperations()) compile(op)\n }\n\n function setInterceptors(next: readonly Interceptor<OpName>[]) {\n list = [...next]\n compileAll()\n }\n\n setInterceptors(options.interceptors ?? [])\n\n return {\n run(op, ctx, core) {\n const chain = chains.get(op) ?? compile(op)\n return chain(ctx, core as AnyCore) as OpResult<typeof op>\n },\n setInterceptors,\n installBoundary(b) {\n if (boundary) {\n throw internalError(\n '*',\n `A boundary interceptor is already installed (\"${boundary.name}\"); ` +\n `\"${b.name}\" was rejected`,\n )\n }\n boundary = b\n compileAll()\n },\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/intercept/runtime.ts"],"sourcesContent":["import { DatakableError, internalError } from '../diagnostics/build'\nimport '../diagnostics/process-guard'\nimport type { Emit } from '../diagnostics/types'\nimport type { InterceptorContext } from './context'\nimport type { Interceptor } from './define'\nimport { getOperation, listOperations, type OpName, type OpResult } from './operations'\n\nexport type Core<O extends OpName> = (ctx: InterceptorContext<O>) => OpResult<O>\n\nexport interface HotOpWarning {\n interceptor: Interceptor<OpName>\n op: string\n message: string\n}\n\nexport interface InterceptorRuntimeOptions {\n interceptors?: readonly Interceptor<OpName>[]\n /**\n * The table's diagnostic emitter. When given, the default hooks below report through it:\n * `DK_INTERCEPTOR_FAILED` and (dev only) `DK_HOT_INTERCEPTOR`. Without it they use the console.\n */\n emit?: Emit\n /**\n * An interceptor threw (or its promise rejected); it was skipped. Overrides the default report\n * (`DK_INTERCEPTOR_FAILED` via `emit`, else console.error).\n */\n onInterceptorError?: (\n error: unknown,\n interceptor: Interceptor<OpName>,\n ctx: InterceptorContext,\n ) => void\n /**\n * An interceptor is attached to a hot op without `hot: true` (checked when the op's chain is\n * compiled, once per interceptor + op). Overrides the default (`DK_HOT_INTERCEPTOR` via `emit`).\n */\n onHotWarning?: (warning: HotOpWarning) => void\n /** Called each time a chain is compiled (tracing / tests). `length` counts the boundary too. */\n onCompile?: (op: string, length: number) => void\n}\n\nexport interface InterceptorRuntime {\n /** Runs `core` for `op` through the compiled chain. */\n run<O extends OpName>(op: O, ctx: InterceptorContext<O>, core: NoInfer<Core<O>>): OpResult<O>\n /** Replaces the user / feature interceptors and recompiles. The boundary slot is kept. */\n setInterceptors(interceptors: readonly Interceptor<OpName>[]): void\n /** Installs the outermost, non-removable interceptor (errorBoundary, T06). Once only. */\n installBoundary(boundary: Interceptor<OpName>): void\n}\n\ntype AnyCtx = InterceptorContext\ntype AnyCore = (ctx: AnyCtx) => unknown\ntype Chain = (ctx: AnyCtx, core: AnyCore) => unknown\n\nconst NOT_CALLED = 0\nconst CALLED = 1\nconst FAILED_INSIDE = 2\n\nconst direct: Chain = (ctx, core) => core(ctx)\n\nconst isThenable = (v: unknown): v is PromiseLike<unknown> =>\n v != null && typeof (v as { then?: unknown }).then === 'function'\n\nconst attaches = (i: Interceptor<OpName>, op: string) =>\n i.on === '*' || (i.on as readonly string[]).includes(op)\n\n/**\n * Wraps one interceptor around `inner`. Skip semantics (§3.4): if the interceptor throws before\n * calling `next`, `next` runs directly; if it throws after, the result `next` produced is kept so\n * the core never runs twice. An error that came out of `next` belongs to an inner layer and is\n * rethrown untouched. Async results get the same rules on rejection.\n */\nfunction wrap(\n i: Interceptor<OpName>,\n inner: Chain,\n mayBeAsync: boolean,\n report: (error: unknown, i: Interceptor<OpName>, ctx: AnyCtx) => void,\n): Chain {\n const intercept = i.intercept as (ctx: AnyCtx, next: () => unknown) => unknown\n return (ctx, core) => {\n let state = NOT_CALLED\n let out: unknown\n const next = () => {\n state = CALLED\n try {\n out = inner(ctx, core)\n } catch (e) {\n state = FAILED_INSIDE\n throw e\n }\n if (mayBeAsync && isThenable(out)) {\n const p = Promise.resolve(out).then(undefined, (e: unknown) => {\n state = FAILED_INSIDE\n throw e\n })\n // Handled here so an interceptor that drops `next()` never causes an unhandled rejection;\n // whoever awaits `p` still sees the rejection.\n p.catch(() => {})\n out = p\n }\n return out\n }\n const recover = (e: unknown) => {\n if (state === FAILED_INSIDE) throw e\n report(e, i, ctx)\n return state === CALLED ? out : inner(ctx, core)\n }\n let r: unknown\n try {\n r = intercept(ctx, next)\n } catch (e) {\n return recover(e)\n }\n return mayBeAsync && isThenable(r) ? Promise.resolve(r).then(undefined, recover) : r\n }\n}\n\nexport function createInterceptorRuntime(\n options: InterceptorRuntimeOptions = {},\n): InterceptorRuntime {\n const { emit, onCompile } = options\n const onError =\n options.onInterceptorError ??\n ((error: unknown, i: Interceptor<OpName>, ctx: AnyCtx) => {\n if (emit) {\n emit(\n 'DK_INTERCEPTOR_FAILED',\n { interceptor: i.name, op: ctx.op, slot: ctx.where },\n { cause: error, run: ctx.run, trigger: ctx.trigger, phase: ctx.phase },\n )\n } else {\n console.error(\n `[DataKable] interceptor \"${i.name}\" failed on ${ctx.op} and was skipped`,\n error,\n )\n }\n })\n // Dev-only (DK_HOT_INTERCEPTOR): `undefined` in production, with the code and its text.\n const onHotWarning = (process.env.NODE_ENV !== \"production\")\n ? (options.onHotWarning ??\n ((w: HotOpWarning) => {\n if (emit) emit('DK_HOT_INTERCEPTOR', { interceptor: w.interceptor.name, op: w.op })\n else console.warn(`[DataKable] ${w.message}`)\n }))\n : undefined\n const report = (error: unknown, i: Interceptor<OpName>, ctx: AnyCtx) => {\n try {\n onError(error, i, ctx)\n } catch (e) {\n // The reporter must never break the operation it reports on — except `strict: true`, whose\n // DatakableError is the requested behaviour.\n if (e instanceof DatakableError) throw e\n }\n }\n\n let list: readonly Interceptor<OpName>[] = []\n let boundary: Interceptor<OpName> | undefined\n const chains = new Map<string, Chain>()\n /** (interceptor, op) pairs already warned about, so recompiles do not repeat the warning. */\n const warned = (process.env.NODE_ENV !== \"production\") ? new WeakMap<Interceptor<OpName>, Set<string>>() : undefined\n\n function warnHot(i: Interceptor<OpName>, op: string) {\n if (!(process.env.NODE_ENV !== \"production\") || !warned || !onHotWarning) return // dev-only: production bundles drop the text below\n let ops = warned.get(i)\n if (ops?.has(op)) return\n if (!ops) {\n ops = new Set()\n warned.set(i, ops)\n }\n ops.add(op)\n try {\n onHotWarning({\n interceptor: i,\n op,\n message:\n `Interceptor \"${i.name}\" is attached to hot op \"${op}\" without hot: true. ` +\n // Measured by intercept/chain.bench.ts (Apple M4 Pro, Node 25.2.1). Inline here, inside\n // the (process.env.NODE_ENV !== \"production\")-only function, so production bundles carry none of it.\n 'It runs once per column per pipeline run; measured cost: ~10 ns per call per ' +\n 'interceptor (+15% on a per-cell format call, spec §9.2) on top of the interceptor ' +\n 'body, which runs columns × pipeline runs times. ' +\n 'Never loop per cell inside it. Set hot: true to accept the cost, ' +\n 'or attach it to a cold op.',\n })\n } catch {\n // A warning must never break compilation.\n }\n }\n\n function compile(op: string): Chain {\n const info = getOperation(op)\n if (!info) {\n throw internalError(op, `unknown-op|${op}`)\n }\n const mine = list.filter((i) => attaches(i, op))\n if (boundary && attaches(boundary, op)) mine.unshift(boundary)\n // Checked here, not when the list is set, so ops registered after creation are covered too.\n if ((process.env.NODE_ENV !== \"production\") && info.hot) for (const i of mine) if (!i.hot) warnHot(i, op)\n const mayBeAsync = info.kind !== 'sync'\n const chain = mine.reduceRight<Chain>((inner, i) => wrap(i, inner, mayBeAsync, report), direct)\n chains.set(op, chain)\n onCompile?.(op, mine.length)\n return chain\n }\n\n function compileAll() {\n chains.clear()\n for (const op of listOperations()) compile(op)\n }\n\n function setInterceptors(next: readonly Interceptor<OpName>[]) {\n list = [...next]\n compileAll()\n }\n\n setInterceptors(options.interceptors ?? [])\n\n return {\n run(op, ctx, core) {\n const chain = chains.get(op) ?? compile(op)\n return chain(ctx, core as AnyCore) as OpResult<typeof op>\n },\n setInterceptors,\n installBoundary(b) {\n if (boundary) {\n throw internalError('*', `boundary-twice|${boundary.name}|${b.name}`)\n }\n boundary = b\n compileAll()\n },\n }\n}\n"],"mappings":"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","names":[]}
@@ -26,6 +26,7 @@ module.exports = __toCommonJS(messages_exports);
26
26
  var import_codes = require("../catalog/codes.cjs");
27
27
  var import_catalog = require("../diagnostics/catalog.cjs");
28
28
  var import_codes2 = require("../diagnostics/codes.cjs");
29
+ var import_prose = require("../diagnostics/prose.cjs");
29
30
  var import_redact = require("../diagnostics/redact.cjs");
30
31
  var import_codes3 = require("../feature/codes.cjs");
31
32
  var import_codes4 = require("../features/column-filters/codes.cjs");
@@ -64,7 +65,9 @@ var allMessages = [
64
65
  import_codes6.searchMessages,
65
66
  import_codes7.sortingMessages,
66
67
  import_codes5.paginationMessages,
67
- import_env_codes.envMessages
68
+ import_env_codes.envMessages,
69
+ // The detail sentences production keeps as keys (`fallback: 'cells-undefined'`).
70
+ import_prose.proseMessages
68
71
  ];
69
72
  (0, import_catalog.installMessages)(...allMessages);
70
73
  // Annotate the CommonJS export names for ESM import in node: