@rybosome/tspice 0.0.7 → 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 (214) hide show
  1. package/README.md +140 -78
  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 +50 -0
  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 +40 -0
  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 +31 -3
  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 +26 -14
  33. package/backend-contract/dist/shared/mat3.js +46 -17
  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 +106 -1
  41. package/backend-contract/dist/shared/vec.d.ts +54 -0
  42. package/backend-contract/dist/shared/vec.js +162 -0
  43. package/backend-fake/dist/.tsbuildinfo +1 -1
  44. package/backend-fake/dist/index.d.ts +19 -1
  45. package/backend-fake/dist/index.js +1103 -18
  46. package/backend-node/dist/.tsbuildinfo +1 -1
  47. package/backend-node/dist/codec/arrays.d.ts +9 -0
  48. package/backend-node/dist/codec/arrays.js +36 -0
  49. package/backend-node/dist/codec/errors.d.ts +6 -6
  50. package/backend-node/dist/codec/errors.js +6 -6
  51. package/backend-node/dist/domains/cells-windows.d.ts +5 -0
  52. package/backend-node/dist/domains/cells-windows.js +112 -0
  53. package/backend-node/dist/domains/coords-vectors.d.ts +1 -0
  54. package/backend-node/dist/domains/coords-vectors.js +64 -1
  55. package/backend-node/dist/domains/dsk.d.ts +6 -0
  56. package/backend-node/dist/domains/dsk.js +108 -0
  57. package/backend-node/dist/domains/ek.d.ts +10 -0
  58. package/backend-node/dist/domains/ek.js +100 -0
  59. package/backend-node/dist/domains/ephemeris.d.ts +5 -1
  60. package/backend-node/dist/domains/ephemeris.js +150 -1
  61. package/backend-node/dist/domains/error.d.ts +5 -0
  62. package/backend-node/dist/domains/error.js +34 -0
  63. package/backend-node/dist/domains/file-io.d.ts +7 -0
  64. package/backend-node/dist/domains/file-io.js +105 -0
  65. package/backend-node/dist/domains/frames.d.ts +1 -0
  66. package/backend-node/dist/domains/frames.js +52 -0
  67. package/backend-node/dist/domains/geometry-gf.d.ts +5 -0
  68. package/backend-node/dist/domains/geometry-gf.js +74 -0
  69. package/backend-node/dist/domains/geometry.d.ts +1 -0
  70. package/backend-node/dist/domains/geometry.js +62 -0
  71. package/backend-node/dist/domains/ids-names.d.ts +2 -1
  72. package/backend-node/dist/domains/ids-names.js +30 -0
  73. package/backend-node/dist/domains/kernel-pool.d.ts +5 -0
  74. package/backend-node/dist/domains/kernel-pool.js +74 -0
  75. package/backend-node/dist/domains/kernels.d.ts +1 -0
  76. package/backend-node/dist/domains/kernels.js +100 -13
  77. package/backend-node/dist/domains/time.d.ts +1 -0
  78. package/backend-node/dist/domains/time.js +75 -1
  79. package/backend-node/dist/index.d.ts +2 -0
  80. package/backend-node/dist/index.js +62 -1
  81. package/backend-node/dist/lowlevel/binding.d.ts +3 -0
  82. package/backend-node/dist/lowlevel/binding.js +115 -0
  83. package/backend-node/dist/runtime/addon.d.ts +271 -0
  84. package/backend-node/dist/runtime/addon.js +3 -0
  85. package/backend-node/dist/runtime/kernel-staging.d.ts +17 -0
  86. package/backend-node/dist/runtime/kernel-staging.js +80 -7
  87. package/backend-node/dist/runtime/spice-handles.d.ts +3 -0
  88. package/backend-node/dist/runtime/spice-handles.js +2 -0
  89. package/backend-node/dist/runtime/virtual-output-staging.d.ts +16 -0
  90. package/backend-node/dist/runtime/virtual-output-staging.js +148 -0
  91. package/backend-wasm/dist/.tsbuildinfo +1 -1
  92. package/backend-wasm/dist/codec/alloc.d.ts +19 -0
  93. package/backend-wasm/dist/codec/alloc.js +64 -0
  94. package/backend-wasm/dist/codec/calls.d.ts +2 -0
  95. package/backend-wasm/dist/codec/calls.js +13 -24
  96. package/backend-wasm/dist/codec/errors.d.ts +6 -0
  97. package/backend-wasm/dist/codec/errors.js +34 -2
  98. package/backend-wasm/dist/codec/found.d.ts +2 -0
  99. package/backend-wasm/dist/codec/found.js +20 -43
  100. package/backend-wasm/dist/codec/strings.d.ts +31 -1
  101. package/backend-wasm/dist/codec/strings.js +93 -6
  102. package/backend-wasm/dist/domains/cells-windows.d.ts +9 -0
  103. package/backend-wasm/dist/domains/cells-windows.js +392 -0
  104. package/backend-wasm/dist/domains/coords-vectors.d.ts +1 -0
  105. package/backend-wasm/dist/domains/coords-vectors.js +377 -187
  106. package/backend-wasm/dist/domains/dsk.d.ts +6 -0
  107. package/backend-wasm/dist/domains/dsk.js +179 -0
  108. package/backend-wasm/dist/domains/ek.d.ts +6 -0
  109. package/backend-wasm/dist/domains/ek.js +543 -0
  110. package/backend-wasm/dist/domains/ephemeris.d.ts +4 -1
  111. package/backend-wasm/dist/domains/ephemeris.js +405 -46
  112. package/backend-wasm/dist/domains/error.d.ts +5 -0
  113. package/backend-wasm/dist/domains/error.js +109 -0
  114. package/backend-wasm/dist/domains/file-io.d.ts +7 -0
  115. package/backend-wasm/dist/domains/file-io.js +462 -0
  116. package/backend-wasm/dist/domains/frames.d.ts +1 -0
  117. package/backend-wasm/dist/domains/frames.js +136 -4
  118. package/backend-wasm/dist/domains/geometry-gf.d.ts +5 -0
  119. package/backend-wasm/dist/domains/geometry-gf.js +178 -0
  120. package/backend-wasm/dist/domains/geometry.d.ts +1 -0
  121. package/backend-wasm/dist/domains/geometry.js +210 -0
  122. package/backend-wasm/dist/domains/ids-names.d.ts +2 -1
  123. package/backend-wasm/dist/domains/ids-names.js +89 -0
  124. package/backend-wasm/dist/domains/kernel-pool.d.ts +5 -0
  125. package/backend-wasm/dist/domains/kernel-pool.js +357 -0
  126. package/backend-wasm/dist/domains/kernels.d.ts +1 -0
  127. package/backend-wasm/dist/domains/kernels.js +91 -2
  128. package/backend-wasm/dist/domains/time.d.ts +2 -0
  129. package/backend-wasm/dist/domains/time.js +235 -133
  130. package/backend-wasm/dist/lowlevel/exports.d.ts +215 -1
  131. package/backend-wasm/dist/lowlevel/exports.js +217 -38
  132. package/backend-wasm/dist/runtime/create-backend-options.d.ts +21 -0
  133. package/backend-wasm/dist/runtime/create-backend.node.d.ts +7 -0
  134. package/backend-wasm/dist/runtime/create-backend.node.js +283 -12
  135. package/backend-wasm/dist/runtime/create-backend.web.d.ts +1 -0
  136. package/backend-wasm/dist/runtime/create-backend.web.js +40 -4
  137. package/backend-wasm/dist/runtime/fs.d.ts +5 -0
  138. package/backend-wasm/dist/runtime/fs.js +5 -0
  139. package/backend-wasm/dist/runtime/spice-handles.d.ts +3 -0
  140. package/backend-wasm/dist/runtime/spice-handles.js +2 -0
  141. package/backend-wasm/dist/runtime/virtual-outputs.d.ts +16 -0
  142. package/backend-wasm/dist/runtime/virtual-outputs.js +35 -0
  143. package/backend-wasm/dist/tspice_backend_wasm.node.js +3 -3
  144. package/backend-wasm/dist/tspice_backend_wasm.wasm +0 -0
  145. package/backend-wasm/dist/tspice_backend_wasm.web.js +1 -1
  146. package/core/dist/.tsbuildinfo +1 -1
  147. package/core/dist/index.d.ts +19 -8
  148. package/core/dist/index.js +19 -8
  149. package/dist/.tsbuildinfo +1 -1
  150. package/dist/backend.d.ts +5 -0
  151. package/dist/clients/createSpiceAsyncFromTransport.d.ts +5 -0
  152. package/dist/clients/createSpiceAsyncFromTransport.js +90 -0
  153. package/dist/clients/createSpiceSyncFromTransport.d.ts +5 -0
  154. package/dist/clients/createSpiceSyncFromTransport.js +88 -0
  155. package/dist/clients/spiceClients.d.ts +59 -0
  156. package/dist/clients/spiceClients.js +292 -0
  157. package/dist/errors.d.ts +4 -0
  158. package/dist/errors.js +4 -0
  159. package/dist/index.d.ts +10 -7
  160. package/dist/index.js +4 -3
  161. package/dist/kernels/defaultKernelPathFromUrl.d.ts +8 -0
  162. package/dist/kernels/defaultKernelPathFromUrl.js +32 -0
  163. package/dist/kernels/kernelPack.d.ts +88 -0
  164. package/dist/kernels/kernelPack.js +122 -0
  165. package/dist/kernels/kernels.d.ts +98 -0
  166. package/dist/kernels/kernels.js +217 -0
  167. package/dist/kernels/naifKernelId.d.ts +2 -0
  168. package/dist/kernels/naifKernelId.js +2 -0
  169. package/dist/kit/math/mat3.d.ts +9 -1
  170. package/dist/kit/math/mat3.js +9 -1
  171. package/dist/kit/spice/create-kit.d.ts +1 -0
  172. package/dist/kit/spice/create-kit.js +1 -0
  173. package/dist/kit/spice/frames.d.ts +1 -0
  174. package/dist/kit/spice/frames.js +1 -0
  175. package/dist/kit/spice/kernels.d.ts +1 -0
  176. package/dist/kit/spice/kernels.js +1 -0
  177. package/dist/kit/spice/state.d.ts +2 -1
  178. package/dist/kit/spice/state.js +8 -4
  179. package/dist/kit/spice/time.d.ts +1 -0
  180. package/dist/kit/spice/time.js +1 -0
  181. package/dist/kit/types/spice-types.d.ts +18 -1
  182. package/dist/spice.d.ts +10 -1
  183. package/dist/spice.js +41 -0
  184. package/dist/transport/caching/policy.d.ts +16 -0
  185. package/dist/transport/caching/policy.js +77 -0
  186. package/dist/transport/caching/withCaching.d.ts +125 -0
  187. package/dist/transport/caching/withCaching.js +335 -0
  188. package/dist/transport/caching/withCachingSync.d.ts +24 -0
  189. package/dist/transport/caching/withCachingSync.js +161 -0
  190. package/dist/transport/rpc/protocol.d.ts +35 -0
  191. package/dist/transport/rpc/protocol.js +56 -0
  192. package/dist/transport/rpc/taskScheduling.d.ts +20 -0
  193. package/dist/transport/rpc/taskScheduling.js +98 -0
  194. package/dist/transport/rpc/valueCodec.d.ts +5 -0
  195. package/dist/transport/rpc/valueCodec.js +106 -0
  196. package/dist/transport/types.d.ts +7 -0
  197. package/dist/transport/types.js +2 -0
  198. package/dist/types.d.ts +8 -5
  199. package/dist/types.js +2 -1
  200. package/dist/worker/browser/createSpiceWorker.d.ts +22 -0
  201. package/dist/worker/browser/createSpiceWorker.js +41 -0
  202. package/dist/worker/browser/createSpiceWorkerClient.d.ts +40 -0
  203. package/dist/worker/browser/createSpiceWorkerClient.js +99 -0
  204. package/dist/worker/browser/spiceWorkerEntry.d.ts +2 -0
  205. package/dist/worker/browser/spiceWorkerEntry.js +129 -0
  206. package/dist/worker/browser/spiceWorkerInlineSource.d.ts +2 -0
  207. package/dist/worker/browser/spiceWorkerInlineSource.js +4 -0
  208. package/dist/worker/index.d.ts +10 -0
  209. package/dist/worker/index.js +7 -0
  210. package/dist/worker/transport/createWorkerTransport.d.ts +69 -0
  211. package/dist/worker/transport/createWorkerTransport.js +398 -0
  212. package/dist/worker/transport/exposeTransportToWorker.d.ts +51 -0
  213. package/dist/worker/transport/exposeTransportToWorker.js +196 -0
  214. package/package.json +4 -4
@@ -24,9 +24,16 @@ function isFiniteNumber(x) {
24
24
  return typeof x === "number" && Number.isFinite(x);
25
25
  }
26
26
  function isTypedArrayView(x) {
27
- // `ArrayBuffer.isView()` is true for TypedArrays *and* DataView.
28
- // We accept TypedArray views but explicitly reject DataView.
29
- return ArrayBuffer.isView(x) && !(x instanceof DataView);
27
+ // We intentionally only accept numeric TypedArrays (not BigInt views, not DataView).
28
+ return (x instanceof Int8Array ||
29
+ x instanceof Uint8Array ||
30
+ x instanceof Uint8ClampedArray ||
31
+ x instanceof Int16Array ||
32
+ x instanceof Uint16Array ||
33
+ x instanceof Int32Array ||
34
+ x instanceof Uint32Array ||
35
+ x instanceof Float32Array ||
36
+ x instanceof Float64Array);
30
37
  }
31
38
  function isLength9ArrayLike(x) {
32
39
  return (x !== null &&
@@ -37,11 +44,11 @@ function isLength9ArrayLike(x) {
37
44
  x.length === 9);
38
45
  }
39
46
  /**
40
- * Runtime validation that an input is a length-9 array-like of finite numbers.
41
- *
42
- * This is intentionally layout-agnostic; it is used by both row-major and
43
- * column-major branded types.
44
- */
47
+ * Runtime validation that an input is a length-9 array-like of finite numbers.
48
+ *
49
+ * This is intentionally layout-agnostic; it is used by both row-major and
50
+ * column-major branded types.
51
+ */
45
52
  export function assertMat3ArrayLike9(value, options) {
46
53
  const label = options?.label ?? "Mat3";
47
54
  if (value instanceof DataView) {
@@ -57,6 +64,22 @@ export function assertMat3ArrayLike9(value, options) {
57
64
  }
58
65
  }
59
66
  }
67
+ /**
68
+ * Structural check: accepts number[] and numeric TypedArrays (excludes DataView).
69
+ *
70
+ * This does **not** assert/require that the value is branded as a row/col-major Mat3.
71
+ */
72
+ export function isMat3ArrayLike9(value) {
73
+ if (value instanceof DataView)
74
+ return false;
75
+ if (!isLength9ArrayLike(value))
76
+ return false;
77
+ for (let i = 0; i < 9; i++) {
78
+ if (!isFiniteNumber(value[i]))
79
+ return false;
80
+ }
81
+ return true;
82
+ }
60
83
  function tryDefineBrand(target, brand) {
61
84
  try {
62
85
  // Non-enumerable to avoid surprising JSON/stringification behavior.
@@ -82,11 +105,11 @@ function maybeFreeze(value, mode) {
82
105
  }
83
106
  }
84
107
  /**
85
- * Validate + brand a value as a row-major Mat3.
86
- *
87
- * Used at backend boundaries (node/wasm/fake) to avoid ad-hoc `as Mat3RowMajor`
88
- * casts.
89
- */
108
+ * Validate + brand a value as a row-major Mat3.
109
+ *
110
+ * Used at backend boundaries (node/wasm/fake) to avoid ad-hoc `as Mat3RowMajor`
111
+ * casts.
112
+ */
90
113
  export function brandMat3RowMajor(value, options) {
91
114
  const label = options?.label ?? "Mat3RowMajor";
92
115
  const freeze = options?.freeze ?? DEFAULT_FREEZE_MODE;
@@ -97,8 +120,8 @@ export function brandMat3RowMajor(value, options) {
97
120
  return maybeFreeze(arr, freeze);
98
121
  }
99
122
  /**
100
- * Validate + brand a value as a column-major Mat3.
101
- */
123
+ * Validate + brand a value as a column-major Mat3.
124
+ */
102
125
  export function brandMat3ColMajor(value, options) {
103
126
  const label = options?.label ?? "Mat3ColMajor";
104
127
  const freeze = options?.freeze ?? DEFAULT_FREEZE_MODE;
@@ -108,12 +131,18 @@ export function brandMat3ColMajor(value, options) {
108
131
  tryDefineBrand(arr, MAT3_COL_MAJOR_BRAND);
109
132
  return maybeFreeze(arr, freeze);
110
133
  }
111
- export function isMat3RowMajor(value) {
134
+ /**
135
+ * Brand-only check: verifies that a value was produced by `brandMat3RowMajor()`.
136
+ */
137
+ export function isBrandedMat3RowMajor(value) {
112
138
  if (!isLength9ArrayLike(value))
113
139
  return false;
114
140
  return Boolean(value[MAT3_ROW_MAJOR_BRAND]);
115
141
  }
116
- export function isMat3ColMajor(value) {
142
+ /**
143
+ * Brand-only check: verifies that a value was produced by `brandMat3ColMajor()`.
144
+ */
145
+ export function isBrandedMat3ColMajor(value) {
117
146
  if (!isLength9ArrayLike(value))
118
147
  return false;
119
148
  return Boolean(value[MAT3_COL_MAJOR_BRAND]);
@@ -0,0 +1,34 @@
1
+ import type { Mat6RowMajor } from "./types.js";
2
+ type FreezeMode = "never" | "dev" | "always";
3
+ export type BrandMat6Options = {
4
+ /**
5
+ * Used for error messages (e.g. `"sxform()"`).
6
+ *
7
+ * Defaults to `"Mat6RowMajor"`.
8
+ */
9
+ readonly label?: string;
10
+ /**
11
+ * If set, freeze branded matrices to prevent mutation at runtime.
12
+ *
13
+ * Defaults to `"dev"`.
14
+ */
15
+ readonly freeze?: FreezeMode;
16
+ };
17
+ /** Runtime validation that an input is a length-36 array-like of finite numbers. */
18
+ export declare function assertMat6ArrayLike36(value: unknown, options?: {
19
+ readonly label?: string;
20
+ }): asserts value is ArrayLike<number>;
21
+ /**
22
+ * Structural check: accepts number[] and numeric TypedArrays (excludes DataView).
23
+ *
24
+ * This does **not** assert/require that the value is branded as a row-major Mat6.
25
+ */
26
+ export declare function isMat6ArrayLike36(value: unknown): value is ArrayLike<number>;
27
+ /** Validate + brand a value as a row-major 6x6 matrix. */
28
+ export declare function brandMat6RowMajor(value: unknown, options?: BrandMat6Options): Mat6RowMajor;
29
+ /**
30
+ * Brand-only check: verifies that a value was produced by `brandMat6RowMajor()`.
31
+ */
32
+ export declare function isBrandedMat6RowMajor(value: unknown): value is Mat6RowMajor;
33
+ export {};
34
+ //# sourceMappingURL=mat6.d.ts.map
@@ -0,0 +1,116 @@
1
+ const DEFAULT_FREEZE_MODE = "dev";
2
+ // Runtime-only brand (module-private).
3
+ const MAT6_ROW_MAJOR_BRAND = Symbol("Mat6RowMajor");
4
+ function isDevEnv() {
5
+ // Safe in non-node runtimes.
6
+ return typeof process !== "undefined" && process?.env?.NODE_ENV !== "production";
7
+ }
8
+ function shouldFreeze(mode) {
9
+ switch (mode) {
10
+ case "never":
11
+ return false;
12
+ case "always":
13
+ return true;
14
+ case "dev":
15
+ return isDevEnv();
16
+ }
17
+ }
18
+ function isFiniteNumber(x) {
19
+ return typeof x === "number" && Number.isFinite(x);
20
+ }
21
+ function isTypedArrayView(x) {
22
+ // We intentionally only accept numeric TypedArrays (not BigInt views, not DataView).
23
+ return (x instanceof Int8Array ||
24
+ x instanceof Uint8Array ||
25
+ x instanceof Uint8ClampedArray ||
26
+ x instanceof Int16Array ||
27
+ x instanceof Uint16Array ||
28
+ x instanceof Int32Array ||
29
+ x instanceof Uint32Array ||
30
+ x instanceof Float32Array ||
31
+ x instanceof Float64Array);
32
+ }
33
+ function isLength36ArrayLike(x) {
34
+ return (x !== null &&
35
+ typeof x === "object" &&
36
+ (Array.isArray(x) || isTypedArrayView(x)) &&
37
+ typeof x.length === "number" &&
38
+ x.length === 36);
39
+ }
40
+ function formatMat6Error(label, detail) {
41
+ return `${label}: expected a length-36 array of finite numbers (${detail})`;
42
+ }
43
+ /** Runtime validation that an input is a length-36 array-like of finite numbers. */
44
+ export function assertMat6ArrayLike36(value, options) {
45
+ const label = options?.label ?? "Mat6";
46
+ if (value instanceof DataView) {
47
+ throw new Error(`${label}: DataView is not a supported Mat6 input (use a TypedArray or number[]).`);
48
+ }
49
+ if (!isLength36ArrayLike(value)) {
50
+ throw new Error(formatMat6Error(label, "wrong shape"));
51
+ }
52
+ for (let i = 0; i < 36; i++) {
53
+ const v = value[i];
54
+ if (!isFiniteNumber(v)) {
55
+ throw new Error(formatMat6Error(label, `index ${i} was ${String(v)}`));
56
+ }
57
+ }
58
+ }
59
+ /**
60
+ * Structural check: accepts number[] and numeric TypedArrays (excludes DataView).
61
+ *
62
+ * This does **not** assert/require that the value is branded as a row-major Mat6.
63
+ */
64
+ export function isMat6ArrayLike36(value) {
65
+ if (value instanceof DataView)
66
+ return false;
67
+ if (!isLength36ArrayLike(value))
68
+ return false;
69
+ for (let i = 0; i < 36; i++) {
70
+ if (!isFiniteNumber(value[i]))
71
+ return false;
72
+ }
73
+ return true;
74
+ }
75
+ function tryDefineBrand(target, brand) {
76
+ try {
77
+ // Non-enumerable to avoid surprising JSON/stringification behavior.
78
+ Object.defineProperty(target, brand, {
79
+ value: true,
80
+ enumerable: false,
81
+ configurable: false,
82
+ writable: false,
83
+ });
84
+ }
85
+ catch {
86
+ // Best-effort.
87
+ }
88
+ }
89
+ function maybeFreeze(value, mode) {
90
+ if (!shouldFreeze(mode))
91
+ return value;
92
+ try {
93
+ return Object.freeze(value);
94
+ }
95
+ catch {
96
+ return value;
97
+ }
98
+ }
99
+ /** Validate + brand a value as a row-major 6x6 matrix. */
100
+ export function brandMat6RowMajor(value, options) {
101
+ const label = options?.label ?? "Mat6RowMajor";
102
+ const freeze = options?.freeze ?? DEFAULT_FREEZE_MODE;
103
+ assertMat6ArrayLike36(value, { label });
104
+ const arr = Array.from(value);
105
+ tryDefineBrand(arr, MAT6_ROW_MAJOR_BRAND);
106
+ return maybeFreeze(arr, freeze);
107
+ }
108
+ /**
109
+ * Brand-only check: verifies that a value was produced by `brandMat6RowMajor()`.
110
+ */
111
+ export function isBrandedMat6RowMajor(value) {
112
+ if (!isLength36ArrayLike(value))
113
+ return false;
114
+ return Boolean(value[MAT6_ROW_MAJOR_BRAND]);
115
+ }
116
+ //# sourceMappingURL=mat6.js.map
@@ -0,0 +1,20 @@
1
+ import type { SpiceHandle } from "./types.js";
2
+ export type SpiceHandleKind = "DAF" | "DAS" | "DLA" | "SPK" | "EK";
3
+ export type SpiceHandleEntry = {
4
+ kind: SpiceHandleKind;
5
+ nativeHandle: number;
6
+ };
7
+ export type SpiceHandleRegistry = {
8
+ register: (kind: SpiceHandleKind, nativeHandle: number) => SpiceHandle;
9
+ lookup: (handle: SpiceHandle, expected: readonly SpiceHandleKind[], context: string) => SpiceHandleEntry;
10
+ close: (handle: SpiceHandle, expected: readonly SpiceHandleKind[], closeNative: (entry: SpiceHandleEntry) => void, context: string) => void;
11
+ size: () => number;
12
+ __entries?: () => ReadonlyArray<readonly [SpiceHandle, SpiceHandleEntry]>;
13
+ };
14
+ /**
15
+ * Create an in-memory registry for opaque {@link SpiceHandle} values.
16
+ *
17
+ * Used by backends to map stable JS handles to backend-native integer handles.
18
+ */
19
+ export declare function createSpiceHandleRegistry(): SpiceHandleRegistry;
20
+ //# sourceMappingURL=spice-handles.d.ts.map
@@ -0,0 +1,82 @@
1
+ import { SPICE_INT32_MAX, SPICE_INT32_MIN } from "./spice-int.js";
2
+ import { SpiceBackendContractError } from "./errors.js";
3
+ function asHandleId(handle, context) {
4
+ const id = handle;
5
+ if (typeof id !== "number" || !Number.isFinite(id) || !Number.isInteger(id)) {
6
+ throw new TypeError(`${context}: expected a SpiceHandle to be an integer number`);
7
+ }
8
+ if (id <= 0) {
9
+ throw new RangeError(`${context}: expected a SpiceHandle to be > 0 (got ${id})`);
10
+ }
11
+ if (!Number.isSafeInteger(id)) {
12
+ throw new RangeError(`${context}: expected a SpiceHandle to be a safe integer (got ${id})`);
13
+ }
14
+ return id;
15
+ }
16
+ function asSpiceHandle(handleId) {
17
+ return handleId;
18
+ }
19
+ /**
20
+ * Create an in-memory registry for opaque {@link SpiceHandle} values.
21
+ *
22
+ * Used by backends to map stable JS handles to backend-native integer handles.
23
+ */
24
+ export function createSpiceHandleRegistry() {
25
+ let nextHandleId = 1;
26
+ const handles = new Map();
27
+ function register(kind, nativeHandle) {
28
+ if (typeof nativeHandle !== "number" ||
29
+ !Number.isInteger(nativeHandle) ||
30
+ nativeHandle < SPICE_INT32_MIN ||
31
+ nativeHandle > SPICE_INT32_MAX) {
32
+ throw new SpiceBackendContractError(`backend contract violation: expected backend to return a 32-bit signed integer handle for ${kind} (got ${nativeHandle})`);
33
+ }
34
+ if (nextHandleId >= Number.MAX_SAFE_INTEGER) {
35
+ throw new SpiceBackendContractError(`backend contract violation: SpiceHandle ID overflow (nextHandleId=${nextHandleId})`);
36
+ }
37
+ // Defensive: never reuse/collide IDs even if `nextHandleId` gets out of sync.
38
+ while (handles.has(nextHandleId)) {
39
+ nextHandleId++;
40
+ if (nextHandleId >= Number.MAX_SAFE_INTEGER) {
41
+ throw new SpiceBackendContractError(`backend contract violation: SpiceHandle ID overflow (nextHandleId=${nextHandleId})`);
42
+ }
43
+ }
44
+ const handleId = nextHandleId++;
45
+ handles.set(handleId, { kind, nativeHandle });
46
+ return asSpiceHandle(handleId);
47
+ }
48
+ function lookup(handle, expected, context) {
49
+ const handleId = asHandleId(handle, `${context}: lookup(handle)`);
50
+ const entry = handles.get(handleId);
51
+ if (!entry) {
52
+ throw new RangeError(`${context}: invalid or closed SpiceHandle ${handleId}`);
53
+ }
54
+ if (!expected.includes(entry.kind)) {
55
+ throw new TypeError(`${context}: SpiceHandle ${handleId} has kind ${entry.kind}, expected ${expected.join(" or ")}`);
56
+ }
57
+ return entry;
58
+ }
59
+ function close(handle, expected, closeNative, context) {
60
+ const handleId = asHandleId(handle, `${context}: close(handle)`);
61
+ const entry = handles.get(handleId);
62
+ if (!entry) {
63
+ throw new RangeError(`${context}: invalid or closed SpiceHandle ${handleId}`);
64
+ }
65
+ if (!expected.includes(entry.kind)) {
66
+ throw new TypeError(`${context}: SpiceHandle ${handleId} has kind ${entry.kind}, expected ${expected.join(" or ")}`);
67
+ }
68
+ // Close-once semantics: only forget the handle after the native close succeeds.
69
+ closeNative(entry);
70
+ handles.delete(handleId);
71
+ }
72
+ return {
73
+ register,
74
+ lookup,
75
+ close,
76
+ size: () => handles.size,
77
+ // Internal hook used by the Node backend to best-effort dispose all open handles.
78
+ // Not part of the public backend contract.
79
+ __entries: () => Array.from(handles.entries()).map(([handleId, entry]) => [asSpiceHandle(handleId), entry]),
80
+ };
81
+ }
82
+ //# sourceMappingURL=spice-handles.js.map
@@ -0,0 +1,32 @@
1
+ export declare const SPICE_INT32_MIN = -2147483648;
2
+ export declare const SPICE_INT32_MAX = 2147483647;
3
+ export type AssertSpiceInt32Options = {
4
+ /** If provided, enforce `value >= min`. */
5
+ min?: number;
6
+ /** If provided, enforce `value <= max`. */
7
+ max?: number;
8
+ };
9
+ /**
10
+ * Runtime validation for values that will cross the JS → native boundary as a
11
+ * CSPICE `SpiceInt`.
12
+ *
13
+ * What this checks:
14
+ * - `value` is a **safe integer** (no fractional values, no `NaN`, no `Infinity`).
15
+ * - `value` is within the **signed 32-bit** range.
16
+ * - Optional extra bounds (`opts.min` / `opts.max`).
17
+ *
18
+ * What this does *not* check:
19
+ * - That the value is valid for a specific CSPICE call (e.g. an index being in
20
+ * range for a particular cell/window).
21
+ * - That the host platform's `SpiceInt` is 32-bit. (Many CSPICE builds use a
22
+ * wider integer type.) We intentionally validate to 32-bit because:
23
+ * - the Node addon reads numbers via `Int32Value()`, and
24
+ * - the WASM backend consumes values as `i32`.
25
+ *
26
+ * If callers pass values outside the 32-bit range, JS → native conversion would
27
+ * otherwise wrap/truncate.
28
+ */
29
+ export declare function assertSpiceInt32(value: number, label: string, opts?: AssertSpiceInt32Options): asserts value is number;
30
+ /** Assert that a value is a non-negative signed 32-bit integer. */
31
+ export declare function assertSpiceInt32NonNegative(value: number, label: string): asserts value is number;
32
+ //# sourceMappingURL=spice-int.d.ts.map
@@ -0,0 +1,41 @@
1
+ export const SPICE_INT32_MIN = -0x80000000; // -2147483648
2
+ export const SPICE_INT32_MAX = 0x7fffffff; // 2147483647
3
+ /**
4
+ * Runtime validation for values that will cross the JS → native boundary as a
5
+ * CSPICE `SpiceInt`.
6
+ *
7
+ * What this checks:
8
+ * - `value` is a **safe integer** (no fractional values, no `NaN`, no `Infinity`).
9
+ * - `value` is within the **signed 32-bit** range.
10
+ * - Optional extra bounds (`opts.min` / `opts.max`).
11
+ *
12
+ * What this does *not* check:
13
+ * - That the value is valid for a specific CSPICE call (e.g. an index being in
14
+ * range for a particular cell/window).
15
+ * - That the host platform's `SpiceInt` is 32-bit. (Many CSPICE builds use a
16
+ * wider integer type.) We intentionally validate to 32-bit because:
17
+ * - the Node addon reads numbers via `Int32Value()`, and
18
+ * - the WASM backend consumes values as `i32`.
19
+ *
20
+ * If callers pass values outside the 32-bit range, JS → native conversion would
21
+ * otherwise wrap/truncate.
22
+ */
23
+ export function assertSpiceInt32(value, label, opts = {}) {
24
+ if (!Number.isSafeInteger(value)) {
25
+ throw new TypeError(`${label} must be a safe integer`);
26
+ }
27
+ if (value < SPICE_INT32_MIN || value > SPICE_INT32_MAX) {
28
+ throw new RangeError(`${label} must be a 32-bit signed integer`);
29
+ }
30
+ if (opts.min !== undefined && value < opts.min) {
31
+ throw new RangeError(`${label} must be >= ${opts.min}`);
32
+ }
33
+ if (opts.max !== undefined && value > opts.max) {
34
+ throw new RangeError(`${label} must be <= ${opts.max}`);
35
+ }
36
+ }
37
+ /** Assert that a value is a non-negative signed 32-bit integer. */
38
+ export function assertSpiceInt32NonNegative(value, label) {
39
+ assertSpiceInt32(value, label, { min: 0 });
40
+ }
41
+ //# sourceMappingURL=spice-int.js.map
@@ -2,22 +2,104 @@ export type KernelSource = string | {
2
2
  path: string;
3
3
  bytes: Uint8Array;
4
4
  };
5
+ /**
6
+ * Virtual output reference used by writer APIs.
7
+ *
8
+ * Lifecycle:
9
+ * - A `VirtualOutput` is only guaranteed to be readable via `readVirtualOutput()`
10
+ * **after** the writer handle has been closed (e.g. `spkcls(handle)` for SPKs).
11
+ * - Backends may reject reads for outputs they did not create via a writer API.
12
+ * `readVirtualOutput()` is not intended to be a generic filesystem read.
13
+ *
14
+ * Backend notes:
15
+ * - WASM: `path` is treated as a *virtual* identifier under the backend's
16
+ * virtual filesystem (currently rooted at `/kernels`).
17
+ * - Node: implementations may stage virtual outputs to a temp file and allow
18
+ * reading bytes back via `readVirtualOutput()`.
19
+ */
20
+ export type VirtualOutput = {
21
+ kind: "virtual-output";
22
+ path: string;
23
+ };
5
24
  /** Kernel types used by summary/introspection APIs. */
6
- export type KernelKind = "ALL" | "SPK" | "CK" | "PCK" | "LSK" | "FK" | "IK" | "SCLK" | "EK" | "META";
25
+ export type KernelKind = "ALL" | "SPK" | "CK" | "PCK" | "DSK" | "TEXT" | "LSK" | "FK" | "IK" | "SCLK" | "EK" | "META";
26
+ /**
27
+ * Optional-return convention for lookups where "not found" is a normal outcome.
28
+ *
29
+ * Conventions:
30
+ * - Return `{ found: false }` when the underlying value simply doesn't exist
31
+ * (e.g. name-to-code lookups for names that aren't present in loaded kernels).
32
+ * - Throw for invalid arguments, SPICE errors, and other exceptional failures.
33
+ * - When `found: true`, extra fields are present on the returned object.
34
+ */
7
35
  export type Found<T> = {
8
36
  found: false;
9
37
  } | ({
10
38
  found: true;
11
39
  } & T);
40
+ /** Convenience alias for the most common Found payload shape. */
41
+ export type FoundValue<T> = Found<{
42
+ value: T;
43
+ }>;
44
+ export type FoundString = FoundValue<string>;
45
+ export type FoundInt = FoundValue<number>;
46
+ export type FoundDouble = FoundValue<number>;
47
+ /** Extract the payload type of a `Found<...>` result. */
48
+ export type FoundPayload<T> = T extends Found<infer P> ? P : never;
12
49
  export type KernelData = {
13
50
  file: string;
14
51
  filtyp: string;
15
52
  source: string;
16
53
  handle: number;
17
54
  };
55
+ /** Result payload for `kinfo()`. */
56
+ export type KernelInfo = {
57
+ filtyp: string;
58
+ source: string;
59
+ handle: number;
60
+ };
18
61
  /** SPICE aberration correction string accepted by `spkezr`/`spkpos`. */
19
62
  export type AbCorr = "NONE" | "LT" | "LT+S" | "CN" | "CN+S" | "XLT" | "XLT+S" | "XCN" | "XCN+S";
20
63
  export type SpiceVector3 = [number, number, number];
64
+ /**
65
+ * A plane encoded as `[normalX, normalY, normalZ, constant]`.
66
+ *
67
+ * This matches CSPICE's `SpicePlane` ABI layout (`normal[3]` + `constant`).
68
+ */
69
+ export type SpicePlane = [number, number, number, number];
70
+ declare const __spiceHandleBrand: unique symbol;
71
+ /** Opaque numeric handle returned by low-level SPICE file APIs (DAF/DAS/DLA). */
72
+ export type SpiceHandle = number & {
73
+ readonly [__spiceHandleBrand]: true;
74
+ };
75
+ declare const __vec3Brand: unique symbol;
76
+ export type Vec3 = readonly [number, number, number] & {
77
+ readonly [__vec3Brand]: true;
78
+ };
79
+ declare const __vec6Brand: unique symbol;
80
+ export type Vec6 = readonly [number, number, number, number, number, number] & {
81
+ readonly [__vec6Brand]: true;
82
+ };
83
+ /**
84
+ * A string returned from (or destined for) a fixed-width output buffer of length `Max`.
85
+ *
86
+ * This is a **type-only** brand used for clarity/documentation. It does not perform any
87
+ * runtime validation, and it does not guarantee the string length.
88
+ */
89
+ declare const __fixedStringMaxBrand: unique symbol;
90
+ export type FixedString<Max extends number> = string & {
91
+ readonly [__fixedStringMaxBrand]: Max;
92
+ };
93
+ /**
94
+ * Result wrapper for APIs that return an array of strings.
95
+ *
96
+ * `truncated` is backend-dependent and should only be set to `true` when the backend can
97
+ * *detect* truncation (for example: when reading fixed-width output buffers).
98
+ */
99
+ export interface StringArrayResult {
100
+ values: string[];
101
+ truncated: boolean;
102
+ }
21
103
  /**
22
104
  * 3x3 matrix encoded as a length-9 array in **row-major** order.
23
105
  *
@@ -94,6 +176,15 @@ export type SpiceMatrix6x6 = [
94
176
  number,
95
177
  number
96
178
  ];
179
+ /**
180
+ * 6x6 matrix encoded as a length-36 array in **row-major** order.
181
+ *
182
+ * Row-major layout: `[m00,m01,...,m05, m10,m11,...,m15, ..., m50,...,m55]`.
183
+ */
184
+ declare const __mat6RowMajorBrand: unique symbol;
185
+ export type Mat6RowMajor = Readonly<SpiceMatrix6x6> & {
186
+ readonly [__mat6RowMajorBrand]: true;
187
+ };
97
188
  export type SpiceStateVector = [
98
189
  number,
99
190
  number,
@@ -130,5 +221,19 @@ export type IluminResult = {
130
221
  /** Emission angle at `spoint`, radians. */
131
222
  emissn: number;
132
223
  };
224
+ /** Result payload for `illumg()`. */
225
+ export type IllumgResult = IluminResult;
226
+ /** Result payload for `illumf()`. */
227
+ export type IllumfResult = IluminResult & {
228
+ /** True if `spoint` is visible to `obsrvr`. */
229
+ visibl: boolean;
230
+ /** True if `spoint` is lit by `ilusrc`. */
231
+ lit: boolean;
232
+ };
233
+ /** Result payload for `pl2nvc()`. */
234
+ export type Pl2nvcResult = {
235
+ normal: SpiceVector3;
236
+ konst: number;
237
+ };
133
238
  export {};
134
239
  //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,54 @@
1
+ import type { Vec3, Vec6 } from "./types.js";
2
+ type FreezeMode = "never" | "dev" | "always";
3
+ export type BrandVecOptions = {
4
+ /**
5
+ * Used for error messages (e.g. `"spkezr()"`).
6
+ *
7
+ * Defaults to `"Vec"`.
8
+ */
9
+ readonly label?: string;
10
+ /**
11
+ * If set, freeze branded values to prevent mutation at runtime.
12
+ *
13
+ * Defaults to `"dev"`.
14
+ */
15
+ readonly freeze?: FreezeMode;
16
+ };
17
+ /** Assert that a value is an array-like Vec3 (length 3) of finite numbers. */
18
+ export declare function assertVec3ArrayLike3(value: unknown, options?: {
19
+ readonly label?: string;
20
+ }): asserts value is ArrayLike<number>;
21
+ /** Assert that a value is an array-like Vec6 (length 6) of finite numbers. */
22
+ export declare function assertVec6ArrayLike6(value: unknown, options?: {
23
+ readonly label?: string;
24
+ }): asserts value is ArrayLike<number>;
25
+ /** Validate and brand a value as a {@link Vec3}. */
26
+ export declare function brandVec3(value: unknown, options?: BrandVecOptions): Vec3;
27
+ /** Validate and brand a value as a {@link Vec6}. */
28
+ export declare function brandVec6(value: unknown, options?: BrandVecOptions): Vec6;
29
+ /**
30
+ * Structural check: accepts number[] and numeric TypedArrays (excludes DataView).
31
+ *
32
+ * This does **not** assert/require that the value is branded as a `Vec3`.
33
+ */
34
+ export declare function isVec3ArrayLike3(value: unknown): value is ArrayLike<number>;
35
+ /**
36
+ * Structural check: accepts number[] and numeric TypedArrays (excludes DataView).
37
+ *
38
+ * This does **not** assert/require that the value is branded as a `Vec6`.
39
+ */
40
+ export declare function isVec6ArrayLike6(value: unknown): value is ArrayLike<number>;
41
+ /**
42
+ * Brand-only check: verifies that a value was produced by `brandVec3()`.
43
+ *
44
+ * Note: this intentionally rejects structurally-valid TypedArrays.
45
+ */
46
+ export declare function isBrandedVec3(value: unknown): value is Vec3;
47
+ /**
48
+ * Brand-only check: verifies that a value was produced by `brandVec6()`.
49
+ *
50
+ * Note: this intentionally rejects structurally-valid TypedArrays.
51
+ */
52
+ export declare function isBrandedVec6(value: unknown): value is Vec6;
53
+ export {};
54
+ //# sourceMappingURL=vec.d.ts.map