@datakable/core 1.0.0 → 1.1.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 (290) hide show
  1. package/README.md +4 -2
  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-BKdS9EiO.d.cts → codes-B9bCK73-.d.cts} +46 -8
  11. package/dist/{codes-BKdS9EiO.d.ts → codes-B9bCK73-.d.ts} +46 -8
  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 +10 -4
  20. package/dist/diagnostics/build.cjs.map +1 -1
  21. package/dist/diagnostics/build.js +8 -3
  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 +6 -5
  48. package/dist/diagnostics/hub.cjs.map +1 -1
  49. package/dist/diagnostics/hub.js +7 -6
  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-aagaYHcy.d.cts → explain-Q8Cg0cZy.d.cts} +13 -4
  73. package/dist/{explain-DcUZfFh5.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/define.cjs +3 -1
  79. package/dist/feature/define.cjs.map +1 -1
  80. package/dist/feature/define.js +3 -1
  81. package/dist/feature/define.js.map +1 -1
  82. package/dist/feature/install.cjs +4 -3
  83. package/dist/feature/install.cjs.map +1 -1
  84. package/dist/feature/install.js +4 -3
  85. package/dist/feature/install.js.map +1 -1
  86. package/dist/feature/runtime.cjs.map +1 -1
  87. package/dist/feature/runtime.js.map +1 -1
  88. package/dist/features/column-filters/codes.cjs +1 -0
  89. package/dist/features/column-filters/codes.cjs.map +1 -1
  90. package/dist/features/column-filters/codes.js +1 -0
  91. package/dist/features/column-filters/codes.js.map +1 -1
  92. package/dist/features/column-filters/column-filters.cjs +4 -2
  93. package/dist/features/column-filters/column-filters.cjs.map +1 -1
  94. package/dist/features/column-filters/column-filters.js +4 -2
  95. package/dist/features/column-filters/column-filters.js.map +1 -1
  96. package/dist/features/column-filters/match.cjs +5 -5
  97. package/dist/features/column-filters/match.cjs.map +1 -1
  98. package/dist/features/column-filters/match.js +5 -5
  99. package/dist/features/column-filters/match.js.map +1 -1
  100. package/dist/features/pagination/codes.cjs +6 -3
  101. package/dist/features/pagination/codes.cjs.map +1 -1
  102. package/dist/features/pagination/codes.js +6 -3
  103. package/dist/features/pagination/codes.js.map +1 -1
  104. package/dist/features/pagination/pagination.cjs +19 -14
  105. package/dist/features/pagination/pagination.cjs.map +1 -1
  106. package/dist/features/pagination/pagination.js +19 -14
  107. package/dist/features/pagination/pagination.js.map +1 -1
  108. package/dist/features/search/codes.cjs +1 -0
  109. package/dist/features/search/codes.cjs.map +1 -1
  110. package/dist/features/search/codes.js +1 -0
  111. package/dist/features/search/codes.js.map +1 -1
  112. package/dist/features/search/search-index.cjs +105 -48
  113. package/dist/features/search/search-index.cjs.map +1 -1
  114. package/dist/features/search/search-index.js +106 -49
  115. package/dist/features/search/search-index.js.map +1 -1
  116. package/dist/features/search/search.cjs +82 -24
  117. package/dist/features/search/search.cjs.map +1 -1
  118. package/dist/features/search/search.js +82 -24
  119. package/dist/features/search/search.js.map +1 -1
  120. package/dist/features/search/skipped-codes.cjs +45 -0
  121. package/dist/features/search/skipped-codes.cjs.map +1 -0
  122. package/dist/features/search/skipped-codes.js +20 -0
  123. package/dist/features/search/skipped-codes.js.map +1 -0
  124. package/dist/features/sorting/codes.cjs +1 -0
  125. package/dist/features/sorting/codes.cjs.map +1 -1
  126. package/dist/features/sorting/codes.js +1 -0
  127. package/dist/features/sorting/codes.js.map +1 -1
  128. package/dist/features/sorting/sorting.cjs +19 -23
  129. package/dist/features/sorting/sorting.cjs.map +1 -1
  130. package/dist/features/sorting/sorting.js +19 -23
  131. package/dist/features/sorting/sorting.js.map +1 -1
  132. package/dist/features/sorting/strategy.cjs +4 -4
  133. package/dist/features/sorting/strategy.cjs.map +1 -1
  134. package/dist/features/sorting/strategy.js +4 -4
  135. package/dist/features/sorting/strategy.js.map +1 -1
  136. package/dist/features/validity/codes.cjs +1 -0
  137. package/dist/features/validity/codes.cjs.map +1 -1
  138. package/dist/features/validity/codes.js +1 -0
  139. package/dist/features/validity/codes.js.map +1 -1
  140. package/dist/features/validity/validity.cjs +3 -3
  141. package/dist/features/validity/validity.cjs.map +1 -1
  142. package/dist/features/validity/validity.js +3 -3
  143. package/dist/features/validity/validity.js.map +1 -1
  144. package/dist/index.d.cts +16 -11
  145. package/dist/index.d.ts +16 -11
  146. package/dist/ingest/data-check-codes.cjs +4 -2
  147. package/dist/ingest/data-check-codes.cjs.map +1 -1
  148. package/dist/ingest/data-check-codes.js +4 -2
  149. package/dist/ingest/data-check-codes.js.map +1 -1
  150. package/dist/ingest/data-checks.cjs +1 -1
  151. package/dist/ingest/data-checks.cjs.map +1 -1
  152. package/dist/ingest/data-checks.js +1 -1
  153. package/dist/ingest/data-checks.js.map +1 -1
  154. package/dist/ingest/row-key-codes.cjs +1 -0
  155. package/dist/ingest/row-key-codes.cjs.map +1 -1
  156. package/dist/ingest/row-key-codes.js +1 -0
  157. package/dist/ingest/row-key-codes.js.map +1 -1
  158. package/dist/ingest/row-key.cjs +23 -20
  159. package/dist/ingest/row-key.cjs.map +1 -1
  160. package/dist/ingest/row-key.js +23 -20
  161. package/dist/ingest/row-key.js.map +1 -1
  162. package/dist/ingest/schema-codes.cjs +1 -0
  163. package/dist/ingest/schema-codes.cjs.map +1 -1
  164. package/dist/ingest/schema-codes.js +1 -0
  165. package/dist/ingest/schema-codes.js.map +1 -1
  166. package/dist/ingest/unique-fields.cjs +2 -2
  167. package/dist/ingest/unique-fields.cjs.map +1 -1
  168. package/dist/ingest/unique-fields.js +2 -2
  169. package/dist/ingest/unique-fields.js.map +1 -1
  170. package/dist/intercept/boundary.cjs +4 -2
  171. package/dist/intercept/boundary.cjs.map +1 -1
  172. package/dist/intercept/boundary.js +4 -2
  173. package/dist/intercept/boundary.js.map +1 -1
  174. package/dist/intercept/cell-batch.cjs +7 -4
  175. package/dist/intercept/cell-batch.cjs.map +1 -1
  176. package/dist/intercept/cell-batch.js +7 -4
  177. package/dist/intercept/cell-batch.js.map +1 -1
  178. package/dist/intercept/codes.cjs +1 -0
  179. package/dist/intercept/codes.cjs.map +1 -1
  180. package/dist/intercept/codes.js +1 -0
  181. package/dist/intercept/codes.js.map +1 -1
  182. package/dist/intercept/fallbacks.cjs +12 -20
  183. package/dist/intercept/fallbacks.cjs.map +1 -1
  184. package/dist/intercept/fallbacks.js +12 -20
  185. package/dist/intercept/fallbacks.js.map +1 -1
  186. package/dist/intercept/runtime.cjs +7 -9
  187. package/dist/intercept/runtime.cjs.map +1 -1
  188. package/dist/intercept/runtime.js +7 -9
  189. package/dist/intercept/runtime.js.map +1 -1
  190. package/dist/messages/index.cjs +4 -1
  191. package/dist/messages/index.cjs.map +1 -1
  192. package/dist/messages/index.js +4 -1
  193. package/dist/messages/index.js.map +1 -1
  194. package/dist/pagination.d.cts +2 -2
  195. package/dist/pagination.d.ts +2 -2
  196. package/dist/pipeline/codes.cjs +1 -0
  197. package/dist/pipeline/codes.cjs.map +1 -1
  198. package/dist/pipeline/codes.js +1 -0
  199. package/dist/pipeline/codes.js.map +1 -1
  200. package/dist/pipeline/column-cache.cjs +94 -76
  201. package/dist/pipeline/column-cache.cjs.map +1 -1
  202. package/dist/pipeline/column-cache.js +92 -75
  203. package/dist/pipeline/column-cache.js.map +1 -1
  204. package/dist/pipeline/dev-checks.cjs +1 -0
  205. package/dist/pipeline/dev-checks.cjs.map +1 -1
  206. package/dist/pipeline/dev-checks.js +1 -0
  207. package/dist/pipeline/dev-checks.js.map +1 -1
  208. package/dist/pipeline/env-codes.cjs +3 -2
  209. package/dist/pipeline/env-codes.cjs.map +1 -1
  210. package/dist/pipeline/env-codes.js +3 -2
  211. package/dist/pipeline/env-codes.js.map +1 -1
  212. package/dist/pipeline/perf-codes.cjs +1 -0
  213. package/dist/pipeline/perf-codes.cjs.map +1 -1
  214. package/dist/pipeline/perf-codes.js +1 -0
  215. package/dist/pipeline/perf-codes.js.map +1 -1
  216. package/dist/pipeline/row.cjs +8 -7
  217. package/dist/pipeline/row.cjs.map +1 -1
  218. package/dist/pipeline/row.js +8 -7
  219. package/dist/pipeline/row.js.map +1 -1
  220. package/dist/pipeline/runner.cjs +17 -9
  221. package/dist/pipeline/runner.cjs.map +1 -1
  222. package/dist/pipeline/runner.js +17 -9
  223. package/dist/pipeline/runner.js.map +1 -1
  224. package/dist/pipeline/slice.cjs +3 -1
  225. package/dist/pipeline/slice.cjs.map +1 -1
  226. package/dist/pipeline/slice.js +3 -1
  227. package/dist/pipeline/slice.js.map +1 -1
  228. package/dist/schema.d.cts +2 -2
  229. package/dist/schema.d.ts +2 -2
  230. package/dist/{search-async-entry-C3mXxLP8.d.cts → search-async-entry-CuLYPfY_.d.cts} +2 -2
  231. package/dist/{search-async-entry-BmQYT120.d.ts → search-async-entry-Cx7xpuVZ.d.ts} +2 -2
  232. package/dist/search-async.d.cts +3 -3
  233. package/dist/search-async.d.ts +3 -3
  234. package/dist/search.d.cts +8 -6
  235. package/dist/search.d.ts +8 -6
  236. package/dist/server.d.cts +3 -3
  237. package/dist/server.d.ts +3 -3
  238. package/dist/sorting.d.cts +6 -3
  239. package/dist/sorting.d.ts +6 -3
  240. package/dist/source/codes.cjs +1 -0
  241. package/dist/source/codes.cjs.map +1 -1
  242. package/dist/source/codes.js +1 -0
  243. package/dist/source/codes.js.map +1 -1
  244. package/dist/source/fetch-codes.cjs +1 -0
  245. package/dist/source/fetch-codes.cjs.map +1 -1
  246. package/dist/source/fetch-codes.js +1 -0
  247. package/dist/source/fetch-codes.js.map +1 -1
  248. package/dist/table/codes.cjs +1 -0
  249. package/dist/table/codes.cjs.map +1 -1
  250. package/dist/table/codes.js +1 -0
  251. package/dist/table/codes.js.map +1 -1
  252. package/dist/table/create-table.cjs +39 -9
  253. package/dist/table/create-table.cjs.map +1 -1
  254. package/dist/table/create-table.js +39 -9
  255. package/dist/table/create-table.js.map +1 -1
  256. package/dist/table/data-mutation.cjs +1 -0
  257. package/dist/table/data-mutation.cjs.map +1 -1
  258. package/dist/table/data-mutation.js +1 -0
  259. package/dist/table/data-mutation.js.map +1 -1
  260. package/dist/table/internals.cjs.map +1 -1
  261. package/dist/table/internals.js.map +1 -1
  262. package/dist/table/ssr-codes.cjs +1 -0
  263. package/dist/table/ssr-codes.cjs.map +1 -1
  264. package/dist/table/ssr-codes.js +1 -0
  265. package/dist/table/ssr-codes.js.map +1 -1
  266. package/dist/table/ssr.cjs +4 -1
  267. package/dist/table/ssr.cjs.map +1 -1
  268. package/dist/table/ssr.js +4 -1
  269. package/dist/table/ssr.js.map +1 -1
  270. package/dist/table/state-feedback.cjs +19 -0
  271. package/dist/table/state-feedback.cjs.map +1 -1
  272. package/dist/table/state-feedback.js +19 -0
  273. package/dist/table/state-feedback.js.map +1 -1
  274. package/dist/table/types.cjs.map +1 -1
  275. package/dist/table/types.js.map +1 -1
  276. package/dist/validity.d.cts +2 -2
  277. package/dist/validity.d.ts +2 -2
  278. package/dist/version.cjs +1 -1
  279. package/dist/version.cjs.map +1 -1
  280. package/dist/version.js +1 -1
  281. package/dist/version.js.map +1 -1
  282. package/dist/versioning/codes.cjs +18 -0
  283. package/dist/versioning/codes.cjs.map +1 -1
  284. package/dist/versioning/codes.js +18 -0
  285. package/dist/versioning/codes.js.map +1 -1
  286. package/dist/versioning/registry.cjs +4 -2
  287. package/dist/versioning/registry.cjs.map +1 -1
  288. package/dist/versioning/registry.js +4 -2
  289. package/dist/versioning/registry.js.map +1 -1
  290. package/package.json +39 -3
package/README.md CHANGED
@@ -17,7 +17,7 @@ constant and remove development-only checks, tracing and message text from produ
17
17
  Vite, webpack, Next.js, Rollup (`@rollup/plugin-replace`) and esbuild
18
18
  (`--define:process.env.NODE_ENV='"production"'`) all replace it. Without a replacement, unbundled
19
19
  browser code throws `ReferenceError: process is not defined`, as React and Redux do. Node needs
20
- nothing.
20
+ nothing beyond Node.js `>=18.18`. The types need TypeScript `>=5.4`.
21
21
 
22
22
  ## Contents
23
23
 
@@ -111,7 +111,9 @@ The features are also exported from `@datakable/core` itself. The pipeline alway
111
111
  (number / bigint / Date, inclusive) and `custom` (`fn(value, filterValue, row)`). Filters AND
112
112
  together; an array cell matches when any element matches.
113
113
  - **Search:** fuzzy matching over the formatted cell values. When a column declares
114
- `search: weight`, only columns with a weight are searched; otherwise every column is, at weight 1. `input` follows the keyboard,
114
+ `search: weight`, only columns with a weight are searched; otherwise the columns of strings,
115
+ numbers and booleans are, at weight 1 (a column of dates, arrays or objects needs a weight;
116
+ `DK_SEARCH_COLUMN_SKIPPED` in development). `input` follows the keyboard,
115
117
  `query` is the applied value; `typing` sets `immediate` / `debounce` / `throttle`, `wait`,
116
118
  `minLength` and `commitOn: 'enter'`. `setSearch` / `flushSearch` return a promise of
117
119
  `{ status: 'applied' | 'superseded' | 'error' }` and never reject. A `searchFn` replaces the
@@ -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 where = (d) => d.feature === void 0 ? { kind: "option", path: d.path } : { kind: "feature", name: d.feature };
29
30
  var label = (d) => d.feature === void 0 ? `options.${d.path}` : `${d.feature}({ ${d.path} })`;
30
31
  var leaf = (path) => path.slice(path.lastIndexOf(".") + 1);
@@ -68,14 +69,17 @@ var optionMessages = {
68
69
  }
69
70
  };
70
71
  var optionDiagnostics = [
71
- (0, import_catalog.defineDiagnostic)(
72
- {
73
- code: "DK_UNKNOWN_OPTION",
74
- level: "warn",
75
- where
76
- },
77
- process.env.NODE_ENV !== "production" && optionMessages.DK_UNKNOWN_OPTION
78
- ),
72
+ // Only the development option validator emits it: no definition in production.
73
+ ...process.env.NODE_ENV !== "production" ? [
74
+ (0, import_catalog.defineDiagnostic)(
75
+ {
76
+ code: "DK_UNKNOWN_OPTION",
77
+ level: "warn",
78
+ where
79
+ },
80
+ process.env.NODE_ENV !== "production" && optionMessages.DK_UNKNOWN_OPTION
81
+ )
82
+ ] : [],
79
83
  (0, import_catalog.defineDiagnostic)(
80
84
  {
81
85
  code: "DK_INVALID_OPTION",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/catalog/codes.ts"],"sourcesContent":["import { type DiagnosticMessages, defineDiagnostic } from '../diagnostics/catalog'\nimport type { Location } from '../diagnostics/types'\n\ndeclare module '../diagnostics/catalog' {\n interface DiagnosticCatalog {\n DK_UNKNOWN_OPTION: {\n /** Option path as written (`colums`, `diagnostics.redcat`); option keys, never values. */\n path: string\n /** Set when the option was given to a feature factory. */\n feature?: string\n /** Close accepted names, best first (did-you-mean). */\n suggestions: string[]\n /** The accepted options at that level. */\n known: string[]\n /** An installed feature that has this option (it was passed to the table instead). */\n owner?: string\n }\n DK_INVALID_OPTION: {\n path: string\n feature?: string\n /** The accepted values in words. */\n expected: string\n /** What was given: a type, or a short constant (`\"ful\"`, `NaN`). */\n received: string\n /** Close accepted values (enums), best first. */\n suggestions: string[]\n /** A fix specific to this mistake, shown first. */\n hint?: string\n /** Where it was given: `createTable` (the table was not created) or `setOptions` (rejected). */\n phase: 'init' | 'setOptions'\n }\n DK_OPTION_NO_EFFECT: {\n path: string\n feature?: string\n /** Why the option is ignored. */\n reason: string\n /** `true` for a read-once option changed with `setOptions`. */\n once: boolean\n }\n }\n}\n\nconst where = (d: { path: string; feature?: string }): Location =>\n d.feature === undefined ? { kind: 'option', path: d.path } : { kind: 'feature', name: d.feature }\n\n/** `options.timeout` / `paging({ pageSize })`. */\nconst label = (d: { path: string; feature?: string }) =>\n d.feature === undefined ? `options.${d.path}` : `${d.feature}({ ${d.path} })`\n\nconst leaf = (path: string) => path.slice(path.lastIndexOf('.') + 1)\n\n/** Message text (§8.2): development builds, or production via `@datakable/core/messages`. */\nexport const optionMessages: DiagnosticMessages<\n 'DK_UNKNOWN_OPTION' | 'DK_INVALID_OPTION' | 'DK_OPTION_NO_EFFECT'\n> = {\n DK_UNKNOWN_OPTION: {\n problem: (d) =>\n d.feature === undefined\n ? `unknown option \"${d.path}\"`\n : `feature \"${d.feature}\" got an unknown option \"${d.path}\"`,\n impact: () => 'the option is ignored',\n fix: (d) => {\n const out: string[] = []\n const s = d.suggestions[0]\n if (s !== undefined) out.push(`did you mean \"${s}\"? rename \"${leaf(d.path)}\" to \"${s}\"`)\n if (d.owner !== undefined) {\n out.push(\n `\"${d.path}\" is an option of feature \"${d.owner}\": pass it to the feature, ` +\n `${d.owner}({ ${d.path}: ... })`,\n )\n }\n out.push(\n `remove \"${leaf(d.path)}\"; accepted ${d.feature === undefined ? '' : `${d.feature} `}` +\n `options here: ${d.known.join(', ') || '(none)'}`,\n )\n return out\n },\n },\n DK_INVALID_OPTION: {\n problem: (d) => `${label(d)} must be ${d.expected}, got ${d.received}`,\n impact: (d) =>\n d.phase === 'init'\n ? 'the table was not created'\n : 'setOptions() was rejected; the previous options are kept',\n fix: (d) => {\n const out: string[] = []\n if (d.hint !== undefined) out.push(d.hint)\n const s = d.suggestions[0]\n if (s !== undefined) out.push(`use '${s}' (the closest accepted value) for ${label(d)}`)\n out.push(`pass ${d.expected} as ${label(d)}, or leave it out for the default`)\n return out\n },\n },\n DK_OPTION_NO_EFFECT: {\n problem: (d) =>\n d.once\n ? `setOptions({ ${d.path} }) has no effect: ${d.reason}`\n : `${label(d)} has no effect: ${d.reason}`,\n impact: (d) =>\n d.once\n ? 'the new value was ignored; the table keeps the value it was created with'\n : 'the option is ignored in this configuration',\n fix: (d) =>\n d.once\n ? [\n `pass ${d.path} to createTable() instead; to change it, create a new table ` +\n '(in React, change the component key)',\n ]\n : [`remove ${label(d)}, or change the configuration so that it applies (${d.reason})`],\n },\n}\n\n/** Codes owned by the options catalog (§3.5, §8.3). */\nexport const optionDiagnostics = [\n defineDiagnostic(\n {\n code: 'DK_UNKNOWN_OPTION',\n level: 'warn',\n where,\n },\n (process.env.NODE_ENV !== \"production\") && optionMessages.DK_UNKNOWN_OPTION,\n ),\n defineDiagnostic(\n {\n code: 'DK_INVALID_OPTION',\n level: 'error',\n config: true,\n where,\n },\n (process.env.NODE_ENV !== \"production\") && optionMessages.DK_INVALID_OPTION,\n ),\n defineDiagnostic(\n {\n code: 'DK_OPTION_NO_EFFECT',\n level: 'warn',\n where,\n },\n (process.env.NODE_ENV !== \"production\") && optionMessages.DK_OPTION_NO_EFFECT,\n ),\n]\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/catalog/codes.ts"],"sourcesContent":["import { type DiagnosticMessages, defineDiagnostic } from '../diagnostics/catalog'\nimport '../diagnostics/process-guard'\nimport type { Location } from '../diagnostics/types'\n\ndeclare module '../diagnostics/catalog' {\n interface DiagnosticCatalog {\n DK_UNKNOWN_OPTION: {\n /** Option path as written (`colums`, `diagnostics.redcat`); option keys, never values. */\n path: string\n /** Set when the option was given to a feature factory. */\n feature?: string\n /** Close accepted names, best first (did-you-mean). */\n suggestions: string[]\n /** The accepted options at that level. */\n known: string[]\n /** An installed feature that has this option (it was passed to the table instead). */\n owner?: string\n }\n DK_INVALID_OPTION: {\n path: string\n feature?: string\n /** The accepted values in words. */\n expected: string\n /** What was given: a type, or a short constant (`\"ful\"`, `NaN`). */\n received: string\n /** Close accepted values (enums), best first. */\n suggestions: string[]\n /** A fix specific to this mistake, shown first. */\n hint?: string\n /** Where it was given: `createTable` (the table was not created) or `setOptions` (rejected). */\n phase: 'init' | 'setOptions'\n }\n DK_OPTION_NO_EFFECT: {\n path: string\n feature?: string\n /** Why the option is ignored. */\n reason: string\n /** `true` for a read-once option changed with `setOptions`. */\n once: boolean\n }\n }\n}\n\nconst where = (d: { path: string; feature?: string }): Location =>\n d.feature === undefined ? { kind: 'option', path: d.path } : { kind: 'feature', name: d.feature }\n\n/** `options.timeout` / `paging({ pageSize })`. */\nconst label = (d: { path: string; feature?: string }) =>\n d.feature === undefined ? `options.${d.path}` : `${d.feature}({ ${d.path} })`\n\nconst leaf = (path: string) => path.slice(path.lastIndexOf('.') + 1)\n\n/** Message text (§8.2): development builds, or production via `@datakable/core/messages`. */\nexport const optionMessages: DiagnosticMessages<\n 'DK_UNKNOWN_OPTION' | 'DK_INVALID_OPTION' | 'DK_OPTION_NO_EFFECT'\n> = {\n DK_UNKNOWN_OPTION: {\n problem: (d) =>\n d.feature === undefined\n ? `unknown option \"${d.path}\"`\n : `feature \"${d.feature}\" got an unknown option \"${d.path}\"`,\n impact: () => 'the option is ignored',\n fix: (d) => {\n const out: string[] = []\n const s = d.suggestions[0]\n if (s !== undefined) out.push(`did you mean \"${s}\"? rename \"${leaf(d.path)}\" to \"${s}\"`)\n if (d.owner !== undefined) {\n out.push(\n `\"${d.path}\" is an option of feature \"${d.owner}\": pass it to the feature, ` +\n `${d.owner}({ ${d.path}: ... })`,\n )\n }\n out.push(\n `remove \"${leaf(d.path)}\"; accepted ${d.feature === undefined ? '' : `${d.feature} `}` +\n `options here: ${d.known.join(', ') || '(none)'}`,\n )\n return out\n },\n },\n DK_INVALID_OPTION: {\n problem: (d) => `${label(d)} must be ${d.expected}, got ${d.received}`,\n impact: (d) =>\n d.phase === 'init'\n ? 'the table was not created'\n : 'setOptions() was rejected; the previous options are kept',\n fix: (d) => {\n const out: string[] = []\n if (d.hint !== undefined) out.push(d.hint)\n const s = d.suggestions[0]\n if (s !== undefined) out.push(`use '${s}' (the closest accepted value) for ${label(d)}`)\n out.push(`pass ${d.expected} as ${label(d)}, or leave it out for the default`)\n return out\n },\n },\n DK_OPTION_NO_EFFECT: {\n problem: (d) =>\n d.once\n ? `setOptions({ ${d.path} }) has no effect: ${d.reason}`\n : `${label(d)} has no effect: ${d.reason}`,\n impact: (d) =>\n d.once\n ? 'the new value was ignored; the table keeps the value it was created with'\n : 'the option is ignored in this configuration',\n fix: (d) =>\n d.once\n ? [\n `pass ${d.path} to createTable() instead; to change it, create a new table ` +\n '(in React, change the component key)',\n ]\n : [`remove ${label(d)}, or change the configuration so that it applies (${d.reason})`],\n },\n}\n\n/** Codes owned by the options catalog (§3.5, §8.3). */\nexport const optionDiagnostics = [\n // Only the development option validator emits it: no definition in production.\n ...((process.env.NODE_ENV !== \"production\")\n ? [\n defineDiagnostic(\n {\n code: 'DK_UNKNOWN_OPTION',\n level: 'warn',\n where,\n },\n (process.env.NODE_ENV !== \"production\") && optionMessages.DK_UNKNOWN_OPTION,\n ),\n ]\n : []),\n defineDiagnostic(\n {\n code: 'DK_INVALID_OPTION',\n level: 'error',\n config: true,\n where,\n },\n (process.env.NODE_ENV !== \"production\") && optionMessages.DK_INVALID_OPTION,\n ),\n defineDiagnostic(\n {\n code: 'DK_OPTION_NO_EFFECT',\n level: 'warn',\n where,\n },\n (process.env.NODE_ENV !== \"production\") && optionMessages.DK_OPTION_NO_EFFECT,\n ),\n]\n"],"mappings":"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","names":[]}
@@ -1,5 +1,6 @@
1
1
  // src/catalog/codes.ts
2
2
  import { defineDiagnostic } from "../diagnostics/catalog.js";
3
+ import "../diagnostics/process-guard.js";
3
4
  var where = (d) => d.feature === void 0 ? { kind: "option", path: d.path } : { kind: "feature", name: d.feature };
4
5
  var label = (d) => d.feature === void 0 ? `options.${d.path}` : `${d.feature}({ ${d.path} })`;
5
6
  var leaf = (path) => path.slice(path.lastIndexOf(".") + 1);
@@ -43,14 +44,17 @@ var optionMessages = {
43
44
  }
44
45
  };
45
46
  var optionDiagnostics = [
46
- defineDiagnostic(
47
- {
48
- code: "DK_UNKNOWN_OPTION",
49
- level: "warn",
50
- where
51
- },
52
- process.env.NODE_ENV !== "production" && optionMessages.DK_UNKNOWN_OPTION
53
- ),
47
+ // Only the development option validator emits it: no definition in production.
48
+ ...process.env.NODE_ENV !== "production" ? [
49
+ defineDiagnostic(
50
+ {
51
+ code: "DK_UNKNOWN_OPTION",
52
+ level: "warn",
53
+ where
54
+ },
55
+ process.env.NODE_ENV !== "production" && optionMessages.DK_UNKNOWN_OPTION
56
+ )
57
+ ] : [],
54
58
  defineDiagnostic(
55
59
  {
56
60
  code: "DK_INVALID_OPTION",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/catalog/codes.ts"],"sourcesContent":["import { type DiagnosticMessages, defineDiagnostic } from '../diagnostics/catalog'\nimport type { Location } from '../diagnostics/types'\n\ndeclare module '../diagnostics/catalog' {\n interface DiagnosticCatalog {\n DK_UNKNOWN_OPTION: {\n /** Option path as written (`colums`, `diagnostics.redcat`); option keys, never values. */\n path: string\n /** Set when the option was given to a feature factory. */\n feature?: string\n /** Close accepted names, best first (did-you-mean). */\n suggestions: string[]\n /** The accepted options at that level. */\n known: string[]\n /** An installed feature that has this option (it was passed to the table instead). */\n owner?: string\n }\n DK_INVALID_OPTION: {\n path: string\n feature?: string\n /** The accepted values in words. */\n expected: string\n /** What was given: a type, or a short constant (`\"ful\"`, `NaN`). */\n received: string\n /** Close accepted values (enums), best first. */\n suggestions: string[]\n /** A fix specific to this mistake, shown first. */\n hint?: string\n /** Where it was given: `createTable` (the table was not created) or `setOptions` (rejected). */\n phase: 'init' | 'setOptions'\n }\n DK_OPTION_NO_EFFECT: {\n path: string\n feature?: string\n /** Why the option is ignored. */\n reason: string\n /** `true` for a read-once option changed with `setOptions`. */\n once: boolean\n }\n }\n}\n\nconst where = (d: { path: string; feature?: string }): Location =>\n d.feature === undefined ? { kind: 'option', path: d.path } : { kind: 'feature', name: d.feature }\n\n/** `options.timeout` / `paging({ pageSize })`. */\nconst label = (d: { path: string; feature?: string }) =>\n d.feature === undefined ? `options.${d.path}` : `${d.feature}({ ${d.path} })`\n\nconst leaf = (path: string) => path.slice(path.lastIndexOf('.') + 1)\n\n/** Message text (§8.2): development builds, or production via `@datakable/core/messages`. */\nexport const optionMessages: DiagnosticMessages<\n 'DK_UNKNOWN_OPTION' | 'DK_INVALID_OPTION' | 'DK_OPTION_NO_EFFECT'\n> = {\n DK_UNKNOWN_OPTION: {\n problem: (d) =>\n d.feature === undefined\n ? `unknown option \"${d.path}\"`\n : `feature \"${d.feature}\" got an unknown option \"${d.path}\"`,\n impact: () => 'the option is ignored',\n fix: (d) => {\n const out: string[] = []\n const s = d.suggestions[0]\n if (s !== undefined) out.push(`did you mean \"${s}\"? rename \"${leaf(d.path)}\" to \"${s}\"`)\n if (d.owner !== undefined) {\n out.push(\n `\"${d.path}\" is an option of feature \"${d.owner}\": pass it to the feature, ` +\n `${d.owner}({ ${d.path}: ... })`,\n )\n }\n out.push(\n `remove \"${leaf(d.path)}\"; accepted ${d.feature === undefined ? '' : `${d.feature} `}` +\n `options here: ${d.known.join(', ') || '(none)'}`,\n )\n return out\n },\n },\n DK_INVALID_OPTION: {\n problem: (d) => `${label(d)} must be ${d.expected}, got ${d.received}`,\n impact: (d) =>\n d.phase === 'init'\n ? 'the table was not created'\n : 'setOptions() was rejected; the previous options are kept',\n fix: (d) => {\n const out: string[] = []\n if (d.hint !== undefined) out.push(d.hint)\n const s = d.suggestions[0]\n if (s !== undefined) out.push(`use '${s}' (the closest accepted value) for ${label(d)}`)\n out.push(`pass ${d.expected} as ${label(d)}, or leave it out for the default`)\n return out\n },\n },\n DK_OPTION_NO_EFFECT: {\n problem: (d) =>\n d.once\n ? `setOptions({ ${d.path} }) has no effect: ${d.reason}`\n : `${label(d)} has no effect: ${d.reason}`,\n impact: (d) =>\n d.once\n ? 'the new value was ignored; the table keeps the value it was created with'\n : 'the option is ignored in this configuration',\n fix: (d) =>\n d.once\n ? [\n `pass ${d.path} to createTable() instead; to change it, create a new table ` +\n '(in React, change the component key)',\n ]\n : [`remove ${label(d)}, or change the configuration so that it applies (${d.reason})`],\n },\n}\n\n/** Codes owned by the options catalog (§3.5, §8.3). */\nexport const optionDiagnostics = [\n defineDiagnostic(\n {\n code: 'DK_UNKNOWN_OPTION',\n level: 'warn',\n where,\n },\n (process.env.NODE_ENV !== \"production\") && optionMessages.DK_UNKNOWN_OPTION,\n ),\n defineDiagnostic(\n {\n code: 'DK_INVALID_OPTION',\n level: 'error',\n config: true,\n where,\n },\n (process.env.NODE_ENV !== \"production\") && optionMessages.DK_INVALID_OPTION,\n ),\n defineDiagnostic(\n {\n code: 'DK_OPTION_NO_EFFECT',\n level: 'warn',\n where,\n },\n (process.env.NODE_ENV !== \"production\") && optionMessages.DK_OPTION_NO_EFFECT,\n ),\n]\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/catalog/codes.ts"],"sourcesContent":["import { type DiagnosticMessages, defineDiagnostic } from '../diagnostics/catalog'\nimport '../diagnostics/process-guard'\nimport type { Location } from '../diagnostics/types'\n\ndeclare module '../diagnostics/catalog' {\n interface DiagnosticCatalog {\n DK_UNKNOWN_OPTION: {\n /** Option path as written (`colums`, `diagnostics.redcat`); option keys, never values. */\n path: string\n /** Set when the option was given to a feature factory. */\n feature?: string\n /** Close accepted names, best first (did-you-mean). */\n suggestions: string[]\n /** The accepted options at that level. */\n known: string[]\n /** An installed feature that has this option (it was passed to the table instead). */\n owner?: string\n }\n DK_INVALID_OPTION: {\n path: string\n feature?: string\n /** The accepted values in words. */\n expected: string\n /** What was given: a type, or a short constant (`\"ful\"`, `NaN`). */\n received: string\n /** Close accepted values (enums), best first. */\n suggestions: string[]\n /** A fix specific to this mistake, shown first. */\n hint?: string\n /** Where it was given: `createTable` (the table was not created) or `setOptions` (rejected). */\n phase: 'init' | 'setOptions'\n }\n DK_OPTION_NO_EFFECT: {\n path: string\n feature?: string\n /** Why the option is ignored. */\n reason: string\n /** `true` for a read-once option changed with `setOptions`. */\n once: boolean\n }\n }\n}\n\nconst where = (d: { path: string; feature?: string }): Location =>\n d.feature === undefined ? { kind: 'option', path: d.path } : { kind: 'feature', name: d.feature }\n\n/** `options.timeout` / `paging({ pageSize })`. */\nconst label = (d: { path: string; feature?: string }) =>\n d.feature === undefined ? `options.${d.path}` : `${d.feature}({ ${d.path} })`\n\nconst leaf = (path: string) => path.slice(path.lastIndexOf('.') + 1)\n\n/** Message text (§8.2): development builds, or production via `@datakable/core/messages`. */\nexport const optionMessages: DiagnosticMessages<\n 'DK_UNKNOWN_OPTION' | 'DK_INVALID_OPTION' | 'DK_OPTION_NO_EFFECT'\n> = {\n DK_UNKNOWN_OPTION: {\n problem: (d) =>\n d.feature === undefined\n ? `unknown option \"${d.path}\"`\n : `feature \"${d.feature}\" got an unknown option \"${d.path}\"`,\n impact: () => 'the option is ignored',\n fix: (d) => {\n const out: string[] = []\n const s = d.suggestions[0]\n if (s !== undefined) out.push(`did you mean \"${s}\"? rename \"${leaf(d.path)}\" to \"${s}\"`)\n if (d.owner !== undefined) {\n out.push(\n `\"${d.path}\" is an option of feature \"${d.owner}\": pass it to the feature, ` +\n `${d.owner}({ ${d.path}: ... })`,\n )\n }\n out.push(\n `remove \"${leaf(d.path)}\"; accepted ${d.feature === undefined ? '' : `${d.feature} `}` +\n `options here: ${d.known.join(', ') || '(none)'}`,\n )\n return out\n },\n },\n DK_INVALID_OPTION: {\n problem: (d) => `${label(d)} must be ${d.expected}, got ${d.received}`,\n impact: (d) =>\n d.phase === 'init'\n ? 'the table was not created'\n : 'setOptions() was rejected; the previous options are kept',\n fix: (d) => {\n const out: string[] = []\n if (d.hint !== undefined) out.push(d.hint)\n const s = d.suggestions[0]\n if (s !== undefined) out.push(`use '${s}' (the closest accepted value) for ${label(d)}`)\n out.push(`pass ${d.expected} as ${label(d)}, or leave it out for the default`)\n return out\n },\n },\n DK_OPTION_NO_EFFECT: {\n problem: (d) =>\n d.once\n ? `setOptions({ ${d.path} }) has no effect: ${d.reason}`\n : `${label(d)} has no effect: ${d.reason}`,\n impact: (d) =>\n d.once\n ? 'the new value was ignored; the table keeps the value it was created with'\n : 'the option is ignored in this configuration',\n fix: (d) =>\n d.once\n ? [\n `pass ${d.path} to createTable() instead; to change it, create a new table ` +\n '(in React, change the component key)',\n ]\n : [`remove ${label(d)}, or change the configuration so that it applies (${d.reason})`],\n },\n}\n\n/** Codes owned by the options catalog (§3.5, §8.3). */\nexport const optionDiagnostics = [\n // Only the development option validator emits it: no definition in production.\n ...((process.env.NODE_ENV !== \"production\")\n ? [\n defineDiagnostic(\n {\n code: 'DK_UNKNOWN_OPTION',\n level: 'warn',\n where,\n },\n (process.env.NODE_ENV !== \"production\") && optionMessages.DK_UNKNOWN_OPTION,\n ),\n ]\n : []),\n defineDiagnostic(\n {\n code: 'DK_INVALID_OPTION',\n level: 'error',\n config: true,\n where,\n },\n (process.env.NODE_ENV !== \"production\") && optionMessages.DK_INVALID_OPTION,\n ),\n defineDiagnostic(\n {\n code: 'DK_OPTION_NO_EFFECT',\n level: 'warn',\n where,\n },\n (process.env.NODE_ENV !== \"production\") && optionMessages.DK_OPTION_NO_EFFECT,\n ),\n]\n"],"mappings":"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","names":[]}
@@ -30,13 +30,16 @@ __export(slots_exports, {
30
30
  });
31
31
  module.exports = __toCommonJS(slots_exports);
32
32
  var import_catalog = require("../diagnostics/catalog.cjs");
33
+ var import_process_guard = require("../diagnostics/process-guard.cjs");
33
34
  var slots = /* @__PURE__ */ new Map();
34
35
  function defineSlot(slot) {
35
- const prev = slots.get(slot.name);
36
- if (process.env.NODE_ENV !== "production" && prev && prev.returns !== slot.returns) {
37
- throw new Error(
38
- `[DataKable] slot "${slot.name}" is already defined to return ${prev.returns}; a slot contract is never redefined \u2014 pick a new slot name`
39
- );
36
+ if (process.env.NODE_ENV !== "production") {
37
+ const prev = slots.get(slot.name);
38
+ if (prev && prev.returns !== slot.returns) {
39
+ throw new Error(
40
+ `[DataKable] slot "${slot.name}" is already defined to return ${prev.returns}; a slot contract is never redefined \u2014 pick a new slot name`
41
+ );
42
+ }
40
43
  }
41
44
  slots.set(slot.name, slot);
42
45
  return slot;
@@ -70,7 +73,8 @@ var expectedReturn = (slot) => expectedText[slot.returns];
70
73
  var formatSlot = defineSlot({
71
74
  name: "format",
72
75
  returns: "string",
73
- fallback: "those cells were coerced with the default formatter"
76
+ fallback: "cells-coerced"
77
+ // prose key (diagnostics/prose.ts)
74
78
  });
75
79
  var rowList = (rows, count) => {
76
80
  if (!rows || rows.length === 0) return "";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/catalog/slots.ts"],"sourcesContent":["import { defineDiagnostic } from '../diagnostics/catalog'\n\n/** What a callback slot must return: a type, or `'sync'` (anything but a thenable). */\nexport type SlotReturns = 'string' | 'number' | 'boolean' | 'sync'\n\n/** A callback return contract (§3.5): read by the slot checks to report `DK_CALLBACK_BAD_RETURN`. */\nexport interface SlotDefinition {\n /** The slot name, as in `columns[i].<name>` (`format`, `cell`). */\n readonly name: string\n readonly returns: SlotReturns\n /** What DataKable does with a bad return (the diagnostic's impact). */\n readonly fallback?: string\n}\n\nconst slots = new Map<string, SlotDefinition>()\n\n/**\n * Adds a callback return contract to the slot catalog and returns it. Like a diagnostic code, a slot\n * is never redefined with another contract (module re-evaluation with the same one is fine).\n */\nexport function defineSlot<const S extends SlotDefinition>(slot: S): S {\n const prev = slots.get(slot.name)\n // Development check: slots are fixed at build time, a production bundle skips it.\n if ((process.env.NODE_ENV !== \"production\") && prev && prev.returns !== slot.returns) {\n throw new Error(\n `[DataKable] slot \"${slot.name}\" is already defined to return ${prev.returns}; ` +\n 'a slot contract is never redefined — pick a new slot name',\n )\n }\n slots.set(slot.name, slot)\n return slot\n}\n\nexport function getSlot(name: string): SlotDefinition | undefined {\n return slots.get(name)\n}\n\nconst isThenable = (v: unknown) =>\n v != null &&\n (typeof v === 'object' || typeof v === 'function') &&\n typeof (v as { then?: unknown }).then === 'function'\n\n/** Whether `value` meets the slot's contract. */\nexport function matchesSlot(slot: Pick<SlotDefinition, 'returns'>, value: unknown): boolean {\n return slot.returns === 'sync' ? !isThenable(value) : typeof value === slot.returns\n}\n\nconst article = (word: string) => (/^[AEIOUaeiou]/.test(word) ? `an ${word}` : `a ${word}`)\n\n/** The type of a returned value in words (`a number`, `an Array`, `a Promise`); never the value. */\nexport function describeReturn(value: unknown): string {\n if (value === null) return 'null'\n if (value === undefined) return 'undefined'\n const type = typeof value\n if (type !== 'object' && type !== 'function') return article(type)\n if (Array.isArray(value)) return 'an Array'\n if (isThenable(value)) return 'a Promise'\n const proto = Object.getPrototypeOf(value) as { constructor?: { name?: unknown } } | null\n const name = proto?.constructor?.name\n return typeof name === 'string' && name !== '' ? article(name) : article(type)\n}\n\nconst expectedText: Record<SlotReturns, string> = {\n string: 'a string',\n number: 'a number',\n boolean: 'a boolean',\n sync: 'a value (not a Promise)',\n}\n\n/** `expected` of a `DK_CALLBACK_BAD_RETURN` for `slot`. */\nexport const expectedReturn = (slot: Pick<SlotDefinition, 'returns'>) => expectedText[slot.returns]\n\n/** `columns[i].format` (§4.1): its value is coerced with the default formatter when not a string. */\nexport const formatSlot = defineSlot({\n name: 'format',\n returns: 'string',\n fallback: 'those cells were coerced with the default formatter',\n})\n\ndeclare module '../diagnostics/catalog' {\n interface DiagnosticCatalog {\n DK_CALLBACK_BAD_RETURN: {\n /** The callback's option path, e.g. `columns[2].format`. */\n slot: string\n /** Column id, for cell slots. */\n column?: string\n /** The contract, in words (`a string`). */\n expected: string\n /** The type of the first bad return (`a number`); never the value. */\n received: string\n /** How many calls returned a bad value. */\n count: number\n /** A sample of the row indices (first few, in order). */\n rows?: readonly number[]\n /** The fallback that was applied. */\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/**\n * The slot contract check (§3.4 `slotContract`). Dev only: the definition, its text and every call\n * site sit behind `(process.env.NODE_ENV !== \"production\")`, so a production bundle has none of it. It runs inside the existing\n * `column:batch` loop (per batch, never an interceptor per cell).\n */\nexport const slotDiagnostics = (process.env.NODE_ENV !== \"production\")\n ? [\n defineDiagnostic({\n code: 'DK_CALLBACK_BAD_RETURN',\n level: 'warn',\n where: (d) => ({ kind: 'option', path: d.slot }),\n problem: (d) =>\n `${d.slot}${d.column === undefined ? '' : ` (column \"${d.column}\")`} returned ` +\n `${d.received} instead of ${d.expected} for ` +\n `${d.count === 1 ? '1 row' : `${d.count} rows`}${rowList(d.rows, d.count)}`,\n impact: (d) => d.fallback,\n fix: (d) => [\n d.expected === 'a string'\n ? `return a string from ${d.slot}, e.g. (v) => String(v) or (v) => v.toFixed(2)`\n : `return ${d.expected} from ${d.slot}`,\n `if ${d.slot} is async or returns markup, compute the value before the table ` +\n '(or render it with cell)',\n ],\n }),\n ]\n : []\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAAiC;AAcjC,IAAM,QAAQ,oBAAI,IAA4B;AAMvC,SAAS,WAA2C,MAAY;AACrE,QAAM,OAAO,MAAM,IAAI,KAAK,IAAI;AAEhC,MAAK,QAAQ,IAAI,aAAa,gBAAiB,QAAQ,KAAK,YAAY,KAAK,SAAS;AACpF,UAAM,IAAI;AAAA,MACR,qBAAqB,KAAK,IAAI,kCAAkC,KAAK,OAAO;AAAA,IAE9E;AAAA,EACF;AACA,QAAM,IAAI,KAAK,MAAM,IAAI;AACzB,SAAO;AACT;AAEO,SAAS,QAAQ,MAA0C;AAChE,SAAO,MAAM,IAAI,IAAI;AACvB;AAEA,IAAM,aAAa,CAAC,MAClB,KAAK,SACJ,OAAO,MAAM,YAAY,OAAO,MAAM,eACvC,OAAQ,EAAyB,SAAS;AAGrC,SAAS,YAAY,MAAuC,OAAyB;AAC1F,SAAO,KAAK,YAAY,SAAS,CAAC,WAAW,KAAK,IAAI,OAAO,UAAU,KAAK;AAC9E;AAEA,IAAM,UAAU,CAAC,SAAkB,gBAAgB,KAAK,IAAI,IAAI,MAAM,IAAI,KAAK,KAAK,IAAI;AAGjF,SAAS,eAAe,OAAwB;AACrD,MAAI,UAAU,KAAM,QAAO;AAC3B,MAAI,UAAU,OAAW,QAAO;AAChC,QAAM,OAAO,OAAO;AACpB,MAAI,SAAS,YAAY,SAAS,WAAY,QAAO,QAAQ,IAAI;AACjE,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO;AACjC,MAAI,WAAW,KAAK,EAAG,QAAO;AAC9B,QAAM,QAAQ,OAAO,eAAe,KAAK;AACzC,QAAM,OAAO,OAAO,aAAa;AACjC,SAAO,OAAO,SAAS,YAAY,SAAS,KAAK,QAAQ,IAAI,IAAI,QAAQ,IAAI;AAC/E;AAEA,IAAM,eAA4C;AAAA,EAChD,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,MAAM;AACR;AAGO,IAAM,iBAAiB,CAAC,SAA0C,aAAa,KAAK,OAAO;AAG3F,IAAM,aAAa,WAAW;AAAA,EACnC,MAAM;AAAA,EACN,SAAS;AAAA,EACT,UAAU;AACZ,CAAC;AAuBD,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;AAOO,IAAM,kBAAmB,QAAQ,IAAI,aAAa,eACrD;AAAA,MACE,iCAAiB;AAAA,IACf,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO,CAAC,OAAO,EAAE,MAAM,UAAU,MAAM,EAAE,KAAK;AAAA,IAC9C,SAAS,CAAC,MACR,GAAG,EAAE,IAAI,GAAG,EAAE,WAAW,SAAY,KAAK,aAAa,EAAE,MAAM,IAAI,aAChE,EAAE,QAAQ,eAAe,EAAE,QAAQ,QACnC,EAAE,UAAU,IAAI,UAAU,GAAG,EAAE,KAAK,OAAO,GAAG,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC;AAAA,IAC3E,QAAQ,CAAC,MAAM,EAAE;AAAA,IACjB,KAAK,CAAC,MAAM;AAAA,MACV,EAAE,aAAa,aACX,wBAAwB,EAAE,IAAI,mDAC9B,UAAU,EAAE,QAAQ,SAAS,EAAE,IAAI;AAAA,MACvC,MAAM,EAAE,IAAI;AAAA,IAEd;AAAA,EACF,CAAC;AACH,IACA,CAAC;","names":[]}
1
+ {"version":3,"sources":["../../src/catalog/slots.ts"],"sourcesContent":["import { defineDiagnostic } from '../diagnostics/catalog'\nimport '../diagnostics/process-guard'\n\n/** What a callback slot must return: a type, or `'sync'` (anything but a thenable). */\nexport type SlotReturns = 'string' | 'number' | 'boolean' | 'sync'\n\n/** A callback return contract (§3.5): read by the slot checks to report `DK_CALLBACK_BAD_RETURN`. */\nexport interface SlotDefinition {\n /** The slot name, as in `columns[i].<name>` (`format`, `cell`). */\n readonly name: string\n readonly returns: SlotReturns\n /** What DataKable does with a bad return (the diagnostic's impact). */\n readonly fallback?: string\n}\n\nconst slots = new Map<string, SlotDefinition>()\n\n/**\n * Adds a callback return contract to the slot catalog and returns it. Like a diagnostic code, a slot\n * is never redefined with another contract (module re-evaluation with the same one is fine).\n */\nexport function defineSlot<const S extends SlotDefinition>(slot: S): S {\n // Development check: slots are fixed at build time, a production bundle skips it.\n if ((process.env.NODE_ENV !== \"production\")) {\n const prev = slots.get(slot.name)\n if (prev && prev.returns !== slot.returns) {\n throw new Error(\n `[DataKable] slot \"${slot.name}\" is already defined to return ${prev.returns}; ` +\n 'a slot contract is never redefined — pick a new slot name',\n )\n }\n }\n slots.set(slot.name, slot)\n return slot\n}\n\nexport function getSlot(name: string): SlotDefinition | undefined {\n return slots.get(name)\n}\n\nconst isThenable = (v: unknown) =>\n v != null &&\n (typeof v === 'object' || typeof v === 'function') &&\n typeof (v as { then?: unknown }).then === 'function'\n\n/** Whether `value` meets the slot's contract. */\nexport function matchesSlot(slot: Pick<SlotDefinition, 'returns'>, value: unknown): boolean {\n return slot.returns === 'sync' ? !isThenable(value) : typeof value === slot.returns\n}\n\nconst article = (word: string) => (/^[AEIOUaeiou]/.test(word) ? `an ${word}` : `a ${word}`)\n\n/** The type of a returned value in words (`a number`, `an Array`, `a Promise`); never the value. */\nexport function describeReturn(value: unknown): string {\n if (value === null) return 'null'\n if (value === undefined) return 'undefined'\n const type = typeof value\n if (type !== 'object' && type !== 'function') return article(type)\n if (Array.isArray(value)) return 'an Array'\n if (isThenable(value)) return 'a Promise'\n const proto = Object.getPrototypeOf(value) as { constructor?: { name?: unknown } } | null\n const name = proto?.constructor?.name\n return typeof name === 'string' && name !== '' ? article(name) : article(type)\n}\n\nconst expectedText: Record<SlotReturns, string> = {\n string: 'a string',\n number: 'a number',\n boolean: 'a boolean',\n sync: 'a value (not a Promise)',\n}\n\n/** `expected` of a `DK_CALLBACK_BAD_RETURN` for `slot`. */\nexport const expectedReturn = (slot: Pick<SlotDefinition, 'returns'>) => expectedText[slot.returns]\n\n/** `columns[i].format` (§4.1): its value is coerced with the default formatter when not a string. */\nexport const formatSlot = defineSlot({\n name: 'format',\n returns: 'string',\n fallback: 'cells-coerced', // prose key (diagnostics/prose.ts)\n})\n\ndeclare module '../diagnostics/catalog' {\n interface DiagnosticCatalog {\n DK_CALLBACK_BAD_RETURN: {\n /** The callback's option path, e.g. `columns[2].format`. */\n slot: string\n /** Column id, for cell slots. */\n column?: string\n /** The contract, in words (`a string`). */\n expected: string\n /** The type of the first bad return (`a number`); never the value. */\n received: string\n /** How many calls returned a bad value. */\n count: number\n /** A sample of the row indices (first few, in order). */\n rows?: readonly number[]\n /** The fallback that was applied. */\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/**\n * The slot contract check (§3.4 `slotContract`). Dev only: the definition, its text and every call\n * site sit behind `(process.env.NODE_ENV !== \"production\")`, so a production bundle has none of it. It runs inside the existing\n * `column:batch` loop (per batch, never an interceptor per cell).\n */\nexport const slotDiagnostics = (process.env.NODE_ENV !== \"production\")\n ? [\n defineDiagnostic({\n code: 'DK_CALLBACK_BAD_RETURN',\n level: 'warn',\n where: (d) => ({ kind: 'option', path: d.slot }),\n problem: (d) =>\n `${d.slot}${d.column === undefined ? '' : ` (column \"${d.column}\")`} returned ` +\n `${d.received} instead of ${d.expected} for ` +\n `${d.count === 1 ? '1 row' : `${d.count} rows`}${rowList(d.rows, d.count)}`,\n impact: (d) => d.fallback,\n fix: (d) => [\n d.expected === 'a string'\n ? `return a string from ${d.slot}, e.g. (v) => String(v) or (v) => v.toFixed(2)`\n : `return ${d.expected} from ${d.slot}`,\n `if ${d.slot} is async or returns markup, compute the value before the table ` +\n '(or render it with cell)',\n ],\n }),\n ]\n : []\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAAiC;AACjC,2BAAO;AAcP,IAAM,QAAQ,oBAAI,IAA4B;AAMvC,SAAS,WAA2C,MAAY;AAErE,MAAK,QAAQ,IAAI,aAAa,cAAe;AAC3C,UAAM,OAAO,MAAM,IAAI,KAAK,IAAI;AAChC,QAAI,QAAQ,KAAK,YAAY,KAAK,SAAS;AACzC,YAAM,IAAI;AAAA,QACR,qBAAqB,KAAK,IAAI,kCAAkC,KAAK,OAAO;AAAA,MAE9E;AAAA,IACF;AAAA,EACF;AACA,QAAM,IAAI,KAAK,MAAM,IAAI;AACzB,SAAO;AACT;AAEO,SAAS,QAAQ,MAA0C;AAChE,SAAO,MAAM,IAAI,IAAI;AACvB;AAEA,IAAM,aAAa,CAAC,MAClB,KAAK,SACJ,OAAO,MAAM,YAAY,OAAO,MAAM,eACvC,OAAQ,EAAyB,SAAS;AAGrC,SAAS,YAAY,MAAuC,OAAyB;AAC1F,SAAO,KAAK,YAAY,SAAS,CAAC,WAAW,KAAK,IAAI,OAAO,UAAU,KAAK;AAC9E;AAEA,IAAM,UAAU,CAAC,SAAkB,gBAAgB,KAAK,IAAI,IAAI,MAAM,IAAI,KAAK,KAAK,IAAI;AAGjF,SAAS,eAAe,OAAwB;AACrD,MAAI,UAAU,KAAM,QAAO;AAC3B,MAAI,UAAU,OAAW,QAAO;AAChC,QAAM,OAAO,OAAO;AACpB,MAAI,SAAS,YAAY,SAAS,WAAY,QAAO,QAAQ,IAAI;AACjE,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO;AACjC,MAAI,WAAW,KAAK,EAAG,QAAO;AAC9B,QAAM,QAAQ,OAAO,eAAe,KAAK;AACzC,QAAM,OAAO,OAAO,aAAa;AACjC,SAAO,OAAO,SAAS,YAAY,SAAS,KAAK,QAAQ,IAAI,IAAI,QAAQ,IAAI;AAC/E;AAEA,IAAM,eAA4C;AAAA,EAChD,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,MAAM;AACR;AAGO,IAAM,iBAAiB,CAAC,SAA0C,aAAa,KAAK,OAAO;AAG3F,IAAM,aAAa,WAAW;AAAA,EACnC,MAAM;AAAA,EACN,SAAS;AAAA,EACT,UAAU;AAAA;AACZ,CAAC;AAuBD,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;AAOO,IAAM,kBAAmB,QAAQ,IAAI,aAAa,eACrD;AAAA,MACE,iCAAiB;AAAA,IACf,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO,CAAC,OAAO,EAAE,MAAM,UAAU,MAAM,EAAE,KAAK;AAAA,IAC9C,SAAS,CAAC,MACR,GAAG,EAAE,IAAI,GAAG,EAAE,WAAW,SAAY,KAAK,aAAa,EAAE,MAAM,IAAI,aAChE,EAAE,QAAQ,eAAe,EAAE,QAAQ,QACnC,EAAE,UAAU,IAAI,UAAU,GAAG,EAAE,KAAK,OAAO,GAAG,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC;AAAA,IAC3E,QAAQ,CAAC,MAAM,EAAE;AAAA,IACjB,KAAK,CAAC,MAAM;AAAA,MACV,EAAE,aAAa,aACX,wBAAwB,EAAE,IAAI,mDAC9B,UAAU,EAAE,QAAQ,SAAS,EAAE,IAAI;AAAA,MACvC,MAAM,EAAE,IAAI;AAAA,IAEd;AAAA,EACF,CAAC;AACH,IACA,CAAC;","names":[]}
@@ -1,12 +1,15 @@
1
1
  // src/catalog/slots.ts
2
2
  import { defineDiagnostic } from "../diagnostics/catalog.js";
3
+ import "../diagnostics/process-guard.js";
3
4
  var slots = /* @__PURE__ */ new Map();
4
5
  function defineSlot(slot) {
5
- const prev = slots.get(slot.name);
6
- if (process.env.NODE_ENV !== "production" && prev && prev.returns !== slot.returns) {
7
- throw new Error(
8
- `[DataKable] slot "${slot.name}" is already defined to return ${prev.returns}; a slot contract is never redefined \u2014 pick a new slot name`
9
- );
6
+ if (process.env.NODE_ENV !== "production") {
7
+ const prev = slots.get(slot.name);
8
+ if (prev && prev.returns !== slot.returns) {
9
+ throw new Error(
10
+ `[DataKable] slot "${slot.name}" is already defined to return ${prev.returns}; a slot contract is never redefined \u2014 pick a new slot name`
11
+ );
12
+ }
10
13
  }
11
14
  slots.set(slot.name, slot);
12
15
  return slot;
@@ -40,7 +43,8 @@ var expectedReturn = (slot) => expectedText[slot.returns];
40
43
  var formatSlot = defineSlot({
41
44
  name: "format",
42
45
  returns: "string",
43
- fallback: "those cells were coerced with the default formatter"
46
+ fallback: "cells-coerced"
47
+ // prose key (diagnostics/prose.ts)
44
48
  });
45
49
  var rowList = (rows, count) => {
46
50
  if (!rows || rows.length === 0) return "";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/catalog/slots.ts"],"sourcesContent":["import { defineDiagnostic } from '../diagnostics/catalog'\n\n/** What a callback slot must return: a type, or `'sync'` (anything but a thenable). */\nexport type SlotReturns = 'string' | 'number' | 'boolean' | 'sync'\n\n/** A callback return contract (§3.5): read by the slot checks to report `DK_CALLBACK_BAD_RETURN`. */\nexport interface SlotDefinition {\n /** The slot name, as in `columns[i].<name>` (`format`, `cell`). */\n readonly name: string\n readonly returns: SlotReturns\n /** What DataKable does with a bad return (the diagnostic's impact). */\n readonly fallback?: string\n}\n\nconst slots = new Map<string, SlotDefinition>()\n\n/**\n * Adds a callback return contract to the slot catalog and returns it. Like a diagnostic code, a slot\n * is never redefined with another contract (module re-evaluation with the same one is fine).\n */\nexport function defineSlot<const S extends SlotDefinition>(slot: S): S {\n const prev = slots.get(slot.name)\n // Development check: slots are fixed at build time, a production bundle skips it.\n if ((process.env.NODE_ENV !== \"production\") && prev && prev.returns !== slot.returns) {\n throw new Error(\n `[DataKable] slot \"${slot.name}\" is already defined to return ${prev.returns}; ` +\n 'a slot contract is never redefined — pick a new slot name',\n )\n }\n slots.set(slot.name, slot)\n return slot\n}\n\nexport function getSlot(name: string): SlotDefinition | undefined {\n return slots.get(name)\n}\n\nconst isThenable = (v: unknown) =>\n v != null &&\n (typeof v === 'object' || typeof v === 'function') &&\n typeof (v as { then?: unknown }).then === 'function'\n\n/** Whether `value` meets the slot's contract. */\nexport function matchesSlot(slot: Pick<SlotDefinition, 'returns'>, value: unknown): boolean {\n return slot.returns === 'sync' ? !isThenable(value) : typeof value === slot.returns\n}\n\nconst article = (word: string) => (/^[AEIOUaeiou]/.test(word) ? `an ${word}` : `a ${word}`)\n\n/** The type of a returned value in words (`a number`, `an Array`, `a Promise`); never the value. */\nexport function describeReturn(value: unknown): string {\n if (value === null) return 'null'\n if (value === undefined) return 'undefined'\n const type = typeof value\n if (type !== 'object' && type !== 'function') return article(type)\n if (Array.isArray(value)) return 'an Array'\n if (isThenable(value)) return 'a Promise'\n const proto = Object.getPrototypeOf(value) as { constructor?: { name?: unknown } } | null\n const name = proto?.constructor?.name\n return typeof name === 'string' && name !== '' ? article(name) : article(type)\n}\n\nconst expectedText: Record<SlotReturns, string> = {\n string: 'a string',\n number: 'a number',\n boolean: 'a boolean',\n sync: 'a value (not a Promise)',\n}\n\n/** `expected` of a `DK_CALLBACK_BAD_RETURN` for `slot`. */\nexport const expectedReturn = (slot: Pick<SlotDefinition, 'returns'>) => expectedText[slot.returns]\n\n/** `columns[i].format` (§4.1): its value is coerced with the default formatter when not a string. */\nexport const formatSlot = defineSlot({\n name: 'format',\n returns: 'string',\n fallback: 'those cells were coerced with the default formatter',\n})\n\ndeclare module '../diagnostics/catalog' {\n interface DiagnosticCatalog {\n DK_CALLBACK_BAD_RETURN: {\n /** The callback's option path, e.g. `columns[2].format`. */\n slot: string\n /** Column id, for cell slots. */\n column?: string\n /** The contract, in words (`a string`). */\n expected: string\n /** The type of the first bad return (`a number`); never the value. */\n received: string\n /** How many calls returned a bad value. */\n count: number\n /** A sample of the row indices (first few, in order). */\n rows?: readonly number[]\n /** The fallback that was applied. */\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/**\n * The slot contract check (§3.4 `slotContract`). Dev only: the definition, its text and every call\n * site sit behind `(process.env.NODE_ENV !== \"production\")`, so a production bundle has none of it. It runs inside the existing\n * `column:batch` loop (per batch, never an interceptor per cell).\n */\nexport const slotDiagnostics = (process.env.NODE_ENV !== \"production\")\n ? [\n defineDiagnostic({\n code: 'DK_CALLBACK_BAD_RETURN',\n level: 'warn',\n where: (d) => ({ kind: 'option', path: d.slot }),\n problem: (d) =>\n `${d.slot}${d.column === undefined ? '' : ` (column \"${d.column}\")`} returned ` +\n `${d.received} instead of ${d.expected} for ` +\n `${d.count === 1 ? '1 row' : `${d.count} rows`}${rowList(d.rows, d.count)}`,\n impact: (d) => d.fallback,\n fix: (d) => [\n d.expected === 'a string'\n ? `return a string from ${d.slot}, e.g. (v) => String(v) or (v) => v.toFixed(2)`\n : `return ${d.expected} from ${d.slot}`,\n `if ${d.slot} is async or returns markup, compute the value before the table ` +\n '(or render it with cell)',\n ],\n }),\n ]\n : []\n"],"mappings":";AAAA,SAAS,wBAAwB;AAcjC,IAAM,QAAQ,oBAAI,IAA4B;AAMvC,SAAS,WAA2C,MAAY;AACrE,QAAM,OAAO,MAAM,IAAI,KAAK,IAAI;AAEhC,MAAK,QAAQ,IAAI,aAAa,gBAAiB,QAAQ,KAAK,YAAY,KAAK,SAAS;AACpF,UAAM,IAAI;AAAA,MACR,qBAAqB,KAAK,IAAI,kCAAkC,KAAK,OAAO;AAAA,IAE9E;AAAA,EACF;AACA,QAAM,IAAI,KAAK,MAAM,IAAI;AACzB,SAAO;AACT;AAEO,SAAS,QAAQ,MAA0C;AAChE,SAAO,MAAM,IAAI,IAAI;AACvB;AAEA,IAAM,aAAa,CAAC,MAClB,KAAK,SACJ,OAAO,MAAM,YAAY,OAAO,MAAM,eACvC,OAAQ,EAAyB,SAAS;AAGrC,SAAS,YAAY,MAAuC,OAAyB;AAC1F,SAAO,KAAK,YAAY,SAAS,CAAC,WAAW,KAAK,IAAI,OAAO,UAAU,KAAK;AAC9E;AAEA,IAAM,UAAU,CAAC,SAAkB,gBAAgB,KAAK,IAAI,IAAI,MAAM,IAAI,KAAK,KAAK,IAAI;AAGjF,SAAS,eAAe,OAAwB;AACrD,MAAI,UAAU,KAAM,QAAO;AAC3B,MAAI,UAAU,OAAW,QAAO;AAChC,QAAM,OAAO,OAAO;AACpB,MAAI,SAAS,YAAY,SAAS,WAAY,QAAO,QAAQ,IAAI;AACjE,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO;AACjC,MAAI,WAAW,KAAK,EAAG,QAAO;AAC9B,QAAM,QAAQ,OAAO,eAAe,KAAK;AACzC,QAAM,OAAO,OAAO,aAAa;AACjC,SAAO,OAAO,SAAS,YAAY,SAAS,KAAK,QAAQ,IAAI,IAAI,QAAQ,IAAI;AAC/E;AAEA,IAAM,eAA4C;AAAA,EAChD,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,MAAM;AACR;AAGO,IAAM,iBAAiB,CAAC,SAA0C,aAAa,KAAK,OAAO;AAG3F,IAAM,aAAa,WAAW;AAAA,EACnC,MAAM;AAAA,EACN,SAAS;AAAA,EACT,UAAU;AACZ,CAAC;AAuBD,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;AAOO,IAAM,kBAAmB,QAAQ,IAAI,aAAa,eACrD;AAAA,EACE,iBAAiB;AAAA,IACf,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO,CAAC,OAAO,EAAE,MAAM,UAAU,MAAM,EAAE,KAAK;AAAA,IAC9C,SAAS,CAAC,MACR,GAAG,EAAE,IAAI,GAAG,EAAE,WAAW,SAAY,KAAK,aAAa,EAAE,MAAM,IAAI,aAChE,EAAE,QAAQ,eAAe,EAAE,QAAQ,QACnC,EAAE,UAAU,IAAI,UAAU,GAAG,EAAE,KAAK,OAAO,GAAG,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC;AAAA,IAC3E,QAAQ,CAAC,MAAM,EAAE;AAAA,IACjB,KAAK,CAAC,MAAM;AAAA,MACV,EAAE,aAAa,aACX,wBAAwB,EAAE,IAAI,mDAC9B,UAAU,EAAE,QAAQ,SAAS,EAAE,IAAI;AAAA,MACvC,MAAM,EAAE,IAAI;AAAA,IAEd;AAAA,EACF,CAAC;AACH,IACA,CAAC;","names":[]}
1
+ {"version":3,"sources":["../../src/catalog/slots.ts"],"sourcesContent":["import { defineDiagnostic } from '../diagnostics/catalog'\nimport '../diagnostics/process-guard'\n\n/** What a callback slot must return: a type, or `'sync'` (anything but a thenable). */\nexport type SlotReturns = 'string' | 'number' | 'boolean' | 'sync'\n\n/** A callback return contract (§3.5): read by the slot checks to report `DK_CALLBACK_BAD_RETURN`. */\nexport interface SlotDefinition {\n /** The slot name, as in `columns[i].<name>` (`format`, `cell`). */\n readonly name: string\n readonly returns: SlotReturns\n /** What DataKable does with a bad return (the diagnostic's impact). */\n readonly fallback?: string\n}\n\nconst slots = new Map<string, SlotDefinition>()\n\n/**\n * Adds a callback return contract to the slot catalog and returns it. Like a diagnostic code, a slot\n * is never redefined with another contract (module re-evaluation with the same one is fine).\n */\nexport function defineSlot<const S extends SlotDefinition>(slot: S): S {\n // Development check: slots are fixed at build time, a production bundle skips it.\n if ((process.env.NODE_ENV !== \"production\")) {\n const prev = slots.get(slot.name)\n if (prev && prev.returns !== slot.returns) {\n throw new Error(\n `[DataKable] slot \"${slot.name}\" is already defined to return ${prev.returns}; ` +\n 'a slot contract is never redefined — pick a new slot name',\n )\n }\n }\n slots.set(slot.name, slot)\n return slot\n}\n\nexport function getSlot(name: string): SlotDefinition | undefined {\n return slots.get(name)\n}\n\nconst isThenable = (v: unknown) =>\n v != null &&\n (typeof v === 'object' || typeof v === 'function') &&\n typeof (v as { then?: unknown }).then === 'function'\n\n/** Whether `value` meets the slot's contract. */\nexport function matchesSlot(slot: Pick<SlotDefinition, 'returns'>, value: unknown): boolean {\n return slot.returns === 'sync' ? !isThenable(value) : typeof value === slot.returns\n}\n\nconst article = (word: string) => (/^[AEIOUaeiou]/.test(word) ? `an ${word}` : `a ${word}`)\n\n/** The type of a returned value in words (`a number`, `an Array`, `a Promise`); never the value. */\nexport function describeReturn(value: unknown): string {\n if (value === null) return 'null'\n if (value === undefined) return 'undefined'\n const type = typeof value\n if (type !== 'object' && type !== 'function') return article(type)\n if (Array.isArray(value)) return 'an Array'\n if (isThenable(value)) return 'a Promise'\n const proto = Object.getPrototypeOf(value) as { constructor?: { name?: unknown } } | null\n const name = proto?.constructor?.name\n return typeof name === 'string' && name !== '' ? article(name) : article(type)\n}\n\nconst expectedText: Record<SlotReturns, string> = {\n string: 'a string',\n number: 'a number',\n boolean: 'a boolean',\n sync: 'a value (not a Promise)',\n}\n\n/** `expected` of a `DK_CALLBACK_BAD_RETURN` for `slot`. */\nexport const expectedReturn = (slot: Pick<SlotDefinition, 'returns'>) => expectedText[slot.returns]\n\n/** `columns[i].format` (§4.1): its value is coerced with the default formatter when not a string. */\nexport const formatSlot = defineSlot({\n name: 'format',\n returns: 'string',\n fallback: 'cells-coerced', // prose key (diagnostics/prose.ts)\n})\n\ndeclare module '../diagnostics/catalog' {\n interface DiagnosticCatalog {\n DK_CALLBACK_BAD_RETURN: {\n /** The callback's option path, e.g. `columns[2].format`. */\n slot: string\n /** Column id, for cell slots. */\n column?: string\n /** The contract, in words (`a string`). */\n expected: string\n /** The type of the first bad return (`a number`); never the value. */\n received: string\n /** How many calls returned a bad value. */\n count: number\n /** A sample of the row indices (first few, in order). */\n rows?: readonly number[]\n /** The fallback that was applied. */\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/**\n * The slot contract check (§3.4 `slotContract`). Dev only: the definition, its text and every call\n * site sit behind `(process.env.NODE_ENV !== \"production\")`, so a production bundle has none of it. It runs inside the existing\n * `column:batch` loop (per batch, never an interceptor per cell).\n */\nexport const slotDiagnostics = (process.env.NODE_ENV !== \"production\")\n ? [\n defineDiagnostic({\n code: 'DK_CALLBACK_BAD_RETURN',\n level: 'warn',\n where: (d) => ({ kind: 'option', path: d.slot }),\n problem: (d) =>\n `${d.slot}${d.column === undefined ? '' : ` (column \"${d.column}\")`} returned ` +\n `${d.received} instead of ${d.expected} for ` +\n `${d.count === 1 ? '1 row' : `${d.count} rows`}${rowList(d.rows, d.count)}`,\n impact: (d) => d.fallback,\n fix: (d) => [\n d.expected === 'a string'\n ? `return a string from ${d.slot}, e.g. (v) => String(v) or (v) => v.toFixed(2)`\n : `return ${d.expected} from ${d.slot}`,\n `if ${d.slot} is async or returns markup, compute the value before the table ` +\n '(or render it with cell)',\n ],\n }),\n ]\n : []\n"],"mappings":";AAAA,SAAS,wBAAwB;AACjC,OAAO;AAcP,IAAM,QAAQ,oBAAI,IAA4B;AAMvC,SAAS,WAA2C,MAAY;AAErE,MAAK,QAAQ,IAAI,aAAa,cAAe;AAC3C,UAAM,OAAO,MAAM,IAAI,KAAK,IAAI;AAChC,QAAI,QAAQ,KAAK,YAAY,KAAK,SAAS;AACzC,YAAM,IAAI;AAAA,QACR,qBAAqB,KAAK,IAAI,kCAAkC,KAAK,OAAO;AAAA,MAE9E;AAAA,IACF;AAAA,EACF;AACA,QAAM,IAAI,KAAK,MAAM,IAAI;AACzB,SAAO;AACT;AAEO,SAAS,QAAQ,MAA0C;AAChE,SAAO,MAAM,IAAI,IAAI;AACvB;AAEA,IAAM,aAAa,CAAC,MAClB,KAAK,SACJ,OAAO,MAAM,YAAY,OAAO,MAAM,eACvC,OAAQ,EAAyB,SAAS;AAGrC,SAAS,YAAY,MAAuC,OAAyB;AAC1F,SAAO,KAAK,YAAY,SAAS,CAAC,WAAW,KAAK,IAAI,OAAO,UAAU,KAAK;AAC9E;AAEA,IAAM,UAAU,CAAC,SAAkB,gBAAgB,KAAK,IAAI,IAAI,MAAM,IAAI,KAAK,KAAK,IAAI;AAGjF,SAAS,eAAe,OAAwB;AACrD,MAAI,UAAU,KAAM,QAAO;AAC3B,MAAI,UAAU,OAAW,QAAO;AAChC,QAAM,OAAO,OAAO;AACpB,MAAI,SAAS,YAAY,SAAS,WAAY,QAAO,QAAQ,IAAI;AACjE,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO;AACjC,MAAI,WAAW,KAAK,EAAG,QAAO;AAC9B,QAAM,QAAQ,OAAO,eAAe,KAAK;AACzC,QAAM,OAAO,OAAO,aAAa;AACjC,SAAO,OAAO,SAAS,YAAY,SAAS,KAAK,QAAQ,IAAI,IAAI,QAAQ,IAAI;AAC/E;AAEA,IAAM,eAA4C;AAAA,EAChD,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,MAAM;AACR;AAGO,IAAM,iBAAiB,CAAC,SAA0C,aAAa,KAAK,OAAO;AAG3F,IAAM,aAAa,WAAW;AAAA,EACnC,MAAM;AAAA,EACN,SAAS;AAAA,EACT,UAAU;AAAA;AACZ,CAAC;AAuBD,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;AAOO,IAAM,kBAAmB,QAAQ,IAAI,aAAa,eACrD;AAAA,EACE,iBAAiB;AAAA,IACf,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO,CAAC,OAAO,EAAE,MAAM,UAAU,MAAM,EAAE,KAAK;AAAA,IAC9C,SAAS,CAAC,MACR,GAAG,EAAE,IAAI,GAAG,EAAE,WAAW,SAAY,KAAK,aAAa,EAAE,MAAM,IAAI,aAChE,EAAE,QAAQ,eAAe,EAAE,QAAQ,QACnC,EAAE,UAAU,IAAI,UAAU,GAAG,EAAE,KAAK,OAAO,GAAG,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC;AAAA,IAC3E,QAAQ,CAAC,MAAM,EAAE;AAAA,IACjB,KAAK,CAAC,MAAM;AAAA,MACV,EAAE,aAAa,aACX,wBAAwB,EAAE,IAAI,mDAC9B,UAAU,EAAE,QAAQ,SAAS,EAAE,IAAI;AAAA,MACvC,MAAM,EAAE,IAAI;AAAA,IAEd;AAAA,EACF,CAAC;AACH,IACA,CAAC;","names":[]}
@@ -86,6 +86,11 @@ interface EmitOptions {
86
86
  run?: number;
87
87
  trigger?: Trigger;
88
88
  phase?: Phase;
89
+ /**
90
+ * Not printed by the default console sink (another table printed it in this process, #38). Still
91
+ * stored and delivered to `onDiagnostic`.
92
+ */
93
+ quiet?: boolean;
89
94
  }
90
95
  /** Emits a catalog diagnostic; `details` is typed by `code` (see `DiagnosticCatalog`). */
91
96
  type Emit = <C extends DiagnosticCode>(code: C, details: DiagnosticDetails<C>, options?: EmitOptions) => void;
@@ -114,7 +119,7 @@ interface RedactionOptions {
114
119
  redact?: RedactFn;
115
120
  /** Ids / keys of `sensitive: true` columns: never logged at any level. */
116
121
  sensitiveColumns?: () => Iterable<string>;
117
- /** The `rowKey` column is sensitive: row keys are hashed at every level. */
122
+ /** The `rowKey` path is, is inside or contains a sensitive column: keys hashed at every level. */
118
123
  rowKeySensitive?: () => boolean;
119
124
  }
120
125
  /**
@@ -148,7 +153,9 @@ declare function hashRowKey(key: unknown): string;
148
153
  declare function describeValue(v: unknown): string;
149
154
  /**
150
155
  * A schema issue as `{ path, message }`. Validators embed received values in their messages, so
151
- * under `'safe'` / `'keys'` (and for sensitive columns) the message is DataKable's own text.
156
+ * under `'safe'` / `'keys'` the message is DataKable's own text. So it is at every level when the
157
+ * table has a sensitive column: any message (a root-level refinement, another field's) may embed
158
+ * its value (#46).
152
159
  */
153
160
  declare function scrubSchemaIssue(issue: unknown, r: Redactor, fieldPath?: string): {
154
161
  path: string;
@@ -307,7 +314,7 @@ declare function describeReturn(value: unknown): string;
307
314
  declare const formatSlot: {
308
315
  readonly name: "format";
309
316
  readonly returns: "string";
310
- readonly fallback: "those cells were coerced with the default formatter";
317
+ readonly fallback: "cells-coerced";
311
318
  };
312
319
  declare module '@datakable/core' {
313
320
  interface DiagnosticCatalog {
@@ -353,19 +360,27 @@ interface RowSource {
353
360
  /** The issues of a flagged row that touch column `id` (`matchCellIssues`). */
354
361
  cellIssues(issues: readonly RowIssue[], id: string): readonly RowIssue[];
355
362
  }
363
+ /**
364
+ * The key a {@link Row} keeps its {@link RowSource} under. A symbol, not a `#private` field: a
365
+ * proxy-based store (Vue `ref` / `reactive`, Pinia, MobX) calls the getters and methods with
366
+ * `this` = its proxy, which has no private slot, so `#source` threw there (#11). A symbol key
367
+ * reads through any proxy, stays out of `Object.keys` and JSON, and is not exported.
368
+ */
369
+ declare const SOURCE: unique symbol;
356
370
  /**
357
371
  * One visible row (§6.6). Created only for the rows `getRowModel()` returns, never for the whole
358
372
  * data set (§9.1), and only when read ({@link lazyRows}); the methods live on the prototype, so a
359
373
  * row costs its four fields.
360
374
  */
361
375
  declare class Row<T = unknown> {
362
- #private;
363
376
  /** The row's `rowKey` value (the row index without `rowKey`). */
364
377
  readonly key: RowKey;
365
378
  /** Position in the ingested data. */
366
379
  readonly index: number;
367
380
  /** The row object as passed in `data`. */
368
381
  readonly original: T;
382
+ /** @internal */
383
+ private readonly [SOURCE];
369
384
  /** @internal Rows are created by the pipeline. */
370
385
  constructor(source: RowSource, index: number, key: RowKey, original: T);
371
386
  /** `false` for a row flagged by schema validation (`invalidRows: 'flag'`). */
@@ -405,7 +420,7 @@ interface BuildInput {
405
420
  phase?: Phase;
406
421
  mode?: Record<string, 'client' | 'server'>;
407
422
  state?: DiagnosticStateSummary;
408
- /** Timestamp for `occurrences`. Default `Date.now()`. */
423
+ /** Timestamp for `occurrences` (epoch ms). Default `wallClock()`. */
409
424
  now?: number;
410
425
  cause?: unknown;
411
426
  causedBy?: string;
@@ -680,8 +695,12 @@ declare const featureDiagnostics: (DiagnosticDefinition<"DK_FEATURE_DUPLICATE">
680
695
  declare module '@datakable/core' {
681
696
  interface DiagnosticCatalog {
682
697
  DK_INVALID_PAGINATION: {
683
- /** The API method that received the value, or `'state'` for a slice written to the store. */
684
- source: 'setPageIndex' | 'setPageSize' | 'state';
698
+ /**
699
+ * The API method that received the value, `'state'` for a slice written to the store, or
700
+ * `'option'` for `pagination({ pageSize })` (checked here in production, where the option
701
+ * validator is off).
702
+ */
703
+ source: 'setPageIndex' | 'setPageSize' | 'state' | 'option';
685
704
  field: 'pageIndex' | 'pageSize';
686
705
  /** The value's type only (`describeValue`), plus the number itself when it is one. */
687
706
  received: string;
@@ -709,6 +728,12 @@ declare module '@datakable/core' {
709
728
  /** Whether a previous `searchFn` result is shown (`false`: none applied yet). */
710
729
  hadResults: boolean;
711
730
  };
731
+ DK_SEARCH_COLUMN_SKIPPED: {
732
+ /** Column id (`key` or `id`). */
733
+ column: string;
734
+ /** Position in the table's columns (`options.columns`, else the derived columns). */
735
+ index: number;
736
+ };
712
737
  }
713
738
  }
714
739
  /** Codes owned by the `search` feature (spec §6.3, §8.3). */
@@ -944,6 +969,14 @@ declare module '@datakable/core' {
944
969
  rows: number;
945
970
  /** The budget, in milliseconds (§9.3: the longest task). */
946
971
  budget: number;
972
+ /** One slice of the step's time-sliced work, run between pipeline runs (#61). */
973
+ sliced?: boolean;
974
+ /** The column slot at least half of the time went to, e.g. `columns[0].format` (#62). */
975
+ slot?: string;
976
+ /** Its column id. */
977
+ column?: string;
978
+ /** Its share of {@link ms}, 0.5 to 1. */
979
+ share?: number;
947
980
  };
948
981
  }
949
982
  }
@@ -1043,6 +1076,11 @@ declare module '@datakable/core' {
1043
1076
  /** Versions of every registered core copy, in registration order (this copy last). */
1044
1077
  versions: string[];
1045
1078
  };
1079
+ DK_DUPLICATE_CORE_SAME_VERSION: {
1080
+ version: string;
1081
+ /** Copies of core registered so far (this copy included), all of `version`. */
1082
+ copies: number;
1083
+ };
1046
1084
  DK_VERSION_MISMATCH: {
1047
1085
  /** The fixed-group package whose version differs, e.g. `@datakable/react`. */
1048
1086
  package: string;
@@ -1071,7 +1109,7 @@ declare module '@datakable/core' {
1071
1109
  }
1072
1110
  }
1073
1111
  /** Codes owned by versioning (§8.5). */
1074
- declare const versioningDiagnostics: (DiagnosticDefinition<"DK_DEPRECATED"> | DiagnosticDefinition<"DK_DUPLICATE_CORE"> | DiagnosticDefinition<"DK_VERSION_MISMATCH"> | DiagnosticDefinition<"DK_DEP_INCOMPATIBLE"> | DiagnosticDefinition<"DK_FEATURE_INCOMPATIBLE">)[];
1112
+ declare const versioningDiagnostics: (DiagnosticDefinition<"DK_DEPRECATED"> | DiagnosticDefinition<"DK_DUPLICATE_CORE"> | DiagnosticDefinition<"DK_DUPLICATE_CORE_SAME_VERSION"> | DiagnosticDefinition<"DK_VERSION_MISMATCH"> | DiagnosticDefinition<"DK_DEP_INCOMPATIBLE"> | DiagnosticDefinition<"DK_FEATURE_INCOMPATIBLE">)[];
1075
1113
 
1076
1114
  declare module '@datakable/core' {
1077
1115
  interface DiagnosticCatalog {
@@ -86,6 +86,11 @@ interface EmitOptions {
86
86
  run?: number;
87
87
  trigger?: Trigger;
88
88
  phase?: Phase;
89
+ /**
90
+ * Not printed by the default console sink (another table printed it in this process, #38). Still
91
+ * stored and delivered to `onDiagnostic`.
92
+ */
93
+ quiet?: boolean;
89
94
  }
90
95
  /** Emits a catalog diagnostic; `details` is typed by `code` (see `DiagnosticCatalog`). */
91
96
  type Emit = <C extends DiagnosticCode>(code: C, details: DiagnosticDetails<C>, options?: EmitOptions) => void;
@@ -114,7 +119,7 @@ interface RedactionOptions {
114
119
  redact?: RedactFn;
115
120
  /** Ids / keys of `sensitive: true` columns: never logged at any level. */
116
121
  sensitiveColumns?: () => Iterable<string>;
117
- /** The `rowKey` column is sensitive: row keys are hashed at every level. */
122
+ /** The `rowKey` path is, is inside or contains a sensitive column: keys hashed at every level. */
118
123
  rowKeySensitive?: () => boolean;
119
124
  }
120
125
  /**
@@ -148,7 +153,9 @@ declare function hashRowKey(key: unknown): string;
148
153
  declare function describeValue(v: unknown): string;
149
154
  /**
150
155
  * A schema issue as `{ path, message }`. Validators embed received values in their messages, so
151
- * under `'safe'` / `'keys'` (and for sensitive columns) the message is DataKable's own text.
156
+ * under `'safe'` / `'keys'` the message is DataKable's own text. So it is at every level when the
157
+ * table has a sensitive column: any message (a root-level refinement, another field's) may embed
158
+ * its value (#46).
152
159
  */
153
160
  declare function scrubSchemaIssue(issue: unknown, r: Redactor, fieldPath?: string): {
154
161
  path: string;
@@ -307,7 +314,7 @@ declare function describeReturn(value: unknown): string;
307
314
  declare const formatSlot: {
308
315
  readonly name: "format";
309
316
  readonly returns: "string";
310
- readonly fallback: "those cells were coerced with the default formatter";
317
+ readonly fallback: "cells-coerced";
311
318
  };
312
319
  declare module '@datakable/core' {
313
320
  interface DiagnosticCatalog {
@@ -353,19 +360,27 @@ interface RowSource {
353
360
  /** The issues of a flagged row that touch column `id` (`matchCellIssues`). */
354
361
  cellIssues(issues: readonly RowIssue[], id: string): readonly RowIssue[];
355
362
  }
363
+ /**
364
+ * The key a {@link Row} keeps its {@link RowSource} under. A symbol, not a `#private` field: a
365
+ * proxy-based store (Vue `ref` / `reactive`, Pinia, MobX) calls the getters and methods with
366
+ * `this` = its proxy, which has no private slot, so `#source` threw there (#11). A symbol key
367
+ * reads through any proxy, stays out of `Object.keys` and JSON, and is not exported.
368
+ */
369
+ declare const SOURCE: unique symbol;
356
370
  /**
357
371
  * One visible row (§6.6). Created only for the rows `getRowModel()` returns, never for the whole
358
372
  * data set (§9.1), and only when read ({@link lazyRows}); the methods live on the prototype, so a
359
373
  * row costs its four fields.
360
374
  */
361
375
  declare class Row<T = unknown> {
362
- #private;
363
376
  /** The row's `rowKey` value (the row index without `rowKey`). */
364
377
  readonly key: RowKey;
365
378
  /** Position in the ingested data. */
366
379
  readonly index: number;
367
380
  /** The row object as passed in `data`. */
368
381
  readonly original: T;
382
+ /** @internal */
383
+ private readonly [SOURCE];
369
384
  /** @internal Rows are created by the pipeline. */
370
385
  constructor(source: RowSource, index: number, key: RowKey, original: T);
371
386
  /** `false` for a row flagged by schema validation (`invalidRows: 'flag'`). */
@@ -405,7 +420,7 @@ interface BuildInput {
405
420
  phase?: Phase;
406
421
  mode?: Record<string, 'client' | 'server'>;
407
422
  state?: DiagnosticStateSummary;
408
- /** Timestamp for `occurrences`. Default `Date.now()`. */
423
+ /** Timestamp for `occurrences` (epoch ms). Default `wallClock()`. */
409
424
  now?: number;
410
425
  cause?: unknown;
411
426
  causedBy?: string;
@@ -680,8 +695,12 @@ declare const featureDiagnostics: (DiagnosticDefinition<"DK_FEATURE_DUPLICATE">
680
695
  declare module '@datakable/core' {
681
696
  interface DiagnosticCatalog {
682
697
  DK_INVALID_PAGINATION: {
683
- /** The API method that received the value, or `'state'` for a slice written to the store. */
684
- source: 'setPageIndex' | 'setPageSize' | 'state';
698
+ /**
699
+ * The API method that received the value, `'state'` for a slice written to the store, or
700
+ * `'option'` for `pagination({ pageSize })` (checked here in production, where the option
701
+ * validator is off).
702
+ */
703
+ source: 'setPageIndex' | 'setPageSize' | 'state' | 'option';
685
704
  field: 'pageIndex' | 'pageSize';
686
705
  /** The value's type only (`describeValue`), plus the number itself when it is one. */
687
706
  received: string;
@@ -709,6 +728,12 @@ declare module '@datakable/core' {
709
728
  /** Whether a previous `searchFn` result is shown (`false`: none applied yet). */
710
729
  hadResults: boolean;
711
730
  };
731
+ DK_SEARCH_COLUMN_SKIPPED: {
732
+ /** Column id (`key` or `id`). */
733
+ column: string;
734
+ /** Position in the table's columns (`options.columns`, else the derived columns). */
735
+ index: number;
736
+ };
712
737
  }
713
738
  }
714
739
  /** Codes owned by the `search` feature (spec §6.3, §8.3). */
@@ -944,6 +969,14 @@ declare module '@datakable/core' {
944
969
  rows: number;
945
970
  /** The budget, in milliseconds (§9.3: the longest task). */
946
971
  budget: number;
972
+ /** One slice of the step's time-sliced work, run between pipeline runs (#61). */
973
+ sliced?: boolean;
974
+ /** The column slot at least half of the time went to, e.g. `columns[0].format` (#62). */
975
+ slot?: string;
976
+ /** Its column id. */
977
+ column?: string;
978
+ /** Its share of {@link ms}, 0.5 to 1. */
979
+ share?: number;
947
980
  };
948
981
  }
949
982
  }
@@ -1043,6 +1076,11 @@ declare module '@datakable/core' {
1043
1076
  /** Versions of every registered core copy, in registration order (this copy last). */
1044
1077
  versions: string[];
1045
1078
  };
1079
+ DK_DUPLICATE_CORE_SAME_VERSION: {
1080
+ version: string;
1081
+ /** Copies of core registered so far (this copy included), all of `version`. */
1082
+ copies: number;
1083
+ };
1046
1084
  DK_VERSION_MISMATCH: {
1047
1085
  /** The fixed-group package whose version differs, e.g. `@datakable/react`. */
1048
1086
  package: string;
@@ -1071,7 +1109,7 @@ declare module '@datakable/core' {
1071
1109
  }
1072
1110
  }
1073
1111
  /** Codes owned by versioning (§8.5). */
1074
- declare const versioningDiagnostics: (DiagnosticDefinition<"DK_DEPRECATED"> | DiagnosticDefinition<"DK_DUPLICATE_CORE"> | DiagnosticDefinition<"DK_VERSION_MISMATCH"> | DiagnosticDefinition<"DK_DEP_INCOMPATIBLE"> | DiagnosticDefinition<"DK_FEATURE_INCOMPATIBLE">)[];
1112
+ declare const versioningDiagnostics: (DiagnosticDefinition<"DK_DEPRECATED"> | DiagnosticDefinition<"DK_DUPLICATE_CORE"> | DiagnosticDefinition<"DK_DUPLICATE_CORE_SAME_VERSION"> | DiagnosticDefinition<"DK_VERSION_MISMATCH"> | DiagnosticDefinition<"DK_DEP_INCOMPATIBLE"> | DiagnosticDefinition<"DK_FEATURE_INCOMPATIBLE">)[];
1075
1113
 
1076
1114
  declare module '@datakable/core' {
1077
1115
  interface DiagnosticCatalog {