@honua/sdk-esri-compat 0.1.12 → 0.1.14

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 (250) hide show
  1. package/README.md +2 -0
  2. package/columnar/apache-arrow.d.ts +17 -0
  3. package/columnar/apache-arrow.d.ts.map +1 -0
  4. package/columnar/apache-arrow.js +1036 -0
  5. package/columnar/batch-cache-conformance.d.ts +66 -0
  6. package/columnar/batch-cache-conformance.d.ts.map +1 -0
  7. package/columnar/batch-cache-conformance.js +317 -0
  8. package/columnar/batch-cache-indexeddb.d.ts +31 -0
  9. package/columnar/batch-cache-indexeddb.d.ts.map +1 -0
  10. package/columnar/batch-cache-indexeddb.js +148 -0
  11. package/columnar/batch-cache.d.ts +298 -0
  12. package/columnar/batch-cache.d.ts.map +1 -0
  13. package/columnar/batch-cache.js +757 -0
  14. package/columnar/geoarrow-aggregate.d.ts +178 -0
  15. package/columnar/geoarrow-aggregate.d.ts.map +1 -0
  16. package/columnar/geoarrow-aggregate.js +976 -0
  17. package/columnar/geoarrow-patch.d.ts +382 -0
  18. package/columnar/geoarrow-patch.d.ts.map +1 -0
  19. package/columnar/geoarrow-patch.js +1656 -0
  20. package/columnar/geoarrow-reproject.d.ts +22 -0
  21. package/columnar/geoarrow-reproject.d.ts.map +1 -0
  22. package/columnar/geoarrow-reproject.js +119 -0
  23. package/columnar/geoarrow-serialization.d.ts +68 -0
  24. package/columnar/geoarrow-serialization.d.ts.map +1 -0
  25. package/columnar/geoarrow-serialization.js +331 -0
  26. package/columnar/geoarrow-types.d.ts +271 -0
  27. package/columnar/geoarrow-types.d.ts.map +1 -0
  28. package/columnar/geoarrow-types.js +15 -0
  29. package/columnar/geoarrow.d.ts +52 -0
  30. package/columnar/geoarrow.d.ts.map +1 -0
  31. package/columnar/geoarrow.js +1469 -0
  32. package/columnar/index.d.ts +43 -0
  33. package/columnar/index.d.ts.map +1 -0
  34. package/columnar/index.js +29 -0
  35. package/columnar/operators.d.ts +70 -0
  36. package/columnar/operators.d.ts.map +1 -0
  37. package/columnar/operators.js +307 -0
  38. package/columnar/result.d.ts +369 -0
  39. package/columnar/result.d.ts.map +1 -0
  40. package/columnar/result.js +815 -0
  41. package/columnar/telemetry.d.ts +152 -0
  42. package/columnar/telemetry.d.ts.map +1 -0
  43. package/columnar/telemetry.js +265 -0
  44. package/columnar/transfer.d.ts +28 -0
  45. package/columnar/transfer.d.ts.map +1 -0
  46. package/columnar/transfer.js +669 -0
  47. package/columnar/types.d.ts +175 -0
  48. package/columnar/types.d.ts.map +1 -0
  49. package/columnar/types.js +22 -0
  50. package/columnar/worker.d.ts +157 -0
  51. package/columnar/worker.d.ts.map +1 -0
  52. package/columnar/worker.js +1059 -0
  53. package/connect-url-safety.d.ts +53 -0
  54. package/connect-url-safety.js +189 -0
  55. package/contract/pmtiles.d.ts +6 -5
  56. package/contract/pmtiles.d.ts.map +1 -1
  57. package/contract/pmtiles.js +30 -5
  58. package/contract/source.d.ts.map +1 -1
  59. package/contract/source.js +11 -8
  60. package/core/client.d.ts.map +1 -1
  61. package/core/client.js +87 -19
  62. package/core/deprecation-notice.d.ts +28 -0
  63. package/core/deprecation-notice.d.ts.map +1 -0
  64. package/core/deprecation-notice.js +22 -0
  65. package/core/esri-geojson.d.ts.map +1 -1
  66. package/core/esri-geojson.js +14 -8
  67. package/core/optional-grpc-peer.d.ts +15 -0
  68. package/core/optional-grpc-peer.d.ts.map +1 -0
  69. package/core/optional-grpc-peer.js +60 -0
  70. package/esri-compat/basemap-gallery.d.ts +2 -0
  71. package/esri-compat/basemap-gallery.d.ts.map +1 -1
  72. package/esri-compat/basemap-gallery.js +12 -0
  73. package/esri-compat/basemap.d.ts +4 -0
  74. package/esri-compat/basemap.d.ts.map +1 -1
  75. package/esri-compat/basemap.js +70 -0
  76. package/esri-compat/bookmarks.d.ts +2 -0
  77. package/esri-compat/bookmarks.d.ts.map +1 -1
  78. package/esri-compat/bookmarks.js +12 -0
  79. package/esri-compat/controls.d.ts +18 -0
  80. package/esri-compat/controls.d.ts.map +1 -1
  81. package/esri-compat/controls.js +120 -57
  82. package/esri-compat/directions.d.ts +4 -0
  83. package/esri-compat/directions.d.ts.map +1 -1
  84. package/esri-compat/directions.js +30 -20
  85. package/esri-compat/editor.d.ts +4 -0
  86. package/esri-compat/editor.d.ts.map +1 -1
  87. package/esri-compat/editor.js +16 -0
  88. package/esri-compat/esri-config.d.ts +2 -1
  89. package/esri-compat/esri-config.d.ts.map +1 -1
  90. package/esri-compat/feature-effect.d.ts +23 -0
  91. package/esri-compat/feature-effect.d.ts.map +1 -0
  92. package/esri-compat/feature-effect.js +12 -0
  93. package/esri-compat/feature-form.d.ts +6 -0
  94. package/esri-compat/feature-form.d.ts.map +1 -1
  95. package/esri-compat/feature-form.js +63 -0
  96. package/esri-compat/feature-layer.d.ts +21 -2
  97. package/esri-compat/feature-layer.d.ts.map +1 -1
  98. package/esri-compat/feature-layer.js +172 -1
  99. package/esri-compat/feature-table.d.ts +5 -0
  100. package/esri-compat/feature-table.d.ts.map +1 -1
  101. package/esri-compat/feature-table.js +23 -0
  102. package/esri-compat/identity-manager.d.ts +1 -1
  103. package/esri-compat/identity-manager.js +1 -1
  104. package/esri-compat/legend.d.ts +2 -0
  105. package/esri-compat/legend.d.ts.map +1 -1
  106. package/esri-compat/legend.js +98 -0
  107. package/esri-compat/locator.d.ts +1 -1
  108. package/esri-compat/locator.js +1 -1
  109. package/esri-compat/map-view-mount.d.ts +1 -0
  110. package/esri-compat/map-view-mount.d.ts.map +1 -1
  111. package/esri-compat/map-view-mount.js +46 -25
  112. package/esri-compat/map-view.d.ts +13 -0
  113. package/esri-compat/map-view.d.ts.map +1 -1
  114. package/esri-compat/map-view.js +94 -8
  115. package/esri-compat/map.d.ts +5 -1
  116. package/esri-compat/map.d.ts.map +1 -1
  117. package/esri-compat/map.js +10 -0
  118. package/esri-compat/measurement.d.ts +2 -0
  119. package/esri-compat/measurement.d.ts.map +1 -1
  120. package/esri-compat/measurement.js +14 -0
  121. package/esri-compat/point.d.ts +7 -0
  122. package/esri-compat/point.d.ts.map +1 -1
  123. package/esri-compat/point.js +33 -3
  124. package/esri-compat/popup.d.ts +2 -0
  125. package/esri-compat/popup.d.ts.map +1 -1
  126. package/esri-compat/popup.js +12 -0
  127. package/esri-compat/portal.d.ts +1 -1
  128. package/esri-compat/portal.js +1 -1
  129. package/esri-compat/print.d.ts +3 -0
  130. package/esri-compat/print.d.ts.map +1 -1
  131. package/esri-compat/print.js +15 -0
  132. package/esri-compat/search.d.ts +4 -0
  133. package/esri-compat/search.d.ts.map +1 -1
  134. package/esri-compat/search.js +25 -28
  135. package/esri-compat/sketch.d.ts +2 -0
  136. package/esri-compat/sketch.d.ts.map +1 -1
  137. package/esri-compat/sketch.js +12 -0
  138. package/esri-compat/widget-host.d.ts +46 -17
  139. package/esri-compat/widget-host.d.ts.map +1 -1
  140. package/esri-compat/widget-host.js +84 -20
  141. package/esri-compat/widget-shell-hosts.d.ts +61 -0
  142. package/esri-compat/widget-shell-hosts.d.ts.map +1 -0
  143. package/esri-compat/widget-shell-hosts.js +76 -0
  144. package/index.d.ts +3 -1
  145. package/index.js +1 -0
  146. package/offline/digest.d.ts +15 -0
  147. package/offline/digest.js +58 -0
  148. package/offline/quota.d.ts +161 -0
  149. package/offline/quota.js +370 -0
  150. package/offline/types.d.ts +349 -0
  151. package/offline/types.js +75 -0
  152. package/package.json +21 -2
  153. package/query-planner/canonical-filter.d.ts +30 -0
  154. package/query-planner/canonical-filter.d.ts.map +1 -0
  155. package/query-planner/canonical-filter.js +30 -0
  156. package/query-planner/canonical.d.ts +7 -0
  157. package/query-planner/canonical.d.ts.map +1 -0
  158. package/query-planner/canonical.js +145 -0
  159. package/query-planner/columnar-plan.d.ts +63 -0
  160. package/query-planner/columnar-plan.d.ts.map +1 -0
  161. package/query-planner/columnar-plan.js +94 -0
  162. package/query-planner/cql2-json.d.ts +17 -0
  163. package/query-planner/cql2-json.d.ts.map +1 -0
  164. package/query-planner/cql2-json.js +646 -0
  165. package/query-planner/diagnostics.d.ts +35 -0
  166. package/query-planner/diagnostics.d.ts.map +1 -0
  167. package/query-planner/diagnostics.js +386 -0
  168. package/query-planner/duckdb.d.ts +79 -0
  169. package/query-planner/duckdb.d.ts.map +1 -0
  170. package/query-planner/duckdb.js +772 -0
  171. package/query-planner/execution-context.d.ts +5 -0
  172. package/query-planner/execution-context.d.ts.map +1 -0
  173. package/query-planner/execution-context.js +52 -0
  174. package/query-planner/executor.d.ts +5 -0
  175. package/query-planner/executor.d.ts.map +1 -0
  176. package/query-planner/executor.js +229 -0
  177. package/query-planner/geoservices.d.ts +91 -0
  178. package/query-planner/geoservices.d.ts.map +1 -0
  179. package/query-planner/geoservices.js +688 -0
  180. package/query-planner/grpc.d.ts +100 -0
  181. package/query-planner/grpc.d.ts.map +1 -0
  182. package/query-planner/grpc.js +760 -0
  183. package/query-planner/index.d.ts +59 -0
  184. package/query-planner/index.d.ts.map +1 -0
  185. package/query-planner/index.js +43 -0
  186. package/query-planner/ir.d.ts +25 -0
  187. package/query-planner/ir.d.ts.map +1 -0
  188. package/query-planner/ir.js +479 -0
  189. package/query-planner/local-aggregate.d.ts +5 -0
  190. package/query-planner/local-aggregate.d.ts.map +1 -0
  191. package/query-planner/local-aggregate.js +126 -0
  192. package/query-planner/odata-protocol-module.d.ts +54 -0
  193. package/query-planner/odata-protocol-module.d.ts.map +1 -0
  194. package/query-planner/odata-protocol-module.js +199 -0
  195. package/query-planner/odata-v1.d.ts +23 -0
  196. package/query-planner/odata-v1.d.ts.map +1 -0
  197. package/query-planner/odata-v1.js +202 -0
  198. package/query-planner/odata.d.ts +45 -0
  199. package/query-planner/odata.d.ts.map +1 -0
  200. package/query-planner/odata.js +519 -0
  201. package/query-planner/ogc-compiler.d.ts +55 -0
  202. package/query-planner/ogc-compiler.d.ts.map +1 -0
  203. package/query-planner/ogc-compiler.js +480 -0
  204. package/query-planner/ogc-features.d.ts +53 -0
  205. package/query-planner/ogc-features.d.ts.map +1 -0
  206. package/query-planner/ogc-features.js +639 -0
  207. package/query-planner/planner.d.ts +17 -0
  208. package/query-planner/planner.d.ts.map +1 -0
  209. package/query-planner/planner.js +937 -0
  210. package/query-planner/representation.d.ts +59 -0
  211. package/query-planner/representation.d.ts.map +1 -0
  212. package/query-planner/representation.js +140 -0
  213. package/query-planner/resource.d.ts +94 -0
  214. package/query-planner/resource.d.ts.map +1 -0
  215. package/query-planner/resource.js +526 -0
  216. package/query-planner/semantic-canonical.d.ts +15 -0
  217. package/query-planner/semantic-canonical.d.ts.map +1 -0
  218. package/query-planner/semantic-canonical.js +62 -0
  219. package/query-planner/semantic-compat.d.ts +10 -0
  220. package/query-planner/semantic-compat.d.ts.map +1 -0
  221. package/query-planner/semantic-compat.js +35 -0
  222. package/query-planner/semantic-compiler.d.ts +64 -0
  223. package/query-planner/semantic-compiler.d.ts.map +1 -0
  224. package/query-planner/semantic-compiler.js +81 -0
  225. package/query-planner/semantic-literals.d.ts +30 -0
  226. package/query-planner/semantic-literals.d.ts.map +1 -0
  227. package/query-planner/semantic-literals.js +133 -0
  228. package/query-planner/semantic-types.d.ts +265 -0
  229. package/query-planner/semantic-types.d.ts.map +1 -0
  230. package/query-planner/semantic-types.js +1 -0
  231. package/query-planner/semantic.d.ts +54 -0
  232. package/query-planner/semantic.d.ts.map +1 -0
  233. package/query-planner/semantic.js +1421 -0
  234. package/query-planner/types.d.ts +712 -0
  235. package/query-planner/types.d.ts.map +1 -0
  236. package/query-planner/types.js +49 -0
  237. package/query-planner/wfs-protocol-module.d.ts +57 -0
  238. package/query-planner/wfs-protocol-module.d.ts.map +1 -0
  239. package/query-planner/wfs-protocol-module.js +731 -0
  240. package/query-planner/wfs-semantic.d.ts +58 -0
  241. package/query-planner/wfs-semantic.d.ts.map +1 -0
  242. package/query-planner/wfs-semantic.js +547 -0
  243. package/query-planner/wfs-v1.d.ts +41 -0
  244. package/query-planner/wfs-v1.d.ts.map +1 -0
  245. package/query-planner/wfs-v1.js +366 -0
  246. package/query-planner/wfs.d.ts +4 -0
  247. package/query-planner/wfs.d.ts.map +1 -0
  248. package/query-planner/wfs.js +2 -0
  249. package/widget-capabilities.d.ts +67 -0
  250. package/widget-capabilities.js +152 -0
@@ -0,0 +1,145 @@
1
+ /** Deterministic JSON serialization with sorted object keys and strict values. */
2
+ export function canonicalStringify(value) {
3
+ return JSON.stringify(sortJson(value));
4
+ }
5
+ export function toJsonValue(value, path = "$") {
6
+ return convertJson(value, path, new WeakSet());
7
+ }
8
+ function convertJson(value, path, ancestors) {
9
+ if (value === null || typeof value === "string" || typeof value === "boolean")
10
+ return value;
11
+ if (typeof value === "number") {
12
+ if (!Number.isFinite(value))
13
+ throw new TypeError(`${path} must contain only finite numbers`);
14
+ return Object.is(value, -0) ? 0 : value;
15
+ }
16
+ if (Array.isArray(value)) {
17
+ if (ancestors.has(value))
18
+ throw new TypeError(`${path} must not contain cycles`);
19
+ ancestors.add(value);
20
+ const converted = value.map((entry, index) => {
21
+ if (entry === undefined)
22
+ throw new TypeError(`${path}[${index}] must not be undefined`);
23
+ return convertJson(entry, `${path}[${index}]`, ancestors);
24
+ });
25
+ ancestors.delete(value);
26
+ return converted;
27
+ }
28
+ if (typeof value === "object") {
29
+ if (ancestors.has(value))
30
+ throw new TypeError(`${path} must not contain cycles`);
31
+ const prototype = Object.getPrototypeOf(value);
32
+ if (prototype !== Object.prototype && prototype !== null) {
33
+ throw new TypeError(`${path} must contain only plain JSON objects`);
34
+ }
35
+ ancestors.add(value);
36
+ const converted = {};
37
+ for (const key of Object.keys(value).sort()) {
38
+ const entry = value[key];
39
+ if (entry !== undefined) {
40
+ Object.defineProperty(converted, key, {
41
+ value: convertJson(entry, `${path}.${key}`, ancestors),
42
+ enumerable: true,
43
+ writable: true,
44
+ configurable: true,
45
+ });
46
+ }
47
+ }
48
+ ancestors.delete(value);
49
+ return converted;
50
+ }
51
+ throw new TypeError(`${path} contains unsupported ${typeof value}`);
52
+ }
53
+ function sortJson(value) {
54
+ if (Array.isArray(value))
55
+ return value.map(sortJson);
56
+ if (value !== null && typeof value === "object") {
57
+ const object = value;
58
+ const sorted = {};
59
+ for (const key of Object.keys(object).sort()) {
60
+ Object.defineProperty(sorted, key, {
61
+ value: sortJson(object[key]),
62
+ enumerable: true,
63
+ writable: true,
64
+ configurable: true,
65
+ });
66
+ }
67
+ return sorted;
68
+ }
69
+ return value;
70
+ }
71
+ /** Portable synchronous SHA-256 over UTF-8 input (browser, worker, and Node). */
72
+ export function sha256(value) {
73
+ const bytes = new TextEncoder().encode(value);
74
+ const bitLength = bytes.length * 8;
75
+ const paddedLength = Math.ceil((bytes.length + 9) / 64) * 64;
76
+ const padded = new Uint8Array(paddedLength);
77
+ padded.set(bytes);
78
+ padded[bytes.length] = 0x80;
79
+ const view = new DataView(padded.buffer);
80
+ const high = Math.floor(bitLength / 0x1_0000_0000);
81
+ const low = bitLength >>> 0;
82
+ view.setUint32(paddedLength - 8, high, false);
83
+ view.setUint32(paddedLength - 4, low, false);
84
+ const state = new Uint32Array([
85
+ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
86
+ ]);
87
+ const words = new Uint32Array(64);
88
+ for (let offset = 0; offset < paddedLength; offset += 64) {
89
+ for (let index = 0; index < 16; index++)
90
+ words[index] = view.getUint32(offset + index * 4, false);
91
+ for (let index = 16; index < 64; index++) {
92
+ const before15 = words[index - 15] ?? 0;
93
+ const before2 = words[index - 2] ?? 0;
94
+ const s0 = rotateRight(before15, 7) ^ rotateRight(before15, 18) ^ (before15 >>> 3);
95
+ const s1 = rotateRight(before2, 17) ^ rotateRight(before2, 19) ^ (before2 >>> 10);
96
+ words[index] = ((words[index - 16] ?? 0) + s0 + (words[index - 7] ?? 0) + s1) >>> 0;
97
+ }
98
+ let a = state[0] ?? 0;
99
+ let b = state[1] ?? 0;
100
+ let c = state[2] ?? 0;
101
+ let d = state[3] ?? 0;
102
+ let e = state[4] ?? 0;
103
+ let f = state[5] ?? 0;
104
+ let g = state[6] ?? 0;
105
+ let h = state[7] ?? 0;
106
+ for (let index = 0; index < 64; index++) {
107
+ const upper1 = rotateRight(e, 6) ^ rotateRight(e, 11) ^ rotateRight(e, 25);
108
+ const choose = (e & f) ^ (~e & g);
109
+ const temp1 = (h + upper1 + choose + (SHA256_CONSTANTS[index] ?? 0) + (words[index] ?? 0)) >>> 0;
110
+ const upper0 = rotateRight(a, 2) ^ rotateRight(a, 13) ^ rotateRight(a, 22);
111
+ const majority = (a & b) ^ (a & c) ^ (b & c);
112
+ const temp2 = (upper0 + majority) >>> 0;
113
+ h = g;
114
+ g = f;
115
+ f = e;
116
+ e = (d + temp1) >>> 0;
117
+ d = c;
118
+ c = b;
119
+ b = a;
120
+ a = (temp1 + temp2) >>> 0;
121
+ }
122
+ state[0] = ((state[0] ?? 0) + a) >>> 0;
123
+ state[1] = ((state[1] ?? 0) + b) >>> 0;
124
+ state[2] = ((state[2] ?? 0) + c) >>> 0;
125
+ state[3] = ((state[3] ?? 0) + d) >>> 0;
126
+ state[4] = ((state[4] ?? 0) + e) >>> 0;
127
+ state[5] = ((state[5] ?? 0) + f) >>> 0;
128
+ state[6] = ((state[6] ?? 0) + g) >>> 0;
129
+ state[7] = ((state[7] ?? 0) + h) >>> 0;
130
+ }
131
+ return `sha256:${Array.from(state, (word) => word.toString(16).padStart(8, "0")).join("")}`;
132
+ }
133
+ function rotateRight(value, amount) {
134
+ return (value >>> amount) | (value << (32 - amount));
135
+ }
136
+ const SHA256_CONSTANTS = new Uint32Array([
137
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98,
138
+ 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
139
+ 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8,
140
+ 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
141
+ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819,
142
+ 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
143
+ 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7,
144
+ 0xc67178f2,
145
+ ]);
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Plan-derived columnar batch identity.
3
+ *
4
+ * `ColumnarBatchIdentityV1` is the cache-key contract shipped by #940: source
5
+ * id, source version, schema version, plan id, authorization scope, ordering,
6
+ * and freshness together decide whether two batches are the same answer. Until
7
+ * now the only source-side producer minted those fields itself, so
8
+ * `columnarBatchCacheKey` keyed on a plan id no planner ever issued.
9
+ *
10
+ * This module closes that: every identity field except freshness is read from
11
+ * an accepted {@link QueryExecutionPlan}, and `planId` is the plan's own
12
+ * `validity.fingerprint`. A plan, schema, scope, or query change therefore
13
+ * changes the cache key by construction rather than by convention.
14
+ *
15
+ * Freshness is the one execution-time input. Planning stays observation-clock
16
+ * free — an observation instant in a plan would make the plan fingerprint
17
+ * change on every explain — so the caller supplies it when the source is
18
+ * actually read.
19
+ *
20
+ * The module imports only types from `../columnar/`, so it adds no runtime edge
21
+ * to the columnar data plane.
22
+ *
23
+ * @module
24
+ */
25
+ import type { ColumnarBatchIdentityV1 } from "../columnar/types.js";
26
+ import { type QueryExecutionPlan } from "./types.js";
27
+ /** Execution-time freshness evidence for a plan-produced batch. */
28
+ export interface ColumnarBatchIdentityFromPlanOptions {
29
+ /**
30
+ * RFC 3339 instant at which the source result was observed. Required, and
31
+ * supplied at execution: it is deliberately not a plan input.
32
+ */
33
+ readonly observedAt: string;
34
+ /** RFC 3339 instant after which the batch must be revalidated. */
35
+ readonly staleAfter?: string;
36
+ /** Opaque source validator, such as an HTTP ETag. Never a credential. */
37
+ readonly validator?: string;
38
+ /** Opaque monotonic source generation or revision. */
39
+ readonly generation?: string;
40
+ }
41
+ /**
42
+ * Derive the batch identity a columnar-selected plan implies.
43
+ *
44
+ * Field derivation:
45
+ * - `planId` — the plan's `validity.fingerprint` verbatim, so two plans that
46
+ * are interchangeable for reuse share a cache entry and two that are not,
47
+ * do not. The broader `plan.fingerprint` also covers cost estimates, which
48
+ * change nothing about which rows come back, so it is deliberately not used.
49
+ * - `sourceId` / `sourceVersion` / `schemaVersion` — the plan's declared source
50
+ * identity, falling back to the plan's own descriptor and schema fingerprints
51
+ * when the source declares no version string. Both fallbacks are plan-derived
52
+ * and change whenever the underlying identity changes.
53
+ * - `authorizationScope` — the plan's authorization-scope *fingerprint*, never
54
+ * the raw scope values.
55
+ * - `ordering` — the canonical query's `orderBy`, as an ordering contract.
56
+ * - `freshness` — from {@link ColumnarBatchIdentityFromPlanOptions}.
57
+ *
58
+ * @throws HonuaCapabilityNotSupportedError when the plan did not select
59
+ * columnar execution. A columnar identity minted from an object plan would
60
+ * let a batch claim provenance the planner never granted.
61
+ */
62
+ export declare function columnarBatchIdentityFromPlan(plan: QueryExecutionPlan, options: ColumnarBatchIdentityFromPlanOptions): ColumnarBatchIdentityV1;
63
+ //# sourceMappingURL=columnar-plan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"columnar-plan.d.ts","sourceRoot":"","sources":["../../../src/query-planner/columnar-plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAA6C,MAAM,sBAAsB,CAAC;AAE/G,OAAO,EAA2B,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAE9E,mEAAmE;AACnE,MAAM,WAAW,oCAAoC;IACnD;;;OAGG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,kEAAkE;IAClE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,yEAAyE;IACzE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,sDAAsD;IACtD,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,kBAAkB,EACxB,OAAO,EAAE,oCAAoC,GAC5C,uBAAuB,CAqBzB"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Plan-derived columnar batch identity.
3
+ *
4
+ * `ColumnarBatchIdentityV1` is the cache-key contract shipped by #940: source
5
+ * id, source version, schema version, plan id, authorization scope, ordering,
6
+ * and freshness together decide whether two batches are the same answer. Until
7
+ * now the only source-side producer minted those fields itself, so
8
+ * `columnarBatchCacheKey` keyed on a plan id no planner ever issued.
9
+ *
10
+ * This module closes that: every identity field except freshness is read from
11
+ * an accepted {@link QueryExecutionPlan}, and `planId` is the plan's own
12
+ * `validity.fingerprint`. A plan, schema, scope, or query change therefore
13
+ * changes the cache key by construction rather than by convention.
14
+ *
15
+ * Freshness is the one execution-time input. Planning stays observation-clock
16
+ * free — an observation instant in a plan would make the plan fingerprint
17
+ * change on every explain — so the caller supplies it when the source is
18
+ * actually read.
19
+ *
20
+ * The module imports only types from `../columnar/`, so it adds no runtime edge
21
+ * to the columnar data plane.
22
+ *
23
+ * @module
24
+ */
25
+ import { HonuaCapabilityNotSupportedError } from "../core/errors.js";
26
+ import { HonuaQueryPlanningError } from "./types.js";
27
+ /**
28
+ * Derive the batch identity a columnar-selected plan implies.
29
+ *
30
+ * Field derivation:
31
+ * - `planId` — the plan's `validity.fingerprint` verbatim, so two plans that
32
+ * are interchangeable for reuse share a cache entry and two that are not,
33
+ * do not. The broader `plan.fingerprint` also covers cost estimates, which
34
+ * change nothing about which rows come back, so it is deliberately not used.
35
+ * - `sourceId` / `sourceVersion` / `schemaVersion` — the plan's declared source
36
+ * identity, falling back to the plan's own descriptor and schema fingerprints
37
+ * when the source declares no version string. Both fallbacks are plan-derived
38
+ * and change whenever the underlying identity changes.
39
+ * - `authorizationScope` — the plan's authorization-scope *fingerprint*, never
40
+ * the raw scope values.
41
+ * - `ordering` — the canonical query's `orderBy`, as an ordering contract.
42
+ * - `freshness` — from {@link ColumnarBatchIdentityFromPlanOptions}.
43
+ *
44
+ * @throws HonuaCapabilityNotSupportedError when the plan did not select
45
+ * columnar execution. A columnar identity minted from an object plan would
46
+ * let a batch claim provenance the planner never granted.
47
+ */
48
+ export function columnarBatchIdentityFromPlan(plan, options) {
49
+ if (plan.validity.representation !== "columnar") {
50
+ throw new HonuaCapabilityNotSupportedError("columnar-execution", plan.ir.source.protocol, plan.ir.source.id, {
51
+ context: { representation: plan.validity.representation, reason: plan.representation.reason },
52
+ });
53
+ }
54
+ const observedAt = requireText(options.observedAt, "observedAt");
55
+ return Object.freeze({
56
+ sourceId: plan.ir.source.id,
57
+ sourceVersion: plan.ir.source.sourceVersion ?? plan.provenance.source.descriptorFingerprint,
58
+ schemaVersion: plan.ir.source.schemaVersion ?? plan.validity.schemaFingerprint,
59
+ planId: plan.validity.fingerprint,
60
+ authorizationScope: plan.provenance.authorizationScope.fingerprint,
61
+ ordering: planOrdering(plan),
62
+ freshness: Object.freeze({
63
+ observedAt,
64
+ ...(options.staleAfter === undefined ? {} : { staleAfter: requireText(options.staleAfter, "staleAfter") }),
65
+ ...(options.validator === undefined ? {} : { validator: requireText(options.validator, "validator") }),
66
+ ...(options.generation === undefined ? {} : { generation: requireText(options.generation, "generation") }),
67
+ }),
68
+ });
69
+ }
70
+ /**
71
+ * The ordering contract the plan's canonical query establishes.
72
+ *
73
+ * Null placement is declared `last` because the compiled DuckDB `ORDER BY`
74
+ * emits no explicit `NULLS` clause and DuckDB's default null order is
75
+ * `NULLS LAST`; the identity states the order the rows actually arrive in
76
+ * rather than leaving it unspecified. A batch whose schema does not carry
77
+ * every ordering key is refused when the batch is created — the identity is
78
+ * never quietly loosened to match a narrower batch.
79
+ */
80
+ function planOrdering(plan) {
81
+ const orderBy = plan.ir.query.orderBy ?? [];
82
+ const keys = orderBy.map((sort) => Object.freeze({
83
+ field: sort.field,
84
+ direction: sort.direction === "desc" ? "descending" : "ascending",
85
+ nulls: "last",
86
+ }));
87
+ return Object.freeze({ stable: keys.length > 0, keys: Object.freeze(keys) });
88
+ }
89
+ function requireText(value, label) {
90
+ if (typeof value !== "string" || value.length === 0) {
91
+ throw new HonuaQueryPlanningError("invalid-query", `columnar batch identity ${label} must be a non-empty string`);
92
+ }
93
+ return value;
94
+ }
@@ -0,0 +1,17 @@
1
+ import { type SourceProtocol } from "../contract/schema.js";
2
+ import type { Cql2JsonExpression, Cql2JsonInterchangeOptions, QueryFilter, SourceSpatiality } from "./semantic-types.js";
3
+ type RuntimeFilter = QueryFilter<Record<string, unknown>, SourceProtocol, SourceSpatiality>;
4
+ /**
5
+ * Export the CQL2-representable semantic-filter subset. CQL2 carries spatial
6
+ * CRS outside the expression, so every spatial export requires `filterCrs`
7
+ * and verifies that each operand uses that exact executable binding.
8
+ */
9
+ export declare function semanticFilterToCql2Json<TRecord, TProtocol extends SourceProtocol, TSpatiality extends SourceSpatiality>(filter: QueryFilter<TRecord, TProtocol, TSpatiality>, options?: Cql2JsonInterchangeOptions): Cql2JsonExpression;
10
+ /**
11
+ * Import the strict CQL2 JSON subset into the same runtime-validated semantic
12
+ * AST used by builders. Unknown functions, property-property comparisons,
13
+ * distance extensions, and other non-representable constructs fail closed.
14
+ */
15
+ export declare function semanticFilterFromCql2Json(value: string | unknown, options?: Cql2JsonInterchangeOptions): RuntimeFilter;
16
+ export {};
17
+ //# sourceMappingURL=cql2-json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cql2-json.d.ts","sourceRoot":"","sources":["../../../src/query-planner/cql2-json.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,cAAc,EAIpB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EACV,kBAAkB,EAClB,0BAA0B,EAC1B,WAAW,EAEX,gBAAgB,EAEjB,MAAM,qBAAqB,CAAC;AAI7B,KAAK,aAAa,GAAG,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,EAAE,gBAAgB,CAAC,CAAC;AAuE5F;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EACP,SAAS,SAAS,cAAc,EAChC,WAAW,SAAS,gBAAgB,EACpC,MAAM,EAAE,WAAW,CAAC,OAAO,EAAE,SAAS,EAAE,WAAW,CAAC,EAAE,OAAO,GAAE,0BAA+B,GAAG,kBAAkB,CAYpH;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,MAAM,GAAG,OAAO,EACvB,OAAO,GAAE,0BAA+B,GACvC,aAAa,CAaf"}