vastgrid 0.1.0 → 0.2.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 (312) hide show
  1. package/README.md +175 -13
  2. package/dist/canvas/geometry.d.ts +92 -0
  3. package/dist/canvas/geometry.d.ts.map +1 -0
  4. package/dist/canvas/geometry.js +197 -0
  5. package/dist/canvas/geometry.js.map +1 -0
  6. package/dist/canvas/grid-canvas.d.ts +161 -0
  7. package/dist/canvas/grid-canvas.d.ts.map +1 -0
  8. package/dist/canvas/grid-canvas.js +1146 -0
  9. package/dist/canvas/grid-canvas.js.map +1 -0
  10. package/dist/canvas/hooks.d.ts +61 -0
  11. package/dist/canvas/hooks.d.ts.map +1 -0
  12. package/dist/canvas/hooks.js +2 -0
  13. package/dist/canvas/hooks.js.map +1 -0
  14. package/dist/canvas/keys.d.ts +26 -0
  15. package/dist/canvas/keys.d.ts.map +1 -0
  16. package/dist/canvas/keys.js +133 -0
  17. package/dist/canvas/keys.js.map +1 -0
  18. package/dist/canvas/layout.d.ts +26 -0
  19. package/dist/canvas/layout.d.ts.map +1 -0
  20. package/dist/canvas/layout.js +73 -0
  21. package/dist/canvas/layout.js.map +1 -0
  22. package/dist/canvas/scroll.d.ts +31 -0
  23. package/dist/canvas/scroll.d.ts.map +1 -0
  24. package/dist/canvas/scroll.js +111 -0
  25. package/dist/canvas/scroll.js.map +1 -0
  26. package/dist/canvas/text.d.ts +23 -0
  27. package/dist/canvas/text.d.ts.map +1 -0
  28. package/dist/canvas/text.js +142 -0
  29. package/dist/canvas/text.js.map +1 -0
  30. package/dist/{theme.d.ts → canvas/theme.d.ts} +8 -0
  31. package/dist/canvas/theme.d.ts.map +1 -0
  32. package/dist/canvas/theme.js +62 -0
  33. package/dist/canvas/theme.js.map +1 -0
  34. package/dist/core/cache.d.ts +48 -0
  35. package/dist/core/cache.d.ts.map +1 -0
  36. package/dist/core/cache.js +222 -0
  37. package/dist/core/cache.js.map +1 -0
  38. package/dist/core/checked.d.ts +20 -0
  39. package/dist/core/checked.d.ts.map +1 -0
  40. package/dist/core/checked.js +61 -0
  41. package/dist/core/checked.js.map +1 -0
  42. package/dist/core/client.d.ts +33 -0
  43. package/dist/core/client.d.ts.map +1 -0
  44. package/dist/core/client.js +103 -0
  45. package/dist/core/client.js.map +1 -0
  46. package/dist/core/conditions.d.ts +48 -0
  47. package/dist/core/conditions.d.ts.map +1 -0
  48. package/dist/core/conditions.js +105 -0
  49. package/dist/core/conditions.js.map +1 -0
  50. package/dist/core/evaluate.d.ts +20 -0
  51. package/dist/core/evaluate.d.ts.map +1 -0
  52. package/dist/core/evaluate.js +210 -0
  53. package/dist/core/evaluate.js.map +1 -0
  54. package/dist/core/filters.d.ts +51 -0
  55. package/dist/core/filters.d.ts.map +1 -0
  56. package/dist/core/filters.js +303 -0
  57. package/dist/core/filters.js.map +1 -0
  58. package/dist/core/format.d.ts +14 -0
  59. package/dist/core/format.d.ts.map +1 -0
  60. package/dist/core/format.js +303 -0
  61. package/dist/core/format.js.map +1 -0
  62. package/dist/core/measures.d.ts +26 -0
  63. package/dist/core/measures.d.ts.map +1 -0
  64. package/dist/core/measures.js +105 -0
  65. package/dist/core/measures.js.map +1 -0
  66. package/dist/core/request-ids.d.ts +20 -0
  67. package/dist/core/request-ids.d.ts.map +1 -0
  68. package/dist/core/request-ids.js +55 -0
  69. package/dist/core/request-ids.js.map +1 -0
  70. package/dist/core/rows.d.ts +79 -0
  71. package/dist/core/rows.d.ts.map +1 -0
  72. package/dist/core/rows.js +173 -0
  73. package/dist/core/rows.js.map +1 -0
  74. package/dist/core/store.d.ts +233 -0
  75. package/dist/core/store.d.ts.map +1 -0
  76. package/dist/core/store.js +1162 -0
  77. package/dist/core/store.js.map +1 -0
  78. package/dist/core/totals.d.ts +24 -0
  79. package/dist/core/totals.d.ts.map +1 -0
  80. package/dist/core/totals.js +49 -0
  81. package/dist/core/totals.js.map +1 -0
  82. package/dist/core/trace.d.ts +7 -0
  83. package/dist/core/trace.d.ts.map +1 -0
  84. package/dist/core/trace.js +26 -0
  85. package/dist/core/trace.js.map +1 -0
  86. package/dist/core/transports.d.ts +50 -0
  87. package/dist/core/transports.d.ts.map +1 -0
  88. package/dist/core/transports.js +160 -0
  89. package/dist/core/transports.js.map +1 -0
  90. package/dist/core/types.d.ts +150 -0
  91. package/dist/core/types.d.ts.map +1 -0
  92. package/dist/core/types.js +45 -0
  93. package/dist/core/types.js.map +1 -0
  94. package/dist/core.d.ts +12 -0
  95. package/dist/core.d.ts.map +1 -0
  96. package/dist/core.js +11 -0
  97. package/dist/core.js.map +1 -0
  98. package/dist/index.d.ts +15 -6
  99. package/dist/index.d.ts.map +1 -1
  100. package/dist/index.js +13 -7
  101. package/dist/index.js.map +1 -1
  102. package/dist/react/accessible-rows.d.ts +13 -0
  103. package/dist/react/accessible-rows.d.ts.map +1 -0
  104. package/dist/react/accessible-rows.js +320 -0
  105. package/dist/react/accessible-rows.js.map +1 -0
  106. package/dist/react/cell-editor.d.ts +22 -0
  107. package/dist/react/cell-editor.d.ts.map +1 -0
  108. package/dist/react/cell-editor.js +431 -0
  109. package/dist/react/cell-editor.js.map +1 -0
  110. package/dist/react/cell-menu.d.ts +18 -0
  111. package/dist/react/cell-menu.d.ts.map +1 -0
  112. package/dist/react/cell-menu.js +299 -0
  113. package/dist/react/cell-menu.js.map +1 -0
  114. package/dist/react/column-menu.d.ts +16 -0
  115. package/dist/react/column-menu.d.ts.map +1 -0
  116. package/dist/react/column-menu.js +1311 -0
  117. package/dist/react/column-menu.js.map +1 -0
  118. package/dist/react/columns-menu.d.ts +7 -0
  119. package/dist/react/columns-menu.d.ts.map +1 -0
  120. package/dist/react/columns-menu.js +249 -0
  121. package/dist/react/columns-menu.js.map +1 -0
  122. package/dist/react/conditions-menu.d.ts +10 -0
  123. package/dist/react/conditions-menu.d.ts.map +1 -0
  124. package/dist/react/conditions-menu.js +795 -0
  125. package/dist/react/conditions-menu.js.map +1 -0
  126. package/dist/react/context.d.ts +29 -0
  127. package/dist/react/context.d.ts.map +1 -0
  128. package/dist/react/context.js +18 -0
  129. package/dist/react/context.js.map +1 -0
  130. package/dist/react/data-grid.d.ts +79 -0
  131. package/dist/react/data-grid.d.ts.map +1 -0
  132. package/dist/react/data-grid.js +653 -0
  133. package/dist/react/data-grid.js.map +1 -0
  134. package/dist/react/detail-panel.d.ts +22 -0
  135. package/dist/react/detail-panel.d.ts.map +1 -0
  136. package/dist/react/detail-panel.js +242 -0
  137. package/dist/react/detail-panel.js.map +1 -0
  138. package/dist/react/export-menu.d.ts +11 -0
  139. package/dist/react/export-menu.d.ts.map +1 -0
  140. package/dist/react/export-menu.js +304 -0
  141. package/dist/react/export-menu.js.map +1 -0
  142. package/dist/react/find-bar.d.ts +11 -0
  143. package/dist/react/find-bar.d.ts.map +1 -0
  144. package/dist/react/find-bar.js +303 -0
  145. package/dist/react/find-bar.js.map +1 -0
  146. package/dist/react/format-form.d.ts +12 -0
  147. package/dist/react/format-form.d.ts.map +1 -0
  148. package/dist/react/format-form.js +863 -0
  149. package/dist/react/format-form.js.map +1 -0
  150. package/dist/react/formula-menu.d.ts +6 -0
  151. package/dist/react/formula-menu.d.ts.map +1 -0
  152. package/dist/react/formula-menu.js +343 -0
  153. package/dist/react/formula-menu.js.map +1 -0
  154. package/dist/react/grid-body.d.ts +33 -0
  155. package/dist/react/grid-body.d.ts.map +1 -0
  156. package/dist/react/grid-body.js +1389 -0
  157. package/dist/react/grid-body.js.map +1 -0
  158. package/dist/react/group-menu.d.ts +7 -0
  159. package/dist/react/group-menu.d.ts.map +1 -0
  160. package/dist/react/group-menu.js +508 -0
  161. package/dist/react/group-menu.js.map +1 -0
  162. package/dist/react/hooks.d.ts +33 -0
  163. package/dist/react/hooks.d.ts.map +1 -0
  164. package/dist/react/hooks.js +161 -0
  165. package/dist/react/hooks.js.map +1 -0
  166. package/dist/react/messages.d.ts +180 -0
  167. package/dist/react/messages.d.ts.map +1 -0
  168. package/dist/react/messages.js +414 -0
  169. package/dist/react/messages.js.map +1 -0
  170. package/dist/react/save.d.ts +9 -0
  171. package/dist/react/save.d.ts.map +1 -0
  172. package/dist/react/save.js +102 -0
  173. package/dist/react/save.js.map +1 -0
  174. package/dist/react/static-rows.d.ts +9 -0
  175. package/dist/react/static-rows.d.ts.map +1 -0
  176. package/dist/react/static-rows.js +176 -0
  177. package/dist/react/static-rows.js.map +1 -0
  178. package/dist/react/status-bar.d.ts +12 -0
  179. package/dist/react/status-bar.d.ts.map +1 -0
  180. package/dist/react/status-bar.js +413 -0
  181. package/dist/react/status-bar.js.map +1 -0
  182. package/dist/react/toolbar-popover.d.ts +14 -0
  183. package/dist/react/toolbar-popover.d.ts.map +1 -0
  184. package/dist/react/toolbar-popover.js +143 -0
  185. package/dist/react/toolbar-popover.js.map +1 -0
  186. package/dist/react/toolbar.d.ts +13 -0
  187. package/dist/react/toolbar.d.ts.map +1 -0
  188. package/dist/react/toolbar.js +344 -0
  189. package/dist/react/toolbar.js.map +1 -0
  190. package/dist/server.d.ts +22 -0
  191. package/dist/server.d.ts.map +1 -0
  192. package/dist/server.js +45 -0
  193. package/dist/server.js.map +1 -0
  194. package/dist/styles.css +496 -316
  195. package/package.json +43 -18
  196. package/src/canvas/geometry.ts +197 -0
  197. package/src/canvas/grid-canvas.ts +1222 -0
  198. package/src/canvas/hooks.ts +61 -0
  199. package/src/canvas/keys.ts +96 -0
  200. package/src/canvas/layout.ts +77 -0
  201. package/src/canvas/scroll.ts +120 -0
  202. package/src/canvas/text.ts +155 -0
  203. package/src/{theme.ts → canvas/theme.ts} +14 -1
  204. package/src/core/cache.ts +247 -0
  205. package/src/core/checked.ts +64 -0
  206. package/src/core/client.ts +103 -0
  207. package/src/core/conditions.ts +89 -0
  208. package/src/core/evaluate.ts +221 -0
  209. package/src/core/filters.ts +268 -0
  210. package/src/core/format.ts +309 -0
  211. package/src/core/measures.ts +99 -0
  212. package/src/core/request-ids.ts +54 -0
  213. package/src/core/rows.ts +213 -0
  214. package/src/core/store.ts +1122 -0
  215. package/src/core/totals.ts +59 -0
  216. package/src/core/trace.ts +44 -0
  217. package/src/core/transports.ts +177 -0
  218. package/src/core/types.ts +168 -0
  219. package/src/core.ts +39 -0
  220. package/src/index.ts +24 -12
  221. package/src/react/accessible-rows.tsx +242 -0
  222. package/src/react/cell-editor.tsx +216 -0
  223. package/src/react/cell-menu.tsx +166 -0
  224. package/src/react/column-menu.tsx +619 -0
  225. package/src/react/columns-menu.tsx +116 -0
  226. package/src/react/conditions-menu.tsx +289 -0
  227. package/src/react/context.ts +33 -0
  228. package/src/react/data-grid.tsx +286 -0
  229. package/src/react/detail-panel.tsx +92 -0
  230. package/src/react/export-menu.tsx +112 -0
  231. package/src/react/find-bar.tsx +112 -0
  232. package/src/react/format-form.tsx +421 -0
  233. package/src/react/formula-menu.tsx +163 -0
  234. package/src/react/grid-body.tsx +744 -0
  235. package/src/react/group-menu.tsx +214 -0
  236. package/src/react/hooks.ts +104 -0
  237. package/src/react/messages.ts +556 -0
  238. package/src/react/save.ts +42 -0
  239. package/src/react/static-rows.tsx +59 -0
  240. package/src/react/status-bar.tsx +175 -0
  241. package/src/react/toolbar-popover.tsx +69 -0
  242. package/src/react/toolbar.tsx +152 -0
  243. package/src/server.ts +58 -0
  244. package/src/styles.css +496 -316
  245. package/dist/components/bars.d.ts +0 -14
  246. package/dist/components/bars.d.ts.map +0 -1
  247. package/dist/components/bars.js +0 -67
  248. package/dist/components/bars.js.map +0 -1
  249. package/dist/components/cell-inspector.d.ts +0 -11
  250. package/dist/components/cell-inspector.d.ts.map +0 -1
  251. package/dist/components/cell-inspector.js +0 -37
  252. package/dist/components/cell-inspector.js.map +0 -1
  253. package/dist/components/columns-panel.d.ts +0 -12
  254. package/dist/components/columns-panel.d.ts.map +0 -1
  255. package/dist/components/columns-panel.js +0 -11
  256. package/dist/components/columns-panel.js.map +0 -1
  257. package/dist/components/filter-panel.d.ts +0 -17
  258. package/dist/components/filter-panel.d.ts.map +0 -1
  259. package/dist/components/filter-panel.js +0 -165
  260. package/dist/components/filter-panel.js.map +0 -1
  261. package/dist/components/find-bar.d.ts +0 -9
  262. package/dist/components/find-bar.d.ts.map +0 -1
  263. package/dist/components/find-bar.js +0 -46
  264. package/dist/components/find-bar.js.map +0 -1
  265. package/dist/components/popover.d.ts +0 -38
  266. package/dist/components/popover.d.ts.map +0 -1
  267. package/dist/components/popover.js +0 -104
  268. package/dist/components/popover.js.map +0 -1
  269. package/dist/components/stats-panel.d.ts +0 -12
  270. package/dist/components/stats-panel.d.ts.map +0 -1
  271. package/dist/components/stats-panel.js +0 -40
  272. package/dist/components/stats-panel.js.map +0 -1
  273. package/dist/controller.d.ts +0 -218
  274. package/dist/controller.d.ts.map +0 -1
  275. package/dist/controller.js +0 -788
  276. package/dist/controller.js.map +0 -1
  277. package/dist/data-grid.d.ts +0 -51
  278. package/dist/data-grid.d.ts.map +0 -1
  279. package/dist/data-grid.js +0 -698
  280. package/dist/data-grid.js.map +0 -1
  281. package/dist/labels.d.ts +0 -9
  282. package/dist/labels.d.ts.map +0 -1
  283. package/dist/labels.js +0 -38
  284. package/dist/labels.js.map +0 -1
  285. package/dist/messages.d.ts +0 -99
  286. package/dist/messages.d.ts.map +0 -1
  287. package/dist/messages.js +0 -276
  288. package/dist/messages.js.map +0 -1
  289. package/dist/renderer.d.ts +0 -52
  290. package/dist/renderer.d.ts.map +0 -1
  291. package/dist/renderer.js +0 -522
  292. package/dist/renderer.js.map +0 -1
  293. package/dist/text.d.ts +0 -14
  294. package/dist/text.d.ts.map +0 -1
  295. package/dist/text.js +0 -63
  296. package/dist/text.js.map +0 -1
  297. package/dist/theme.d.ts.map +0 -1
  298. package/dist/theme.js +0 -54
  299. package/dist/theme.js.map +0 -1
  300. package/src/components/bars.tsx +0 -179
  301. package/src/components/cell-inspector.tsx +0 -70
  302. package/src/components/columns-panel.tsx +0 -59
  303. package/src/components/filter-panel.tsx +0 -290
  304. package/src/components/find-bar.tsx +0 -104
  305. package/src/components/popover.tsx +0 -194
  306. package/src/components/stats-panel.tsx +0 -153
  307. package/src/controller.ts +0 -887
  308. package/src/data-grid.tsx +0 -1029
  309. package/src/labels.ts +0 -46
  310. package/src/messages.ts +0 -390
  311. package/src/renderer.ts +0 -535
  312. package/src/text.ts +0 -55
@@ -0,0 +1 @@
1
+ {"version":3,"names":["decimalLiteral","numberInput","value","Number","isFinite","text","trim","test","numberFormatter","locale","format","grouping","style","currency","RangeError","options","useGrouping","minimumFractionDigits","fractionDigits","maximumFractionDigits","currencyDisplay","notation","signDisplay","undefined","Math","min","Intl","NumberFormat","resolvedOptions","intl","prefix","suffix","isoDateTime","isoTime","parseOffset","toUpperCase","sign","startsWith","digits","slice","replace","parseDate","date","exec","year","month","day","hour","minute","second","fraction","offset","hasDate","hasTime","time","wallClock","parts","Date","setUTCFullYear","setUTCHours","padEnd","patternToken","dateFormatter","pattern","timeZone","DateTimeFormat","custom","Object","keys","length","formats","Map","key","make","item","get","set","local","instant","getTime","fields","hourCycle","era","formatToParts","field","type","find","part","bc","tokens","match","texts","split","name","pad","String","padStart","shown","forEach","token","index","abs","weekday","hour12","replaceAll","zone","shape","defaults","assign","isNumeric","column","TEMPORAL","Set","formatterFor","number","has","error","input"],"sources":["format.ts"],"sourcesContent":["/**\n * How cells show their values with the `number` and `date` of a column's format (§5.1 of the specification): 0.1's\n * `NumberFormat` and `DateFormat`, ported from `vastgrid-core` (Intl formats, with the exact digits of decimals,\n * and date patterns such as `yyyy/MM/dd`).\n */\nimport type { Column, ColumnFormat, DateFormat, JsonValue, NumberFormat } from \"vastgrid-spec\";\n\nconst decimalLiteral = /^[+-]?(?:\\d+\\.?\\d*|\\.\\d+)(?:[eE][+-]?\\d+)?$/;\n\n/**\n * A value as input for `Intl.NumberFormat`, or null when it is not a finite number. Numeric strings\n * stay strings, which `Intl.NumberFormat` formats from their exact digits.\n */\nfunction numberInput(value: JsonValue): number | string | null {\n if (typeof value === \"number\") return Number.isFinite(value) ? value : null;\n if (typeof value !== \"string\") return null;\n const text = value.trim();\n return decimalLiteral.test(text) ? text : null;\n}\n\nfunction numberFormatter(locale: string | undefined, format: NumberFormat, grouping: boolean) {\n const style = format.style ?? \"decimal\";\n if (style === \"currency\" && !format.currency) throw new RangeError(\"A currency format needs `currency`.\");\n const options: Intl.NumberFormatOptions = {\n style,\n useGrouping: format.grouping ?? grouping,\n minimumFractionDigits: format.fractionDigits ?? format.minimumFractionDigits,\n maximumFractionDigits: format.fractionDigits ?? format.maximumFractionDigits,\n };\n if (style === \"currency\") {\n options.currency = format.currency;\n if (format.currencyDisplay) options.currencyDisplay = format.currencyDisplay;\n }\n if (format.notation) options.notation = format.notation;\n if (format.signDisplay) options.signDisplay = format.signDisplay;\n // A maximum below the style's default minimum (2 for USD, 0 for percent) lowers the minimum too.\n if (options.maximumFractionDigits !== undefined && options.minimumFractionDigits === undefined) {\n options.minimumFractionDigits = Math.min(\n options.maximumFractionDigits,\n new Intl.NumberFormat(locale, { ...options, maximumFractionDigits: undefined }).resolvedOptions()\n .minimumFractionDigits ?? 0,\n );\n }\n const intl = new Intl.NumberFormat(locale, options);\n const prefix = format.prefix ?? \"\";\n const suffix = format.suffix ?? \"\";\n // `format` takes exact decimal strings (Intl.NumberFormat v3); the types only list numbers.\n return (value: number | string) => `${prefix}${intl.format(value as number)}${suffix}`;\n}\n\n/** The parts of an ISO-like date, time or timestamp. */\ninterface DateParts {\n year: number;\n month: number;\n day: number;\n hour: number;\n minute: number;\n second: number;\n /** Fraction digits of the second, as written. */\n fraction: string;\n hasDate: boolean;\n hasTime: boolean;\n /** Offset from UTC in minutes, for values with one. */\n offset: number | null;\n}\n\nconst isoDateTime =\n /^([+-]?\\d{4,})-(\\d{2})-(\\d{2})(?:[T ](\\d{2}):(\\d{2})(?::(\\d{2})(?:\\.(\\d+))?)?)?\\s*(Z|[+-]\\d{2}(?::?\\d{2})?)?$/i;\nconst isoTime = /^(\\d{2}):(\\d{2})(?::(\\d{2})(?:\\.(\\d+))?)?$/;\n\nfunction parseOffset(text: string | undefined) {\n if (!text) return null;\n if (text.toUpperCase() === \"Z\") return 0;\n const sign = text.startsWith(\"-\") ? -1 : 1;\n const digits = text.slice(1).replace(\":\", \"\");\n return sign * (Number(digits.slice(0, 2)) * 60 + Number(digits.slice(2) || 0));\n}\n\nfunction parseDate(text: string): DateParts | null {\n const date = isoDateTime.exec(text.trim());\n if (date) {\n const [, year, month, day, hour, minute, second, fraction, offset] = date;\n return {\n year: Number(year),\n month: Number(month),\n day: Number(day),\n hour: Number(hour ?? 0),\n minute: Number(minute ?? 0),\n second: Number(second ?? 0),\n fraction: fraction ?? \"\",\n hasDate: true,\n hasTime: hour !== undefined,\n offset: parseOffset(offset),\n };\n }\n const time = isoTime.exec(text.trim());\n if (!time) return null;\n const [, hour, minute, second, fraction] = time;\n return {\n year: 1970,\n month: 1,\n day: 1,\n hour: Number(hour),\n minute: Number(minute),\n second: Number(second ?? 0),\n fraction: fraction ?? \"\",\n hasDate: false,\n hasTime: true,\n offset: null,\n };\n}\n\n/** The UTC time of the parts' wall clock (ignoring their offset). Years below 100 are kept. */\nfunction wallClock(parts: DateParts) {\n const date = new Date(0);\n date.setUTCFullYear(parts.year, parts.month - 1, parts.day);\n date.setUTCHours(parts.hour, parts.minute, parts.second, Number(parts.fraction.slice(0, 3).padEnd(3, \"0\")));\n return date;\n}\n\nconst patternToken = /'(?:[^']|'')*'|yyyy|yy|MMMM|MMM|MM|M|dd|d|EEEE|EEE|HH|H|hh|h|mm|m|ss|s|S+|a/g;\n\nfunction dateFormatter(locale: string | undefined, format: DateFormat) {\n const { pattern, timeZone, ...options } = format;\n // Checks the time zone and the options now, not on the first value.\n new Intl.DateTimeFormat(locale, { ...options, timeZone });\n const custom = Object.keys(options).length > 0;\n const formats = new Map<string, Intl.DateTimeFormat>();\n const intl = (key: string, make: () => Intl.DateTimeFormat) => {\n let item = formats.get(key);\n if (!item) {\n item = make();\n formats.set(key, item);\n }\n return item;\n };\n /** The parts in the shown time zone: values with an offset move to `timeZone`. */\n const local = (parts: DateParts): DateParts => {\n if (parts.offset === null) return parts;\n const instant = new Date(wallClock(parts).getTime() - parts.offset * 60_000);\n const fields = intl(\n \"parts\",\n () =>\n new Intl.DateTimeFormat(\"en-US-u-nu-latn\", {\n timeZone,\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"numeric\",\n second: \"numeric\",\n hourCycle: \"h23\",\n era: \"short\",\n }),\n ).formatToParts(instant);\n const field = (type: string) => Number(fields.find((part) => part.type === type)?.value ?? 0);\n const bc = fields.find((part) => part.type === \"era\")?.value.startsWith(\"B\");\n return {\n ...parts,\n year: bc ? 1 - field(\"year\") : field(\"year\"),\n month: field(\"month\"),\n day: field(\"day\"),\n hour: field(\"hour\"),\n minute: field(\"minute\"),\n second: field(\"second\"),\n offset: null,\n };\n };\n\n if (pattern !== undefined) {\n const tokens = pattern.match(patternToken) ?? [];\n const texts = pattern.split(patternToken);\n const name = (key: string, options: Intl.DateTimeFormatOptions, date: Date) =>\n intl(key, () => new Intl.DateTimeFormat(locale, { ...options, timeZone: \"UTC\" })).format(date);\n const pad = (value: number, length: number) =>\n value < 0 ? `-${String(-value).padStart(length, \"0\")}` : String(value).padStart(length, \"0\");\n return (parts: DateParts) => {\n const shown = local(parts);\n const date = wallClock(shown);\n let text = texts[0];\n tokens.forEach((token, index) => {\n let part: string;\n switch (token) {\n case \"yyyy\":\n part = pad(shown.year, 4);\n break;\n case \"yy\":\n part = pad(Math.abs(shown.year) % 100, 2);\n break;\n case \"MMMM\":\n part = name(\"MMMM\", { month: \"long\" }, date);\n break;\n case \"MMM\":\n part = name(\"MMM\", { month: \"short\" }, date);\n break;\n case \"MM\":\n part = pad(shown.month, 2);\n break;\n case \"M\":\n part = String(shown.month);\n break;\n case \"dd\":\n part = pad(shown.day, 2);\n break;\n case \"d\":\n part = String(shown.day);\n break;\n case \"EEEE\":\n part = name(\"EEEE\", { weekday: \"long\" }, date);\n break;\n case \"EEE\":\n part = name(\"EEE\", { weekday: \"short\" }, date);\n break;\n case \"HH\":\n part = pad(shown.hour, 2);\n break;\n case \"H\":\n part = String(shown.hour);\n break;\n case \"hh\":\n part = pad(shown.hour % 12 || 12, 2);\n break;\n case \"h\":\n part = String(shown.hour % 12 || 12);\n break;\n case \"a\":\n part =\n intl(\"a\", () => new Intl.DateTimeFormat(locale, { hour: \"numeric\", hour12: true, timeZone: \"UTC\" }))\n .formatToParts(date)\n .find((item) => item.type === \"dayPeriod\")?.value ?? (shown.hour < 12 ? \"AM\" : \"PM\");\n break;\n case \"mm\":\n part = pad(shown.minute, 2);\n break;\n case \"m\":\n part = String(shown.minute);\n break;\n case \"ss\":\n part = pad(shown.second, 2);\n break;\n case \"s\":\n part = String(shown.second);\n break;\n default:\n part = token.startsWith(\"S\")\n ? shown.fraction.slice(0, token.length).padEnd(token.length, \"0\")\n : token.slice(1, -1).replaceAll(\"''\", \"'\");\n }\n text += part + texts[index + 1];\n });\n return text;\n };\n }\n\n return (parts: DateParts) => {\n const zone = parts.offset !== null ? \"z\" : \"\";\n const shape = custom ? `custom${zone}` : `${parts.hasDate ? \"d\" : \"\"}${parts.hasTime ? \"t\" : \"\"}${zone}`;\n const item = intl(shape, () => {\n const defaults: Intl.DateTimeFormatOptions = custom ? options : {};\n if (!custom && parts.hasDate) Object.assign(defaults, { year: \"numeric\", month: \"2-digit\", day: \"2-digit\" });\n if (!custom && parts.hasTime) Object.assign(defaults, { hour: \"2-digit\", minute: \"2-digit\", second: \"2-digit\" });\n // Values without an offset are wall-clock times: show them as they are.\n return new Intl.DateTimeFormat(locale, { ...defaults, timeZone: parts.offset !== null ? timeZone : \"UTC\" });\n });\n const time = wallClock(parts).getTime() - (parts.offset ?? 0) * 60_000;\n return item.format(time);\n };\n}\n\n/** Whether a column holds numbers. */\nexport function isNumeric(column: Column) {\n return column.type === \"integer\" || column.type === \"bigint\" || column.type === \"decimal\" || column.type === \"float\";\n}\n\nconst TEMPORAL = new Set([\"date\", \"time\", \"timestamp\", \"timestamptz\"]);\n\n/**\n * The text of values of a column by its format, or null where the format says nothing about a value (the grid then\n * shows its text form, §2.4). Formats that Intl refuses (an unknown currency or time zone) give null for every value.\n */\nexport function formatterFor(\n column: Column,\n format: ColumnFormat | undefined,\n locale: string | undefined,\n): ((value: JsonValue) => string | null) | null {\n if (!format?.number && !format?.date) return null;\n let number: ((value: number | string) => string) | null = null;\n let date: ((parts: DateParts) => string) | null = null;\n try {\n if (format.number && isNumeric(column)) number = numberFormatter(locale, format.number, true);\n if (format.date && TEMPORAL.has(column.type)) date = dateFormatter(locale, format.date);\n } catch (error) {\n if (error instanceof RangeError) return null;\n throw error;\n }\n if (!number && !date) return null;\n return (value) => {\n if (value === null) return null;\n if (number) {\n const input = numberInput(value);\n return input === null ? null : number(input);\n }\n if (date && typeof value === \"string\") {\n const parts = parseDate(value.replace(/\\+00$/, \"Z\"));\n return parts ? date(parts) : null;\n }\n return null;\n };\n}\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Measures over the rows of a view (§4.5 of the specification), for the column statistics and the totals row: both
3
+ * are an `aggregate` without keys over the plan's rows (Appendix A), read with `rows` like any view.
4
+ */
5
+ import { type Capabilities, type Column, type DisplayedColumn, type Measure, type MeasureName, type Plan } from "vastgrid-spec";
6
+ import type { TableInfo } from "./types.js";
7
+ /** Whether the engine evaluates a measure (§4.10: absent `measures` are all of them). */
8
+ export declare function offers(capabilities: Capabilities | undefined, fn: MeasureName): boolean;
9
+ /** A statistic of a column: what it is, and the measure that gives it. */
10
+ export interface Statistic {
11
+ kind: "rows" | "values" | "distinct" | "min" | "max" | "sum" | "average" | "median" | "stddev";
12
+ measure: Measure;
13
+ }
14
+ /** The statistics of a column that the engine evaluates and that take its type, with the number of rows first. */
15
+ export declare function statisticsOf(column: Column, capabilities: Capabilities | undefined): Statistic[];
16
+ /** The measures of the totals row (§5.1): one per displayed column with a total, named after the column. */
17
+ export declare function totalMeasures(displayed: readonly DisplayedColumn[]): Measure[];
18
+ /** The plan of measures over the rows of a plan, or null when it groups rows. */
19
+ export declare function measuresPlan(plan: Plan, measures: Measure[]): Plan | null;
20
+ /** The measures that a total can be, for a column's type, in the order the menu offers them. */
21
+ export declare const TOTALS: MeasureName[];
22
+ /** A measure's name as 0.1 wrote it, `sum(amount)` or `count(*)`, with ` (2)`, ` (3)`, … when it is taken. */
23
+ export declare function measureName(fn: MeasureName, column: string | undefined, taken: ReadonlySet<string>): string;
24
+ /** The columns of the rows before grouping: the table's and the derived ones, or the table's when the plan fails. */
25
+ export declare function rowColumns(plan: Plan | undefined, table: TableInfo): readonly Column[];
26
+ //# sourceMappingURL=measures.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"measures.d.ts","sourceRoot":"","sources":["../../src/core/measures.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,MAAM,EAEX,KAAK,eAAe,EACpB,KAAK,OAAO,EACZ,KAAK,WAAW,EAEhB,KAAK,IAAI,EAEV,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAQ5C,yFAAyF;AACzF,wBAAgB,MAAM,CAAC,YAAY,EAAE,YAAY,GAAG,SAAS,EAAE,EAAE,EAAE,WAAW,GAAG,OAAO,CAGvF;AAED,0EAA0E;AAC1E,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC/F,OAAO,EAAE,OAAO,CAAC;CAClB;AAaD,kHAAkH;AAClH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,GAAG,SAAS,GAAG,SAAS,EAAE,CAQhG;AAED,4GAA4G;AAC5G,wBAAgB,aAAa,CAAC,SAAS,EAAE,SAAS,eAAe,EAAE,GAAG,OAAO,EAAE,CAa9E;AAED,iFAAiF;AACjF,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,IAAI,GAAG,IAAI,CAGzE;AAED,gGAAgG;AAChG,eAAO,MAAM,MAAM,EAAE,WAAW,EAA4D,CAAC;AAE7F,8GAA8G;AAC9G,wBAAgB,WAAW,CAAC,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,MAAM,CAK3G;AAED,qHAAqH;AACrH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,EAAE,KAAK,EAAE,SAAS,GAAG,SAAS,MAAM,EAAE,CAOtF"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Measures over the rows of a view (§4.5 of the specification), for the column statistics and the totals row: both
3
+ * are an `aggregate` without keys over the plan's rows (Appendix A), read with `rows` like any view.
4
+ */
5
+ import { checkPlan, measureTakes, planOptions } from "vastgrid-spec";
6
+ /** The rows of a plan before grouping: its derived columns and `where`. Null when the plan groups rows. */
7
+ function rowsPlan(plan) {
8
+ if (plan.aggregate) return null;
9
+ return {
10
+ ...(plan.derive ? {
11
+ derive: plan.derive
12
+ } : {}),
13
+ ...(plan.where ? {
14
+ where: plan.where
15
+ } : {})
16
+ };
17
+ }
18
+
19
+ /** Whether the engine evaluates a measure (§4.10: absent `measures` are all of them). */
20
+ export function offers(capabilities, fn) {
21
+ if (capabilities?.plan?.aggregate === false) return false;
22
+ return capabilities?.measures?.includes(fn) ?? true;
23
+ }
24
+
25
+ /** A statistic of a column: what it is, and the measure that gives it. */
26
+
27
+ const STATISTICS = [["values", "count"], ["distinct", "count_distinct"], ["min", "min"], ["max", "max"], ["sum", "sum"], ["average", "avg"], ["median", "quantile", 0.5], ["stddev", "stddev"]];
28
+
29
+ /** The statistics of a column that the engine evaluates and that take its type, with the number of rows first. */
30
+ export function statisticsOf(column, capabilities) {
31
+ if (!offers(capabilities, "count")) return [];
32
+ const list = [{
33
+ kind: "rows",
34
+ measure: {
35
+ name: "rows",
36
+ fn: "count"
37
+ }
38
+ }];
39
+ for (const [kind, fn, p] of STATISTICS) {
40
+ if (!offers(capabilities, fn) || !measureTakes(fn, column)) continue;
41
+ list.push({
42
+ kind,
43
+ measure: {
44
+ name: kind,
45
+ fn,
46
+ column: column.name,
47
+ ...(p === undefined ? {} : {
48
+ p
49
+ })
50
+ }
51
+ });
52
+ }
53
+ return list;
54
+ }
55
+
56
+ /** The measures of the totals row (§5.1): one per displayed column with a total, named after the column. */
57
+ export function totalMeasures(displayed) {
58
+ return displayed.flatMap(({
59
+ column,
60
+ setting
61
+ }) => setting.total ? [{
62
+ name: column.name,
63
+ fn: setting.total.fn,
64
+ column: column.name,
65
+ ...(setting.total.p === undefined ? {} : {
66
+ p: setting.total.p
67
+ })
68
+ }] : []);
69
+ }
70
+
71
+ /** The plan of measures over the rows of a plan, or null when it groups rows. */
72
+ export function measuresPlan(plan, measures) {
73
+ const rows = rowsPlan(plan);
74
+ return rows && {
75
+ ...rows,
76
+ aggregate: {
77
+ keys: [],
78
+ measures
79
+ }
80
+ };
81
+ }
82
+
83
+ /** The measures that a total can be, for a column's type, in the order the menu offers them. */
84
+ export const TOTALS = ["sum", "avg", "count", "count_distinct", "min", "max"];
85
+
86
+ /** A measure's name as 0.1 wrote it, `sum(amount)` or `count(*)`, with ` (2)`, ` (3)`, … when it is taken. */
87
+ export function measureName(fn, column, taken) {
88
+ const base = `${fn}(${column ?? "*"})`;
89
+ let name = base;
90
+ for (let n = 2; taken.has(name); n++) name = `${base} (${n})`;
91
+ return name;
92
+ }
93
+
94
+ /** The columns of the rows before grouping: the table's and the derived ones, or the table's when the plan fails. */
95
+ export function rowColumns(plan, table) {
96
+ try {
97
+ return checkPlan(rowsPlan({
98
+ ...plan,
99
+ aggregate: undefined
100
+ }) ?? {}, table.columns, planOptions(table.capabilities)).rows;
101
+ } catch {
102
+ return table.columns;
103
+ }
104
+ }
105
+ //# sourceMappingURL=measures.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["checkPlan","measureTakes","planOptions","rowsPlan","plan","aggregate","derive","where","offers","capabilities","fn","measures","includes","STATISTICS","statisticsOf","column","list","kind","measure","name","p","push","undefined","totalMeasures","displayed","flatMap","setting","total","measuresPlan","rows","keys","TOTALS","measureName","taken","base","n","has","rowColumns","table","columns"],"sources":["measures.ts"],"sourcesContent":["/**\n * Measures over the rows of a view (§4.5 of the specification), for the column statistics and the totals row: both\n * are an `aggregate` without keys over the plan's rows (Appendix A), read with `rows` like any view.\n */\nimport {\n type Capabilities,\n type Column,\n checkPlan,\n type DisplayedColumn,\n type Measure,\n type MeasureName,\n measureTakes,\n type Plan,\n planOptions,\n} from \"vastgrid-spec\";\nimport type { TableInfo } from \"./types.js\";\n\n/** The rows of a plan before grouping: its derived columns and `where`. Null when the plan groups rows. */\nfunction rowsPlan(plan: Plan): Plan | null {\n if (plan.aggregate) return null;\n return { ...(plan.derive ? { derive: plan.derive } : {}), ...(plan.where ? { where: plan.where } : {}) };\n}\n\n/** Whether the engine evaluates a measure (§4.10: absent `measures` are all of them). */\nexport function offers(capabilities: Capabilities | undefined, fn: MeasureName): boolean {\n if (capabilities?.plan?.aggregate === false) return false;\n return capabilities?.measures?.includes(fn) ?? true;\n}\n\n/** A statistic of a column: what it is, and the measure that gives it. */\nexport interface Statistic {\n kind: \"rows\" | \"values\" | \"distinct\" | \"min\" | \"max\" | \"sum\" | \"average\" | \"median\" | \"stddev\";\n measure: Measure;\n}\n\nconst STATISTICS: [Statistic[\"kind\"], MeasureName, number?][] = [\n [\"values\", \"count\"],\n [\"distinct\", \"count_distinct\"],\n [\"min\", \"min\"],\n [\"max\", \"max\"],\n [\"sum\", \"sum\"],\n [\"average\", \"avg\"],\n [\"median\", \"quantile\", 0.5],\n [\"stddev\", \"stddev\"],\n];\n\n/** The statistics of a column that the engine evaluates and that take its type, with the number of rows first. */\nexport function statisticsOf(column: Column, capabilities: Capabilities | undefined): Statistic[] {\n if (!offers(capabilities, \"count\")) return [];\n const list: Statistic[] = [{ kind: \"rows\", measure: { name: \"rows\", fn: \"count\" } }];\n for (const [kind, fn, p] of STATISTICS) {\n if (!offers(capabilities, fn) || !measureTakes(fn, column)) continue;\n list.push({ kind, measure: { name: kind, fn, column: column.name, ...(p === undefined ? {} : { p }) } });\n }\n return list;\n}\n\n/** The measures of the totals row (§5.1): one per displayed column with a total, named after the column. */\nexport function totalMeasures(displayed: readonly DisplayedColumn[]): Measure[] {\n return displayed.flatMap(({ column, setting }) =>\n setting.total\n ? [\n {\n name: column.name,\n fn: setting.total.fn,\n column: column.name,\n ...(setting.total.p === undefined ? {} : { p: setting.total.p }),\n },\n ]\n : [],\n );\n}\n\n/** The plan of measures over the rows of a plan, or null when it groups rows. */\nexport function measuresPlan(plan: Plan, measures: Measure[]): Plan | null {\n const rows = rowsPlan(plan);\n return rows && { ...rows, aggregate: { keys: [], measures } };\n}\n\n/** The measures that a total can be, for a column's type, in the order the menu offers them. */\nexport const TOTALS: MeasureName[] = [\"sum\", \"avg\", \"count\", \"count_distinct\", \"min\", \"max\"];\n\n/** A measure's name as 0.1 wrote it, `sum(amount)` or `count(*)`, with ` (2)`, ` (3)`, … when it is taken. */\nexport function measureName(fn: MeasureName, column: string | undefined, taken: ReadonlySet<string>): string {\n const base = `${fn}(${column ?? \"*\"})`;\n let name = base;\n for (let n = 2; taken.has(name); n++) name = `${base} (${n})`;\n return name;\n}\n\n/** The columns of the rows before grouping: the table's and the derived ones, or the table's when the plan fails. */\nexport function rowColumns(plan: Plan | undefined, table: TableInfo): readonly Column[] {\n try {\n return checkPlan(rowsPlan({ ...plan, aggregate: undefined }) ?? {}, table.columns, planOptions(table.capabilities))\n .rows;\n } catch {\n return table.columns;\n }\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA,SAGEA,SAAS,EAITC,YAAY,EAEZC,WAAW,QACN,eAAe;AAGtB;AACA,SAASC,QAAQA,CAACC,IAAU,EAAe;EACzC,IAAIA,IAAI,CAACC,SAAS,EAAE,OAAO,IAAI;EAC/B,OAAO;IAAE,IAAID,IAAI,CAACE,MAAM,GAAG;MAAEA,MAAM,EAAEF,IAAI,CAACE;IAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IAAE,IAAIF,IAAI,CAACG,KAAK,GAAG;MAAEA,KAAK,EAAEH,IAAI,CAACG;IAAM,CAAC,GAAG,CAAC,CAAC;EAAE,CAAC;AAC1G;;AAEA;AACA,OAAO,SAASC,MAAMA,CAACC,YAAsC,EAAEC,EAAe,EAAW;EACvF,IAAID,YAAY,EAAEL,IAAI,EAAEC,SAAS,KAAK,KAAK,EAAE,OAAO,KAAK;EACzD,OAAOI,YAAY,EAAEE,QAAQ,EAAEC,QAAQ,CAACF,EAAE,CAAC,IAAI,IAAI;AACrD;;AAEA;;AAMA,MAAMG,UAAuD,GAAG,CAC9D,CAAC,QAAQ,EAAE,OAAO,CAAC,EACnB,CAAC,UAAU,EAAE,gBAAgB,CAAC,EAC9B,CAAC,KAAK,EAAE,KAAK,CAAC,EACd,CAAC,KAAK,EAAE,KAAK,CAAC,EACd,CAAC,KAAK,EAAE,KAAK,CAAC,EACd,CAAC,SAAS,EAAE,KAAK,CAAC,EAClB,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,CAAC,EAC3B,CAAC,QAAQ,EAAE,QAAQ,CAAC,CACrB;;AAED;AACA,OAAO,SAASC,YAAYA,CAACC,MAAc,EAAEN,YAAsC,EAAe;EAChG,IAAI,CAACD,MAAM,CAACC,YAAY,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE;EAC7C,MAAMO,IAAiB,GAAG,CAAC;IAAEC,IAAI,EAAE,MAAM;IAAEC,OAAO,EAAE;MAAEC,IAAI,EAAE,MAAM;MAAET,EAAE,EAAE;IAAQ;EAAE,CAAC,CAAC;EACpF,KAAK,MAAM,CAACO,IAAI,EAAEP,EAAE,EAAEU,CAAC,CAAC,IAAIP,UAAU,EAAE;IACtC,IAAI,CAACL,MAAM,CAACC,YAAY,EAAEC,EAAE,CAAC,IAAI,CAACT,YAAY,CAACS,EAAE,EAAEK,MAAM,CAAC,EAAE;IAC5DC,IAAI,CAACK,IAAI,CAAC;MAAEJ,IAAI;MAAEC,OAAO,EAAE;QAAEC,IAAI,EAAEF,IAAI;QAAEP,EAAE;QAAEK,MAAM,EAAEA,MAAM,CAACI,IAAI;QAAE,IAAIC,CAAC,KAAKE,SAAS,GAAG,CAAC,CAAC,GAAG;UAAEF;QAAE,CAAC;MAAE;IAAE,CAAC,CAAC;EAC1G;EACA,OAAOJ,IAAI;AACb;;AAEA;AACA,OAAO,SAASO,aAAaA,CAACC,SAAqC,EAAa;EAC9E,OAAOA,SAAS,CAACC,OAAO,CAAC,CAAC;IAAEV,MAAM;IAAEW;EAAQ,CAAC,KAC3CA,OAAO,CAACC,KAAK,GACT,CACE;IACER,IAAI,EAAEJ,MAAM,CAACI,IAAI;IACjBT,EAAE,EAAEgB,OAAO,CAACC,KAAK,CAACjB,EAAE;IACpBK,MAAM,EAAEA,MAAM,CAACI,IAAI;IACnB,IAAIO,OAAO,CAACC,KAAK,CAACP,CAAC,KAAKE,SAAS,GAAG,CAAC,CAAC,GAAG;MAAEF,CAAC,EAAEM,OAAO,CAACC,KAAK,CAACP;IAAE,CAAC;EACjE,CAAC,CACF,GACD,EACN,CAAC;AACH;;AAEA;AACA,OAAO,SAASQ,YAAYA,CAACxB,IAAU,EAAEO,QAAmB,EAAe;EACzE,MAAMkB,IAAI,GAAG1B,QAAQ,CAACC,IAAI,CAAC;EAC3B,OAAOyB,IAAI,IAAI;IAAE,GAAGA,IAAI;IAAExB,SAAS,EAAE;MAAEyB,IAAI,EAAE,EAAE;MAAEnB;IAAS;EAAE,CAAC;AAC/D;;AAEA;AACA,OAAO,MAAMoB,MAAqB,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,gBAAgB,EAAE,KAAK,EAAE,KAAK,CAAC;;AAE5F;AACA,OAAO,SAASC,WAAWA,CAACtB,EAAe,EAAEK,MAA0B,EAAEkB,KAA0B,EAAU;EAC3G,MAAMC,IAAI,GAAG,GAAGxB,EAAE,IAAIK,MAAM,IAAI,GAAG,GAAG;EACtC,IAAII,IAAI,GAAGe,IAAI;EACf,KAAK,IAAIC,CAAC,GAAG,CAAC,EAAEF,KAAK,CAACG,GAAG,CAACjB,IAAI,CAAC,EAAEgB,CAAC,EAAE,EAAEhB,IAAI,GAAG,GAAGe,IAAI,KAAKC,CAAC,GAAG;EAC7D,OAAOhB,IAAI;AACb;;AAEA;AACA,OAAO,SAASkB,UAAUA,CAACjC,IAAsB,EAAEkC,KAAgB,EAAqB;EACtF,IAAI;IACF,OAAOtC,SAAS,CAACG,QAAQ,CAAC;MAAE,GAAGC,IAAI;MAAEC,SAAS,EAAEiB;IAAU,CAAC,CAAC,IAAI,CAAC,CAAC,EAAEgB,KAAK,CAACC,OAAO,EAAErC,WAAW,CAACoC,KAAK,CAAC7B,YAAY,CAAC,CAAC,CAChHoB,IAAI;EACT,CAAC,CAAC,MAAM;IACN,OAAOS,KAAK,CAACC,OAAO;EACtB;AACF","ignoreList":[]}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Ids of requests (§8.1 of the specification) for several clients of one engine, such as the Apps and the grids of
3
+ * an MCP server or the webviews of an editor. Each client chooses ids of its own, which the engine would mix up (a `cancel` of one
4
+ * client's request would stop another's): the requests of each client get ids that are unique in the engine, and
5
+ * the answers get the client's ids back.
6
+ */
7
+ /** What the clients share: the engine's `handle`, as `DuckDBEngine` has it. */
8
+ export interface Handler {
9
+ handle(message: unknown, options?: {
10
+ signal?: AbortSignal;
11
+ }): Promise<unknown>;
12
+ }
13
+ export declare class RequestIds {
14
+ private readonly engine;
15
+ private next;
16
+ constructor(engine: Handler);
17
+ /** A client of the engine whose requests keep their ids apart from those of the others. */
18
+ client(): Handler;
19
+ }
20
+ //# sourceMappingURL=request-ids.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-ids.d.ts","sourceRoot":"","sources":["../../src/core/request-ids.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,+EAA+E;AAC/E,MAAM,WAAW,OAAO;IACtB,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAChF;AAUD,qBAAa,UAAU;IAGT,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFnC,OAAO,CAAC,IAAI,CAAK;IAEjB,YAA6B,MAAM,EAAE,OAAO,EAAI;IAEhD,2FAA2F;IAC3F,MAAM,IAAI,OAAO,CAwBhB;CACF"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Ids of requests (§8.1 of the specification) for several clients of one engine, such as the Apps and the grids of
3
+ * an MCP server or the webviews of an editor. Each client chooses ids of its own, which the engine would mix up (a `cancel` of one
4
+ * client's request would stop another's): the requests of each client get ids that are unique in the engine, and
5
+ * the answers get the client's ids back.
6
+ */
7
+
8
+ /** What the clients share: the engine's `handle`, as `DuckDBEngine` has it. */
9
+
10
+ function isObject(value) {
11
+ return value !== null && typeof value === "object" && !Array.isArray(value);
12
+ }
13
+ function isId(value) {
14
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
15
+ }
16
+ export class RequestIds {
17
+ next = 1;
18
+ constructor(engine) {
19
+ this.engine = engine;
20
+ }
21
+
22
+ /** A client of the engine whose requests keep their ids apart from those of the others. */
23
+ client() {
24
+ // The engine's ids of this client's requests in flight, by the client's ids.
25
+ const running = new Map();
26
+ return {
27
+ handle: async (message, options) => {
28
+ // A message without a valid id is the engine's to refuse, as it is (§8.1).
29
+ if (!isObject(message) || !isId(message.id)) return this.engine.handle(message, options);
30
+ const own = message.id;
31
+ const id = this.next++;
32
+ const sent = {
33
+ ...message,
34
+ id
35
+ };
36
+ if (message.op === "cancel" && isId(message.request)) {
37
+ // A request that is not running any more is cancelled under an id that no request has.
38
+ sent.request = running.get(message.request) ?? this.next++;
39
+ } else {
40
+ running.set(own, id);
41
+ }
42
+ try {
43
+ const answer = await this.engine.handle(sent, options);
44
+ return isObject(answer) && answer.id === id ? {
45
+ ...answer,
46
+ id: own
47
+ } : answer;
48
+ } finally {
49
+ if (running.get(own) === id) running.delete(own);
50
+ }
51
+ }
52
+ };
53
+ }
54
+ }
55
+ //# sourceMappingURL=request-ids.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["isObject","value","Array","isArray","isId","Number","isSafeInteger","RequestIds","next","constructor","engine","client","running","Map","handle","message","options","id","own","sent","op","request","get","set","answer","delete"],"sources":["request-ids.ts"],"sourcesContent":["/**\n * Ids of requests (§8.1 of the specification) for several clients of one engine, such as the Apps and the grids of\n * an MCP server or the webviews of an editor. Each client chooses ids of its own, which the engine would mix up (a `cancel` of one\n * client's request would stop another's): the requests of each client get ids that are unique in the engine, and\n * the answers get the client's ids back.\n */\n\ntype Json = Record<string, unknown>;\n\n/** What the clients share: the engine's `handle`, as `DuckDBEngine` has it. */\nexport interface Handler {\n handle(message: unknown, options?: { signal?: AbortSignal }): Promise<unknown>;\n}\n\nfunction isObject(value: unknown): value is Json {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction isId(value: unknown): value is number {\n return typeof value === \"number\" && Number.isSafeInteger(value) && value >= 0;\n}\n\nexport class RequestIds {\n private next = 1;\n\n constructor(private readonly engine: Handler) {}\n\n /** A client of the engine whose requests keep their ids apart from those of the others. */\n client(): Handler {\n // The engine's ids of this client's requests in flight, by the client's ids.\n const running = new Map<number, number>();\n return {\n handle: async (message, options) => {\n // A message without a valid id is the engine's to refuse, as it is (§8.1).\n if (!isObject(message) || !isId(message.id)) return this.engine.handle(message, options);\n const own = message.id;\n const id = this.next++;\n const sent: Json = { ...message, id };\n if (message.op === \"cancel\" && isId(message.request)) {\n // A request that is not running any more is cancelled under an id that no request has.\n sent.request = running.get(message.request) ?? this.next++;\n } else {\n running.set(own, id);\n }\n try {\n const answer = await this.engine.handle(sent, options);\n return isObject(answer) && answer.id === id ? { ...answer, id: own } : answer;\n } finally {\n if (running.get(own) === id) running.delete(own);\n }\n },\n };\n }\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;;AAIA;;AAKA,SAASA,QAAQA,CAACC,KAAc,EAAiB;EAC/C,OAAOA,KAAK,KAAK,IAAI,IAAI,OAAOA,KAAK,KAAK,QAAQ,IAAI,CAACC,KAAK,CAACC,OAAO,CAACF,KAAK,CAAC;AAC7E;AAEA,SAASG,IAAIA,CAACH,KAAc,EAAmB;EAC7C,OAAO,OAAOA,KAAK,KAAK,QAAQ,IAAII,MAAM,CAACC,aAAa,CAACL,KAAK,CAAC,IAAIA,KAAK,IAAI,CAAC;AAC/E;AAEA,OAAO,MAAMM,UAAU,CAAC;EACdC,IAAI,GAAG,CAAC;EAEhBC,WAAWA,CAAkBC,MAAe,EAAE;IAAA,KAAjBA,MAAe,GAAfA,MAAe;EAAG;;EAE/C;EACAC,MAAMA,CAAA,EAAY;IAChB;IACA,MAAMC,OAAO,GAAG,IAAIC,GAAG,CAAiB,CAAC;IACzC,OAAO;MACLC,MAAM,EAAE,MAAAA,CAAOC,OAAO,EAAEC,OAAO,KAAK;QAClC;QACA,IAAI,CAAChB,QAAQ,CAACe,OAAO,CAAC,IAAI,CAACX,IAAI,CAACW,OAAO,CAACE,EAAE,CAAC,EAAE,OAAO,IAAI,CAACP,MAAM,CAACI,MAAM,CAACC,OAAO,EAAEC,OAAO,CAAC;QACxF,MAAME,GAAG,GAAGH,OAAO,CAACE,EAAE;QACtB,MAAMA,EAAE,GAAG,IAAI,CAACT,IAAI,EAAE;QACtB,MAAMW,IAAU,GAAG;UAAE,GAAGJ,OAAO;UAAEE;QAAG,CAAC;QACrC,IAAIF,OAAO,CAACK,EAAE,KAAK,QAAQ,IAAIhB,IAAI,CAACW,OAAO,CAACM,OAAO,CAAC,EAAE;UACpD;UACAF,IAAI,CAACE,OAAO,GAAGT,OAAO,CAACU,GAAG,CAACP,OAAO,CAACM,OAAO,CAAC,IAAI,IAAI,CAACb,IAAI,EAAE;QAC5D,CAAC,MAAM;UACLI,OAAO,CAACW,GAAG,CAACL,GAAG,EAAED,EAAE,CAAC;QACtB;QACA,IAAI;UACF,MAAMO,MAAM,GAAG,MAAM,IAAI,CAACd,MAAM,CAACI,MAAM,CAACK,IAAI,EAAEH,OAAO,CAAC;UACtD,OAAOhB,QAAQ,CAACwB,MAAM,CAAC,IAAIA,MAAM,CAACP,EAAE,KAAKA,EAAE,GAAG;YAAE,GAAGO,MAAM;YAAEP,EAAE,EAAEC;UAAI,CAAC,GAAGM,MAAM;QAC/E,CAAC,SAAS;UACR,IAAIZ,OAAO,CAACU,GAAG,CAACJ,GAAG,CAAC,KAAKD,EAAE,EAAEL,OAAO,CAACa,MAAM,CAACP,GAAG,CAAC;QAClD;MACF;IACF,CAAC;EACH;AACF","ignoreList":[]}
@@ -0,0 +1,79 @@
1
+ import { type CheckedPlan, type Column, type Plan } from "vastgrid-spec";
2
+ import { type Read, type ViewCache } from "./cache.js";
3
+ import type { GridClient } from "./client.js";
4
+ import type { TableInfo, ViewInfo } from "./types.js";
5
+ /** Where the canvas is: its first row, how many rows it shows and the columns it draws. */
6
+ export interface Viewport {
7
+ top: number;
8
+ rows: number;
9
+ columns: readonly string[];
10
+ }
11
+ /** A view of the document's plan, being read or on screen. */
12
+ export interface View {
13
+ readonly key: string;
14
+ readonly plan: Plan;
15
+ readonly checked: CheckedPlan;
16
+ /** The table's revision and edits version that the view's rows belong to. */
17
+ readonly revision: string | null;
18
+ readonly edits: number;
19
+ info: ViewInfo | null;
20
+ readonly cache: ViewCache;
21
+ readonly abort: AbortController;
22
+ }
23
+ /** Whether two lists of columns have the same names and types. */
24
+ export declare function sameColumns(a: readonly Column[], b: readonly Column[]): boolean;
25
+ /** What a `RowReader` reads with: the views, the connection and the state of its store, and where rows go. */
26
+ export interface ReadHost {
27
+ /** The view on screen. */
28
+ current(): View | null;
29
+ /** The view being made, which comes on screen once its first rows are read (§4.2 of react.md). */
30
+ next(): View | null;
31
+ client(): GridClient | null;
32
+ table(): TableInfo | null;
33
+ /** Whether the table is open for the current connection. */
34
+ opened(): boolean;
35
+ /** The document's row key column (§5.3). */
36
+ rowKey(): string | undefined;
37
+ /** Whether the session's active cell has the key of its row (§5.2). */
38
+ keyed(): boolean;
39
+ /** A read changed the info of the view on screen. */
40
+ showView(info: ViewInfo): void;
41
+ /** Rows of the view on screen arrived. */
42
+ showRows(): void;
43
+ /** A read of the view on screen or of the one being made failed. */
44
+ fail(error: unknown): void;
45
+ }
46
+ /**
47
+ * Reads the rows of a store's views into their caches (§4.1 of react.md): those on screen and a page around
48
+ * them, within a budget of bytes, and those that the store asks for. Rows that come for a view that is no longer
49
+ * on screen or being made are dropped.
50
+ */
51
+ export declare class RowReader {
52
+ private readonly host;
53
+ private readonly budget;
54
+ /** What the canvas shows, as `setViewport` was told last. */
55
+ viewport: Viewport;
56
+ private scheduled;
57
+ constructor(host: ReadHost, budget: number);
58
+ /** Follows what the canvas shows, and reads those rows and a page around them. */
59
+ setViewport(viewport: Viewport): void;
60
+ /** Reads rows `[start, end)` of `columns` of the view on screen if they are not read, for cells React renders. */
61
+ ensure(start: number, end: number, columns: readonly string[]): void;
62
+ /** Reads the rows on screen once the current task is done, once for all the changes it makes. */
63
+ schedule(): void;
64
+ /** The rows from `row` for a viewport, in whole blocks. */
65
+ around(row: number, rowCount: number | null, columns: readonly string[]): Read;
66
+ /** The columns of a view to read: those asked for that it has and its row key column, at least one. */
67
+ withKeyFor(view: View, columns: readonly string[]): string[];
68
+ /** Reads the rows that a command needs (`not_loaded`, §6.1), in whole blocks. */
69
+ load(view: View, details: {
70
+ rows: [number, number][];
71
+ columns: string[];
72
+ }): Promise<void>;
73
+ /** Reads rows of a view into its cache. */
74
+ read(view: View, read: Read): Promise<void>;
75
+ /** The columns to read: those asked for, and the row key column (§5.3), which commands need. */
76
+ private withKey;
77
+ private readVisible;
78
+ }
79
+ //# sourceMappingURL=rows.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rows.d.ts","sourceRoot":"","sources":["../../src/core/rows.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,173 @@
1
+ import { canonicalJson, decodeBlock } from "vastgrid-spec";
2
+ import { BLOCK_ROWS } from "./cache.js";
3
+
4
+ /** Where the canvas is: its first row, how many rows it shows and the columns it draws. */
5
+
6
+ /** A view of the document's plan, being read or on screen. */
7
+
8
+ /** Whether two lists of columns have the same names and types. */
9
+ export function sameColumns(a, b) {
10
+ return a.length === b.length && a.every((column, index) => canonicalJson(column) === canonicalJson(b[index]));
11
+ }
12
+
13
+ /** What a `RowReader` reads with: the views, the connection and the state of its store, and where rows go. */
14
+
15
+ /**
16
+ * Reads the rows of a store's views into their caches (§4.1 of react.md): those on screen and a page around
17
+ * them, within a budget of bytes, and those that the store asks for. Rows that come for a view that is no longer
18
+ * on screen or being made are dropped.
19
+ */
20
+ export class RowReader {
21
+ /** What the canvas shows, as `setViewport` was told last. */
22
+ viewport = {
23
+ top: 0,
24
+ rows: 0,
25
+ columns: []
26
+ };
27
+ scheduled = false;
28
+ constructor(host, budget) {
29
+ this.host = host;
30
+ this.budget = budget;
31
+ }
32
+
33
+ /** Follows what the canvas shows, and reads those rows and a page around them. */
34
+ setViewport(viewport) {
35
+ const before = this.viewport;
36
+ if (before.top === viewport.top && before.rows === viewport.rows && before.columns.length === viewport.columns.length && before.columns.every((column, index) => column === viewport.columns[index])) {
37
+ return;
38
+ }
39
+ this.viewport = viewport;
40
+ this.schedule();
41
+ }
42
+
43
+ /** Reads rows `[start, end)` of `columns` of the view on screen if they are not read, for cells React renders. */
44
+ ensure(start, end, columns) {
45
+ const view = this.host.current();
46
+ if (!view?.info || !this.host.opened() || this.host.next() || view.abort.signal.aborted) return;
47
+ for (const read of view.cache.reads(start, end, this.withKey(columns), view.info.rowCount)) {
48
+ void this.read(view, read).catch(() => {});
49
+ }
50
+ }
51
+
52
+ /** Reads the rows on screen once the current task is done, once for all the changes it makes. */
53
+ schedule() {
54
+ if (this.scheduled) return;
55
+ this.scheduled = true;
56
+ queueMicrotask(() => {
57
+ this.scheduled = false;
58
+ this.readVisible();
59
+ });
60
+ }
61
+
62
+ /** The rows from `row` for a viewport, in whole blocks. */
63
+ around(row, rowCount, columns) {
64
+ const start = Math.floor(row / BLOCK_ROWS) * BLOCK_ROWS;
65
+ const rows = Math.max(this.viewport.rows, 1);
66
+ let end = Math.ceil((row + rows) / BLOCK_ROWS) * BLOCK_ROWS;
67
+ if (rowCount !== null) end = Math.min(end, Math.max(rowCount, start + 1));
68
+ return {
69
+ start,
70
+ end: Math.max(end, start + 1),
71
+ columns: [...columns]
72
+ };
73
+ }
74
+
75
+ /** The columns of a view to read: those asked for that it has and its row key column, at least one. */
76
+ withKeyFor(view, columns) {
77
+ const names = new Set(view.checked.columns.map(column => column.name));
78
+ const wanted = columns.filter(column => names.has(column));
79
+ const key = this.host.rowKey();
80
+ if (key !== undefined && names.has(key) && !wanted.includes(key)) wanted.push(key);
81
+ if (wanted.length === 0 && view.checked.columns.length > 0) wanted.push(view.checked.columns[0].name);
82
+ return wanted;
83
+ }
84
+
85
+ /** Reads the rows that a command needs (`not_loaded`, §6.1), in whole blocks. */
86
+ async load(view, details) {
87
+ const rowCount = view.info?.rowCount ?? 0;
88
+ const columns = this.withKeyFor(view, details.columns);
89
+ const reads = [];
90
+ for (const [start, end] of details.rows) {
91
+ const first = Math.floor(start / BLOCK_ROWS) * BLOCK_ROWS;
92
+ const last = Math.min(rowCount, Math.ceil(end / BLOCK_ROWS) * BLOCK_ROWS);
93
+ for (let at = first; at < last; at += BLOCK_ROWS * 16) {
94
+ reads.push(this.read(view, {
95
+ start: at,
96
+ end: Math.min(last, at + BLOCK_ROWS * 16),
97
+ columns
98
+ }));
99
+ }
100
+ }
101
+ await Promise.all(reads);
102
+ }
103
+
104
+ /** Reads rows of a view into its cache. */
105
+ async read(view, read) {
106
+ const client = this.host.client();
107
+ const table = this.host.table();
108
+ if (!client || !table) return;
109
+ view.cache.reading(read, true);
110
+ try {
111
+ const result = await client.request("rows", {
112
+ table: table.table,
113
+ revision: view.revision,
114
+ plan: view.plan,
115
+ start: read.start,
116
+ end: read.end,
117
+ columns: read.columns,
118
+ // A keyed selection needs locate on the complete view before its position can change.
119
+ ...(!view.info && table.capabilities.preview && !this.host.keyed() ? {
120
+ preview: true
121
+ } : {})
122
+ }, view.abort.signal);
123
+ if (view !== this.host.current() && view !== this.host.next()) return;
124
+ const block = decodeBlock(result.block.bytes);
125
+ view.cache.receive(result.start, result.rowIds, block.columns.map(column => column.name), block.rows, result.truncated);
126
+ const info = result.view;
127
+ view.cache.reading(read, false);
128
+ // A ready event can arrive before the response containing the preview.
129
+ if (!(view.info?.status === "ready" && info.status === "building") && (!view.info || view.info.rowCount !== info.rowCount || view.info.status !== info.status || view.info.readableRows !== info.readableRows)) {
130
+ view.info = view.info && sameColumns(view.info.columns, info.columns) ? {
131
+ ...info,
132
+ columns: view.info.columns
133
+ } : info;
134
+ if (view === this.host.current()) this.host.showView(view.info);
135
+ }
136
+ if (view === this.host.current()) this.host.showRows();
137
+ } catch (error) {
138
+ view.cache.reading(read, false);
139
+ if (view === this.host.current() || view === this.host.next()) this.host.fail(error);
140
+ throw error;
141
+ }
142
+ }
143
+
144
+ /** The columns to read: those asked for, and the row key column (§5.3), which commands need. */
145
+ withKey(columns) {
146
+ const key = this.host.rowKey();
147
+ const view = this.host.current()?.info?.columns ?? [];
148
+ if (key === undefined || columns.includes(key) || !view.some(column => column.name === key)) {
149
+ return [...columns];
150
+ }
151
+ return [...columns, key];
152
+ }
153
+ readVisible() {
154
+ const view = this.host.current();
155
+ if (!view?.info || !this.host.opened() || this.host.next() || view.abort.signal.aborted) return;
156
+ const {
157
+ top,
158
+ rows,
159
+ columns
160
+ } = this.viewport;
161
+ if (columns.length === 0) return;
162
+ const margin = Math.max(rows, 32);
163
+ const start = Math.max(0, top - margin);
164
+ const readable = view.info.status === "building" ? view.info.readableRows : view.info.rowCount;
165
+ const end = Math.min(readable, top + rows + margin);
166
+ view.cache.touch(top, top + rows);
167
+ for (const read of view.cache.reads(start, end, this.withKey(columns), readable)) {
168
+ void this.read(view, read).catch(() => {});
169
+ }
170
+ view.cache.evict(this.budget, start, end);
171
+ }
172
+ }
173
+ //# sourceMappingURL=rows.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["canonicalJson","decodeBlock","BLOCK_ROWS","sameColumns","a","b","length","every","column","index","RowReader","viewport","top","rows","columns","scheduled","constructor","host","budget","setViewport","before","schedule","ensure","start","end","view","current","info","opened","next","abort","signal","aborted","read","cache","reads","withKey","rowCount","catch","queueMicrotask","readVisible","around","row","Math","floor","max","ceil","min","withKeyFor","names","Set","checked","map","name","wanted","filter","has","key","rowKey","undefined","includes","push","load","details","first","last","at","Promise","all","client","table","reading","result","request","revision","plan","capabilities","preview","keyed","block","bytes","receive","rowIds","truncated","status","readableRows","showView","showRows","error","fail","some","margin","readable","touch","evict"],"sources":["rows.ts"],"sourcesContent":["import { type CheckedPlan, type Column, canonicalJson, decodeBlock, type Plan } from \"vastgrid-spec\";\nimport { BLOCK_ROWS, type Read, type ViewCache } from \"./cache.js\";\nimport type { GridClient } from \"./client.js\";\nimport type { RowsResult, TableInfo, ViewInfo } from \"./types.js\";\n\n/** Where the canvas is: its first row, how many rows it shows and the columns it draws. */\nexport interface Viewport {\n top: number;\n rows: number;\n columns: readonly string[];\n}\n\n/** A view of the document's plan, being read or on screen. */\nexport interface View {\n readonly key: string;\n readonly plan: Plan;\n readonly checked: CheckedPlan;\n /** The table's revision and edits version that the view's rows belong to. */\n readonly revision: string | null;\n readonly edits: number;\n info: ViewInfo | null;\n readonly cache: ViewCache;\n readonly abort: AbortController;\n}\n\n/** Whether two lists of columns have the same names and types. */\nexport function sameColumns(a: readonly Column[], b: readonly Column[]) {\n return a.length === b.length && a.every((column, index) => canonicalJson(column) === canonicalJson(b[index]));\n}\n\n/** What a `RowReader` reads with: the views, the connection and the state of its store, and where rows go. */\nexport interface ReadHost {\n /** The view on screen. */\n current(): View | null;\n /** The view being made, which comes on screen once its first rows are read (§4.2 of react.md). */\n next(): View | null;\n client(): GridClient | null;\n table(): TableInfo | null;\n /** Whether the table is open for the current connection. */\n opened(): boolean;\n /** The document's row key column (§5.3). */\n rowKey(): string | undefined;\n /** Whether the session's active cell has the key of its row (§5.2). */\n keyed(): boolean;\n /** A read changed the info of the view on screen. */\n showView(info: ViewInfo): void;\n /** Rows of the view on screen arrived. */\n showRows(): void;\n /** A read of the view on screen or of the one being made failed. */\n fail(error: unknown): void;\n}\n\n/**\n * Reads the rows of a store's views into their caches (§4.1 of react.md): those on screen and a page around\n * them, within a budget of bytes, and those that the store asks for. Rows that come for a view that is no longer\n * on screen or being made are dropped.\n */\nexport class RowReader {\n /** What the canvas shows, as `setViewport` was told last. */\n viewport: Viewport = { top: 0, rows: 0, columns: [] };\n private scheduled = false;\n\n constructor(\n private readonly host: ReadHost,\n private readonly budget: number,\n ) {}\n\n /** Follows what the canvas shows, and reads those rows and a page around them. */\n setViewport(viewport: Viewport) {\n const before = this.viewport;\n if (\n before.top === viewport.top &&\n before.rows === viewport.rows &&\n before.columns.length === viewport.columns.length &&\n before.columns.every((column, index) => column === viewport.columns[index])\n ) {\n return;\n }\n this.viewport = viewport;\n this.schedule();\n }\n\n /** Reads rows `[start, end)` of `columns` of the view on screen if they are not read, for cells React renders. */\n ensure(start: number, end: number, columns: readonly string[]) {\n const view = this.host.current();\n if (!view?.info || !this.host.opened() || this.host.next() || view.abort.signal.aborted) return;\n for (const read of view.cache.reads(start, end, this.withKey(columns), view.info.rowCount)) {\n void this.read(view, read).catch(() => {});\n }\n }\n\n /** Reads the rows on screen once the current task is done, once for all the changes it makes. */\n schedule() {\n if (this.scheduled) return;\n this.scheduled = true;\n queueMicrotask(() => {\n this.scheduled = false;\n this.readVisible();\n });\n }\n\n /** The rows from `row` for a viewport, in whole blocks. */\n around(row: number, rowCount: number | null, columns: readonly string[]): Read {\n const start = Math.floor(row / BLOCK_ROWS) * BLOCK_ROWS;\n const rows = Math.max(this.viewport.rows, 1);\n let end = Math.ceil((row + rows) / BLOCK_ROWS) * BLOCK_ROWS;\n if (rowCount !== null) end = Math.min(end, Math.max(rowCount, start + 1));\n return { start, end: Math.max(end, start + 1), columns: [...columns] };\n }\n\n /** The columns of a view to read: those asked for that it has and its row key column, at least one. */\n withKeyFor(view: View, columns: readonly string[]): string[] {\n const names = new Set(view.checked.columns.map((column) => column.name));\n const wanted = columns.filter((column) => names.has(column));\n const key = this.host.rowKey();\n if (key !== undefined && names.has(key) && !wanted.includes(key)) wanted.push(key);\n if (wanted.length === 0 && view.checked.columns.length > 0) wanted.push(view.checked.columns[0].name);\n return wanted;\n }\n\n /** Reads the rows that a command needs (`not_loaded`, §6.1), in whole blocks. */\n async load(view: View, details: { rows: [number, number][]; columns: string[] }) {\n const rowCount = view.info?.rowCount ?? 0;\n const columns = this.withKeyFor(view, details.columns);\n const reads: Promise<void>[] = [];\n for (const [start, end] of details.rows) {\n const first = Math.floor(start / BLOCK_ROWS) * BLOCK_ROWS;\n const last = Math.min(rowCount, Math.ceil(end / BLOCK_ROWS) * BLOCK_ROWS);\n for (let at = first; at < last; at += BLOCK_ROWS * 16) {\n reads.push(this.read(view, { start: at, end: Math.min(last, at + BLOCK_ROWS * 16), columns }));\n }\n }\n await Promise.all(reads);\n }\n\n /** Reads rows of a view into its cache. */\n async read(view: View, read: Read): Promise<void> {\n const client = this.host.client();\n const table = this.host.table();\n if (!client || !table) return;\n view.cache.reading(read, true);\n try {\n const result = await client.request<RowsResult>(\n \"rows\",\n {\n table: table.table,\n revision: view.revision,\n plan: view.plan,\n start: read.start,\n end: read.end,\n columns: read.columns,\n // A keyed selection needs locate on the complete view before its position can change.\n ...(!view.info && table.capabilities.preview && !this.host.keyed() ? { preview: true } : {}),\n },\n view.abort.signal,\n );\n if (view !== this.host.current() && view !== this.host.next()) return;\n const block = decodeBlock(result.block.bytes);\n view.cache.receive(\n result.start,\n result.rowIds,\n block.columns.map((column) => column.name),\n block.rows,\n result.truncated,\n );\n const info = result.view;\n view.cache.reading(read, false);\n // A ready event can arrive before the response containing the preview.\n if (\n !(view.info?.status === \"ready\" && info.status === \"building\") &&\n (!view.info ||\n view.info.rowCount !== info.rowCount ||\n view.info.status !== info.status ||\n view.info.readableRows !== info.readableRows)\n ) {\n view.info =\n view.info && sameColumns(view.info.columns, info.columns) ? { ...info, columns: view.info.columns } : info;\n if (view === this.host.current()) this.host.showView(view.info);\n }\n if (view === this.host.current()) this.host.showRows();\n } catch (error) {\n view.cache.reading(read, false);\n if (view === this.host.current() || view === this.host.next()) this.host.fail(error);\n throw error;\n }\n }\n\n /** The columns to read: those asked for, and the row key column (§5.3), which commands need. */\n private withKey(columns: readonly string[]): string[] {\n const key = this.host.rowKey();\n const view = this.host.current()?.info?.columns ?? [];\n if (key === undefined || columns.includes(key) || !view.some((column) => column.name === key)) {\n return [...columns];\n }\n return [...columns, key];\n }\n\n private readVisible() {\n const view = this.host.current();\n if (!view?.info || !this.host.opened() || this.host.next() || view.abort.signal.aborted) return;\n const { top, rows, columns } = this.viewport;\n if (columns.length === 0) return;\n const margin = Math.max(rows, 32);\n const start = Math.max(0, top - margin);\n const readable = view.info.status === \"building\" ? view.info.readableRows : view.info.rowCount;\n const end = Math.min(readable, top + rows + margin);\n view.cache.touch(top, top + rows);\n for (const read of view.cache.reads(start, end, this.withKey(columns), readable)) {\n void this.read(view, read).catch(() => {});\n }\n view.cache.evict(this.budget, start, end);\n }\n}\n"],"mappings":"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","ignoreList":[]}