@rybosome/tspice 0.0.3 → 0.0.8

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 (221) hide show
  1. package/README.md +145 -84
  2. package/backend-contract/dist/.tsbuildinfo +1 -1
  3. package/backend-contract/dist/domains/cells-windows.d.ts +94 -0
  4. package/backend-contract/dist/domains/cells-windows.js +10 -0
  5. package/backend-contract/dist/domains/coords-vectors.d.ts +53 -3
  6. package/backend-contract/dist/domains/dsk.d.ts +49 -0
  7. package/backend-contract/dist/domains/dsk.js +2 -0
  8. package/backend-contract/dist/domains/ek.d.ts +186 -0
  9. package/backend-contract/dist/domains/ek.js +8 -0
  10. package/backend-contract/dist/domains/ephemeris.d.ts +141 -3
  11. package/backend-contract/dist/domains/error.d.ts +42 -0
  12. package/backend-contract/dist/domains/error.js +33 -0
  13. package/backend-contract/dist/domains/file-io.d.ts +114 -0
  14. package/backend-contract/dist/domains/file-io.js +8 -0
  15. package/backend-contract/dist/domains/frames.d.ts +44 -4
  16. package/backend-contract/dist/domains/geometry-gf.d.ts +44 -0
  17. package/backend-contract/dist/domains/geometry-gf.js +14 -0
  18. package/backend-contract/dist/domains/geometry.d.ts +21 -1
  19. package/backend-contract/dist/domains/ids-names-normalize.d.ts +3 -0
  20. package/backend-contract/dist/domains/ids-names-normalize.js +74 -0
  21. package/backend-contract/dist/domains/ids-names.d.ts +37 -0
  22. package/backend-contract/dist/domains/kernel-pool.d.ts +134 -0
  23. package/backend-contract/dist/domains/kernel-pool.js +2 -0
  24. package/backend-contract/dist/domains/kernels-utils.d.ts +44 -0
  25. package/backend-contract/dist/domains/kernels-utils.js +265 -0
  26. package/backend-contract/dist/domains/kernels.d.ts +39 -3
  27. package/backend-contract/dist/domains/time.d.ts +102 -0
  28. package/backend-contract/dist/index.d.ts +34 -15
  29. package/backend-contract/dist/index.js +15 -1
  30. package/backend-contract/dist/shared/errors.d.ts +6 -0
  31. package/backend-contract/dist/shared/errors.js +8 -0
  32. package/backend-contract/dist/shared/mat3.d.ts +52 -0
  33. package/backend-contract/dist/shared/mat3.js +150 -0
  34. package/backend-contract/dist/shared/mat6.d.ts +34 -0
  35. package/backend-contract/dist/shared/mat6.js +116 -0
  36. package/backend-contract/dist/shared/spice-handles.d.ts +20 -0
  37. package/backend-contract/dist/shared/spice-handles.js +82 -0
  38. package/backend-contract/dist/shared/spice-int.d.ts +32 -0
  39. package/backend-contract/dist/shared/spice-int.js +41 -0
  40. package/backend-contract/dist/shared/types.d.ts +136 -5
  41. package/backend-contract/dist/shared/types.js +1 -1
  42. package/backend-contract/dist/shared/vec.d.ts +54 -0
  43. package/backend-contract/dist/shared/vec.js +162 -0
  44. package/backend-fake/dist/.tsbuildinfo +1 -1
  45. package/backend-fake/dist/index.d.ts +21 -1
  46. package/backend-fake/dist/index.js +1112 -33
  47. package/backend-node/dist/.tsbuildinfo +1 -1
  48. package/backend-node/dist/codec/arrays.d.ts +9 -0
  49. package/backend-node/dist/codec/arrays.js +36 -0
  50. package/backend-node/dist/codec/errors.d.ts +6 -6
  51. package/backend-node/dist/codec/errors.js +6 -6
  52. package/backend-node/dist/domains/cells-windows.d.ts +5 -0
  53. package/backend-node/dist/domains/cells-windows.js +112 -0
  54. package/backend-node/dist/domains/coords-vectors.d.ts +1 -0
  55. package/backend-node/dist/domains/coords-vectors.js +66 -0
  56. package/backend-node/dist/domains/dsk.d.ts +6 -0
  57. package/backend-node/dist/domains/dsk.js +108 -0
  58. package/backend-node/dist/domains/ek.d.ts +10 -0
  59. package/backend-node/dist/domains/ek.js +100 -0
  60. package/backend-node/dist/domains/ephemeris.d.ts +5 -1
  61. package/backend-node/dist/domains/ephemeris.js +150 -1
  62. package/backend-node/dist/domains/error.d.ts +5 -0
  63. package/backend-node/dist/domains/error.js +34 -0
  64. package/backend-node/dist/domains/file-io.d.ts +7 -0
  65. package/backend-node/dist/domains/file-io.js +105 -0
  66. package/backend-node/dist/domains/frames.d.ts +1 -0
  67. package/backend-node/dist/domains/frames.js +58 -6
  68. package/backend-node/dist/domains/geometry-gf.d.ts +5 -0
  69. package/backend-node/dist/domains/geometry-gf.js +74 -0
  70. package/backend-node/dist/domains/geometry.d.ts +1 -0
  71. package/backend-node/dist/domains/geometry.js +62 -0
  72. package/backend-node/dist/domains/ids-names.d.ts +2 -1
  73. package/backend-node/dist/domains/ids-names.js +30 -0
  74. package/backend-node/dist/domains/kernel-pool.d.ts +5 -0
  75. package/backend-node/dist/domains/kernel-pool.js +74 -0
  76. package/backend-node/dist/domains/kernels.d.ts +1 -0
  77. package/backend-node/dist/domains/kernels.js +100 -13
  78. package/backend-node/dist/domains/time.d.ts +1 -0
  79. package/backend-node/dist/domains/time.js +75 -1
  80. package/backend-node/dist/index.d.ts +5 -1
  81. package/backend-node/dist/index.js +62 -1
  82. package/backend-node/dist/lowlevel/binding.d.ts +3 -0
  83. package/backend-node/dist/lowlevel/binding.js +115 -0
  84. package/backend-node/dist/runtime/addon.d.ts +273 -2
  85. package/backend-node/dist/runtime/addon.js +3 -0
  86. package/backend-node/dist/runtime/kernel-staging.d.ts +17 -0
  87. package/backend-node/dist/runtime/kernel-staging.js +80 -7
  88. package/backend-node/dist/runtime/spice-handles.d.ts +3 -0
  89. package/backend-node/dist/runtime/spice-handles.js +2 -0
  90. package/backend-node/dist/runtime/virtual-output-staging.d.ts +16 -0
  91. package/backend-node/dist/runtime/virtual-output-staging.js +148 -0
  92. package/backend-wasm/dist/.tsbuildinfo +1 -1
  93. package/backend-wasm/dist/codec/alloc.d.ts +19 -0
  94. package/backend-wasm/dist/codec/alloc.js +64 -0
  95. package/backend-wasm/dist/codec/calls.d.ts +2 -0
  96. package/backend-wasm/dist/codec/calls.js +13 -24
  97. package/backend-wasm/dist/codec/errors.d.ts +6 -0
  98. package/backend-wasm/dist/codec/errors.js +34 -2
  99. package/backend-wasm/dist/codec/found.d.ts +2 -0
  100. package/backend-wasm/dist/codec/found.js +20 -43
  101. package/backend-wasm/dist/codec/strings.d.ts +31 -1
  102. package/backend-wasm/dist/codec/strings.js +93 -6
  103. package/backend-wasm/dist/domains/cells-windows.d.ts +9 -0
  104. package/backend-wasm/dist/domains/cells-windows.js +392 -0
  105. package/backend-wasm/dist/domains/coords-vectors.d.ts +1 -0
  106. package/backend-wasm/dist/domains/coords-vectors.js +377 -184
  107. package/backend-wasm/dist/domains/dsk.d.ts +6 -0
  108. package/backend-wasm/dist/domains/dsk.js +179 -0
  109. package/backend-wasm/dist/domains/ek.d.ts +6 -0
  110. package/backend-wasm/dist/domains/ek.js +543 -0
  111. package/backend-wasm/dist/domains/ephemeris.d.ts +4 -1
  112. package/backend-wasm/dist/domains/ephemeris.js +405 -46
  113. package/backend-wasm/dist/domains/error.d.ts +5 -0
  114. package/backend-wasm/dist/domains/error.js +109 -0
  115. package/backend-wasm/dist/domains/file-io.d.ts +7 -0
  116. package/backend-wasm/dist/domains/file-io.js +462 -0
  117. package/backend-wasm/dist/domains/frames.d.ts +1 -0
  118. package/backend-wasm/dist/domains/frames.js +139 -6
  119. package/backend-wasm/dist/domains/geometry-gf.d.ts +5 -0
  120. package/backend-wasm/dist/domains/geometry-gf.js +178 -0
  121. package/backend-wasm/dist/domains/geometry.d.ts +1 -0
  122. package/backend-wasm/dist/domains/geometry.js +210 -0
  123. package/backend-wasm/dist/domains/ids-names.d.ts +2 -1
  124. package/backend-wasm/dist/domains/ids-names.js +89 -0
  125. package/backend-wasm/dist/domains/kernel-pool.d.ts +5 -0
  126. package/backend-wasm/dist/domains/kernel-pool.js +357 -0
  127. package/backend-wasm/dist/domains/kernels.d.ts +1 -0
  128. package/backend-wasm/dist/domains/kernels.js +108 -4
  129. package/backend-wasm/dist/domains/time.d.ts +2 -0
  130. package/backend-wasm/dist/domains/time.js +235 -133
  131. package/backend-wasm/dist/index.d.ts +4 -2
  132. package/backend-wasm/dist/lowlevel/exports.d.ts +215 -1
  133. package/backend-wasm/dist/lowlevel/exports.js +217 -38
  134. package/backend-wasm/dist/runtime/create-backend-options.d.ts +21 -0
  135. package/backend-wasm/dist/runtime/create-backend.node.d.ts +11 -2
  136. package/backend-wasm/dist/runtime/create-backend.node.js +283 -14
  137. package/backend-wasm/dist/runtime/create-backend.web.d.ts +5 -2
  138. package/backend-wasm/dist/runtime/create-backend.web.js +40 -6
  139. package/backend-wasm/dist/runtime/fs.d.ts +6 -0
  140. package/backend-wasm/dist/runtime/fs.js +29 -3
  141. package/backend-wasm/dist/runtime/spice-handles.d.ts +3 -0
  142. package/backend-wasm/dist/runtime/spice-handles.js +2 -0
  143. package/backend-wasm/dist/runtime/virtual-outputs.d.ts +16 -0
  144. package/backend-wasm/dist/runtime/virtual-outputs.js +35 -0
  145. package/backend-wasm/dist/tspice_backend_wasm.node.js +3 -3
  146. package/backend-wasm/dist/tspice_backend_wasm.wasm +0 -0
  147. package/backend-wasm/dist/tspice_backend_wasm.web.js +1 -1
  148. package/core/dist/.tsbuildinfo +1 -1
  149. package/core/dist/index.d.ts +21 -0
  150. package/core/dist/index.js +57 -0
  151. package/dist/.tsbuildinfo +1 -1
  152. package/dist/backend.d.ts +15 -6
  153. package/dist/backend.js +3 -6
  154. package/dist/clients/createSpiceAsyncFromTransport.d.ts +5 -0
  155. package/dist/clients/createSpiceAsyncFromTransport.js +90 -0
  156. package/dist/clients/createSpiceSyncFromTransport.d.ts +5 -0
  157. package/dist/clients/createSpiceSyncFromTransport.js +88 -0
  158. package/dist/clients/spiceClients.d.ts +59 -0
  159. package/dist/clients/spiceClients.js +292 -0
  160. package/dist/errors.d.ts +4 -0
  161. package/dist/errors.js +4 -0
  162. package/dist/index.d.ts +12 -7
  163. package/dist/index.js +5 -2
  164. package/dist/kernels/defaultKernelPathFromUrl.d.ts +8 -0
  165. package/dist/kernels/defaultKernelPathFromUrl.js +32 -0
  166. package/dist/kernels/kernelPack.d.ts +88 -0
  167. package/dist/kernels/kernelPack.js +122 -0
  168. package/dist/kernels/kernels.d.ts +98 -0
  169. package/dist/kernels/kernels.js +217 -0
  170. package/dist/kernels/naifKernelId.d.ts +2 -0
  171. package/dist/kernels/naifKernelId.js +2 -0
  172. package/dist/kit/index.d.ts +4 -0
  173. package/dist/kit/index.js +3 -0
  174. package/dist/kit/math/mat3.d.ts +31 -0
  175. package/dist/kit/math/mat3.js +82 -0
  176. package/dist/kit/spice/create-kit.d.ts +12 -0
  177. package/dist/kit/spice/create-kit.js +23 -0
  178. package/dist/kit/spice/frames.d.ts +8 -0
  179. package/dist/kit/spice/frames.js +16 -0
  180. package/dist/kit/spice/kernels.d.ts +14 -0
  181. package/dist/kit/spice/kernels.js +39 -0
  182. package/dist/kit/spice/state.d.ts +7 -0
  183. package/dist/kit/spice/state.js +36 -0
  184. package/dist/kit/spice/time.d.ts +9 -0
  185. package/dist/kit/spice/time.js +31 -0
  186. package/dist/kit/types/spice-types.d.ts +51 -0
  187. package/dist/spice.d.ts +10 -1
  188. package/dist/spice.js +84 -72
  189. package/dist/transport/caching/policy.d.ts +16 -0
  190. package/dist/transport/caching/policy.js +77 -0
  191. package/dist/transport/caching/withCaching.d.ts +125 -0
  192. package/dist/transport/caching/withCaching.js +335 -0
  193. package/dist/transport/caching/withCachingSync.d.ts +24 -0
  194. package/dist/transport/caching/withCachingSync.js +161 -0
  195. package/dist/transport/rpc/protocol.d.ts +35 -0
  196. package/dist/transport/rpc/protocol.js +56 -0
  197. package/dist/transport/rpc/taskScheduling.d.ts +20 -0
  198. package/dist/transport/rpc/taskScheduling.js +98 -0
  199. package/dist/transport/rpc/valueCodec.d.ts +5 -0
  200. package/dist/transport/rpc/valueCodec.js +106 -0
  201. package/dist/transport/types.d.ts +7 -0
  202. package/dist/transport/types.js +2 -0
  203. package/dist/types.d.ts +8 -17
  204. package/dist/types.js +2 -1
  205. package/dist/worker/browser/createSpiceWorker.d.ts +22 -0
  206. package/dist/worker/browser/createSpiceWorker.js +41 -0
  207. package/dist/worker/browser/createSpiceWorkerClient.d.ts +40 -0
  208. package/dist/worker/browser/createSpiceWorkerClient.js +99 -0
  209. package/dist/worker/browser/spiceWorkerEntry.d.ts +2 -0
  210. package/dist/worker/browser/spiceWorkerEntry.js +129 -0
  211. package/dist/worker/browser/spiceWorkerInlineSource.d.ts +2 -0
  212. package/dist/worker/browser/spiceWorkerInlineSource.js +4 -0
  213. package/dist/worker/index.d.ts +10 -0
  214. package/dist/worker/index.js +7 -0
  215. package/dist/worker/transport/createWorkerTransport.d.ts +69 -0
  216. package/dist/worker/transport/createWorkerTransport.js +398 -0
  217. package/dist/worker/transport/exposeTransportToWorker.d.ts +51 -0
  218. package/dist/worker/transport/exposeTransportToWorker.js +196 -0
  219. package/package.json +4 -4
  220. package/dist/spice-types.d.ts +0 -36
  221. /package/dist/{spice-types.js → kit/types/spice-types.js} +0 -0
@@ -0,0 +1,543 @@
1
+ import { assertSpiceInt32, assertSpiceInt32NonNegative } from "#backend-contract";
2
+ import { WASM_ERR_MAX_BYTES, WASM_MAX_ALLOC_BYTES, withAllocs, withMalloc } from "../codec/alloc.js";
3
+ import { throwWasmSpiceError } from "../codec/errors.js";
4
+ import { readFixedWidthCString, writeUtf8CString } from "../codec/strings.js";
5
+ import { resolveKernelPath } from "../runtime/fs.js";
6
+ const UTF8_ENCODER = new TextEncoder();
7
+ const INT32_MAX = 2_147_483_647;
8
+ // Keep parity with the Node backend's `kMaxEkArrayLen`.
9
+ const kMaxEkArrayLen = 1_000_000;
10
+ // Prevent pathological `vallen` from forcing enormous allocations.
11
+ const kMaxEkVallenBytes = 1_000_000;
12
+ const EK_ONLY = ["EK"];
13
+ function utf8TruncateLen(encoded, maxBytes) {
14
+ if (maxBytes <= 0) {
15
+ return 0;
16
+ }
17
+ if (encoded.length <= maxBytes) {
18
+ return encoded.length;
19
+ }
20
+ // Truncate to a UTF-8 boundary so we don't split a multi-byte codepoint.
21
+ //
22
+ // We only need to inspect the last few bytes because UTF-8 sequences are
23
+ // at most 4 bytes long.
24
+ let len = maxBytes;
25
+ let start = len - 1;
26
+ // Walk backwards over continuation bytes (10xxxxxx).
27
+ while (start >= 0 && (encoded[start] & 0b1100_0000) === 0b1000_0000) {
28
+ start--;
29
+ }
30
+ if (start < 0) {
31
+ // The slice starts mid-codepoint (e.g. maxBytes < first codepoint length).
32
+ return 0;
33
+ }
34
+ const lead = encoded[start];
35
+ let seqLen;
36
+ if ((lead & 0b1000_0000) === 0) {
37
+ seqLen = 1;
38
+ }
39
+ else if ((lead & 0b1110_0000) === 0b1100_0000) {
40
+ seqLen = 2;
41
+ }
42
+ else if ((lead & 0b1111_0000) === 0b1110_0000) {
43
+ seqLen = 3;
44
+ }
45
+ else if ((lead & 0b1111_1000) === 0b1111_0000) {
46
+ seqLen = 4;
47
+ }
48
+ else {
49
+ // Shouldn't happen for TextEncoder output; treat as a single byte.
50
+ seqLen = 1;
51
+ }
52
+ // If the last codepoint would extend past our slice, drop it.
53
+ if (start + seqLen > len) {
54
+ len = start;
55
+ }
56
+ return len;
57
+ }
58
+ function writeFixedWidthStringArray(module, ptr, stride, values) {
59
+ const totalBytes = stride * values.length;
60
+ module.HEAPU8.fill(0, ptr, ptr + totalBytes);
61
+ const maxBytes = Math.max(0, stride - 1);
62
+ let offset = ptr;
63
+ for (const value of values) {
64
+ const encoded = UTF8_ENCODER.encode(value);
65
+ const copyLen = utf8TruncateLen(encoded, maxBytes);
66
+ if (copyLen > 0) {
67
+ module.HEAPU8.set(encoded.subarray(0, copyLen), offset);
68
+ }
69
+ module.HEAPU8[offset + copyLen] = 0;
70
+ offset += stride;
71
+ }
72
+ }
73
+ function sumEntszsChecked(entszs, nlflgs, context) {
74
+ if (entszs.length !== nlflgs.length) {
75
+ throw new RangeError(`${context}: expected entszs.length === nlflgs.length`);
76
+ }
77
+ let sum = 0;
78
+ for (let i = 0; i < entszs.length; i++) {
79
+ const isNull = nlflgs[i];
80
+ if (typeof isNull !== "boolean") {
81
+ throw new TypeError(`${context}: expected nlflgs[${i}] to be a boolean`);
82
+ }
83
+ // CSPICE semantics (keep parity with the C shim + Node addon):
84
+ // - NULL entries may have entszs[i] == 0 (and are allowed to be any value >= 0)
85
+ // - non-NULL entries must have entszs[i] >= 1
86
+ assertSpiceInt32(entszs[i], `${context}(entszs[${i}])`, { min: isNull ? 0 : 1 });
87
+ sum += entszs[i];
88
+ if (sum > INT32_MAX) {
89
+ throw new RangeError(`${context}: sum(entszs) overflow (max ${INT32_MAX})`);
90
+ }
91
+ if (sum > kMaxEkArrayLen) {
92
+ throw new RangeError(`${context}: sum(entszs) must be <= ${kMaxEkArrayLen}`);
93
+ }
94
+ }
95
+ return sum;
96
+ }
97
+ function readHeapI32(module, idx, context) {
98
+ const heap = module.HEAP32;
99
+ const v = heap[idx];
100
+ if (v === undefined) {
101
+ throw new RangeError(`${context}: out-of-bounds HEAP32 read (idx=${idx}, heapLen=${heap.length})`);
102
+ }
103
+ return v;
104
+ }
105
+ function callVoidHandle(module, fn, handle) {
106
+ withMalloc(module, WASM_ERR_MAX_BYTES, (errPtr) => {
107
+ const code = fn(handle, errPtr, WASM_ERR_MAX_BYTES);
108
+ if (code !== 0) {
109
+ throwWasmSpiceError(module, errPtr, WASM_ERR_MAX_BYTES, code);
110
+ }
111
+ });
112
+ }
113
+ /** Create an {@link EkApi} implementation backed by a WASM Emscripten module. */
114
+ export function createEkApi(module, spiceHandles) {
115
+ const TABLE_NAME_MAX_BYTES = 256;
116
+ const api = {
117
+ ekopr: (path) => {
118
+ const resolved = resolveKernelPath(path);
119
+ const pathPtr = writeUtf8CString(module, resolved);
120
+ try {
121
+ const nativeHandle = withAllocs(module, [4, WASM_ERR_MAX_BYTES], (outHandlePtr, errPtr) => {
122
+ module.HEAP32[outHandlePtr >> 2] = 0;
123
+ const code = module._tspice_ekopr(pathPtr, outHandlePtr, errPtr, WASM_ERR_MAX_BYTES);
124
+ if (code !== 0) {
125
+ throwWasmSpiceError(module, errPtr, WASM_ERR_MAX_BYTES, code);
126
+ }
127
+ return readHeapI32(module, outHandlePtr >> 2, "ekopr(outHandlePtr)");
128
+ });
129
+ return spiceHandles.register("EK", nativeHandle);
130
+ }
131
+ finally {
132
+ module._free(pathPtr);
133
+ }
134
+ },
135
+ ekopw: (path) => {
136
+ const resolved = resolveKernelPath(path);
137
+ const pathPtr = writeUtf8CString(module, resolved);
138
+ try {
139
+ const nativeHandle = withAllocs(module, [4, WASM_ERR_MAX_BYTES], (outHandlePtr, errPtr) => {
140
+ module.HEAP32[outHandlePtr >> 2] = 0;
141
+ const code = module._tspice_ekopw(pathPtr, outHandlePtr, errPtr, WASM_ERR_MAX_BYTES);
142
+ if (code !== 0) {
143
+ throwWasmSpiceError(module, errPtr, WASM_ERR_MAX_BYTES, code);
144
+ }
145
+ return readHeapI32(module, outHandlePtr >> 2, "ekopw(outHandlePtr)");
146
+ });
147
+ return spiceHandles.register("EK", nativeHandle);
148
+ }
149
+ finally {
150
+ module._free(pathPtr);
151
+ }
152
+ },
153
+ ekopn: (path, ifname, ncomch) => {
154
+ assertSpiceInt32NonNegative(ncomch, "ekopn(ncomch)");
155
+ const resolved = resolveKernelPath(path);
156
+ // `ekopn_c` creates the output file via C stdio, so we must ensure the
157
+ // directory exists in the Emscripten FS.
158
+ const dir = resolved.split("/").slice(0, -1).join("/") || "/";
159
+ if (dir && dir !== "/") {
160
+ module.FS.mkdirTree(dir);
161
+ }
162
+ const pathPtr = writeUtf8CString(module, resolved);
163
+ const ifnamePtr = writeUtf8CString(module, ifname);
164
+ try {
165
+ const nativeHandle = withAllocs(module, [4, WASM_ERR_MAX_BYTES], (outHandlePtr, errPtr) => {
166
+ module.HEAP32[outHandlePtr >> 2] = 0;
167
+ const code = module._tspice_ekopn(pathPtr, ifnamePtr, ncomch, outHandlePtr, errPtr, WASM_ERR_MAX_BYTES);
168
+ if (code !== 0) {
169
+ throwWasmSpiceError(module, errPtr, WASM_ERR_MAX_BYTES, code);
170
+ }
171
+ return readHeapI32(module, outHandlePtr >> 2, "ekopn(outHandlePtr)");
172
+ });
173
+ return spiceHandles.register("EK", nativeHandle);
174
+ }
175
+ finally {
176
+ module._free(ifnamePtr);
177
+ module._free(pathPtr);
178
+ }
179
+ },
180
+ ekcls: (handle) => spiceHandles.close(handle, EK_ONLY, (entry) => callVoidHandle(module, module._tspice_ekcls, entry.nativeHandle), "ekcls"),
181
+ ekntab: () => withAllocs(module, [4, WASM_ERR_MAX_BYTES], (outNPtr, errPtr) => {
182
+ module.HEAP32[outNPtr >> 2] = 0;
183
+ const code = module._tspice_ekntab(outNPtr, errPtr, WASM_ERR_MAX_BYTES);
184
+ if (code !== 0) {
185
+ throwWasmSpiceError(module, errPtr, WASM_ERR_MAX_BYTES, code);
186
+ }
187
+ const n = readHeapI32(module, outNPtr >> 2, "ekntab(outNPtr)");
188
+ assertSpiceInt32NonNegative(n, "ekntab()");
189
+ return n;
190
+ }),
191
+ ektnam: (n) => {
192
+ assertSpiceInt32NonNegative(n, "ektnam(n)");
193
+ return withAllocs(module, [TABLE_NAME_MAX_BYTES, WASM_ERR_MAX_BYTES], (outNamePtr, errPtr) => {
194
+ module.HEAPU8[outNamePtr] = 0;
195
+ const code = module._tspice_ektnam(n, outNamePtr, TABLE_NAME_MAX_BYTES, errPtr, WASM_ERR_MAX_BYTES);
196
+ if (code !== 0) {
197
+ throwWasmSpiceError(module, errPtr, WASM_ERR_MAX_BYTES, code);
198
+ }
199
+ return readFixedWidthCString(module, outNamePtr, TABLE_NAME_MAX_BYTES);
200
+ });
201
+ },
202
+ eknseg: (handle) => {
203
+ const nativeHandle = spiceHandles.lookup(handle, EK_ONLY, "eknseg").nativeHandle;
204
+ return withAllocs(module, [4, WASM_ERR_MAX_BYTES], (outNsegPtr, errPtr) => {
205
+ module.HEAP32[outNsegPtr >> 2] = 0;
206
+ const code = module._tspice_eknseg(nativeHandle, outNsegPtr, errPtr, WASM_ERR_MAX_BYTES);
207
+ if (code !== 0) {
208
+ throwWasmSpiceError(module, errPtr, WASM_ERR_MAX_BYTES, code);
209
+ }
210
+ const nseg = readHeapI32(module, outNsegPtr >> 2, "eknseg(outNsegPtr)");
211
+ assertSpiceInt32NonNegative(nseg, "eknseg(handle)");
212
+ return nseg;
213
+ });
214
+ },
215
+ ekfind: (query) => {
216
+ const queryPtr = writeUtf8CString(module, query);
217
+ const outErrmsgMaxBytes = WASM_ERR_MAX_BYTES;
218
+ try {
219
+ return withAllocs(module, [4, 4, outErrmsgMaxBytes, WASM_ERR_MAX_BYTES], (outNmrowsPtr, outErrorPtr, outErrmsgPtr, errPtr) => {
220
+ module.HEAP32[outNmrowsPtr >> 2] = 0;
221
+ module.HEAP32[outErrorPtr >> 2] = 0;
222
+ module.HEAPU8[outErrmsgPtr] = 0;
223
+ const code = module._tspice_ekfind(queryPtr, outErrmsgMaxBytes, outNmrowsPtr, outErrorPtr, outErrmsgPtr, errPtr, WASM_ERR_MAX_BYTES);
224
+ if (code !== 0) {
225
+ throwWasmSpiceError(module, errPtr, WASM_ERR_MAX_BYTES, code);
226
+ }
227
+ const error = readHeapI32(module, outErrorPtr >> 2, "ekfind(outErrorPtr)") !== 0;
228
+ if (error) {
229
+ return { ok: false, errmsg: readFixedWidthCString(module, outErrmsgPtr, outErrmsgMaxBytes) };
230
+ }
231
+ const nmrows = readHeapI32(module, outNmrowsPtr >> 2, "ekfind(outNmrowsPtr)");
232
+ return { ok: true, nmrows };
233
+ });
234
+ }
235
+ finally {
236
+ module._free(queryPtr);
237
+ }
238
+ },
239
+ ekgc: (selidx, row, elment) => {
240
+ assertSpiceInt32NonNegative(selidx, "ekgc(selidx)");
241
+ assertSpiceInt32NonNegative(row, "ekgc(row)");
242
+ assertSpiceInt32NonNegative(elment, "ekgc(elment)");
243
+ // Keep parity with backend-node's `kOutMaxBytes`: large enough to avoid truncating
244
+ // before CSPICE's own ~1024-char EK string limit (1024 + NUL).
245
+ const outMaxBytes = WASM_ERR_MAX_BYTES;
246
+ return withAllocs(module, [outMaxBytes, 4, 4, WASM_ERR_MAX_BYTES], (outCdataPtr, outNullPtr, outFoundPtr, errPtr) => {
247
+ module.HEAPU8[outCdataPtr] = 0;
248
+ module.HEAP32[outNullPtr >> 2] = 0;
249
+ module.HEAP32[outFoundPtr >> 2] = 0;
250
+ const code = module._tspice_ekgc(selidx, row, elment, outCdataPtr, outMaxBytes, outNullPtr, outFoundPtr, errPtr, WASM_ERR_MAX_BYTES);
251
+ if (code !== 0) {
252
+ throwWasmSpiceError(module, errPtr, WASM_ERR_MAX_BYTES, code);
253
+ }
254
+ const found = readHeapI32(module, outFoundPtr >> 2, "ekgc(outFoundPtr)") !== 0;
255
+ if (!found) {
256
+ return { found: false };
257
+ }
258
+ const isNull = readHeapI32(module, outNullPtr >> 2, "ekgc(outNullPtr)") !== 0;
259
+ if (isNull) {
260
+ return { found: true, isNull: true };
261
+ }
262
+ return {
263
+ found: true,
264
+ isNull: false,
265
+ value: readFixedWidthCString(module, outCdataPtr, outMaxBytes),
266
+ };
267
+ });
268
+ },
269
+ ekgd: (selidx, row, elment) => {
270
+ assertSpiceInt32NonNegative(selidx, "ekgd(selidx)");
271
+ assertSpiceInt32NonNegative(row, "ekgd(row)");
272
+ assertSpiceInt32NonNegative(elment, "ekgd(elment)");
273
+ return withAllocs(module, [8, 4, 4, WASM_ERR_MAX_BYTES], (outDdataPtr, outNullPtr, outFoundPtr, errPtr) => {
274
+ module.HEAPF64[outDdataPtr >> 3] = 0;
275
+ module.HEAP32[outNullPtr >> 2] = 0;
276
+ module.HEAP32[outFoundPtr >> 2] = 0;
277
+ const code = module._tspice_ekgd(selidx, row, elment, outDdataPtr, outNullPtr, outFoundPtr, errPtr, WASM_ERR_MAX_BYTES);
278
+ if (code !== 0) {
279
+ throwWasmSpiceError(module, errPtr, WASM_ERR_MAX_BYTES, code);
280
+ }
281
+ const found = readHeapI32(module, outFoundPtr >> 2, "ekgd(outFoundPtr)") !== 0;
282
+ if (!found) {
283
+ return { found: false };
284
+ }
285
+ const isNull = readHeapI32(module, outNullPtr >> 2, "ekgd(outNullPtr)") !== 0;
286
+ if (isNull) {
287
+ return { found: true, isNull: true };
288
+ }
289
+ const value = module.HEAPF64[outDdataPtr >> 3];
290
+ return { found: true, isNull: false, value };
291
+ });
292
+ },
293
+ ekgi: (selidx, row, elment) => {
294
+ assertSpiceInt32NonNegative(selidx, "ekgi(selidx)");
295
+ assertSpiceInt32NonNegative(row, "ekgi(row)");
296
+ assertSpiceInt32NonNegative(elment, "ekgi(elment)");
297
+ return withAllocs(module, [4, 4, 4, WASM_ERR_MAX_BYTES], (outIdataPtr, outNullPtr, outFoundPtr, errPtr) => {
298
+ module.HEAP32[outIdataPtr >> 2] = 0;
299
+ module.HEAP32[outNullPtr >> 2] = 0;
300
+ module.HEAP32[outFoundPtr >> 2] = 0;
301
+ const code = module._tspice_ekgi(selidx, row, elment, outIdataPtr, outNullPtr, outFoundPtr, errPtr, WASM_ERR_MAX_BYTES);
302
+ if (code !== 0) {
303
+ throwWasmSpiceError(module, errPtr, WASM_ERR_MAX_BYTES, code);
304
+ }
305
+ const found = readHeapI32(module, outFoundPtr >> 2, "ekgi(outFoundPtr)") !== 0;
306
+ if (!found) {
307
+ return { found: false };
308
+ }
309
+ const isNull = readHeapI32(module, outNullPtr >> 2, "ekgi(outNullPtr)") !== 0;
310
+ if (isNull) {
311
+ return { found: true, isNull: true };
312
+ }
313
+ const value = readHeapI32(module, outIdataPtr >> 2, "ekgi(outIdataPtr)");
314
+ return { found: true, isNull: false, value };
315
+ });
316
+ },
317
+ ekifld: (handle, tabnam, nrows, cnames, decls) => {
318
+ assertSpiceInt32(nrows, "ekifld(nrows)", { min: 1 });
319
+ // Hard cap to defend against pathological `nrows` values that would otherwise trigger
320
+ // massive native allocations (e.g. rcptrs).
321
+ if (nrows > kMaxEkArrayLen) {
322
+ throw new RangeError(`ekifld(): expected nrows <= ${kMaxEkArrayLen}`);
323
+ }
324
+ if (cnames.length === 0) {
325
+ throw new RangeError("ekifld(cnames): expected cnames.length > 0");
326
+ }
327
+ if (decls.length !== cnames.length) {
328
+ throw new RangeError("ekifld(decls): expected decls.length === cnames.length");
329
+ }
330
+ const ncols = cnames.length;
331
+ let cnamln = 2;
332
+ for (const s of cnames) {
333
+ cnamln = Math.max(cnamln, UTF8_ENCODER.encode(s).length + 1);
334
+ }
335
+ let declen = 2;
336
+ for (const s of decls) {
337
+ declen = Math.max(declen, UTF8_ENCODER.encode(s).length + 1);
338
+ }
339
+ const nativeHandle = spiceHandles.lookup(handle, EK_ONLY, "ekifld").nativeHandle;
340
+ const tabnamPtr = writeUtf8CString(module, tabnam);
341
+ try {
342
+ return withAllocs(module, [ncols * cnamln, ncols * declen, 4, nrows * 4, WASM_ERR_MAX_BYTES], (cnamesPtr, declsPtr, outSegnoPtr, outRcptrsPtr, errPtr) => {
343
+ writeFixedWidthStringArray(module, cnamesPtr, cnamln, cnames);
344
+ writeFixedWidthStringArray(module, declsPtr, declen, decls);
345
+ module.HEAP32[outSegnoPtr >> 2] = 0;
346
+ const code = module._tspice_ekifld(nativeHandle, tabnamPtr, ncols, nrows, cnamln, cnamesPtr, declen, declsPtr, outSegnoPtr, outRcptrsPtr, errPtr, WASM_ERR_MAX_BYTES);
347
+ if (code !== 0) {
348
+ throwWasmSpiceError(module, errPtr, WASM_ERR_MAX_BYTES, code);
349
+ }
350
+ const segno = readHeapI32(module, outSegnoPtr >> 2, "ekifld(outSegnoPtr)");
351
+ const rcptrsView = module.HEAP32.subarray(outRcptrsPtr >> 2, (outRcptrsPtr >> 2) + nrows);
352
+ return { segno, rcptrs: Array.from(rcptrsView) };
353
+ });
354
+ }
355
+ finally {
356
+ module._free(tabnamPtr);
357
+ }
358
+ },
359
+ ekacli: (handle, segno, column, ivals, entszs, nlflgs, rcptrs) => {
360
+ assertSpiceInt32NonNegative(segno, "ekacli(segno)");
361
+ const nrows = rcptrs.length;
362
+ if (entszs.length !== nrows || nlflgs.length !== nrows) {
363
+ throw new RangeError("ekacli(): expected entszs/nlflgs/rcptrs to have the same length");
364
+ }
365
+ if (nrows === 0) {
366
+ throw new RangeError("ekacli(): expected rcptrs.length > 0");
367
+ }
368
+ if (nrows > kMaxEkArrayLen) {
369
+ throw new RangeError(`ekacli(): expected nrows <= ${kMaxEkArrayLen}`);
370
+ }
371
+ const required = sumEntszsChecked(entszs, nlflgs, "ekacli()");
372
+ if (ivals.length !== required) {
373
+ throw new RangeError("ekacli(): expected ivals.length === sum(entszs)");
374
+ }
375
+ for (let i = 0; i < ivals.length; i++) {
376
+ assertSpiceInt32(ivals[i], `ekacli(ivals[${i}])`);
377
+ }
378
+ for (let i = 0; i < rcptrs.length; i++) {
379
+ assertSpiceInt32(rcptrs[i], `ekacli(rcptrs[${i}])`);
380
+ }
381
+ const nativeHandle = spiceHandles.lookup(handle, EK_ONLY, "ekacli").nativeHandle;
382
+ const columnPtr = writeUtf8CString(module, column);
383
+ // `withAllocs()` rejects 0-byte allocations; when all rows are NULL,
384
+ // `sum(entszs) === 0` and the values buffer can be empty.
385
+ const ivalsBytes = Math.max(1, ivals.length) * 4;
386
+ try {
387
+ return withAllocs(module, [ivalsBytes, nrows * 4, nrows * 4, nrows * 4, WASM_ERR_MAX_BYTES], (ivalsPtr, entszsPtr, nlflgsPtr, rcptrsPtr, errPtr) => {
388
+ module.HEAP32.set(Int32Array.from(ivals), ivalsPtr >> 2);
389
+ module.HEAP32.set(Int32Array.from(entszs), entszsPtr >> 2);
390
+ module.HEAP32.set(Int32Array.from(nlflgs.map((b) => (b ? 1 : 0))), nlflgsPtr >> 2);
391
+ module.HEAP32.set(Int32Array.from(rcptrs), rcptrsPtr >> 2);
392
+ const code = module._tspice_ekacli(nativeHandle, segno, columnPtr, nrows, ivalsPtr, ivals.length, entszsPtr, nlflgsPtr, rcptrsPtr, errPtr, WASM_ERR_MAX_BYTES);
393
+ if (code !== 0) {
394
+ throwWasmSpiceError(module, errPtr, WASM_ERR_MAX_BYTES, code);
395
+ }
396
+ });
397
+ }
398
+ finally {
399
+ module._free(columnPtr);
400
+ }
401
+ },
402
+ ekacld: (handle, segno, column, dvals, entszs, nlflgs, rcptrs) => {
403
+ assertSpiceInt32NonNegative(segno, "ekacld(segno)");
404
+ const nrows = rcptrs.length;
405
+ if (entszs.length !== nrows || nlflgs.length !== nrows) {
406
+ throw new RangeError("ekacld(): expected entszs/nlflgs/rcptrs to have the same length");
407
+ }
408
+ if (nrows === 0) {
409
+ throw new RangeError("ekacld(): expected rcptrs.length > 0");
410
+ }
411
+ if (nrows > kMaxEkArrayLen) {
412
+ throw new RangeError(`ekacld(): expected nrows <= ${kMaxEkArrayLen}`);
413
+ }
414
+ const required = sumEntszsChecked(entszs, nlflgs, "ekacld()");
415
+ if (dvals.length !== required) {
416
+ throw new RangeError("ekacld(): expected dvals.length === sum(entszs)");
417
+ }
418
+ for (let i = 0; i < dvals.length; i++) {
419
+ if (!Number.isFinite(dvals[i])) {
420
+ throw new TypeError(`ekacld(dvals[${i}]) must be a finite number`);
421
+ }
422
+ }
423
+ for (let i = 0; i < rcptrs.length; i++) {
424
+ assertSpiceInt32(rcptrs[i], `ekacld(rcptrs[${i}])`);
425
+ }
426
+ const nativeHandle = spiceHandles.lookup(handle, EK_ONLY, "ekacld").nativeHandle;
427
+ const columnPtr = writeUtf8CString(module, column);
428
+ // `withAllocs()` rejects 0-byte allocations; when all rows are NULL,
429
+ // `sum(entszs) === 0` and the values buffer can be empty.
430
+ const dvalsBytes = Math.max(1, dvals.length) * 8;
431
+ try {
432
+ return withAllocs(module, [dvalsBytes, nrows * 4, nrows * 4, nrows * 4, WASM_ERR_MAX_BYTES], (dvalsPtr, entszsPtr, nlflgsPtr, rcptrsPtr, errPtr) => {
433
+ module.HEAPF64.set(Float64Array.from(dvals), dvalsPtr >> 3);
434
+ module.HEAP32.set(Int32Array.from(entszs), entszsPtr >> 2);
435
+ module.HEAP32.set(Int32Array.from(nlflgs.map((b) => (b ? 1 : 0))), nlflgsPtr >> 2);
436
+ module.HEAP32.set(Int32Array.from(rcptrs), rcptrsPtr >> 2);
437
+ const code = module._tspice_ekacld(nativeHandle, segno, columnPtr, nrows, dvalsPtr, dvals.length, entszsPtr, nlflgsPtr, rcptrsPtr, errPtr, WASM_ERR_MAX_BYTES);
438
+ if (code !== 0) {
439
+ throwWasmSpiceError(module, errPtr, WASM_ERR_MAX_BYTES, code);
440
+ }
441
+ });
442
+ }
443
+ finally {
444
+ module._free(columnPtr);
445
+ }
446
+ },
447
+ ekaclc: (handle, segno, column, cvals, entszs, nlflgs, rcptrs) => {
448
+ assertSpiceInt32NonNegative(segno, "ekaclc(segno)");
449
+ const nrows = rcptrs.length;
450
+ if (entszs.length !== nrows || nlflgs.length !== nrows) {
451
+ throw new RangeError("ekaclc(): expected entszs/nlflgs/rcptrs to have the same length");
452
+ }
453
+ if (nrows === 0) {
454
+ throw new RangeError("ekaclc(): expected rcptrs.length > 0");
455
+ }
456
+ if (nrows > kMaxEkArrayLen) {
457
+ throw new RangeError(`ekaclc(): expected nrows <= ${kMaxEkArrayLen}`);
458
+ }
459
+ const required = sumEntszsChecked(entszs, nlflgs, "ekaclc()");
460
+ if (cvals.length !== required) {
461
+ throw new RangeError("ekaclc(): expected cvals.length === sum(entszs)");
462
+ }
463
+ const nvals = cvals.length;
464
+ let vallen = 1;
465
+ for (const s of cvals) {
466
+ const bytes = UTF8_ENCODER.encode(s).length + 1;
467
+ if (bytes > kMaxEkVallenBytes) {
468
+ throw new RangeError(`ekaclc(): value byte length exceeds cap (${kMaxEkVallenBytes})`);
469
+ }
470
+ vallen = Math.max(vallen, bytes);
471
+ }
472
+ if (nvals > kMaxEkArrayLen) {
473
+ throw new RangeError(`ekaclc(): expected nvals <= ${kMaxEkArrayLen}`);
474
+ }
475
+ if (!Number.isSafeInteger(nvals * vallen)) {
476
+ throw new RangeError("ekaclc(): cvals buffer size overflow");
477
+ }
478
+ const cvalsMaxBytes = nvals * vallen;
479
+ if (cvalsMaxBytes > WASM_MAX_ALLOC_BYTES) {
480
+ throw new RangeError(`ekaclc(): cvals buffer too large (${cvalsMaxBytes} bytes)`);
481
+ }
482
+ const nativeHandle = spiceHandles.lookup(handle, EK_ONLY, "ekaclc").nativeHandle;
483
+ const columnPtr = writeUtf8CString(module, column);
484
+ // `withAllocs()` rejects 0-byte allocations; when all rows are NULL,
485
+ // `sum(entszs) === 0` and the values buffer can be empty.
486
+ const cvalsAllocBytes = Math.max(1, cvalsMaxBytes);
487
+ try {
488
+ return withAllocs(module, [cvalsAllocBytes, nrows * 4, nrows * 4, nrows * 4, WASM_ERR_MAX_BYTES], (cvalsPtr, entszsPtr, nlflgsPtr, rcptrsPtr, errPtr) => {
489
+ writeFixedWidthStringArray(module, cvalsPtr, vallen, cvals);
490
+ module.HEAP32.set(Int32Array.from(entszs), entszsPtr >> 2);
491
+ module.HEAP32.set(Int32Array.from(nlflgs.map((b) => (b ? 1 : 0))), nlflgsPtr >> 2);
492
+ module.HEAP32.set(Int32Array.from(rcptrs), rcptrsPtr >> 2);
493
+ const code = module._tspice_ekaclc(nativeHandle, segno, columnPtr, nrows, nvals, vallen, cvalsMaxBytes, cvalsPtr, entszsPtr, nlflgsPtr, rcptrsPtr, errPtr, WASM_ERR_MAX_BYTES);
494
+ if (code !== 0) {
495
+ throwWasmSpiceError(module, errPtr, WASM_ERR_MAX_BYTES, code);
496
+ }
497
+ });
498
+ }
499
+ finally {
500
+ module._free(columnPtr);
501
+ }
502
+ },
503
+ ekffld: (handle, segno, rcptrs) => {
504
+ assertSpiceInt32NonNegative(segno, "ekffld(segno)");
505
+ const nrows = rcptrs.length;
506
+ if (nrows === 0) {
507
+ throw new RangeError("ekffld(rcptrs): expected rcptrs.length > 0");
508
+ }
509
+ if (nrows > kMaxEkArrayLen) {
510
+ throw new RangeError(`ekffld(): expected rcptrs.length <= ${kMaxEkArrayLen}`);
511
+ }
512
+ for (let i = 0; i < nrows; i++) {
513
+ assertSpiceInt32(rcptrs[i], `ekffld(rcptrs[${i}])`);
514
+ }
515
+ const nativeHandle = spiceHandles.lookup(handle, EK_ONLY, "ekffld").nativeHandle;
516
+ return withAllocs(module, [rcptrs.length * 4, WASM_ERR_MAX_BYTES], (rcptrsPtr, errPtr) => {
517
+ module.HEAP32.set(Int32Array.from(rcptrs), rcptrsPtr >> 2);
518
+ const code = module._tspice_ekffld(nativeHandle, segno, rcptrsPtr, errPtr, WASM_ERR_MAX_BYTES);
519
+ if (code !== 0) {
520
+ throwWasmSpiceError(module, errPtr, WASM_ERR_MAX_BYTES, code);
521
+ }
522
+ });
523
+ },
524
+ };
525
+ Object.defineProperty(api, "__debugOpenHandleCount", {
526
+ value: () => {
527
+ const entries = spiceHandles.__entries?.();
528
+ if (!entries) {
529
+ return spiceHandles.size();
530
+ }
531
+ let count = 0;
532
+ for (const [, entry] of entries) {
533
+ if (entry.kind === "EK") {
534
+ count++;
535
+ }
536
+ }
537
+ return count;
538
+ },
539
+ enumerable: false,
540
+ });
541
+ return api;
542
+ }
543
+ //# sourceMappingURL=ek.js.map
@@ -1,4 +1,7 @@
1
1
  import type { EphemerisApi } from "#backend-contract";
2
2
  import type { EmscriptenModule } from "../lowlevel/exports.js";
3
- export declare function createEphemerisApi(module: EmscriptenModule): EphemerisApi;
3
+ import type { SpiceHandleRegistry } from "../runtime/spice-handles.js";
4
+ import type { VirtualOutputRegistry } from "../runtime/virtual-outputs.js";
5
+ /** Create an {@link EphemerisApi} implementation backed by a WASM Emscripten module. */
6
+ export declare function createEphemerisApi(module: EmscriptenModule, handles: SpiceHandleRegistry, virtualOutputs: VirtualOutputRegistry): EphemerisApi;
4
7
  //# sourceMappingURL=ephemeris.d.ts.map