@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
@@ -1,4 +1,4 @@
1
- import { R as RowIssue, E as Emit, a as EmitOptions, D as Diagnostic, T as Trigger, P as Phase, I as InvalidRowsMode, F as FlaggedRow, b as Row, c as DiagnosticCode, d as DiagnosticDetails, e as TableSchema, f as RedactLevel, g as RedactFn, h as InvalidRow, i as RowKey } from './codes-BKdS9EiO.cjs';
1
+ import { R as RowIssue, E as Emit, a as EmitOptions, D as Diagnostic, T as Trigger, P as Phase, I as InvalidRowsMode, F as FlaggedRow, b as Row, c as DiagnosticCode, d as DiagnosticDetails, e as TableSchema, f as RedactLevel, g as RedactFn, h as InvalidRow, i as RowKey } from './codes-B9bCK73-.cjs';
2
2
 
3
3
  /** Runtime types an option can accept (`'array'` is checked before `'object'`). */
4
4
  type OptionType = 'string' | 'number' | 'boolean' | 'function' | 'object' | 'array';
@@ -130,7 +130,11 @@ type SortAlgorithm = 'auto' | 'tim' | 'radix' | 'counting' | 'native' | ((indice
130
130
  /** Fields shared by every column whose value type is `V`. */
131
131
  type BaseColumn<T, V, R> = {
132
132
  header?: string;
133
- /** Search weight; omit to exclude the column from search. */
133
+ /**
134
+ * Search weight. Once any column declares one, only weighted columns are searched; when none
135
+ * does, the columns of strings, numbers and booleans are (a date, array or object column needs a
136
+ * weight to be searched).
137
+ */
134
138
  search?: number;
135
139
  sortable?: boolean;
136
140
  sortFn?: (a: V, b: V) => number;
@@ -635,7 +639,7 @@ interface TableDiagnosticsOptions {
635
639
  /**
636
640
  * Redaction (§8.2): a level, or a custom `redact(path, value)` on top of the default level
637
641
  * (`'keys'` in development, `'safe'` in production). Columns with `sensitive: true` are never
638
- * logged; a sensitive `rowKey` column is hashed at every level.
642
+ * logged; a `rowKey` path into a sensitive column is hashed at every level.
639
643
  */
640
644
  redact?: RedactLevel | RedactFn;
641
645
  }
@@ -950,8 +954,13 @@ interface ExplainStep {
950
954
  readonly cached: boolean;
951
955
  /** The step threw or returned a bad output and passed its input through. */
952
956
  readonly failed: boolean;
953
- /** Duration (tracer only, development or `interceptors: [tracer()]`). */
957
+ /**
958
+ * Duration (tracer only, development or `interceptors: [tracer()]`). A step that waited on
959
+ * time-sliced work: the total of its runs and of the slices between them (#61).
960
+ */
954
961
  readonly ms?: number;
962
+ /** Time-sliced work (#61): the runs {@link ms} spans; absent when the step ran in one. */
963
+ readonly runs?: number;
955
964
  }
956
965
  /** What `table.explain()` returns (§8.4); `String(e)` is the console summary. */
957
966
  interface TableExplanation {
@@ -1,4 +1,4 @@
1
- import { R as RowIssue, E as Emit, a as EmitOptions, D as Diagnostic, T as Trigger, P as Phase, I as InvalidRowsMode, F as FlaggedRow, b as Row, c as DiagnosticCode, d as DiagnosticDetails, e as TableSchema, f as RedactLevel, g as RedactFn, h as InvalidRow, i as RowKey } from './codes-BKdS9EiO.js';
1
+ import { R as RowIssue, E as Emit, a as EmitOptions, D as Diagnostic, T as Trigger, P as Phase, I as InvalidRowsMode, F as FlaggedRow, b as Row, c as DiagnosticCode, d as DiagnosticDetails, e as TableSchema, f as RedactLevel, g as RedactFn, h as InvalidRow, i as RowKey } from './codes-B9bCK73-.js';
2
2
 
3
3
  /** Runtime types an option can accept (`'array'` is checked before `'object'`). */
4
4
  type OptionType = 'string' | 'number' | 'boolean' | 'function' | 'object' | 'array';
@@ -130,7 +130,11 @@ type SortAlgorithm = 'auto' | 'tim' | 'radix' | 'counting' | 'native' | ((indice
130
130
  /** Fields shared by every column whose value type is `V`. */
131
131
  type BaseColumn<T, V, R> = {
132
132
  header?: string;
133
- /** Search weight; omit to exclude the column from search. */
133
+ /**
134
+ * Search weight. Once any column declares one, only weighted columns are searched; when none
135
+ * does, the columns of strings, numbers and booleans are (a date, array or object column needs a
136
+ * weight to be searched).
137
+ */
134
138
  search?: number;
135
139
  sortable?: boolean;
136
140
  sortFn?: (a: V, b: V) => number;
@@ -635,7 +639,7 @@ interface TableDiagnosticsOptions {
635
639
  /**
636
640
  * Redaction (§8.2): a level, or a custom `redact(path, value)` on top of the default level
637
641
  * (`'keys'` in development, `'safe'` in production). Columns with `sensitive: true` are never
638
- * logged; a sensitive `rowKey` column is hashed at every level.
642
+ * logged; a `rowKey` path into a sensitive column is hashed at every level.
639
643
  */
640
644
  redact?: RedactLevel | RedactFn;
641
645
  }
@@ -950,8 +954,13 @@ interface ExplainStep {
950
954
  readonly cached: boolean;
951
955
  /** The step threw or returned a bad output and passed its input through. */
952
956
  readonly failed: boolean;
953
- /** Duration (tracer only, development or `interceptors: [tracer()]`). */
957
+ /**
958
+ * Duration (tracer only, development or `interceptors: [tracer()]`). A step that waited on
959
+ * time-sliced work: the total of its runs and of the slices between them (#61).
960
+ */
954
961
  readonly ms?: number;
962
+ /** Time-sliced work (#61): the runs {@link ms} spans; absent when the step ran in one. */
963
+ readonly runs?: number;
955
964
  }
956
965
  /** What `table.explain()` returns (§8.4); `String(e)` is the console summary. */
957
966
  interface TableExplanation {
@@ -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 capitalize = (s) => s.charAt(0).toUpperCase() + s.slice(1);
29
30
  var featureMessages = {
30
31
  DK_FEATURE_DUPLICATE: {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/feature/codes.ts"],"sourcesContent":["import { type DiagnosticMessages, defineDiagnostic } from '../diagnostics/catalog'\n\ndeclare module '../diagnostics/catalog' {\n interface DiagnosticCatalog {\n DK_FEATURE_DUPLICATE: {\n feature: string\n /** Positions in `options.features` of the first and the repeated entry. */\n first: number\n second: number\n }\n DK_FEATURE_API_CONFLICT: {\n method: string\n /** The feature whose API was installed last (the one rejected). */\n feature: string\n /** Who already owns `method`: another feature's name, or `null` for the table itself. */\n owner: string | null\n }\n DK_FEATURE_FAILED: {\n feature: string\n /** The hook that threw. `rowModel` is reported by the pipeline runner (T09). */\n hook: 'initialState' | 'createApi' | 'rowModel'\n /** The fallback that was applied. */\n fallback: string\n /** `error.name` only; the full error is `context.cause`. */\n errorName?: string\n /**\n * Dev: a method of a feature whose `createApi()` threw was called later (`hook: 'createApi'`);\n * `feature` names every feature whose API is missing.\n */\n method?: string\n }\n }\n}\n\nconst capitalize = (s: string) => s.charAt(0).toUpperCase() + s.slice(1)\n\n/** Message text (§8.2): development builds, or production via `@datakable/core/messages`. */\nexport const featureMessages: DiagnosticMessages<\n 'DK_FEATURE_DUPLICATE' | 'DK_FEATURE_API_CONFLICT' | 'DK_FEATURE_FAILED'\n> = {\n DK_FEATURE_DUPLICATE: {\n problem: (d) =>\n `feature \"${d.feature}\" is installed twice (features[${d.first}] and features[${d.second}]); ` +\n 'a feature name is its state slice key and must be unique per table',\n impact: () => 'the table was not created',\n fix: (d) => [\n `remove features[${d.second}] (or features[${d.first}]): pass \"${d.feature}\" once, with all ` +\n 'its options in one call',\n 'for two different features that share a name, rename one: defineFeature({ name: ... })',\n ],\n },\n DK_FEATURE_API_CONFLICT: {\n problem: (d) =>\n `feature \"${d.feature}\" exposes \"${d.method}\", which ` +\n (d.owner === null\n ? 'the table already has (a core table method)'\n : `feature \"${d.owner}\" already exposes`),\n impact: () => 'the table was not created: one of the two methods would be unreachable',\n fix: (d) => [\n `namespace the method in feature \"${d.feature}\": ` +\n `${d.feature}${capitalize(d.method)}() or ${d.feature}.${d.method}()`,\n d.owner === null\n ? `core table methods cannot be replaced; use an interceptor (e.g. on state:dispatch) to ` +\n `change what table.${d.method}() does`\n : `or rename it in feature \"${d.owner}\", or install only one of the two features`,\n ],\n },\n DK_FEATURE_FAILED: {\n problem: (d) =>\n d.method === undefined\n ? `feature \"${d.feature}\" ${d.hook}() threw${d.errorName ? ` ${d.errorName}` : ''}`\n : `table.${d.method}() was called, but it does not exist: createApi() threw at creation ` +\n `for feature \"${d.feature}\", so its API is missing`,\n impact: (d) => `${d.fallback}; the rest of the table is unaffected`,\n fix: (d) => [\n ...(d.method === undefined\n ? []\n : [\n `see the first DK_FEATURE_FAILED of feature \"${d.feature}\" (trigger init): its ` +\n 'context.cause is the createApi() error',\n ]),\n `fix ${d.hook}() of feature \"${d.feature}\": it must not throw` +\n (d.hook === 'rowModel' ? ' (return its input indices when it cannot filter)' : ''),\n 'the original error is context.cause (passed to onDiagnostic)',\n ],\n },\n}\n\n/** Codes owned by the feature contract (§3.3, §8.3). */\nexport const featureDiagnostics = [\n defineDiagnostic(\n {\n code: 'DK_FEATURE_DUPLICATE',\n level: 'error',\n config: true,\n where: (d) => ({ kind: 'feature', name: d.feature }),\n },\n (process.env.NODE_ENV !== \"production\") && featureMessages.DK_FEATURE_DUPLICATE,\n ),\n defineDiagnostic(\n {\n code: 'DK_FEATURE_API_CONFLICT',\n level: 'error',\n config: true,\n where: (d) => ({ kind: 'feature', name: d.feature }),\n },\n (process.env.NODE_ENV !== \"production\") && featureMessages.DK_FEATURE_API_CONFLICT,\n ),\n defineDiagnostic(\n {\n code: 'DK_FEATURE_FAILED',\n level: 'error',\n where: (d) => ({ kind: 'feature', name: d.feature }),\n },\n (process.env.NODE_ENV !== \"production\") && featureMessages.DK_FEATURE_FAILED,\n ),\n]\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAA0D;AAkC1D,IAAM,aAAa,CAAC,MAAc,EAAE,OAAO,CAAC,EAAE,YAAY,IAAI,EAAE,MAAM,CAAC;AAGhE,IAAM,kBAET;AAAA,EACF,sBAAsB;AAAA,IACpB,SAAS,CAAC,MACR,YAAY,EAAE,OAAO,kCAAkC,EAAE,KAAK,kBAAkB,EAAE,MAAM;AAAA,IAE1F,QAAQ,MAAM;AAAA,IACd,KAAK,CAAC,MAAM;AAAA,MACV,mBAAmB,EAAE,MAAM,kBAAkB,EAAE,KAAK,aAAa,EAAE,OAAO;AAAA,MAE1E;AAAA,IACF;AAAA,EACF;AAAA,EACA,yBAAyB;AAAA,IACvB,SAAS,CAAC,MACR,YAAY,EAAE,OAAO,cAAc,EAAE,MAAM,eAC1C,EAAE,UAAU,OACT,gDACA,YAAY,EAAE,KAAK;AAAA,IACzB,QAAQ,MAAM;AAAA,IACd,KAAK,CAAC,MAAM;AAAA,MACV,oCAAoC,EAAE,OAAO,MACxC,EAAE,OAAO,GAAG,WAAW,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,IAAI,EAAE,MAAM;AAAA,MACnE,EAAE,UAAU,OACR,2GACqB,EAAE,MAAM,YAC7B,4BAA4B,EAAE,KAAK;AAAA,IACzC;AAAA,EACF;AAAA,EACA,mBAAmB;AAAA,IACjB,SAAS,CAAC,MACR,EAAE,WAAW,SACT,YAAY,EAAE,OAAO,KAAK,EAAE,IAAI,WAAW,EAAE,YAAY,IAAI,EAAE,SAAS,KAAK,EAAE,KAC/E,SAAS,EAAE,MAAM,oFACD,EAAE,OAAO;AAAA,IAC/B,QAAQ,CAAC,MAAM,GAAG,EAAE,QAAQ;AAAA,IAC5B,KAAK,CAAC,MAAM;AAAA,MACV,GAAI,EAAE,WAAW,SACb,CAAC,IACD;AAAA,QACE,+CAA+C,EAAE,OAAO;AAAA,MAE1D;AAAA,MACJ,OAAO,EAAE,IAAI,kBAAkB,EAAE,OAAO,0BACrC,EAAE,SAAS,aAAa,sDAAsD;AAAA,MACjF;AAAA,IACF;AAAA,EACF;AACF;AAGO,IAAM,qBAAqB;AAAA,MAChC;AAAA,IACE;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,OAAO,CAAC,OAAO,EAAE,MAAM,WAAW,MAAM,EAAE,QAAQ;AAAA,IACpD;AAAA,IACC,QAAQ,IAAI,aAAa,gBAAiB,gBAAgB;AAAA,EAC7D;AAAA,MACA;AAAA,IACE;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,OAAO,CAAC,OAAO,EAAE,MAAM,WAAW,MAAM,EAAE,QAAQ;AAAA,IACpD;AAAA,IACC,QAAQ,IAAI,aAAa,gBAAiB,gBAAgB;AAAA,EAC7D;AAAA,MACA;AAAA,IACE;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MACP,OAAO,CAAC,OAAO,EAAE,MAAM,WAAW,MAAM,EAAE,QAAQ;AAAA,IACpD;AAAA,IACC,QAAQ,IAAI,aAAa,gBAAiB,gBAAgB;AAAA,EAC7D;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/feature/codes.ts"],"sourcesContent":["import { type DiagnosticMessages, defineDiagnostic } from '../diagnostics/catalog'\nimport '../diagnostics/process-guard'\n\ndeclare module '../diagnostics/catalog' {\n interface DiagnosticCatalog {\n DK_FEATURE_DUPLICATE: {\n feature: string\n /** Positions in `options.features` of the first and the repeated entry. */\n first: number\n second: number\n }\n DK_FEATURE_API_CONFLICT: {\n method: string\n /** The feature whose API was installed last (the one rejected). */\n feature: string\n /** Who already owns `method`: another feature's name, or `null` for the table itself. */\n owner: string | null\n }\n DK_FEATURE_FAILED: {\n feature: string\n /** The hook that threw. `rowModel` is reported by the pipeline runner (T09). */\n hook: 'initialState' | 'createApi' | 'rowModel'\n /** The fallback that was applied. */\n fallback: string\n /** `error.name` only; the full error is `context.cause`. */\n errorName?: string\n /**\n * Dev: a method of a feature whose `createApi()` threw was called later (`hook: 'createApi'`);\n * `feature` names every feature whose API is missing.\n */\n method?: string\n }\n }\n}\n\nconst capitalize = (s: string) => s.charAt(0).toUpperCase() + s.slice(1)\n\n/** Message text (§8.2): development builds, or production via `@datakable/core/messages`. */\nexport const featureMessages: DiagnosticMessages<\n 'DK_FEATURE_DUPLICATE' | 'DK_FEATURE_API_CONFLICT' | 'DK_FEATURE_FAILED'\n> = {\n DK_FEATURE_DUPLICATE: {\n problem: (d) =>\n `feature \"${d.feature}\" is installed twice (features[${d.first}] and features[${d.second}]); ` +\n 'a feature name is its state slice key and must be unique per table',\n impact: () => 'the table was not created',\n fix: (d) => [\n `remove features[${d.second}] (or features[${d.first}]): pass \"${d.feature}\" once, with all ` +\n 'its options in one call',\n 'for two different features that share a name, rename one: defineFeature({ name: ... })',\n ],\n },\n DK_FEATURE_API_CONFLICT: {\n problem: (d) =>\n `feature \"${d.feature}\" exposes \"${d.method}\", which ` +\n (d.owner === null\n ? 'the table already has (a core table method)'\n : `feature \"${d.owner}\" already exposes`),\n impact: () => 'the table was not created: one of the two methods would be unreachable',\n fix: (d) => [\n `namespace the method in feature \"${d.feature}\": ` +\n `${d.feature}${capitalize(d.method)}() or ${d.feature}.${d.method}()`,\n d.owner === null\n ? `core table methods cannot be replaced; use an interceptor (e.g. on state:dispatch) to ` +\n `change what table.${d.method}() does`\n : `or rename it in feature \"${d.owner}\", or install only one of the two features`,\n ],\n },\n DK_FEATURE_FAILED: {\n problem: (d) =>\n d.method === undefined\n ? `feature \"${d.feature}\" ${d.hook}() threw${d.errorName ? ` ${d.errorName}` : ''}`\n : `table.${d.method}() was called, but it does not exist: createApi() threw at creation ` +\n `for feature \"${d.feature}\", so its API is missing`,\n impact: (d) => `${d.fallback}; the rest of the table is unaffected`,\n fix: (d) => [\n ...(d.method === undefined\n ? []\n : [\n `see the first DK_FEATURE_FAILED of feature \"${d.feature}\" (trigger init): its ` +\n 'context.cause is the createApi() error',\n ]),\n `fix ${d.hook}() of feature \"${d.feature}\": it must not throw` +\n (d.hook === 'rowModel' ? ' (return its input indices when it cannot filter)' : ''),\n 'the original error is context.cause (passed to onDiagnostic)',\n ],\n },\n}\n\n/** Codes owned by the feature contract (§3.3, §8.3). */\nexport const featureDiagnostics = [\n defineDiagnostic(\n {\n code: 'DK_FEATURE_DUPLICATE',\n level: 'error',\n config: true,\n where: (d) => ({ kind: 'feature', name: d.feature }),\n },\n (process.env.NODE_ENV !== \"production\") && featureMessages.DK_FEATURE_DUPLICATE,\n ),\n defineDiagnostic(\n {\n code: 'DK_FEATURE_API_CONFLICT',\n level: 'error',\n config: true,\n where: (d) => ({ kind: 'feature', name: d.feature }),\n },\n (process.env.NODE_ENV !== \"production\") && featureMessages.DK_FEATURE_API_CONFLICT,\n ),\n defineDiagnostic(\n {\n code: 'DK_FEATURE_FAILED',\n level: 'error',\n where: (d) => ({ kind: 'feature', name: d.feature }),\n },\n (process.env.NODE_ENV !== \"production\") && featureMessages.DK_FEATURE_FAILED,\n ),\n]\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAA0D;AAC1D,2BAAO;AAkCP,IAAM,aAAa,CAAC,MAAc,EAAE,OAAO,CAAC,EAAE,YAAY,IAAI,EAAE,MAAM,CAAC;AAGhE,IAAM,kBAET;AAAA,EACF,sBAAsB;AAAA,IACpB,SAAS,CAAC,MACR,YAAY,EAAE,OAAO,kCAAkC,EAAE,KAAK,kBAAkB,EAAE,MAAM;AAAA,IAE1F,QAAQ,MAAM;AAAA,IACd,KAAK,CAAC,MAAM;AAAA,MACV,mBAAmB,EAAE,MAAM,kBAAkB,EAAE,KAAK,aAAa,EAAE,OAAO;AAAA,MAE1E;AAAA,IACF;AAAA,EACF;AAAA,EACA,yBAAyB;AAAA,IACvB,SAAS,CAAC,MACR,YAAY,EAAE,OAAO,cAAc,EAAE,MAAM,eAC1C,EAAE,UAAU,OACT,gDACA,YAAY,EAAE,KAAK;AAAA,IACzB,QAAQ,MAAM;AAAA,IACd,KAAK,CAAC,MAAM;AAAA,MACV,oCAAoC,EAAE,OAAO,MACxC,EAAE,OAAO,GAAG,WAAW,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,IAAI,EAAE,MAAM;AAAA,MACnE,EAAE,UAAU,OACR,2GACqB,EAAE,MAAM,YAC7B,4BAA4B,EAAE,KAAK;AAAA,IACzC;AAAA,EACF;AAAA,EACA,mBAAmB;AAAA,IACjB,SAAS,CAAC,MACR,EAAE,WAAW,SACT,YAAY,EAAE,OAAO,KAAK,EAAE,IAAI,WAAW,EAAE,YAAY,IAAI,EAAE,SAAS,KAAK,EAAE,KAC/E,SAAS,EAAE,MAAM,oFACD,EAAE,OAAO;AAAA,IAC/B,QAAQ,CAAC,MAAM,GAAG,EAAE,QAAQ;AAAA,IAC5B,KAAK,CAAC,MAAM;AAAA,MACV,GAAI,EAAE,WAAW,SACb,CAAC,IACD;AAAA,QACE,+CAA+C,EAAE,OAAO;AAAA,MAE1D;AAAA,MACJ,OAAO,EAAE,IAAI,kBAAkB,EAAE,OAAO,0BACrC,EAAE,SAAS,aAAa,sDAAsD;AAAA,MACjF;AAAA,IACF;AAAA,EACF;AACF;AAGO,IAAM,qBAAqB;AAAA,MAChC;AAAA,IACE;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,OAAO,CAAC,OAAO,EAAE,MAAM,WAAW,MAAM,EAAE,QAAQ;AAAA,IACpD;AAAA,IACC,QAAQ,IAAI,aAAa,gBAAiB,gBAAgB;AAAA,EAC7D;AAAA,MACA;AAAA,IACE;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,OAAO,CAAC,OAAO,EAAE,MAAM,WAAW,MAAM,EAAE,QAAQ;AAAA,IACpD;AAAA,IACC,QAAQ,IAAI,aAAa,gBAAiB,gBAAgB;AAAA,EAC7D;AAAA,MACA;AAAA,IACE;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MACP,OAAO,CAAC,OAAO,EAAE,MAAM,WAAW,MAAM,EAAE,QAAQ;AAAA,IACpD;AAAA,IACC,QAAQ,IAAI,aAAa,gBAAiB,gBAAgB;AAAA,EAC7D;AACF;","names":[]}
@@ -1,5 +1,6 @@
1
1
  // src/feature/codes.ts
2
2
  import { defineDiagnostic } from "../diagnostics/catalog.js";
3
+ import "../diagnostics/process-guard.js";
3
4
  var capitalize = (s) => s.charAt(0).toUpperCase() + s.slice(1);
4
5
  var featureMessages = {
5
6
  DK_FEATURE_DUPLICATE: {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/feature/codes.ts"],"sourcesContent":["import { type DiagnosticMessages, defineDiagnostic } from '../diagnostics/catalog'\n\ndeclare module '../diagnostics/catalog' {\n interface DiagnosticCatalog {\n DK_FEATURE_DUPLICATE: {\n feature: string\n /** Positions in `options.features` of the first and the repeated entry. */\n first: number\n second: number\n }\n DK_FEATURE_API_CONFLICT: {\n method: string\n /** The feature whose API was installed last (the one rejected). */\n feature: string\n /** Who already owns `method`: another feature's name, or `null` for the table itself. */\n owner: string | null\n }\n DK_FEATURE_FAILED: {\n feature: string\n /** The hook that threw. `rowModel` is reported by the pipeline runner (T09). */\n hook: 'initialState' | 'createApi' | 'rowModel'\n /** The fallback that was applied. */\n fallback: string\n /** `error.name` only; the full error is `context.cause`. */\n errorName?: string\n /**\n * Dev: a method of a feature whose `createApi()` threw was called later (`hook: 'createApi'`);\n * `feature` names every feature whose API is missing.\n */\n method?: string\n }\n }\n}\n\nconst capitalize = (s: string) => s.charAt(0).toUpperCase() + s.slice(1)\n\n/** Message text (§8.2): development builds, or production via `@datakable/core/messages`. */\nexport const featureMessages: DiagnosticMessages<\n 'DK_FEATURE_DUPLICATE' | 'DK_FEATURE_API_CONFLICT' | 'DK_FEATURE_FAILED'\n> = {\n DK_FEATURE_DUPLICATE: {\n problem: (d) =>\n `feature \"${d.feature}\" is installed twice (features[${d.first}] and features[${d.second}]); ` +\n 'a feature name is its state slice key and must be unique per table',\n impact: () => 'the table was not created',\n fix: (d) => [\n `remove features[${d.second}] (or features[${d.first}]): pass \"${d.feature}\" once, with all ` +\n 'its options in one call',\n 'for two different features that share a name, rename one: defineFeature({ name: ... })',\n ],\n },\n DK_FEATURE_API_CONFLICT: {\n problem: (d) =>\n `feature \"${d.feature}\" exposes \"${d.method}\", which ` +\n (d.owner === null\n ? 'the table already has (a core table method)'\n : `feature \"${d.owner}\" already exposes`),\n impact: () => 'the table was not created: one of the two methods would be unreachable',\n fix: (d) => [\n `namespace the method in feature \"${d.feature}\": ` +\n `${d.feature}${capitalize(d.method)}() or ${d.feature}.${d.method}()`,\n d.owner === null\n ? `core table methods cannot be replaced; use an interceptor (e.g. on state:dispatch) to ` +\n `change what table.${d.method}() does`\n : `or rename it in feature \"${d.owner}\", or install only one of the two features`,\n ],\n },\n DK_FEATURE_FAILED: {\n problem: (d) =>\n d.method === undefined\n ? `feature \"${d.feature}\" ${d.hook}() threw${d.errorName ? ` ${d.errorName}` : ''}`\n : `table.${d.method}() was called, but it does not exist: createApi() threw at creation ` +\n `for feature \"${d.feature}\", so its API is missing`,\n impact: (d) => `${d.fallback}; the rest of the table is unaffected`,\n fix: (d) => [\n ...(d.method === undefined\n ? []\n : [\n `see the first DK_FEATURE_FAILED of feature \"${d.feature}\" (trigger init): its ` +\n 'context.cause is the createApi() error',\n ]),\n `fix ${d.hook}() of feature \"${d.feature}\": it must not throw` +\n (d.hook === 'rowModel' ? ' (return its input indices when it cannot filter)' : ''),\n 'the original error is context.cause (passed to onDiagnostic)',\n ],\n },\n}\n\n/** Codes owned by the feature contract (§3.3, §8.3). */\nexport const featureDiagnostics = [\n defineDiagnostic(\n {\n code: 'DK_FEATURE_DUPLICATE',\n level: 'error',\n config: true,\n where: (d) => ({ kind: 'feature', name: d.feature }),\n },\n (process.env.NODE_ENV !== \"production\") && featureMessages.DK_FEATURE_DUPLICATE,\n ),\n defineDiagnostic(\n {\n code: 'DK_FEATURE_API_CONFLICT',\n level: 'error',\n config: true,\n where: (d) => ({ kind: 'feature', name: d.feature }),\n },\n (process.env.NODE_ENV !== \"production\") && featureMessages.DK_FEATURE_API_CONFLICT,\n ),\n defineDiagnostic(\n {\n code: 'DK_FEATURE_FAILED',\n level: 'error',\n where: (d) => ({ kind: 'feature', name: d.feature }),\n },\n (process.env.NODE_ENV !== \"production\") && featureMessages.DK_FEATURE_FAILED,\n ),\n]\n"],"mappings":";AAAA,SAAkC,wBAAwB;AAkC1D,IAAM,aAAa,CAAC,MAAc,EAAE,OAAO,CAAC,EAAE,YAAY,IAAI,EAAE,MAAM,CAAC;AAGhE,IAAM,kBAET;AAAA,EACF,sBAAsB;AAAA,IACpB,SAAS,CAAC,MACR,YAAY,EAAE,OAAO,kCAAkC,EAAE,KAAK,kBAAkB,EAAE,MAAM;AAAA,IAE1F,QAAQ,MAAM;AAAA,IACd,KAAK,CAAC,MAAM;AAAA,MACV,mBAAmB,EAAE,MAAM,kBAAkB,EAAE,KAAK,aAAa,EAAE,OAAO;AAAA,MAE1E;AAAA,IACF;AAAA,EACF;AAAA,EACA,yBAAyB;AAAA,IACvB,SAAS,CAAC,MACR,YAAY,EAAE,OAAO,cAAc,EAAE,MAAM,eAC1C,EAAE,UAAU,OACT,gDACA,YAAY,EAAE,KAAK;AAAA,IACzB,QAAQ,MAAM;AAAA,IACd,KAAK,CAAC,MAAM;AAAA,MACV,oCAAoC,EAAE,OAAO,MACxC,EAAE,OAAO,GAAG,WAAW,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,IAAI,EAAE,MAAM;AAAA,MACnE,EAAE,UAAU,OACR,2GACqB,EAAE,MAAM,YAC7B,4BAA4B,EAAE,KAAK;AAAA,IACzC;AAAA,EACF;AAAA,EACA,mBAAmB;AAAA,IACjB,SAAS,CAAC,MACR,EAAE,WAAW,SACT,YAAY,EAAE,OAAO,KAAK,EAAE,IAAI,WAAW,EAAE,YAAY,IAAI,EAAE,SAAS,KAAK,EAAE,KAC/E,SAAS,EAAE,MAAM,oFACD,EAAE,OAAO;AAAA,IAC/B,QAAQ,CAAC,MAAM,GAAG,EAAE,QAAQ;AAAA,IAC5B,KAAK,CAAC,MAAM;AAAA,MACV,GAAI,EAAE,WAAW,SACb,CAAC,IACD;AAAA,QACE,+CAA+C,EAAE,OAAO;AAAA,MAE1D;AAAA,MACJ,OAAO,EAAE,IAAI,kBAAkB,EAAE,OAAO,0BACrC,EAAE,SAAS,aAAa,sDAAsD;AAAA,MACjF;AAAA,IACF;AAAA,EACF;AACF;AAGO,IAAM,qBAAqB;AAAA,EAChC;AAAA,IACE;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,OAAO,CAAC,OAAO,EAAE,MAAM,WAAW,MAAM,EAAE,QAAQ;AAAA,IACpD;AAAA,IACC,QAAQ,IAAI,aAAa,gBAAiB,gBAAgB;AAAA,EAC7D;AAAA,EACA;AAAA,IACE;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,OAAO,CAAC,OAAO,EAAE,MAAM,WAAW,MAAM,EAAE,QAAQ;AAAA,IACpD;AAAA,IACC,QAAQ,IAAI,aAAa,gBAAiB,gBAAgB;AAAA,EAC7D;AAAA,EACA;AAAA,IACE;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MACP,OAAO,CAAC,OAAO,EAAE,MAAM,WAAW,MAAM,EAAE,QAAQ;AAAA,IACpD;AAAA,IACC,QAAQ,IAAI,aAAa,gBAAiB,gBAAgB;AAAA,EAC7D;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/feature/codes.ts"],"sourcesContent":["import { type DiagnosticMessages, defineDiagnostic } from '../diagnostics/catalog'\nimport '../diagnostics/process-guard'\n\ndeclare module '../diagnostics/catalog' {\n interface DiagnosticCatalog {\n DK_FEATURE_DUPLICATE: {\n feature: string\n /** Positions in `options.features` of the first and the repeated entry. */\n first: number\n second: number\n }\n DK_FEATURE_API_CONFLICT: {\n method: string\n /** The feature whose API was installed last (the one rejected). */\n feature: string\n /** Who already owns `method`: another feature's name, or `null` for the table itself. */\n owner: string | null\n }\n DK_FEATURE_FAILED: {\n feature: string\n /** The hook that threw. `rowModel` is reported by the pipeline runner (T09). */\n hook: 'initialState' | 'createApi' | 'rowModel'\n /** The fallback that was applied. */\n fallback: string\n /** `error.name` only; the full error is `context.cause`. */\n errorName?: string\n /**\n * Dev: a method of a feature whose `createApi()` threw was called later (`hook: 'createApi'`);\n * `feature` names every feature whose API is missing.\n */\n method?: string\n }\n }\n}\n\nconst capitalize = (s: string) => s.charAt(0).toUpperCase() + s.slice(1)\n\n/** Message text (§8.2): development builds, or production via `@datakable/core/messages`. */\nexport const featureMessages: DiagnosticMessages<\n 'DK_FEATURE_DUPLICATE' | 'DK_FEATURE_API_CONFLICT' | 'DK_FEATURE_FAILED'\n> = {\n DK_FEATURE_DUPLICATE: {\n problem: (d) =>\n `feature \"${d.feature}\" is installed twice (features[${d.first}] and features[${d.second}]); ` +\n 'a feature name is its state slice key and must be unique per table',\n impact: () => 'the table was not created',\n fix: (d) => [\n `remove features[${d.second}] (or features[${d.first}]): pass \"${d.feature}\" once, with all ` +\n 'its options in one call',\n 'for two different features that share a name, rename one: defineFeature({ name: ... })',\n ],\n },\n DK_FEATURE_API_CONFLICT: {\n problem: (d) =>\n `feature \"${d.feature}\" exposes \"${d.method}\", which ` +\n (d.owner === null\n ? 'the table already has (a core table method)'\n : `feature \"${d.owner}\" already exposes`),\n impact: () => 'the table was not created: one of the two methods would be unreachable',\n fix: (d) => [\n `namespace the method in feature \"${d.feature}\": ` +\n `${d.feature}${capitalize(d.method)}() or ${d.feature}.${d.method}()`,\n d.owner === null\n ? `core table methods cannot be replaced; use an interceptor (e.g. on state:dispatch) to ` +\n `change what table.${d.method}() does`\n : `or rename it in feature \"${d.owner}\", or install only one of the two features`,\n ],\n },\n DK_FEATURE_FAILED: {\n problem: (d) =>\n d.method === undefined\n ? `feature \"${d.feature}\" ${d.hook}() threw${d.errorName ? ` ${d.errorName}` : ''}`\n : `table.${d.method}() was called, but it does not exist: createApi() threw at creation ` +\n `for feature \"${d.feature}\", so its API is missing`,\n impact: (d) => `${d.fallback}; the rest of the table is unaffected`,\n fix: (d) => [\n ...(d.method === undefined\n ? []\n : [\n `see the first DK_FEATURE_FAILED of feature \"${d.feature}\" (trigger init): its ` +\n 'context.cause is the createApi() error',\n ]),\n `fix ${d.hook}() of feature \"${d.feature}\": it must not throw` +\n (d.hook === 'rowModel' ? ' (return its input indices when it cannot filter)' : ''),\n 'the original error is context.cause (passed to onDiagnostic)',\n ],\n },\n}\n\n/** Codes owned by the feature contract (§3.3, §8.3). */\nexport const featureDiagnostics = [\n defineDiagnostic(\n {\n code: 'DK_FEATURE_DUPLICATE',\n level: 'error',\n config: true,\n where: (d) => ({ kind: 'feature', name: d.feature }),\n },\n (process.env.NODE_ENV !== \"production\") && featureMessages.DK_FEATURE_DUPLICATE,\n ),\n defineDiagnostic(\n {\n code: 'DK_FEATURE_API_CONFLICT',\n level: 'error',\n config: true,\n where: (d) => ({ kind: 'feature', name: d.feature }),\n },\n (process.env.NODE_ENV !== \"production\") && featureMessages.DK_FEATURE_API_CONFLICT,\n ),\n defineDiagnostic(\n {\n code: 'DK_FEATURE_FAILED',\n level: 'error',\n where: (d) => ({ kind: 'feature', name: d.feature }),\n },\n (process.env.NODE_ENV !== \"production\") && featureMessages.DK_FEATURE_FAILED,\n ),\n]\n"],"mappings":";AAAA,SAAkC,wBAAwB;AAC1D,OAAO;AAkCP,IAAM,aAAa,CAAC,MAAc,EAAE,OAAO,CAAC,EAAE,YAAY,IAAI,EAAE,MAAM,CAAC;AAGhE,IAAM,kBAET;AAAA,EACF,sBAAsB;AAAA,IACpB,SAAS,CAAC,MACR,YAAY,EAAE,OAAO,kCAAkC,EAAE,KAAK,kBAAkB,EAAE,MAAM;AAAA,IAE1F,QAAQ,MAAM;AAAA,IACd,KAAK,CAAC,MAAM;AAAA,MACV,mBAAmB,EAAE,MAAM,kBAAkB,EAAE,KAAK,aAAa,EAAE,OAAO;AAAA,MAE1E;AAAA,IACF;AAAA,EACF;AAAA,EACA,yBAAyB;AAAA,IACvB,SAAS,CAAC,MACR,YAAY,EAAE,OAAO,cAAc,EAAE,MAAM,eAC1C,EAAE,UAAU,OACT,gDACA,YAAY,EAAE,KAAK;AAAA,IACzB,QAAQ,MAAM;AAAA,IACd,KAAK,CAAC,MAAM;AAAA,MACV,oCAAoC,EAAE,OAAO,MACxC,EAAE,OAAO,GAAG,WAAW,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,IAAI,EAAE,MAAM;AAAA,MACnE,EAAE,UAAU,OACR,2GACqB,EAAE,MAAM,YAC7B,4BAA4B,EAAE,KAAK;AAAA,IACzC;AAAA,EACF;AAAA,EACA,mBAAmB;AAAA,IACjB,SAAS,CAAC,MACR,EAAE,WAAW,SACT,YAAY,EAAE,OAAO,KAAK,EAAE,IAAI,WAAW,EAAE,YAAY,IAAI,EAAE,SAAS,KAAK,EAAE,KAC/E,SAAS,EAAE,MAAM,oFACD,EAAE,OAAO;AAAA,IAC/B,QAAQ,CAAC,MAAM,GAAG,EAAE,QAAQ;AAAA,IAC5B,KAAK,CAAC,MAAM;AAAA,MACV,GAAI,EAAE,WAAW,SACb,CAAC,IACD;AAAA,QACE,+CAA+C,EAAE,OAAO;AAAA,MAE1D;AAAA,MACJ,OAAO,EAAE,IAAI,kBAAkB,EAAE,OAAO,0BACrC,EAAE,SAAS,aAAa,sDAAsD;AAAA,MACjF;AAAA,IACF;AAAA,EACF;AACF;AAGO,IAAM,qBAAqB;AAAA,EAChC;AAAA,IACE;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,OAAO,CAAC,OAAO,EAAE,MAAM,WAAW,MAAM,EAAE,QAAQ;AAAA,IACpD;AAAA,IACC,QAAQ,IAAI,aAAa,gBAAiB,gBAAgB;AAAA,EAC7D;AAAA,EACA;AAAA,IACE;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,OAAO,CAAC,OAAO,EAAE,MAAM,WAAW,MAAM,EAAE,QAAQ;AAAA,IACpD;AAAA,IACC,QAAQ,IAAI,aAAa,gBAAiB,gBAAgB;AAAA,EAC7D;AAAA,EACA;AAAA,IACE;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MACP,OAAO,CAAC,OAAO,EAAE,MAAM,WAAW,MAAM,EAAE,QAAQ;AAAA,IACpD;AAAA,IACC,QAAQ,IAAI,aAAa,gBAAiB,gBAAgB;AAAA,EAC7D;AACF;","names":[]}
@@ -29,7 +29,7 @@ var import_slice = require("../pipeline/slice.cjs");
29
29
  var import_install = require("./install.cjs");
30
30
  var import_order = require("./order.cjs");
31
31
  var import_runtime = require("./runtime.cjs");
32
- import_runtime.featureRuntime.current ??= {
32
+ var runtime = {
33
33
  orderFeatures: import_order.orderFeatures,
34
34
  initialSlices: import_install.initialSlices,
35
35
  installApis: import_install.installApis,
@@ -37,7 +37,9 @@ import_runtime.featureRuntime.current ??= {
37
37
  createSlicer: import_slice.createSlicer,
38
38
  explainDetail: import_explain_detail.explainDetail
39
39
  };
40
+ import_runtime.featureRuntime.current ??= runtime;
40
41
  function defineFeature(definition) {
42
+ import_runtime.featureRuntime.current ??= runtime;
41
43
  return definition;
42
44
  }
43
45
  // Annotate the CommonJS export names for ESM import in node:
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/feature/define.ts"],"sourcesContent":["import { explainDetail } from '../diagnostics/explain-detail'\nimport { createColumnCache } from '../pipeline/column-cache'\nimport { createSlicer } from '../pipeline/slice'\nimport { initialSlices, installApis } from './install'\nimport { orderFeatures } from './order'\nimport { featureRuntime } from './runtime'\nimport type {\n AnyRow,\n Feature,\n FeatureContext,\n FeatureTypes,\n FixedTypes,\n RowModelContext,\n} from './types'\n\n// Features bring their runtime (§3.3, changed 2026-10-13 for §9.3): loading defineFeature installs\n// it, so a table without features never bundles it.\nfeatureRuntime.current ??= {\n orderFeatures,\n initialSlices,\n installApis,\n createColumnCache,\n createSlicer,\n explainDetail,\n}\n\n/** A feature whose state `S` and API `A` do not depend on the row type (inferred). */\nexport interface FixedFeatureDefinition<Name extends string, S, A>\n extends Omit<\n Feature<Name, FixedTypes<S, A>>,\n '_types' | 'initialState' | 'createApi' | 'rowModel'\n > {\n initialState: () => S\n createApi: (ctx: FeatureContext<S>) => A\n rowModel?: (indices: Uint32Array, state: S, ctx: RowModelContext<AnyRow>) => Uint32Array\n}\n\n/**\n * Defines a feature (§3.3). Identity at runtime; it exists for typing.\n *\n * Row-typed feature (all built-ins): declare the types interface and pass both type arguments.\n *\n * ```ts\n * interface SortingTypes extends FeatureTypes { state: SortState<this['T']>; api: SortApi<this['T']> }\n * export const sorting = (opts: SortingOptions = {}) =>\n * defineFeature<'sorting', SortingTypes>({ name: 'sorting', stage: 'sort', ... })\n * ```\n *\n * Feature that does not depend on `T`: no type arguments, state and API are inferred.\n */\nexport function defineFeature<const Name extends string, S, A extends object>(\n definition: FixedFeatureDefinition<Name, S, A>,\n): Feature<Name, FixedTypes<S, A>>\nexport function defineFeature<const Name extends string, F extends FeatureTypes>(\n definition: Feature<Name, F>,\n): Feature<Name, F>\nexport function defineFeature(definition: Feature): Feature {\n return definition\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAA8B;AAC9B,0BAAkC;AAClC,mBAA6B;AAC7B,qBAA2C;AAC3C,mBAA8B;AAC9B,qBAA+B;AAY/B,8BAAe,YAAY;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAgCO,SAAS,cAAc,YAA8B;AAC1D,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../src/feature/define.ts"],"sourcesContent":["import { explainDetail } from '../diagnostics/explain-detail'\nimport { createColumnCache } from '../pipeline/column-cache'\nimport { createSlicer } from '../pipeline/slice'\nimport { initialSlices, installApis } from './install'\nimport { orderFeatures } from './order'\nimport { featureRuntime } from './runtime'\nimport type {\n AnyRow,\n Feature,\n FeatureContext,\n FeatureTypes,\n FixedTypes,\n RowModelContext,\n} from './types'\n\n// Features bring their runtime (§3.3, changed 2026-10-13 for §9.3): defineFeature installs it, so a\n// table without features never bundles it. It is installed by the CALL, not only by loading this\n// module: the package is `sideEffects`-free here, and a bundler that inlines an identity\n// defineFeature (esbuild --minify) then drops this module with its top-level statement (#5).\nconst runtime = {\n orderFeatures,\n initialSlices,\n installApis,\n createColumnCache,\n createSlicer,\n explainDetail,\n}\nfeatureRuntime.current ??= runtime\n\n/** A feature whose state `S` and API `A` do not depend on the row type (inferred). */\nexport interface FixedFeatureDefinition<Name extends string, S, A>\n extends Omit<\n Feature<Name, FixedTypes<S, A>>,\n '_types' | 'initialState' | 'createApi' | 'rowModel'\n > {\n initialState: () => S\n createApi: (ctx: FeatureContext<S>) => A\n rowModel?: (indices: Uint32Array, state: S, ctx: RowModelContext<AnyRow>) => Uint32Array\n}\n\n/**\n * Defines a feature (§3.3). Returns `definition` as is (it exists for typing) and installs the\n * feature runtime.\n *\n * Row-typed feature (all built-ins): declare the types interface and pass both type arguments.\n *\n * ```ts\n * interface SortingTypes extends FeatureTypes { state: SortState<this['T']>; api: SortApi<this['T']> }\n * export const sorting = (opts: SortingOptions = {}) =>\n * defineFeature<'sorting', SortingTypes>({ name: 'sorting', stage: 'sort', ... })\n * ```\n *\n * Feature that does not depend on `T`: no type arguments, state and API are inferred.\n */\nexport function defineFeature<const Name extends string, S, A extends object>(\n definition: FixedFeatureDefinition<Name, S, A>,\n): Feature<Name, FixedTypes<S, A>>\nexport function defineFeature<const Name extends string, F extends FeatureTypes>(\n definition: Feature<Name, F>,\n): Feature<Name, F>\nexport function defineFeature(definition: Feature): Feature {\n featureRuntime.current ??= runtime\n return definition\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAA8B;AAC9B,0BAAkC;AAClC,mBAA6B;AAC7B,qBAA2C;AAC3C,mBAA8B;AAC9B,qBAA+B;AAc/B,IAAM,UAAU;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AACA,8BAAe,YAAY;AAiCpB,SAAS,cAAc,YAA8B;AAC1D,gCAAe,YAAY;AAC3B,SAAO;AACT;","names":[]}
@@ -5,7 +5,7 @@ import { createSlicer } from "../pipeline/slice.js";
5
5
  import { initialSlices, installApis } from "./install.js";
6
6
  import { orderFeatures } from "./order.js";
7
7
  import { featureRuntime } from "./runtime.js";
8
- featureRuntime.current ??= {
8
+ var runtime = {
9
9
  orderFeatures,
10
10
  initialSlices,
11
11
  installApis,
@@ -13,7 +13,9 @@ featureRuntime.current ??= {
13
13
  createSlicer,
14
14
  explainDetail
15
15
  };
16
+ featureRuntime.current ??= runtime;
16
17
  function defineFeature(definition) {
18
+ featureRuntime.current ??= runtime;
17
19
  return definition;
18
20
  }
19
21
  export {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/feature/define.ts"],"sourcesContent":["import { explainDetail } from '../diagnostics/explain-detail'\nimport { createColumnCache } from '../pipeline/column-cache'\nimport { createSlicer } from '../pipeline/slice'\nimport { initialSlices, installApis } from './install'\nimport { orderFeatures } from './order'\nimport { featureRuntime } from './runtime'\nimport type {\n AnyRow,\n Feature,\n FeatureContext,\n FeatureTypes,\n FixedTypes,\n RowModelContext,\n} from './types'\n\n// Features bring their runtime (§3.3, changed 2026-10-13 for §9.3): loading defineFeature installs\n// it, so a table without features never bundles it.\nfeatureRuntime.current ??= {\n orderFeatures,\n initialSlices,\n installApis,\n createColumnCache,\n createSlicer,\n explainDetail,\n}\n\n/** A feature whose state `S` and API `A` do not depend on the row type (inferred). */\nexport interface FixedFeatureDefinition<Name extends string, S, A>\n extends Omit<\n Feature<Name, FixedTypes<S, A>>,\n '_types' | 'initialState' | 'createApi' | 'rowModel'\n > {\n initialState: () => S\n createApi: (ctx: FeatureContext<S>) => A\n rowModel?: (indices: Uint32Array, state: S, ctx: RowModelContext<AnyRow>) => Uint32Array\n}\n\n/**\n * Defines a feature (§3.3). Identity at runtime; it exists for typing.\n *\n * Row-typed feature (all built-ins): declare the types interface and pass both type arguments.\n *\n * ```ts\n * interface SortingTypes extends FeatureTypes { state: SortState<this['T']>; api: SortApi<this['T']> }\n * export const sorting = (opts: SortingOptions = {}) =>\n * defineFeature<'sorting', SortingTypes>({ name: 'sorting', stage: 'sort', ... })\n * ```\n *\n * Feature that does not depend on `T`: no type arguments, state and API are inferred.\n */\nexport function defineFeature<const Name extends string, S, A extends object>(\n definition: FixedFeatureDefinition<Name, S, A>,\n): Feature<Name, FixedTypes<S, A>>\nexport function defineFeature<const Name extends string, F extends FeatureTypes>(\n definition: Feature<Name, F>,\n): Feature<Name, F>\nexport function defineFeature(definition: Feature): Feature {\n return definition\n}\n"],"mappings":";AAAA,SAAS,qBAAqB;AAC9B,SAAS,yBAAyB;AAClC,SAAS,oBAAoB;AAC7B,SAAS,eAAe,mBAAmB;AAC3C,SAAS,qBAAqB;AAC9B,SAAS,sBAAsB;AAY/B,eAAe,YAAY;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAgCO,SAAS,cAAc,YAA8B;AAC1D,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../src/feature/define.ts"],"sourcesContent":["import { explainDetail } from '../diagnostics/explain-detail'\nimport { createColumnCache } from '../pipeline/column-cache'\nimport { createSlicer } from '../pipeline/slice'\nimport { initialSlices, installApis } from './install'\nimport { orderFeatures } from './order'\nimport { featureRuntime } from './runtime'\nimport type {\n AnyRow,\n Feature,\n FeatureContext,\n FeatureTypes,\n FixedTypes,\n RowModelContext,\n} from './types'\n\n// Features bring their runtime (§3.3, changed 2026-10-13 for §9.3): defineFeature installs it, so a\n// table without features never bundles it. It is installed by the CALL, not only by loading this\n// module: the package is `sideEffects`-free here, and a bundler that inlines an identity\n// defineFeature (esbuild --minify) then drops this module with its top-level statement (#5).\nconst runtime = {\n orderFeatures,\n initialSlices,\n installApis,\n createColumnCache,\n createSlicer,\n explainDetail,\n}\nfeatureRuntime.current ??= runtime\n\n/** A feature whose state `S` and API `A` do not depend on the row type (inferred). */\nexport interface FixedFeatureDefinition<Name extends string, S, A>\n extends Omit<\n Feature<Name, FixedTypes<S, A>>,\n '_types' | 'initialState' | 'createApi' | 'rowModel'\n > {\n initialState: () => S\n createApi: (ctx: FeatureContext<S>) => A\n rowModel?: (indices: Uint32Array, state: S, ctx: RowModelContext<AnyRow>) => Uint32Array\n}\n\n/**\n * Defines a feature (§3.3). Returns `definition` as is (it exists for typing) and installs the\n * feature runtime.\n *\n * Row-typed feature (all built-ins): declare the types interface and pass both type arguments.\n *\n * ```ts\n * interface SortingTypes extends FeatureTypes { state: SortState<this['T']>; api: SortApi<this['T']> }\n * export const sorting = (opts: SortingOptions = {}) =>\n * defineFeature<'sorting', SortingTypes>({ name: 'sorting', stage: 'sort', ... })\n * ```\n *\n * Feature that does not depend on `T`: no type arguments, state and API are inferred.\n */\nexport function defineFeature<const Name extends string, S, A extends object>(\n definition: FixedFeatureDefinition<Name, S, A>,\n): Feature<Name, FixedTypes<S, A>>\nexport function defineFeature<const Name extends string, F extends FeatureTypes>(\n definition: Feature<Name, F>,\n): Feature<Name, F>\nexport function defineFeature(definition: Feature): Feature {\n featureRuntime.current ??= runtime\n return definition\n}\n"],"mappings":";AAAA,SAAS,qBAAqB;AAC9B,SAAS,yBAAyB;AAClC,SAAS,oBAAoB;AAC7B,SAAS,eAAe,mBAAmB;AAC3C,SAAS,qBAAqB;AAC9B,SAAS,sBAAsB;AAc/B,IAAM,UAAU;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AACA,eAAe,YAAY;AAiCpB,SAAS,cAAc,YAA8B;AAC1D,iBAAe,YAAY;AAC3B,SAAO;AACT;","names":[]}
@@ -26,6 +26,7 @@ __export(install_exports, {
26
26
  module.exports = __toCommonJS(install_exports);
27
27
  var import_build = require("../diagnostics/build.cjs");
28
28
  var import_catalog = require("../diagnostics/catalog.cjs");
29
+ var import_process_guard = require("../diagnostics/process-guard.cjs");
29
30
  var import_classify = require("../intercept/classify.cjs");
30
31
  var import_codes = require("./codes.cjs");
31
32
  (0, import_catalog.keepDiagnostics)(import_codes.featureDiagnostics);
@@ -45,7 +46,7 @@ function initialSlices(features, given, emit) {
45
46
  out[f.name] = f.initialState();
46
47
  } catch (e) {
47
48
  out[f.name] = void 0;
48
- reportFailure(emit, f.name, "initialState", "the slice starts as undefined", e);
49
+ reportFailure(emit, f.name, "initialState", "slice-undefined", e);
49
50
  }
50
51
  }
51
52
  return given ? Object.assign(out, given) : out;
@@ -68,7 +69,7 @@ function installApis(features, host) {
68
69
  try {
69
70
  api = f.createApi(ctx);
70
71
  } catch (e) {
71
- reportFailure(host.emit, name, "createApi", "its API was not installed", e);
72
+ reportFailure(host.emit, name, "createApi", "api-not-installed", e);
72
73
  failed.push(name);
73
74
  continue;
74
75
  }
@@ -120,7 +121,7 @@ function missingApi(failed, host) {
120
121
  feature,
121
122
  hook: "createApi",
122
123
  method: key,
123
- fallback: `table.${key}() did nothing (the API of ${failed.length === 1 ? "that feature" : "those features"} was not installed)`
124
+ fallback: `${failed.length === 1 ? "api" : "apis"}-missing|${key}`
124
125
  })
125
126
  );
126
127
  return void 0;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/feature/install.ts"],"sourcesContent":["import { throwConfigError } from '../diagnostics/build'\nimport { keepDiagnostics } from '../diagnostics/catalog'\nimport type { Emit } from '../diagnostics/types'\nimport { errorName } from '../intercept/classify'\nimport type { Table, TableState } from '../table/types'\nimport { featureDiagnostics } from './codes'\nimport type { AnyFeature, FeatureContext, SliceUpdater } from './types'\n\nkeepDiagnostics(featureDiagnostics)\n\n/** What `createTable` gives the installer: the store operations a feature context needs. */\nexport interface FeatureHost {\n readonly table: Table<unknown, TableState>\n /** The table name, for config errors thrown before the first emit. */\n readonly tableName: string\n readonly emit: Emit\n getSlice(name: string): unknown\n /** `state:dispatch` of one slice (where = the feature name); notifies unless inside an API call. */\n setSlice(name: string, updater: SliceUpdater<unknown>): void\n /**\n * Runs an API method: no-op + `DK_TABLE_DESTROYED` after destroy (returning `destroyed?.()`),\n * trigger `api:<method>`, listeners notified once when the outermost call returns.\n */\n call(method: string, fn: () => unknown, destroyed?: () => unknown): unknown\n}\n\nfunction reportFailure(\n emit: Emit,\n feature: string,\n hook: 'initialState' | 'createApi',\n fallback: string,\n e: unknown,\n) {\n const name = errorName(e)\n emit(\n 'DK_FEATURE_FAILED',\n { feature, hook, fallback, ...(name === undefined ? {} : { errorName: name }) },\n { cause: e },\n )\n}\n\n/**\n * The starting snapshot: each feature's `initialState()` under its name, then `given`\n * (`options.initialState`) per slice on top. `initialState()` is not called for a given slice.\n */\nexport function initialSlices(\n features: readonly AnyFeature[],\n given: object | undefined,\n emit: Emit,\n): TableState {\n const out: TableState = {}\n for (const f of features) {\n if (given && Object.hasOwn(given, f.name)) continue\n try {\n out[f.name] = f.initialState()\n } catch (e) {\n out[f.name] = undefined\n reportFailure(emit, f.name, 'initialState', 'the slice starts as undefined', e)\n }\n }\n return given ? Object.assign(out, given) : out\n}\n\n/**\n * Creates every feature API (in the order the features were listed) and merges it onto the table.\n * Throws `DatakableConfigError` `DK_FEATURE_API_CONFLICT` when a member name is already taken by a\n * core table method or by an earlier feature. Methods are wrapped once here (cold path).\n */\nexport function installApis(features: readonly AnyFeature[], host: FeatureHost): void {\n const target = host.table as unknown as Record<string, unknown>\n const owners = new Map<string, string | null>()\n for (const k of Object.keys(target)) owners.set(k, null)\n /** Features whose `createApi()` threw: their methods are missing from the table. */\n const failed: string[] = []\n\n for (const f of features) {\n const name = f.name\n const ctx: FeatureContext<unknown> = {\n name,\n getState: () => host.getSlice(name),\n setState: (updater) => host.setSlice(name, updater),\n table: host.table,\n emit: host.emit,\n }\n let api: unknown\n try {\n api = f.createApi(ctx)\n } catch (e) {\n reportFailure(host.emit, name, 'createApi', 'its API was not installed', e)\n failed.push(name)\n continue\n }\n if (api === null || typeof api !== 'object') continue\n const members = api as Record<string, unknown>\n const keys = Object.keys(members)\n for (const method of keys) {\n if (owners.has(method)) {\n throwConfigError(\n 'DK_FEATURE_API_CONFLICT',\n { method, feature: name, owner: owners.get(method) ?? null },\n { table: host.tableName },\n )\n }\n }\n for (const method of keys) {\n owners.set(method, name)\n const member = members[method]\n const destroyed = f.destroyedResult?.[method]\n target[method] =\n typeof member === 'function'\n ? (...args: unknown[]) => host.call(method, () => member.apply(members, args), destroyed)\n : member\n }\n }\n if ((process.env.NODE_ENV !== \"production\") && failed.length > 0) Object.setPrototypeOf(target, missingApi(failed, host))\n}\n\n/**\n * Names generic code probes on any object (await, JSON, React, test runners, inspectors): never a\n * feature method, so never stubbed.\n */\nconst PROBES = new Set([\n 'then',\n 'catch',\n 'finally',\n 'toJSON',\n 'asymmetricMatch',\n 'nodeType',\n 'tagName',\n])\nconst isProbe = (k: string) => PROBES.has(k) || /^[_$@]/.test(k)\n\n/**\n * Dev (R4): the prototype of a table where a feature's `createApi()` threw. The types still promise\n * that feature's methods, so a call to a name the table does not have is a no-op that reports\n * `DK_FEATURE_FAILED` (with the method) instead of a raw TypeError at the caller. Only reads of\n * missing names reach it: the table keeps its identity and own members, `in` / `hasOwn` stay\n * false, and `Object.prototype` members, symbols and generic probes (`then`, `toJSON`, …) resolve\n * as usual.\n */\nfunction missingApi(failed: readonly string[], host: FeatureHost): object {\n const feature = failed.join(', ')\n const stubs = new Map<string, () => undefined>()\n return new Proxy(Object.prototype, {\n get(proto, key, receiver) {\n if (typeof key !== 'string' || key in proto || isProbe(key)) {\n return Reflect.get(proto, key, receiver)\n }\n let stub = stubs.get(key)\n if (!stub) {\n stub = () => {\n host.call(key, () =>\n host.emit('DK_FEATURE_FAILED', {\n feature,\n hook: 'createApi',\n method: key,\n fallback: `table.${key}() did nothing (the API of ${failed.length === 1 ? 'that feature' : 'those features'} was not installed)`,\n }),\n )\n return undefined\n }\n stubs.set(key, stub)\n }\n return stub\n },\n })\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/feature/install.ts"],"sourcesContent":["import { throwConfigError } from '../diagnostics/build'\nimport { keepDiagnostics } from '../diagnostics/catalog'\nimport '../diagnostics/process-guard'\nimport type { Emit } from '../diagnostics/types'\nimport { errorName } from '../intercept/classify'\nimport type { Table, TableState } from '../table/types'\nimport { featureDiagnostics } from './codes'\nimport type { AnyFeature, FeatureContext, SliceUpdater } from './types'\n\nkeepDiagnostics(featureDiagnostics)\n\n/** What `createTable` gives the installer: the store operations a feature context needs. */\nexport interface FeatureHost {\n readonly table: Table<unknown, TableState>\n /** The table name, for config errors thrown before the first emit. */\n readonly tableName: string\n readonly emit: Emit\n getSlice(name: string): unknown\n /** `state:dispatch` of one slice (where = the feature name); notifies unless inside an API call. */\n setSlice(name: string, updater: SliceUpdater<unknown>): void\n /**\n * Runs an API method: no-op + `DK_TABLE_DESTROYED` after destroy (returning `destroyed?.()`),\n * trigger `api:<method>`, listeners notified once when the outermost call returns.\n */\n call(method: string, fn: () => unknown, destroyed?: () => unknown): unknown\n}\n\nfunction reportFailure(\n emit: Emit,\n feature: string,\n hook: 'initialState' | 'createApi',\n fallback: string,\n e: unknown,\n) {\n const name = errorName(e)\n emit(\n 'DK_FEATURE_FAILED',\n { feature, hook, fallback, ...(name === undefined ? {} : { errorName: name }) },\n { cause: e },\n )\n}\n\n/**\n * The starting snapshot: each feature's `initialState()` under its name, then `given`\n * (`options.initialState`) per slice on top. `initialState()` is not called for a given slice.\n */\nexport function initialSlices(\n features: readonly AnyFeature[],\n given: object | undefined,\n emit: Emit,\n): TableState {\n const out: TableState = {}\n for (const f of features) {\n if (given && Object.hasOwn(given, f.name)) continue\n try {\n out[f.name] = f.initialState()\n } catch (e) {\n out[f.name] = undefined\n reportFailure(emit, f.name, 'initialState', 'slice-undefined', e)\n }\n }\n return given ? Object.assign(out, given) : out\n}\n\n/**\n * Creates every feature API (in the order the features were listed) and merges it onto the table.\n * Throws `DatakableConfigError` `DK_FEATURE_API_CONFLICT` when a member name is already taken by a\n * core table method or by an earlier feature. Methods are wrapped once here (cold path).\n */\nexport function installApis(features: readonly AnyFeature[], host: FeatureHost): void {\n const target = host.table as unknown as Record<string, unknown>\n const owners = new Map<string, string | null>()\n for (const k of Object.keys(target)) owners.set(k, null)\n /** Features whose `createApi()` threw: their methods are missing from the table. */\n const failed: string[] = []\n\n for (const f of features) {\n const name = f.name\n const ctx: FeatureContext<unknown> = {\n name,\n getState: () => host.getSlice(name),\n setState: (updater) => host.setSlice(name, updater),\n table: host.table,\n emit: host.emit,\n }\n let api: unknown\n try {\n api = f.createApi(ctx)\n } catch (e) {\n reportFailure(host.emit, name, 'createApi', 'api-not-installed', e)\n failed.push(name)\n continue\n }\n if (api === null || typeof api !== 'object') continue\n const members = api as Record<string, unknown>\n const keys = Object.keys(members)\n for (const method of keys) {\n if (owners.has(method)) {\n throwConfigError(\n 'DK_FEATURE_API_CONFLICT',\n { method, feature: name, owner: owners.get(method) ?? null },\n { table: host.tableName },\n )\n }\n }\n for (const method of keys) {\n owners.set(method, name)\n const member = members[method]\n const destroyed = f.destroyedResult?.[method]\n target[method] =\n typeof member === 'function'\n ? (...args: unknown[]) => host.call(method, () => member.apply(members, args), destroyed)\n : member\n }\n }\n if ((process.env.NODE_ENV !== \"production\") && failed.length > 0) Object.setPrototypeOf(target, missingApi(failed, host))\n}\n\n/**\n * Names generic code probes on any object (await, JSON, React, test runners, inspectors): never a\n * feature method, so never stubbed.\n */\nconst PROBES = new Set([\n 'then',\n 'catch',\n 'finally',\n 'toJSON',\n 'asymmetricMatch',\n 'nodeType',\n 'tagName',\n])\nconst isProbe = (k: string) => PROBES.has(k) || /^[_$@]/.test(k)\n\n/**\n * Dev (R4): the prototype of a table where a feature's `createApi()` threw. The types still promise\n * that feature's methods, so a call to a name the table does not have is a no-op that reports\n * `DK_FEATURE_FAILED` (with the method) instead of a raw TypeError at the caller. Only reads of\n * missing names reach it: the table keeps its identity and own members, `in` / `hasOwn` stay\n * false, and `Object.prototype` members, symbols and generic probes (`then`, `toJSON`, …) resolve\n * as usual.\n */\nfunction missingApi(failed: readonly string[], host: FeatureHost): object {\n const feature = failed.join(', ')\n const stubs = new Map<string, () => undefined>()\n return new Proxy(Object.prototype, {\n get(proto, key, receiver) {\n if (typeof key !== 'string' || key in proto || isProbe(key)) {\n return Reflect.get(proto, key, receiver)\n }\n let stub = stubs.get(key)\n if (!stub) {\n stub = () => {\n host.call(key, () =>\n host.emit('DK_FEATURE_FAILED', {\n feature,\n hook: 'createApi',\n method: key,\n fallback: `${failed.length === 1 ? 'api' : 'apis'}-missing|${key}`,\n }),\n )\n return undefined\n }\n stubs.set(key, stub)\n }\n return stub\n },\n })\n}\n"],"mappings":"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","names":[]}
@@ -1,6 +1,7 @@
1
1
  // src/feature/install.ts
2
2
  import { throwConfigError } from "../diagnostics/build.js";
3
3
  import { keepDiagnostics } from "../diagnostics/catalog.js";
4
+ import "../diagnostics/process-guard.js";
4
5
  import { errorName } from "../intercept/classify.js";
5
6
  import { featureDiagnostics } from "./codes.js";
6
7
  keepDiagnostics(featureDiagnostics);
@@ -20,7 +21,7 @@ function initialSlices(features, given, emit) {
20
21
  out[f.name] = f.initialState();
21
22
  } catch (e) {
22
23
  out[f.name] = void 0;
23
- reportFailure(emit, f.name, "initialState", "the slice starts as undefined", e);
24
+ reportFailure(emit, f.name, "initialState", "slice-undefined", e);
24
25
  }
25
26
  }
26
27
  return given ? Object.assign(out, given) : out;
@@ -43,7 +44,7 @@ function installApis(features, host) {
43
44
  try {
44
45
  api = f.createApi(ctx);
45
46
  } catch (e) {
46
- reportFailure(host.emit, name, "createApi", "its API was not installed", e);
47
+ reportFailure(host.emit, name, "createApi", "api-not-installed", e);
47
48
  failed.push(name);
48
49
  continue;
49
50
  }
@@ -95,7 +96,7 @@ function missingApi(failed, host) {
95
96
  feature,
96
97
  hook: "createApi",
97
98
  method: key,
98
- fallback: `table.${key}() did nothing (the API of ${failed.length === 1 ? "that feature" : "those features"} was not installed)`
99
+ fallback: `${failed.length === 1 ? "api" : "apis"}-missing|${key}`
99
100
  })
100
101
  );
101
102
  return void 0;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/feature/install.ts"],"sourcesContent":["import { throwConfigError } from '../diagnostics/build'\nimport { keepDiagnostics } from '../diagnostics/catalog'\nimport type { Emit } from '../diagnostics/types'\nimport { errorName } from '../intercept/classify'\nimport type { Table, TableState } from '../table/types'\nimport { featureDiagnostics } from './codes'\nimport type { AnyFeature, FeatureContext, SliceUpdater } from './types'\n\nkeepDiagnostics(featureDiagnostics)\n\n/** What `createTable` gives the installer: the store operations a feature context needs. */\nexport interface FeatureHost {\n readonly table: Table<unknown, TableState>\n /** The table name, for config errors thrown before the first emit. */\n readonly tableName: string\n readonly emit: Emit\n getSlice(name: string): unknown\n /** `state:dispatch` of one slice (where = the feature name); notifies unless inside an API call. */\n setSlice(name: string, updater: SliceUpdater<unknown>): void\n /**\n * Runs an API method: no-op + `DK_TABLE_DESTROYED` after destroy (returning `destroyed?.()`),\n * trigger `api:<method>`, listeners notified once when the outermost call returns.\n */\n call(method: string, fn: () => unknown, destroyed?: () => unknown): unknown\n}\n\nfunction reportFailure(\n emit: Emit,\n feature: string,\n hook: 'initialState' | 'createApi',\n fallback: string,\n e: unknown,\n) {\n const name = errorName(e)\n emit(\n 'DK_FEATURE_FAILED',\n { feature, hook, fallback, ...(name === undefined ? {} : { errorName: name }) },\n { cause: e },\n )\n}\n\n/**\n * The starting snapshot: each feature's `initialState()` under its name, then `given`\n * (`options.initialState`) per slice on top. `initialState()` is not called for a given slice.\n */\nexport function initialSlices(\n features: readonly AnyFeature[],\n given: object | undefined,\n emit: Emit,\n): TableState {\n const out: TableState = {}\n for (const f of features) {\n if (given && Object.hasOwn(given, f.name)) continue\n try {\n out[f.name] = f.initialState()\n } catch (e) {\n out[f.name] = undefined\n reportFailure(emit, f.name, 'initialState', 'the slice starts as undefined', e)\n }\n }\n return given ? Object.assign(out, given) : out\n}\n\n/**\n * Creates every feature API (in the order the features were listed) and merges it onto the table.\n * Throws `DatakableConfigError` `DK_FEATURE_API_CONFLICT` when a member name is already taken by a\n * core table method or by an earlier feature. Methods are wrapped once here (cold path).\n */\nexport function installApis(features: readonly AnyFeature[], host: FeatureHost): void {\n const target = host.table as unknown as Record<string, unknown>\n const owners = new Map<string, string | null>()\n for (const k of Object.keys(target)) owners.set(k, null)\n /** Features whose `createApi()` threw: their methods are missing from the table. */\n const failed: string[] = []\n\n for (const f of features) {\n const name = f.name\n const ctx: FeatureContext<unknown> = {\n name,\n getState: () => host.getSlice(name),\n setState: (updater) => host.setSlice(name, updater),\n table: host.table,\n emit: host.emit,\n }\n let api: unknown\n try {\n api = f.createApi(ctx)\n } catch (e) {\n reportFailure(host.emit, name, 'createApi', 'its API was not installed', e)\n failed.push(name)\n continue\n }\n if (api === null || typeof api !== 'object') continue\n const members = api as Record<string, unknown>\n const keys = Object.keys(members)\n for (const method of keys) {\n if (owners.has(method)) {\n throwConfigError(\n 'DK_FEATURE_API_CONFLICT',\n { method, feature: name, owner: owners.get(method) ?? null },\n { table: host.tableName },\n )\n }\n }\n for (const method of keys) {\n owners.set(method, name)\n const member = members[method]\n const destroyed = f.destroyedResult?.[method]\n target[method] =\n typeof member === 'function'\n ? (...args: unknown[]) => host.call(method, () => member.apply(members, args), destroyed)\n : member\n }\n }\n if ((process.env.NODE_ENV !== \"production\") && failed.length > 0) Object.setPrototypeOf(target, missingApi(failed, host))\n}\n\n/**\n * Names generic code probes on any object (await, JSON, React, test runners, inspectors): never a\n * feature method, so never stubbed.\n */\nconst PROBES = new Set([\n 'then',\n 'catch',\n 'finally',\n 'toJSON',\n 'asymmetricMatch',\n 'nodeType',\n 'tagName',\n])\nconst isProbe = (k: string) => PROBES.has(k) || /^[_$@]/.test(k)\n\n/**\n * Dev (R4): the prototype of a table where a feature's `createApi()` threw. The types still promise\n * that feature's methods, so a call to a name the table does not have is a no-op that reports\n * `DK_FEATURE_FAILED` (with the method) instead of a raw TypeError at the caller. Only reads of\n * missing names reach it: the table keeps its identity and own members, `in` / `hasOwn` stay\n * false, and `Object.prototype` members, symbols and generic probes (`then`, `toJSON`, …) resolve\n * as usual.\n */\nfunction missingApi(failed: readonly string[], host: FeatureHost): object {\n const feature = failed.join(', ')\n const stubs = new Map<string, () => undefined>()\n return new Proxy(Object.prototype, {\n get(proto, key, receiver) {\n if (typeof key !== 'string' || key in proto || isProbe(key)) {\n return Reflect.get(proto, key, receiver)\n }\n let stub = stubs.get(key)\n if (!stub) {\n stub = () => {\n host.call(key, () =>\n host.emit('DK_FEATURE_FAILED', {\n feature,\n hook: 'createApi',\n method: key,\n fallback: `table.${key}() did nothing (the API of ${failed.length === 1 ? 'that feature' : 'those features'} was not installed)`,\n }),\n )\n return undefined\n }\n stubs.set(key, stub)\n }\n return stub\n },\n })\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/feature/install.ts"],"sourcesContent":["import { throwConfigError } from '../diagnostics/build'\nimport { keepDiagnostics } from '../diagnostics/catalog'\nimport '../diagnostics/process-guard'\nimport type { Emit } from '../diagnostics/types'\nimport { errorName } from '../intercept/classify'\nimport type { Table, TableState } from '../table/types'\nimport { featureDiagnostics } from './codes'\nimport type { AnyFeature, FeatureContext, SliceUpdater } from './types'\n\nkeepDiagnostics(featureDiagnostics)\n\n/** What `createTable` gives the installer: the store operations a feature context needs. */\nexport interface FeatureHost {\n readonly table: Table<unknown, TableState>\n /** The table name, for config errors thrown before the first emit. */\n readonly tableName: string\n readonly emit: Emit\n getSlice(name: string): unknown\n /** `state:dispatch` of one slice (where = the feature name); notifies unless inside an API call. */\n setSlice(name: string, updater: SliceUpdater<unknown>): void\n /**\n * Runs an API method: no-op + `DK_TABLE_DESTROYED` after destroy (returning `destroyed?.()`),\n * trigger `api:<method>`, listeners notified once when the outermost call returns.\n */\n call(method: string, fn: () => unknown, destroyed?: () => unknown): unknown\n}\n\nfunction reportFailure(\n emit: Emit,\n feature: string,\n hook: 'initialState' | 'createApi',\n fallback: string,\n e: unknown,\n) {\n const name = errorName(e)\n emit(\n 'DK_FEATURE_FAILED',\n { feature, hook, fallback, ...(name === undefined ? {} : { errorName: name }) },\n { cause: e },\n )\n}\n\n/**\n * The starting snapshot: each feature's `initialState()` under its name, then `given`\n * (`options.initialState`) per slice on top. `initialState()` is not called for a given slice.\n */\nexport function initialSlices(\n features: readonly AnyFeature[],\n given: object | undefined,\n emit: Emit,\n): TableState {\n const out: TableState = {}\n for (const f of features) {\n if (given && Object.hasOwn(given, f.name)) continue\n try {\n out[f.name] = f.initialState()\n } catch (e) {\n out[f.name] = undefined\n reportFailure(emit, f.name, 'initialState', 'slice-undefined', e)\n }\n }\n return given ? Object.assign(out, given) : out\n}\n\n/**\n * Creates every feature API (in the order the features were listed) and merges it onto the table.\n * Throws `DatakableConfigError` `DK_FEATURE_API_CONFLICT` when a member name is already taken by a\n * core table method or by an earlier feature. Methods are wrapped once here (cold path).\n */\nexport function installApis(features: readonly AnyFeature[], host: FeatureHost): void {\n const target = host.table as unknown as Record<string, unknown>\n const owners = new Map<string, string | null>()\n for (const k of Object.keys(target)) owners.set(k, null)\n /** Features whose `createApi()` threw: their methods are missing from the table. */\n const failed: string[] = []\n\n for (const f of features) {\n const name = f.name\n const ctx: FeatureContext<unknown> = {\n name,\n getState: () => host.getSlice(name),\n setState: (updater) => host.setSlice(name, updater),\n table: host.table,\n emit: host.emit,\n }\n let api: unknown\n try {\n api = f.createApi(ctx)\n } catch (e) {\n reportFailure(host.emit, name, 'createApi', 'api-not-installed', e)\n failed.push(name)\n continue\n }\n if (api === null || typeof api !== 'object') continue\n const members = api as Record<string, unknown>\n const keys = Object.keys(members)\n for (const method of keys) {\n if (owners.has(method)) {\n throwConfigError(\n 'DK_FEATURE_API_CONFLICT',\n { method, feature: name, owner: owners.get(method) ?? null },\n { table: host.tableName },\n )\n }\n }\n for (const method of keys) {\n owners.set(method, name)\n const member = members[method]\n const destroyed = f.destroyedResult?.[method]\n target[method] =\n typeof member === 'function'\n ? (...args: unknown[]) => host.call(method, () => member.apply(members, args), destroyed)\n : member\n }\n }\n if ((process.env.NODE_ENV !== \"production\") && failed.length > 0) Object.setPrototypeOf(target, missingApi(failed, host))\n}\n\n/**\n * Names generic code probes on any object (await, JSON, React, test runners, inspectors): never a\n * feature method, so never stubbed.\n */\nconst PROBES = new Set([\n 'then',\n 'catch',\n 'finally',\n 'toJSON',\n 'asymmetricMatch',\n 'nodeType',\n 'tagName',\n])\nconst isProbe = (k: string) => PROBES.has(k) || /^[_$@]/.test(k)\n\n/**\n * Dev (R4): the prototype of a table where a feature's `createApi()` threw. The types still promise\n * that feature's methods, so a call to a name the table does not have is a no-op that reports\n * `DK_FEATURE_FAILED` (with the method) instead of a raw TypeError at the caller. Only reads of\n * missing names reach it: the table keeps its identity and own members, `in` / `hasOwn` stay\n * false, and `Object.prototype` members, symbols and generic probes (`then`, `toJSON`, …) resolve\n * as usual.\n */\nfunction missingApi(failed: readonly string[], host: FeatureHost): object {\n const feature = failed.join(', ')\n const stubs = new Map<string, () => undefined>()\n return new Proxy(Object.prototype, {\n get(proto, key, receiver) {\n if (typeof key !== 'string' || key in proto || isProbe(key)) {\n return Reflect.get(proto, key, receiver)\n }\n let stub = stubs.get(key)\n if (!stub) {\n stub = () => {\n host.call(key, () =>\n host.emit('DK_FEATURE_FAILED', {\n feature,\n hook: 'createApi',\n method: key,\n fallback: `${failed.length === 1 ? 'api' : 'apis'}-missing|${key}`,\n }),\n )\n return undefined\n }\n stubs.set(key, stub)\n }\n return stub\n },\n })\n}\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/feature/runtime.ts"],"sourcesContent":["import type { explainDetail } from '../diagnostics/explain-detail'\nimport type { createColumnCache } from '../pipeline/column-cache'\nimport type { createSlicer } from '../pipeline/slice'\nimport type { initialSlices, installApis } from './install'\nimport type { orderFeatures } from './order'\n\n/**\n * What features bring to the table they are installed in (§3.3, changed 2026-10-13 for §9.3): the\n * stage ordering and API install, the column cache and time-slicing of the pipeline steps, and the\n * step details of `explainRow`. `defineFeature` (every built-in feature uses it) loads it, so a\n * table without features does not bundle it.\n */\nexport interface FeatureRuntime {\n readonly orderFeatures: typeof orderFeatures\n readonly initialSlices: typeof initialSlices\n readonly installApis: typeof installApis\n readonly createColumnCache: typeof createColumnCache\n readonly createSlicer: typeof createSlicer\n readonly explainDetail: typeof explainDetail\n}\n\n/** Set when `feature/define.ts` is loaded (the same module-scoped registry as the catalogs). */\nexport const featureRuntime: { current?: FeatureRuntime | undefined } = {}\n\n/** The runtime for `features`: `undefined` without features; throws when none was loaded. */\nexport function runtimeFor(features: readonly unknown[]): FeatureRuntime | undefined {\n if (features.length === 0) return undefined\n const rt = featureRuntime.current\n if (!rt) {\n throw new TypeError(\n '[DataKable] options.features is set but no feature runtime is loaded: create features with ' +\n \"defineFeature() from '@datakable/core' (every built-in feature does)\",\n )\n }\n return rt\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAsBO,IAAM,iBAA2D,CAAC;AAGlE,SAAS,WAAW,UAA0D;AACnF,MAAI,SAAS,WAAW,EAAG,QAAO;AAClC,QAAM,KAAK,eAAe;AAC1B,MAAI,CAAC,IAAI;AACP,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AACA,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../src/feature/runtime.ts"],"sourcesContent":["import type { explainDetail } from '../diagnostics/explain-detail'\nimport type { createColumnCache } from '../pipeline/column-cache'\nimport type { createSlicer } from '../pipeline/slice'\nimport type { initialSlices, installApis } from './install'\nimport type { orderFeatures } from './order'\n\n/**\n * What features bring to the table they are installed in (§3.3, changed 2026-10-13 for §9.3): the\n * stage ordering and API install, the column cache and time-slicing of the pipeline steps, and the\n * step details of `explainRow`. Calling `defineFeature` (every built-in feature does) installs it,\n * so a table without features does not bundle it.\n */\nexport interface FeatureRuntime {\n readonly orderFeatures: typeof orderFeatures\n readonly initialSlices: typeof initialSlices\n readonly installApis: typeof installApis\n readonly createColumnCache: typeof createColumnCache\n readonly createSlicer: typeof createSlicer\n readonly explainDetail: typeof explainDetail\n}\n\n/** Set by `defineFeature` and when `feature/define.ts` loads (module-scoped, as the catalogs). */\nexport const featureRuntime: { current?: FeatureRuntime | undefined } = {}\n\n/** The runtime for `features`: `undefined` without features; throws when none was loaded. */\nexport function runtimeFor(features: readonly unknown[]): FeatureRuntime | undefined {\n if (features.length === 0) return undefined\n const rt = featureRuntime.current\n if (!rt) {\n throw new TypeError(\n '[DataKable] options.features is set but no feature runtime is loaded: create features with ' +\n \"defineFeature() from '@datakable/core' (every built-in feature does)\",\n )\n }\n return rt\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAsBO,IAAM,iBAA2D,CAAC;AAGlE,SAAS,WAAW,UAA0D;AACnF,MAAI,SAAS,WAAW,EAAG,QAAO;AAClC,QAAM,KAAK,eAAe;AAC1B,MAAI,CAAC,IAAI;AACP,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AACA,SAAO;AACT;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/feature/runtime.ts"],"sourcesContent":["import type { explainDetail } from '../diagnostics/explain-detail'\nimport type { createColumnCache } from '../pipeline/column-cache'\nimport type { createSlicer } from '../pipeline/slice'\nimport type { initialSlices, installApis } from './install'\nimport type { orderFeatures } from './order'\n\n/**\n * What features bring to the table they are installed in (§3.3, changed 2026-10-13 for §9.3): the\n * stage ordering and API install, the column cache and time-slicing of the pipeline steps, and the\n * step details of `explainRow`. `defineFeature` (every built-in feature uses it) loads it, so a\n * table without features does not bundle it.\n */\nexport interface FeatureRuntime {\n readonly orderFeatures: typeof orderFeatures\n readonly initialSlices: typeof initialSlices\n readonly installApis: typeof installApis\n readonly createColumnCache: typeof createColumnCache\n readonly createSlicer: typeof createSlicer\n readonly explainDetail: typeof explainDetail\n}\n\n/** Set when `feature/define.ts` is loaded (the same module-scoped registry as the catalogs). */\nexport const featureRuntime: { current?: FeatureRuntime | undefined } = {}\n\n/** The runtime for `features`: `undefined` without features; throws when none was loaded. */\nexport function runtimeFor(features: readonly unknown[]): FeatureRuntime | undefined {\n if (features.length === 0) return undefined\n const rt = featureRuntime.current\n if (!rt) {\n throw new TypeError(\n '[DataKable] options.features is set but no feature runtime is loaded: create features with ' +\n \"defineFeature() from '@datakable/core' (every built-in feature does)\",\n )\n }\n return rt\n}\n"],"mappings":";AAsBO,IAAM,iBAA2D,CAAC;AAGlE,SAAS,WAAW,UAA0D;AACnF,MAAI,SAAS,WAAW,EAAG,QAAO;AAClC,QAAM,KAAK,eAAe;AAC1B,MAAI,CAAC,IAAI;AACP,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AACA,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../src/feature/runtime.ts"],"sourcesContent":["import type { explainDetail } from '../diagnostics/explain-detail'\nimport type { createColumnCache } from '../pipeline/column-cache'\nimport type { createSlicer } from '../pipeline/slice'\nimport type { initialSlices, installApis } from './install'\nimport type { orderFeatures } from './order'\n\n/**\n * What features bring to the table they are installed in (§3.3, changed 2026-10-13 for §9.3): the\n * stage ordering and API install, the column cache and time-slicing of the pipeline steps, and the\n * step details of `explainRow`. Calling `defineFeature` (every built-in feature does) installs it,\n * so a table without features does not bundle it.\n */\nexport interface FeatureRuntime {\n readonly orderFeatures: typeof orderFeatures\n readonly initialSlices: typeof initialSlices\n readonly installApis: typeof installApis\n readonly createColumnCache: typeof createColumnCache\n readonly createSlicer: typeof createSlicer\n readonly explainDetail: typeof explainDetail\n}\n\n/** Set by `defineFeature` and when `feature/define.ts` loads (module-scoped, as the catalogs). */\nexport const featureRuntime: { current?: FeatureRuntime | undefined } = {}\n\n/** The runtime for `features`: `undefined` without features; throws when none was loaded. */\nexport function runtimeFor(features: readonly unknown[]): FeatureRuntime | undefined {\n if (features.length === 0) return undefined\n const rt = featureRuntime.current\n if (!rt) {\n throw new TypeError(\n '[DataKable] options.features is set but no feature runtime is loaded: create features with ' +\n \"defineFeature() from '@datakable/core' (every built-in feature does)\",\n )\n }\n return rt\n}\n"],"mappings":";AAsBO,IAAM,iBAA2D,CAAC;AAGlE,SAAS,WAAW,UAA0D;AACnF,MAAI,SAAS,WAAW,EAAG,QAAO;AAClC,QAAM,KAAK,eAAe;AAC1B,MAAI,CAAC,IAAI;AACP,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AACA,SAAO;AACT;","names":[]}
@@ -27,6 +27,7 @@ __export(codes_exports, {
27
27
  module.exports = __toCommonJS(codes_exports);
28
28
  var import_suggest = require("../../catalog/suggest.cjs");
29
29
  var import_catalog = require("../../diagnostics/catalog.cjs");
30
+ var import_process_guard = require("../../diagnostics/process-guard.cjs");
30
31
  var FILTER_KINDS = ["equals", "contains", "in", "range", "custom"];
31
32
  var rowList = (rows, count) => {
32
33
  if (rows.length === 0) return "";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/features/column-filters/codes.ts"],"sourcesContent":["import { suggest } from '../../catalog/suggest'\nimport { type DiagnosticMessages, defineDiagnostic } from '../../diagnostics/catalog'\n\ndeclare module '../../diagnostics/catalog' {\n interface DiagnosticCatalog {\n DK_FILTER_TYPE_MISMATCH: {\n /** Column id (`key` or `id`). */\n column: string\n /** Position in `options.columns`. */\n index: number\n /** The filter kind (`type`) as given, e.g. `contains`. */\n filter: string\n /** `cell`: cell values of the wrong type; `filter`: the filter value itself is malformed. */\n source: 'cell' | 'filter'\n /** What the filter accepts, e.g. `string`, `number | bigint`, `Date`, `array`. */\n expected: string\n /** The type of the first offending value (`string`, `number`, `Date`, `array`, …). */\n received: string\n /** Cells of the wrong type (0 for `source: 'filter'`). */\n count: number\n /** A sample of their row indices (first few, in order). */\n rows: readonly number[]\n }\n DK_STATE_UNKNOWN_KEY: {\n /** The state slice holding the key, e.g. `columnFilters`. */\n slice: string\n /** The key that names no column. */\n key: string\n /** The table's column ids (did-you-mean). */\n known: readonly string[]\n }\n }\n}\n\n/** The filter kinds of §6.1. */\nexport const FILTER_KINDS = ['equals', 'contains', 'in', 'range', 'custom'] as const\n\nconst rowList = (rows: readonly number[], count: number) => {\n if (rows.length === 0) return ''\n const list = rows.map((r) => `#${r}`).join(', ')\n return count > rows.length ? ` (first: ${list}, …)` : ` (rows ${list})`\n}\n\nconst plural = (n: number, one: string, many: string) => (n === 1 ? `1 ${one}` : `${n} ${many}`)\n\n/** A conversion from `received` to `expected`, as code, when one is obvious. */\nfunction convert(expected: string, received: string): string | undefined {\n if (expected.includes('number') && received === 'string') return 'Number(x)'\n if (expected === 'string' && (received === 'number' || received === 'bigint')) return 'String(x)'\n if (expected === 'Date' && (received === 'string' || received === 'number')) return 'new Date(x)'\n return undefined\n}\n\n/** Message text (§8.2): development builds, or production via `@datakable/core/messages`. */\nexport const columnFiltersMessages: DiagnosticMessages<\n 'DK_FILTER_TYPE_MISMATCH' | 'DK_STATE_UNKNOWN_KEY'\n> = {\n DK_STATE_UNKNOWN_KEY: {\n problem: (d) => `state.${d.slice} has an entry for \"${d.key}\", which is not a column`,\n impact: () =>\n 'the entry is ignored (the other entries still apply); it may come from an older URL or ' +\n 'saved state, or the column was renamed or removed',\n fix: (d) => {\n const near = suggest(d.key, d.known)\n return [\n near.length > 0\n ? `did you mean \"${near[0]}\"? (state.${d.slice}[\"${near[0]}\"])`\n : `use one of the column ids: ${d.known.map((k) => `\"${k}\"`).join(', ')}`,\n `drop \"${d.key}\" when parsing initialState / state (e.g. from the URL), or add the column`,\n ]\n },\n },\n DK_FILTER_TYPE_MISMATCH: {\n problem: (d) =>\n d.source === 'filter'\n ? `the \"${d.filter}\" filter on column \"${d.column}\" has a value of type ${d.received}; ` +\n `it expects ${d.expected}`\n : `the \"${d.filter}\" filter on column \"${d.column}\" compares ${d.expected} values, but ` +\n `${plural(d.count, 'cell holds', 'cells hold')} another type (first: ` +\n `${d.received})${rowList(d.rows, d.count)}`,\n impact: (d) =>\n d.source === 'filter'\n ? 'the filter matches no rows until its value is fixed'\n : 'those rows are treated as non-matching; the other rows are filtered normally',\n fix: (d) => {\n const at = `state.columnFilters[\"${d.column}\"]`\n if (d.source === 'filter') {\n if (!(FILTER_KINDS as readonly string[]).includes(d.filter)) {\n const near = suggest(d.filter, FILTER_KINDS)\n return [\n near.length > 0\n ? `did you mean type: '${near[0]}'? (${at})`\n : `use one of the filter kinds ${FILTER_KINDS.join(', ')} in ${at}`,\n ]\n }\n return [\n `give ${at} a value of type ${d.expected}: { type: '${d.filter}', value: … }`,\n 'remove the filter (setColumnFilter(id, undefined)) while there is no value',\n ]\n }\n const out: string[] = []\n const c = convert(d.expected, d.received)\n if (c) {\n out.push(\n `if the filter value is the wrong type, convert it before setting it: ${c.replace('x', 'input')}`,\n `if the data is the wrong type, normalise the column: ` +\n `{ id: '${d.column}', accessor: (row) => ${c.replace('x', 'row.<field>')} } ` +\n `(columns[${d.index}])`,\n )\n } else {\n out.push(\n `normalise the column so every cell is ${d.expected}: an accessor on columns[${d.index}]`,\n )\n }\n out.push(\n `or filter with a kind that fits ${d.received} cells, or a custom filter: ` +\n `{ type: 'custom', value, fn: (cell, value, row) => boolean }`,\n )\n return out\n },\n },\n}\n\n/** Codes owned by the `columnFilters` feature (§6.1, §8.3). */\nexport const columnFiltersDiagnostics = [\n defineDiagnostic(\n {\n code: 'DK_FILTER_TYPE_MISMATCH',\n level: 'warn',\n where: (d) => ({ kind: 'column', index: d.index, id: d.column }),\n },\n (process.env.NODE_ENV !== \"production\") && columnFiltersMessages.DK_FILTER_TYPE_MISMATCH,\n ),\n defineDiagnostic(\n {\n code: 'DK_STATE_UNKNOWN_KEY',\n level: 'warn',\n where: (d) => ({ kind: 'option', path: `state.${d.slice}.${d.key}` }),\n },\n (process.env.NODE_ENV !== \"production\") && columnFiltersMessages.DK_STATE_UNKNOWN_KEY,\n ),\n]\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/features/column-filters/codes.ts"],"sourcesContent":["import { suggest } from '../../catalog/suggest'\nimport { type DiagnosticMessages, defineDiagnostic } from '../../diagnostics/catalog'\nimport '../../diagnostics/process-guard'\n\ndeclare module '../../diagnostics/catalog' {\n interface DiagnosticCatalog {\n DK_FILTER_TYPE_MISMATCH: {\n /** Column id (`key` or `id`). */\n column: string\n /** Position in `options.columns`. */\n index: number\n /** The filter kind (`type`) as given, e.g. `contains`. */\n filter: string\n /** `cell`: cell values of the wrong type; `filter`: the filter value itself is malformed. */\n source: 'cell' | 'filter'\n /** What the filter accepts, e.g. `string`, `number | bigint`, `Date`, `array`. */\n expected: string\n /** The type of the first offending value (`string`, `number`, `Date`, `array`, …). */\n received: string\n /** Cells of the wrong type (0 for `source: 'filter'`). */\n count: number\n /** A sample of their row indices (first few, in order). */\n rows: readonly number[]\n }\n DK_STATE_UNKNOWN_KEY: {\n /** The state slice holding the key, e.g. `columnFilters`. */\n slice: string\n /** The key that names no column. */\n key: string\n /** The table's column ids (did-you-mean). */\n known: readonly string[]\n }\n }\n}\n\n/** The filter kinds of §6.1. */\nexport const FILTER_KINDS = ['equals', 'contains', 'in', 'range', 'custom'] as const\n\nconst rowList = (rows: readonly number[], count: number) => {\n if (rows.length === 0) return ''\n const list = rows.map((r) => `#${r}`).join(', ')\n return count > rows.length ? ` (first: ${list}, …)` : ` (rows ${list})`\n}\n\nconst plural = (n: number, one: string, many: string) => (n === 1 ? `1 ${one}` : `${n} ${many}`)\n\n/** A conversion from `received` to `expected`, as code, when one is obvious. */\nfunction convert(expected: string, received: string): string | undefined {\n if (expected.includes('number') && received === 'string') return 'Number(x)'\n if (expected === 'string' && (received === 'number' || received === 'bigint')) return 'String(x)'\n if (expected === 'Date' && (received === 'string' || received === 'number')) return 'new Date(x)'\n return undefined\n}\n\n/** Message text (§8.2): development builds, or production via `@datakable/core/messages`. */\nexport const columnFiltersMessages: DiagnosticMessages<\n 'DK_FILTER_TYPE_MISMATCH' | 'DK_STATE_UNKNOWN_KEY'\n> = {\n DK_STATE_UNKNOWN_KEY: {\n problem: (d) => `state.${d.slice} has an entry for \"${d.key}\", which is not a column`,\n impact: () =>\n 'the entry is ignored (the other entries still apply); it may come from an older URL or ' +\n 'saved state, or the column was renamed or removed',\n fix: (d) => {\n const near = suggest(d.key, d.known)\n return [\n near.length > 0\n ? `did you mean \"${near[0]}\"? (state.${d.slice}[\"${near[0]}\"])`\n : `use one of the column ids: ${d.known.map((k) => `\"${k}\"`).join(', ')}`,\n `drop \"${d.key}\" when parsing initialState / state (e.g. from the URL), or add the column`,\n ]\n },\n },\n DK_FILTER_TYPE_MISMATCH: {\n problem: (d) =>\n d.source === 'filter'\n ? `the \"${d.filter}\" filter on column \"${d.column}\" has a value of type ${d.received}; ` +\n `it expects ${d.expected}`\n : `the \"${d.filter}\" filter on column \"${d.column}\" compares ${d.expected} values, but ` +\n `${plural(d.count, 'cell holds', 'cells hold')} another type (first: ` +\n `${d.received})${rowList(d.rows, d.count)}`,\n impact: (d) =>\n d.source === 'filter'\n ? 'the filter matches no rows until its value is fixed'\n : 'those rows are treated as non-matching; the other rows are filtered normally',\n fix: (d) => {\n const at = `state.columnFilters[\"${d.column}\"]`\n if (d.source === 'filter') {\n if (!(FILTER_KINDS as readonly string[]).includes(d.filter)) {\n const near = suggest(d.filter, FILTER_KINDS)\n return [\n near.length > 0\n ? `did you mean type: '${near[0]}'? (${at})`\n : `use one of the filter kinds ${FILTER_KINDS.join(', ')} in ${at}`,\n ]\n }\n return [\n `give ${at} a value of type ${d.expected}: { type: '${d.filter}', value: … }`,\n 'remove the filter (setColumnFilter(id, undefined)) while there is no value',\n ]\n }\n const out: string[] = []\n const c = convert(d.expected, d.received)\n if (c) {\n out.push(\n `if the filter value is the wrong type, convert it before setting it: ${c.replace('x', 'input')}`,\n `if the data is the wrong type, normalise the column: ` +\n `{ id: '${d.column}', accessor: (row) => ${c.replace('x', 'row.<field>')} } ` +\n `(columns[${d.index}])`,\n )\n } else {\n out.push(\n `normalise the column so every cell is ${d.expected}: an accessor on columns[${d.index}]`,\n )\n }\n out.push(\n `or filter with a kind that fits ${d.received} cells, or a custom filter: ` +\n `{ type: 'custom', value, fn: (cell, value, row) => boolean }`,\n )\n return out\n },\n },\n}\n\n/** Codes owned by the `columnFilters` feature (§6.1, §8.3). */\nexport const columnFiltersDiagnostics = [\n defineDiagnostic(\n {\n code: 'DK_FILTER_TYPE_MISMATCH',\n level: 'warn',\n where: (d) => ({ kind: 'column', index: d.index, id: d.column }),\n },\n (process.env.NODE_ENV !== \"production\") && columnFiltersMessages.DK_FILTER_TYPE_MISMATCH,\n ),\n defineDiagnostic(\n {\n code: 'DK_STATE_UNKNOWN_KEY',\n level: 'warn',\n where: (d) => ({ kind: 'option', path: `state.${d.slice}.${d.key}` }),\n },\n (process.env.NODE_ENV !== \"production\") && columnFiltersMessages.DK_STATE_UNKNOWN_KEY,\n ),\n]\n"],"mappings":"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","names":[]}
@@ -1,6 +1,7 @@
1
1
  // src/features/column-filters/codes.ts
2
2
  import { suggest } from "../../catalog/suggest.js";
3
3
  import { defineDiagnostic } from "../../diagnostics/catalog.js";
4
+ import "../../diagnostics/process-guard.js";
4
5
  var FILTER_KINDS = ["equals", "contains", "in", "range", "custom"];
5
6
  var rowList = (rows, count) => {
6
7
  if (rows.length === 0) return "";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/features/column-filters/codes.ts"],"sourcesContent":["import { suggest } from '../../catalog/suggest'\nimport { type DiagnosticMessages, defineDiagnostic } from '../../diagnostics/catalog'\n\ndeclare module '../../diagnostics/catalog' {\n interface DiagnosticCatalog {\n DK_FILTER_TYPE_MISMATCH: {\n /** Column id (`key` or `id`). */\n column: string\n /** Position in `options.columns`. */\n index: number\n /** The filter kind (`type`) as given, e.g. `contains`. */\n filter: string\n /** `cell`: cell values of the wrong type; `filter`: the filter value itself is malformed. */\n source: 'cell' | 'filter'\n /** What the filter accepts, e.g. `string`, `number | bigint`, `Date`, `array`. */\n expected: string\n /** The type of the first offending value (`string`, `number`, `Date`, `array`, …). */\n received: string\n /** Cells of the wrong type (0 for `source: 'filter'`). */\n count: number\n /** A sample of their row indices (first few, in order). */\n rows: readonly number[]\n }\n DK_STATE_UNKNOWN_KEY: {\n /** The state slice holding the key, e.g. `columnFilters`. */\n slice: string\n /** The key that names no column. */\n key: string\n /** The table's column ids (did-you-mean). */\n known: readonly string[]\n }\n }\n}\n\n/** The filter kinds of §6.1. */\nexport const FILTER_KINDS = ['equals', 'contains', 'in', 'range', 'custom'] as const\n\nconst rowList = (rows: readonly number[], count: number) => {\n if (rows.length === 0) return ''\n const list = rows.map((r) => `#${r}`).join(', ')\n return count > rows.length ? ` (first: ${list}, …)` : ` (rows ${list})`\n}\n\nconst plural = (n: number, one: string, many: string) => (n === 1 ? `1 ${one}` : `${n} ${many}`)\n\n/** A conversion from `received` to `expected`, as code, when one is obvious. */\nfunction convert(expected: string, received: string): string | undefined {\n if (expected.includes('number') && received === 'string') return 'Number(x)'\n if (expected === 'string' && (received === 'number' || received === 'bigint')) return 'String(x)'\n if (expected === 'Date' && (received === 'string' || received === 'number')) return 'new Date(x)'\n return undefined\n}\n\n/** Message text (§8.2): development builds, or production via `@datakable/core/messages`. */\nexport const columnFiltersMessages: DiagnosticMessages<\n 'DK_FILTER_TYPE_MISMATCH' | 'DK_STATE_UNKNOWN_KEY'\n> = {\n DK_STATE_UNKNOWN_KEY: {\n problem: (d) => `state.${d.slice} has an entry for \"${d.key}\", which is not a column`,\n impact: () =>\n 'the entry is ignored (the other entries still apply); it may come from an older URL or ' +\n 'saved state, or the column was renamed or removed',\n fix: (d) => {\n const near = suggest(d.key, d.known)\n return [\n near.length > 0\n ? `did you mean \"${near[0]}\"? (state.${d.slice}[\"${near[0]}\"])`\n : `use one of the column ids: ${d.known.map((k) => `\"${k}\"`).join(', ')}`,\n `drop \"${d.key}\" when parsing initialState / state (e.g. from the URL), or add the column`,\n ]\n },\n },\n DK_FILTER_TYPE_MISMATCH: {\n problem: (d) =>\n d.source === 'filter'\n ? `the \"${d.filter}\" filter on column \"${d.column}\" has a value of type ${d.received}; ` +\n `it expects ${d.expected}`\n : `the \"${d.filter}\" filter on column \"${d.column}\" compares ${d.expected} values, but ` +\n `${plural(d.count, 'cell holds', 'cells hold')} another type (first: ` +\n `${d.received})${rowList(d.rows, d.count)}`,\n impact: (d) =>\n d.source === 'filter'\n ? 'the filter matches no rows until its value is fixed'\n : 'those rows are treated as non-matching; the other rows are filtered normally',\n fix: (d) => {\n const at = `state.columnFilters[\"${d.column}\"]`\n if (d.source === 'filter') {\n if (!(FILTER_KINDS as readonly string[]).includes(d.filter)) {\n const near = suggest(d.filter, FILTER_KINDS)\n return [\n near.length > 0\n ? `did you mean type: '${near[0]}'? (${at})`\n : `use one of the filter kinds ${FILTER_KINDS.join(', ')} in ${at}`,\n ]\n }\n return [\n `give ${at} a value of type ${d.expected}: { type: '${d.filter}', value: … }`,\n 'remove the filter (setColumnFilter(id, undefined)) while there is no value',\n ]\n }\n const out: string[] = []\n const c = convert(d.expected, d.received)\n if (c) {\n out.push(\n `if the filter value is the wrong type, convert it before setting it: ${c.replace('x', 'input')}`,\n `if the data is the wrong type, normalise the column: ` +\n `{ id: '${d.column}', accessor: (row) => ${c.replace('x', 'row.<field>')} } ` +\n `(columns[${d.index}])`,\n )\n } else {\n out.push(\n `normalise the column so every cell is ${d.expected}: an accessor on columns[${d.index}]`,\n )\n }\n out.push(\n `or filter with a kind that fits ${d.received} cells, or a custom filter: ` +\n `{ type: 'custom', value, fn: (cell, value, row) => boolean }`,\n )\n return out\n },\n },\n}\n\n/** Codes owned by the `columnFilters` feature (§6.1, §8.3). */\nexport const columnFiltersDiagnostics = [\n defineDiagnostic(\n {\n code: 'DK_FILTER_TYPE_MISMATCH',\n level: 'warn',\n where: (d) => ({ kind: 'column', index: d.index, id: d.column }),\n },\n (process.env.NODE_ENV !== \"production\") && columnFiltersMessages.DK_FILTER_TYPE_MISMATCH,\n ),\n defineDiagnostic(\n {\n code: 'DK_STATE_UNKNOWN_KEY',\n level: 'warn',\n where: (d) => ({ kind: 'option', path: `state.${d.slice}.${d.key}` }),\n },\n (process.env.NODE_ENV !== \"production\") && columnFiltersMessages.DK_STATE_UNKNOWN_KEY,\n ),\n]\n"],"mappings":";AAAA,SAAS,eAAe;AACxB,SAAkC,wBAAwB;AAkCnD,IAAM,eAAe,CAAC,UAAU,YAAY,MAAM,SAAS,QAAQ;AAE1E,IAAM,UAAU,CAAC,MAAyB,UAAkB;AAC1D,MAAI,KAAK,WAAW,EAAG,QAAO;AAC9B,QAAM,OAAO,KAAK,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,EAAE,KAAK,IAAI;AAC/C,SAAO,QAAQ,KAAK,SAAS,YAAY,IAAI,cAAS,UAAU,IAAI;AACtE;AAEA,IAAM,SAAS,CAAC,GAAW,KAAa,SAAkB,MAAM,IAAI,KAAK,GAAG,KAAK,GAAG,CAAC,IAAI,IAAI;AAG7F,SAAS,QAAQ,UAAkB,UAAsC;AACvE,MAAI,SAAS,SAAS,QAAQ,KAAK,aAAa,SAAU,QAAO;AACjE,MAAI,aAAa,aAAa,aAAa,YAAY,aAAa,UAAW,QAAO;AACtF,MAAI,aAAa,WAAW,aAAa,YAAY,aAAa,UAAW,QAAO;AACpF,SAAO;AACT;AAGO,IAAM,wBAET;AAAA,EACF,sBAAsB;AAAA,IACpB,SAAS,CAAC,MAAM,SAAS,EAAE,KAAK,sBAAsB,EAAE,GAAG;AAAA,IAC3D,QAAQ,MACN;AAAA,IAEF,KAAK,CAAC,MAAM;AACV,YAAM,OAAO,QAAQ,EAAE,KAAK,EAAE,KAAK;AACnC,aAAO;AAAA,QACL,KAAK,SAAS,IACV,iBAAiB,KAAK,CAAC,CAAC,aAAa,EAAE,KAAK,KAAK,KAAK,CAAC,CAAC,QACxD,8BAA8B,EAAE,MAAM,IAAI,CAAC,MAAM,IAAI,CAAC,GAAG,EAAE,KAAK,IAAI,CAAC;AAAA,QACzE,SAAS,EAAE,GAAG;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAAA,EACA,yBAAyB;AAAA,IACvB,SAAS,CAAC,MACR,EAAE,WAAW,WACT,QAAQ,EAAE,MAAM,uBAAuB,EAAE,MAAM,yBAAyB,EAAE,QAAQ,gBACpE,EAAE,QAAQ,KACxB,QAAQ,EAAE,MAAM,uBAAuB,EAAE,MAAM,cAAc,EAAE,QAAQ,gBACpE,OAAO,EAAE,OAAO,cAAc,YAAY,CAAC,yBAC3C,EAAE,QAAQ,IAAI,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC;AAAA,IAC/C,QAAQ,CAAC,MACP,EAAE,WAAW,WACT,wDACA;AAAA,IACN,KAAK,CAAC,MAAM;AACV,YAAM,KAAK,wBAAwB,EAAE,MAAM;AAC3C,UAAI,EAAE,WAAW,UAAU;AACzB,YAAI,CAAE,aAAmC,SAAS,EAAE,MAAM,GAAG;AAC3D,gBAAM,OAAO,QAAQ,EAAE,QAAQ,YAAY;AAC3C,iBAAO;AAAA,YACL,KAAK,SAAS,IACV,uBAAuB,KAAK,CAAC,CAAC,OAAO,EAAE,MACvC,+BAA+B,aAAa,KAAK,IAAI,CAAC,OAAO,EAAE;AAAA,UACrE;AAAA,QACF;AACA,eAAO;AAAA,UACL,QAAQ,EAAE,oBAAoB,EAAE,QAAQ,cAAc,EAAE,MAAM;AAAA,UAC9D;AAAA,QACF;AAAA,MACF;AACA,YAAM,MAAgB,CAAC;AACvB,YAAM,IAAI,QAAQ,EAAE,UAAU,EAAE,QAAQ;AACxC,UAAI,GAAG;AACL,YAAI;AAAA,UACF,wEAAwE,EAAE,QAAQ,KAAK,OAAO,CAAC;AAAA,UAC/F,+DACY,EAAE,MAAM,yBAAyB,EAAE,QAAQ,KAAK,aAAa,CAAC,eAC5D,EAAE,KAAK;AAAA,QACvB;AAAA,MACF,OAAO;AACL,YAAI;AAAA,UACF,yCAAyC,EAAE,QAAQ,4BAA4B,EAAE,KAAK;AAAA,QACxF;AAAA,MACF;AACA,UAAI;AAAA,QACF,mCAAmC,EAAE,QAAQ;AAAA,MAE/C;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAGO,IAAM,2BAA2B;AAAA,EACtC;AAAA,IACE;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MACP,OAAO,CAAC,OAAO,EAAE,MAAM,UAAU,OAAO,EAAE,OAAO,IAAI,EAAE,OAAO;AAAA,IAChE;AAAA,IACC,QAAQ,IAAI,aAAa,gBAAiB,sBAAsB;AAAA,EACnE;AAAA,EACA;AAAA,IACE;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MACP,OAAO,CAAC,OAAO,EAAE,MAAM,UAAU,MAAM,SAAS,EAAE,KAAK,IAAI,EAAE,GAAG,GAAG;AAAA,IACrE;AAAA,IACC,QAAQ,IAAI,aAAa,gBAAiB,sBAAsB;AAAA,EACnE;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../src/features/column-filters/codes.ts"],"sourcesContent":["import { suggest } from '../../catalog/suggest'\nimport { type DiagnosticMessages, defineDiagnostic } from '../../diagnostics/catalog'\nimport '../../diagnostics/process-guard'\n\ndeclare module '../../diagnostics/catalog' {\n interface DiagnosticCatalog {\n DK_FILTER_TYPE_MISMATCH: {\n /** Column id (`key` or `id`). */\n column: string\n /** Position in `options.columns`. */\n index: number\n /** The filter kind (`type`) as given, e.g. `contains`. */\n filter: string\n /** `cell`: cell values of the wrong type; `filter`: the filter value itself is malformed. */\n source: 'cell' | 'filter'\n /** What the filter accepts, e.g. `string`, `number | bigint`, `Date`, `array`. */\n expected: string\n /** The type of the first offending value (`string`, `number`, `Date`, `array`, …). */\n received: string\n /** Cells of the wrong type (0 for `source: 'filter'`). */\n count: number\n /** A sample of their row indices (first few, in order). */\n rows: readonly number[]\n }\n DK_STATE_UNKNOWN_KEY: {\n /** The state slice holding the key, e.g. `columnFilters`. */\n slice: string\n /** The key that names no column. */\n key: string\n /** The table's column ids (did-you-mean). */\n known: readonly string[]\n }\n }\n}\n\n/** The filter kinds of §6.1. */\nexport const FILTER_KINDS = ['equals', 'contains', 'in', 'range', 'custom'] as const\n\nconst rowList = (rows: readonly number[], count: number) => {\n if (rows.length === 0) return ''\n const list = rows.map((r) => `#${r}`).join(', ')\n return count > rows.length ? ` (first: ${list}, …)` : ` (rows ${list})`\n}\n\nconst plural = (n: number, one: string, many: string) => (n === 1 ? `1 ${one}` : `${n} ${many}`)\n\n/** A conversion from `received` to `expected`, as code, when one is obvious. */\nfunction convert(expected: string, received: string): string | undefined {\n if (expected.includes('number') && received === 'string') return 'Number(x)'\n if (expected === 'string' && (received === 'number' || received === 'bigint')) return 'String(x)'\n if (expected === 'Date' && (received === 'string' || received === 'number')) return 'new Date(x)'\n return undefined\n}\n\n/** Message text (§8.2): development builds, or production via `@datakable/core/messages`. */\nexport const columnFiltersMessages: DiagnosticMessages<\n 'DK_FILTER_TYPE_MISMATCH' | 'DK_STATE_UNKNOWN_KEY'\n> = {\n DK_STATE_UNKNOWN_KEY: {\n problem: (d) => `state.${d.slice} has an entry for \"${d.key}\", which is not a column`,\n impact: () =>\n 'the entry is ignored (the other entries still apply); it may come from an older URL or ' +\n 'saved state, or the column was renamed or removed',\n fix: (d) => {\n const near = suggest(d.key, d.known)\n return [\n near.length > 0\n ? `did you mean \"${near[0]}\"? (state.${d.slice}[\"${near[0]}\"])`\n : `use one of the column ids: ${d.known.map((k) => `\"${k}\"`).join(', ')}`,\n `drop \"${d.key}\" when parsing initialState / state (e.g. from the URL), or add the column`,\n ]\n },\n },\n DK_FILTER_TYPE_MISMATCH: {\n problem: (d) =>\n d.source === 'filter'\n ? `the \"${d.filter}\" filter on column \"${d.column}\" has a value of type ${d.received}; ` +\n `it expects ${d.expected}`\n : `the \"${d.filter}\" filter on column \"${d.column}\" compares ${d.expected} values, but ` +\n `${plural(d.count, 'cell holds', 'cells hold')} another type (first: ` +\n `${d.received})${rowList(d.rows, d.count)}`,\n impact: (d) =>\n d.source === 'filter'\n ? 'the filter matches no rows until its value is fixed'\n : 'those rows are treated as non-matching; the other rows are filtered normally',\n fix: (d) => {\n const at = `state.columnFilters[\"${d.column}\"]`\n if (d.source === 'filter') {\n if (!(FILTER_KINDS as readonly string[]).includes(d.filter)) {\n const near = suggest(d.filter, FILTER_KINDS)\n return [\n near.length > 0\n ? `did you mean type: '${near[0]}'? (${at})`\n : `use one of the filter kinds ${FILTER_KINDS.join(', ')} in ${at}`,\n ]\n }\n return [\n `give ${at} a value of type ${d.expected}: { type: '${d.filter}', value: … }`,\n 'remove the filter (setColumnFilter(id, undefined)) while there is no value',\n ]\n }\n const out: string[] = []\n const c = convert(d.expected, d.received)\n if (c) {\n out.push(\n `if the filter value is the wrong type, convert it before setting it: ${c.replace('x', 'input')}`,\n `if the data is the wrong type, normalise the column: ` +\n `{ id: '${d.column}', accessor: (row) => ${c.replace('x', 'row.<field>')} } ` +\n `(columns[${d.index}])`,\n )\n } else {\n out.push(\n `normalise the column so every cell is ${d.expected}: an accessor on columns[${d.index}]`,\n )\n }\n out.push(\n `or filter with a kind that fits ${d.received} cells, or a custom filter: ` +\n `{ type: 'custom', value, fn: (cell, value, row) => boolean }`,\n )\n return out\n },\n },\n}\n\n/** Codes owned by the `columnFilters` feature (§6.1, §8.3). */\nexport const columnFiltersDiagnostics = [\n defineDiagnostic(\n {\n code: 'DK_FILTER_TYPE_MISMATCH',\n level: 'warn',\n where: (d) => ({ kind: 'column', index: d.index, id: d.column }),\n },\n (process.env.NODE_ENV !== \"production\") && columnFiltersMessages.DK_FILTER_TYPE_MISMATCH,\n ),\n defineDiagnostic(\n {\n code: 'DK_STATE_UNKNOWN_KEY',\n level: 'warn',\n where: (d) => ({ kind: 'option', path: `state.${d.slice}.${d.key}` }),\n },\n (process.env.NODE_ENV !== \"production\") && columnFiltersMessages.DK_STATE_UNKNOWN_KEY,\n ),\n]\n"],"mappings":"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","names":[]}
@@ -25,6 +25,7 @@ __export(column_filters_exports, {
25
25
  module.exports = __toCommonJS(column_filters_exports);
26
26
  var import_options = require("../../catalog/options.cjs");
27
27
  var import_catalog = require("../../diagnostics/catalog.cjs");
28
+ var import_process_guard = require("../../diagnostics/process-guard.cjs");
28
29
  var import_define = require("../../feature/define.cjs");
29
30
  var import_cell_batch = require("../../intercept/cell-batch.cjs");
30
31
  var import_classify = require("../../intercept/classify.cjs");
@@ -105,7 +106,7 @@ function report(ctx, c, id, kind, index) {
105
106
  column: id,
106
107
  rows: Array.from(failures.sample()),
107
108
  count: failures.count,
108
- fallback: "the failed rows are treated as non-matching",
109
+ fallback: "rows-unmatched",
109
110
  ...name === void 0 ? {} : { errorName: name }
110
111
  },
111
112
  { cause: first.error }
@@ -191,12 +192,13 @@ var columnFilters = (opts = {}) => (0, import_define.defineFeature)({
191
192
  initialState: () => ({}),
192
193
  createApi: (ctx) => ({
193
194
  setColumnFilter: (id, filter) => ctx.setState((prev) => {
195
+ if (prev[id] === filter) return prev;
194
196
  const next = { ...prev };
195
197
  if (filter === void 0) delete next[id];
196
198
  else next[id] = filter;
197
199
  return next;
198
200
  }),
199
- resetColumnFilters: () => ctx.setState({})
201
+ resetColumnFilters: () => ctx.setState((prev) => Object.keys(prev).length ? {} : prev)
200
202
  }),
201
203
  rowModel: filterRows
202
204
  });