castrum 0.7.0 → 0.9.1

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 (207) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +154 -368
  3. package/castrum.linux-x64-gnu.node +0 -0
  4. package/dist/index.d.ts +2763 -0
  5. package/dist/index.js +8707 -0
  6. package/docs/API.md +337 -0
  7. package/docs/ARCHITECTURE.md +507 -0
  8. package/docs/BENCHMARKS.md +343 -0
  9. package/docs/CASE_STUDY.md +240 -0
  10. package/docs/ENVIRONMENT.md +81 -0
  11. package/docs/FFI_BUN_GUIDE.md +327 -0
  12. package/docs/GETTING_STARTED.md +192 -0
  13. package/docs/INGRESS-ROUTER.md +81 -0
  14. package/docs/INGRESS.md +746 -0
  15. package/docs/NATIVE-ROUTE.md +53 -0
  16. package/docs/REPO_MAP.md +279 -0
  17. package/docs/adr/0001-two-wire-formats.md +39 -0
  18. package/docs/adr/0002-zero-dom-fast-schema.md +38 -0
  19. package/docs/adr/0003-bun-builtins-delegation.md +43 -0
  20. package/docs/bun-builtins-decision-matrix.md +115 -0
  21. package/index.ts +44 -8
  22. package/package.json +98 -33
  23. package/src/ingress/body.ts +289 -0
  24. package/src/ingress/constants.ts +220 -48
  25. package/src/ingress/context.ts +136 -0
  26. package/src/ingress/decode/baked-result.ts +121 -0
  27. package/src/ingress/decode/fast-result.ts +160 -0
  28. package/src/ingress/decode/packed-sections.ts +56 -0
  29. package/src/ingress/decode/result-base.ts +172 -0
  30. package/src/ingress/errors.ts +72 -0
  31. package/src/ingress/fast.ts +152 -1021
  32. package/src/ingress/handlers.ts +639 -1001
  33. package/src/ingress/headers/baked-templates.ts +102 -0
  34. package/src/ingress/headers/cors.ts +44 -0
  35. package/src/ingress/headers/fast-templates.ts +238 -0
  36. package/src/ingress/headers/hsts.ts +83 -0
  37. package/src/ingress/health.ts +68 -0
  38. package/src/ingress/index.ts +142 -405
  39. package/src/ingress/metrics.ts +132 -0
  40. package/src/ingress/options.ts +197 -0
  41. package/src/ingress/packing/gather-raw-headers.ts +139 -0
  42. package/src/ingress/packing/header-packing.ts +75 -0
  43. package/src/ingress/packing/input-packer.ts +164 -0
  44. package/src/ingress/packing/scratch.ts +50 -0
  45. package/src/ingress/packing/select-headers.ts +102 -0
  46. package/src/ingress/response/error-bodies.ts +75 -0
  47. package/src/ingress/response/terminal.ts +59 -0
  48. package/src/ingress/router.ts +237 -0
  49. package/src/ingress/routes/common.ts +79 -0
  50. package/src/ingress/routes/delete.ts +14 -0
  51. package/src/ingress/routes/echo.ts +107 -0
  52. package/src/ingress/routes/fallback.ts +23 -0
  53. package/src/ingress/routes/head.ts +27 -0
  54. package/src/ingress/routes/index.ts +11 -0
  55. package/src/ingress/routes/json-write.ts +129 -0
  56. package/src/ingress/routes/options.ts +26 -0
  57. package/src/ingress/routes/read.ts +35 -0
  58. package/src/ingress/routes/responder.ts +159 -0
  59. package/src/ingress/server-node.ts +376 -0
  60. package/src/ingress/server.ts +475 -0
  61. package/src/ingress/shared.ts +132 -0
  62. package/src/ingress/status.ts +97 -0
  63. package/src/ingress/types.ts +191 -0
  64. package/src/integration/batch.ts +58 -0
  65. package/src/integration/index.ts +29 -0
  66. package/src/integration/pipeline.ts +220 -0
  67. package/src/integration/streaming.ts +78 -0
  68. package/src/integration/websocket.ts +93 -0
  69. package/src/loader/batch.ts +137 -0
  70. package/src/loader/cost.ts +105 -0
  71. package/src/loader/index.ts +745 -0
  72. package/src/loader/ops.ts +657 -0
  73. package/src/loader/state.ts +84 -0
  74. package/src/loader/types.ts +145 -0
  75. package/src/native/ffi/constants.ts +58 -0
  76. package/src/native/ffi/selftest.ts +729 -0
  77. package/src/native/ffi/types.ts +474 -0
  78. package/src/native/ffi.ts +1775 -0
  79. package/src/native/index.ts +8 -207
  80. package/src/native/loader.ts +240 -0
  81. package/src/native/types/instances.ts +274 -0
  82. package/src/native/types.ts +401 -0
  83. package/src/runtime/builtins.ts +131 -0
  84. package/src/runtime/codec.ts +147 -0
  85. package/src/runtime/detect.ts +36 -0
  86. package/src/runtime/index.ts +28 -0
  87. package/src/runtime/native.ts +35 -0
  88. package/src/runtime/server.ts +31 -0
  89. package/src/runtime/transport.ts +64 -0
  90. package/src/runtime/types.ts +173 -0
  91. package/src/runtime/uuid.ts +45 -0
  92. package/src/runtime/websocket.ts +30 -0
  93. package/src/rust-ffi/addon.ts +10 -0
  94. package/src/rust-ffi/batch/build.ts +155 -0
  95. package/src/rust-ffi/batch/index.ts +8 -0
  96. package/src/rust-ffi/batch/types.ts +92 -0
  97. package/src/rust-ffi/client.ts +87 -0
  98. package/src/rust-ffi/context.ts +193 -0
  99. package/src/rust-ffi/index.ts +51 -541
  100. package/src/rust-ffi/into.ts +21 -0
  101. package/src/rust-ffi/options.ts +113 -0
  102. package/src/rust-ffi/packed.ts +253 -0
  103. package/src/rust-ffi/proven.ts +28 -0
  104. package/src/rust-ffi/scalar/crypto.ts +346 -0
  105. package/src/rust-ffi/scalar/factories.ts +459 -0
  106. package/src/rust-ffi/scalar/hashing.ts +74 -0
  107. package/src/rust-ffi/scalar/http.ts +337 -0
  108. package/src/rust-ffi/scalar/index.ts +31 -0
  109. package/src/rust-ffi/scalar/interface.ts +325 -0
  110. package/src/rust-ffi/scalar/json-packed.ts +175 -0
  111. package/src/rust-ffi/scalar/json.ts +61 -0
  112. package/src/rust-ffi/scalar/payload.ts +241 -0
  113. package/src/rust-ffi/text.ts +121 -0
  114. package/src/selection.json +194 -0
  115. package/src/selection.ts +73 -0
  116. package/src/shared/adaptive.ts +67 -0
  117. package/src/shared/buffer-pool.ts +264 -0
  118. package/src/shared/bytes.ts +108 -9
  119. package/src/shared/codec.ts +78 -0
  120. package/src/shared/env.ts +20 -0
  121. package/src/shared/log.ts +75 -0
  122. package/src/shared/metrics.ts +247 -0
  123. package/src/shared/packed/index.ts +10 -0
  124. package/src/shared/packed/parsers.ts +31 -0
  125. package/src/shared/packed/schema.ts +23 -0
  126. package/src/shared/packed/wire.ts +504 -0
  127. package/src/shared/proven.ts +289 -0
  128. package/src/shared/request-id.ts +67 -0
  129. package/src/shared/response.ts +104 -0
  130. package/src/shared/runtime.ts +29 -0
  131. package/src/shared/trace.ts +81 -0
  132. package/src/shared/uuid.ts +15 -0
  133. package/Cargo.toml +0 -73
  134. package/bench.ts +0 -3
  135. package/rust/batch.rs +0 -195
  136. package/rust/cookie_parser.rs +0 -70
  137. package/rust/cors.rs +0 -263
  138. package/rust/hashing.rs +0 -164
  139. package/rust/headers.rs +0 -234
  140. package/rust/hmac_sha256.rs +0 -113
  141. package/rust/http_parser.rs +0 -132
  142. package/rust/ingress.rs +0 -616
  143. package/rust/ingress_constants.rs +0 -89
  144. package/rust/ip_trust.rs +0 -185
  145. package/rust/json_ops.rs +0 -66
  146. package/rust/json_patch_ops.rs +0 -25
  147. package/rust/json_schema.rs +0 -151
  148. package/rust/json_ser.rs +0 -429
  149. package/rust/lib.rs +0 -48
  150. package/rust/method.rs +0 -141
  151. package/rust/mime_lookup.rs +0 -76
  152. package/rust/output.rs +0 -238
  153. package/rust/proxy.rs +0 -90
  154. package/rust/query_parser.rs +0 -141
  155. package/rust/random_token.rs +0 -52
  156. package/rust/rate_limit.rs +0 -203
  157. package/rust/terminal.rs +0 -95
  158. package/rust/unit_tests.rs +0 -843
  159. package/rust/url_codec.rs +0 -133
  160. package/rust/util.rs +0 -537
  161. package/rust/validation.rs +0 -107
  162. package/rust/websocket.rs +0 -23
  163. package/src/baseline/index.ts +0 -12
  164. package/src/baseline/tasks/cookie.ts +0 -22
  165. package/src/baseline/tasks/hashing.ts +0 -18
  166. package/src/baseline/tasks/hmac.ts +0 -38
  167. package/src/baseline/tasks/http.ts +0 -62
  168. package/src/baseline/tasks/json-patch.ts +0 -12
  169. package/src/baseline/tasks/json.ts +0 -50
  170. package/src/baseline/tasks/mime.ts +0 -5
  171. package/src/baseline/tasks/query.ts +0 -14
  172. package/src/baseline/tasks/token.ts +0 -15
  173. package/src/baseline/tasks/url.ts +0 -11
  174. package/src/baseline/tasks/validation.ts +0 -19
  175. package/src/baseline/tasks/websocket.ts +0 -14
  176. package/src/bench/assert.ts +0 -70
  177. package/src/bench/checks.ts +0 -227
  178. package/src/bench/checksum.ts +0 -27
  179. package/src/bench/comparisons.ts +0 -70
  180. package/src/bench/concurrent-worker.ts +0 -135
  181. package/src/bench/fixtures.ts +0 -233
  182. package/src/bench/index.ts +0 -2
  183. package/src/bench/measure.ts +0 -177
  184. package/src/bench/now.ts +0 -3
  185. package/src/bench/report.ts +0 -79
  186. package/src/bench/run.ts +0 -57
  187. package/src/bench/tasks/complex.ts +0 -232
  188. package/src/bench/tasks/concurrent.ts +0 -213
  189. package/src/bench/tasks/cookie.ts +0 -44
  190. package/src/bench/tasks/hashing.ts +0 -33
  191. package/src/bench/tasks/hmac.ts +0 -36
  192. package/src/bench/tasks/http.ts +0 -50
  193. package/src/bench/tasks/index.ts +0 -52
  194. package/src/bench/tasks/json-patch.ts +0 -21
  195. package/src/bench/tasks/json.ts +0 -33
  196. package/src/bench/tasks/mime.ts +0 -21
  197. package/src/bench/tasks/query.ts +0 -44
  198. package/src/bench/tasks/stress.ts +0 -142
  199. package/src/bench/tasks/token.ts +0 -20
  200. package/src/bench/tasks/url.ts +0 -34
  201. package/src/bench/tasks/validation.ts +0 -57
  202. package/src/bench/tasks/websocket.ts +0 -21
  203. package/src/bench/types.ts +0 -60
  204. package/src/data/json-rows.ts +0 -33
  205. package/src/ingress/packed-input.ts +0 -59
  206. package/src/shared/json.ts +0 -18
  207. package/src/shared/packed.ts +0 -316
@@ -0,0 +1,84 @@
1
+ // src/loader/state.ts — internal loader dispatch state (pure types).
2
+ //
3
+ // The per-op dispatch context, memoized op-fn entry, and the aggregate
4
+ // `LoaderState` shared by the dispatch core (index.ts). `KEY_SEP` is the
5
+ // cache-key separator for `op + '\0' + key`.
6
+
7
+ import type { LoaderCache, TickCoalescer } from './batch'
8
+ import type { LoaderCostModel } from './cost'
9
+ import type { LoaderOpName } from './ops'
10
+ import type { LoaderOpFn, LoaderOptions } from './types'
11
+
12
+ // ── Internal state ──────────────────────────────────────────────────────────
13
+
14
+ /** Per-op dispatch counters: scalar calls, batch calls, items dispatched, and
15
+ * cache hits. Advanced on every dispatch and exposed via `loader.stats()`. */
16
+ export interface OpCounters {
17
+ scalarCalls: number
18
+ batchCalls: number
19
+ itemsDispatched: number
20
+ cachedHits: number
21
+ }
22
+
23
+ /**
24
+ * Pre-bound per-op dispatch context — avoids Map lookups on the hot path.
25
+ * Holds the load-aware `load()` strategy plus its cheap integer signals so
26
+ * the single-vs-coalesce decision costs no Map lookup or allocation.
27
+ */
28
+ export interface OpDispatchCtx {
29
+ cost: LoaderCostModel
30
+ counters: OpCounters
31
+ sampleEvery: number
32
+ /** Per-op sample tick counter (advances on every dispatch). */
33
+ counter: number
34
+ /** Current `load()` strategy for this op. */
35
+ mode: 'single' | 'coalesce'
36
+ /** Consecutive single-load flushes observed (coalesce mode only). */
37
+ singleStreak: number
38
+ /** A single-mode load is waiting on its microtask to dispatch. */
39
+ pendingSingle: boolean
40
+ pendingInput: Uint8Array | null
41
+ pendingResolve: ((value: unknown) => void) | null
42
+ pendingReject: ((error: unknown) => void) | null
43
+ pendingKey: string | undefined
44
+ /** Default-key attempts (adaptive key computation). */
45
+ keyAttempts: number
46
+ /** Default-key cache hits observed. */
47
+ keyHits: number
48
+ /** Periodic re-probe counter for skipped default keys. */
49
+ keyProbeCounter: number
50
+ }
51
+
52
+ /** A memoized op fn plus a hook to rebind its dispatch context on configure. */
53
+ export interface OpFnEntry {
54
+ op: LoaderOpName
55
+ fn: LoaderOpFn<LoaderOpName>
56
+ /** Rebind to a fresh context after `configure()` so dispatch + stats stay current. */
57
+ rebind(ctx: OpDispatchCtx): void
58
+ }
59
+
60
+ /** Aggregate loader state shared by the dispatch core (index.ts): the resolved
61
+ * options, per-op dispatch contexts, the LRU cache + tick coalescer, memoized
62
+ * op fns, and the reusable zero-alloc pack/out/key scratch buffers. */
63
+ export interface LoaderState {
64
+ options: Required<
65
+ Pick<
66
+ LoaderOptions,
67
+ 'adaptive' | 'batchMin' | 'maxCacheKeys' | 'caching' | 'sampleEvery' | 'loadStrategy'
68
+ >
69
+ >
70
+ ctxs: Map<LoaderOpName, OpDispatchCtx>
71
+ cache: LoaderCache
72
+ coalescer: TickCoalescer
73
+ opFns: Map<LoaderOpName, OpFnEntry>
74
+ flushes: number
75
+ /** Reusable packed-input scratch for the zero-alloc fast flush (grows). */
76
+ packScratch: Uint8Array
77
+ /** Reusable packed-output buffer for the zero-alloc fast flush (grows). */
78
+ outScratch: Uint8Array
79
+ /** Reusable packed-key output buffer for the batched default-key flush. */
80
+ keyScratch: Uint8Array
81
+ }
82
+
83
+ /** NUL separator used to join composite cache keys (never appears in keys). */
84
+ export const KEY_SEP = '\u0000'
@@ -0,0 +1,145 @@
1
+ // src/loader/types.ts — public loader type surface (pure types).
2
+ //
3
+ // The callable loader contract (`Loader`), its option/stats shapes, the
4
+ // specialized op-function type (`LoaderOpFn`), and the `load()` helpers.
5
+ // No runtime code — erased at compile time.
6
+
7
+ import type { SchemaValidator } from '../shared/packed'
8
+ import type { LoaderBulk, LoaderBulkArgs, LoaderOpArgs, LoaderOpName, LoaderScalar } from './ops'
9
+
10
+ // ── Public types ────────────────────────────────────────────────────────────
11
+
12
+ /** Options for `createLoader()` / `loader.configure()`. */
13
+ export interface LoaderOptions {
14
+ /** Let each op adapt `batchMin` from measured dispatch cost. Default true. */
15
+ adaptive?: boolean
16
+ /** Initial batch threshold in [2, 8]. Default 2 (batch wins for n >= 2). */
17
+ batchMin?: number
18
+ /** Max cached keys (bounded LRU). 0 disables caching. Default 256. */
19
+ maxCacheKeys?: number
20
+ /** Default `cache` behavior for `load()`. Default true. */
21
+ caching?: boolean
22
+ /** Sample timing every N dispatches (hot-path cost control). Default 32. */
23
+ sampleEvery?: number
24
+ /**
25
+ * `load()` dispatch strategy. `"auto"` (default) switches each op between
26
+ * `"single"` (low load → direct scalar call, no coalescer) and
27
+ * `"coalesce"` (rising load → one packed batch call) from observed load.
28
+ */
29
+ loadStrategy?: LoadStrategy
30
+ }
31
+
32
+ /** Options for `load()` / `opFn.load()`. */
33
+ export interface LoadOptions {
34
+ /**
35
+ * Explicit cache key. When omitted (and caching is on) the default key is
36
+ * `fnv1a64(input)` — which costs one extra native call per load.
37
+ */
38
+ key?: string
39
+ /** Override the loader-wide caching toggle for this call. Default true. */
40
+ cache?: boolean
41
+ }
42
+
43
+ /** Per-op counters exposed on `opFn.stats`. */
44
+ export interface LoaderOpStats {
45
+ scalarCalls: number
46
+ batchCalls: number
47
+ itemsDispatched: number
48
+ cachedHits: number
49
+ /** Current learned batch threshold for this op. */
50
+ batchMin: number
51
+ /** Current `load()` strategy: "single" (low load) or "coalesce" (bulk). */
52
+ mode: 'single' | 'coalesce'
53
+ }
54
+
55
+ /** Aggregate loader statistics. */
56
+ export interface LoaderStats {
57
+ scalarCalls: number
58
+ batchCalls: number
59
+ itemsDispatched: number
60
+ flushes: number
61
+ cachedHits: number
62
+ cacheSize: number
63
+ cacheEvictions: number
64
+ }
65
+
66
+ /** A specialized, pre-bound op function returned by `loader(op)`. */
67
+ export interface LoaderOpFn<K extends LoaderOpName> {
68
+ /** Single item → scalar result. */
69
+ (input: Uint8Array, ...rest: LoaderOpArgs[K]): LoaderScalar<K>
70
+ /** Bulk items → ONE packed batch call; same shape as `rust.batch.<op>`. */
71
+ (inputs: Uint8Array[], ...rest: LoaderBulkArgs<K>): LoaderBulk<K>
72
+ readonly name: K
73
+ readonly stats: LoaderOpStats
74
+ clear(): void
75
+ /** Sync cache peek (default key `fnv1a64(input)` unless `key` given). */
76
+ cache(input: Uint8Array, key?: string): LoaderScalar<K> | undefined
77
+ /**
78
+ * Coalesced, cache-aware load. Unavailable (`undefined`) on ops that require
79
+ * extra arguments (e.g. `hmacSha256`, `signCookie`) — use `run` for those.
80
+ */
81
+ load: K extends LoadableName ? LoaderLoadFn<K> : undefined
82
+ }
83
+
84
+ type LoaderLoadFn<K extends LoaderOpName> = (
85
+ input: Uint8Array,
86
+ opts?: LoadOptions,
87
+ ) => Promise<LoaderScalar<K>>
88
+
89
+ /** Ops whose extra args are all optional/empty → they support `load()`. */
90
+ export type LoadableName = {
91
+ [K in LoaderOpName]: LoaderOpArgs[K] extends
92
+ | []
93
+ | [unknown?]
94
+ | [unknown?, unknown?]
95
+ | [unknown?, unknown?, unknown?]
96
+ ? K
97
+ : never
98
+ }[LoaderOpName]
99
+
100
+ /** A validator-bound helper returned by `loader.schema(validator)`. */
101
+ export interface LoaderSchemaFn {
102
+ /** Single JSON document → valid? */
103
+ (input: Uint8Array): boolean
104
+ /** Bulk JSON documents → bitset (1 per doc). */
105
+ (inputs: Uint8Array[]): Uint8Array
106
+ /** Count how many bulk documents are valid. */
107
+ count(inputs: Uint8Array[]): number
108
+ }
109
+
110
+ /** The global callable loader. */
111
+ export interface Loader {
112
+ /** Higher-order function: `loader(op)` → specialized hot op function. */
113
+ <K extends LoaderOpName>(op: K): LoaderOpFn<K>
114
+ /** Single-item dispatch. */
115
+ run<K extends LoaderOpName>(op: K, input: Uint8Array, ...rest: LoaderOpArgs[K]): LoaderScalar<K>
116
+ /** Bulk dispatch (one packed batch call, or adaptive scalar loop). */
117
+ run<K extends LoaderOpName>(
118
+ op: K,
119
+ inputs: Uint8Array[],
120
+ ...rest: LoaderBulkArgs<K>
121
+ ): LoaderBulk<K>
122
+ /** Coalesced, cache-aware load (ops with required extra args throw). */
123
+ load<K extends LoadableName>(
124
+ op: K,
125
+ input: Uint8Array,
126
+ opts?: LoadOptions,
127
+ ): Promise<LoaderScalar<K>>
128
+ /** Sync cache peek. */
129
+ cache<K extends LoaderOpName>(op: K, input: Uint8Array, key?: string): LoaderScalar<K> | undefined
130
+ /**
131
+ * Bind a `SchemaValidator` for repeated single/bulk JSON-schema validation
132
+ * plus a whole-batch `count`. The returned callable uses the loader's normal
133
+ * dispatch machinery (cost model + counters).
134
+ */
135
+ schema(validator: SchemaValidator): LoaderSchemaFn
136
+ /** Clear the shared cache (pending coalesced loads still flush). */
137
+ clear(): void
138
+ /** Update options at runtime. */
139
+ configure(options: LoaderOptions): void
140
+ readonly stats: LoaderStats
141
+ readonly opNames: LoaderOpName[]
142
+ }
143
+
144
+ /** Load-dispatch strategy selector for `load()`. */
145
+ export type LoadStrategy = 'auto' | 'single' | 'coalesce'
@@ -0,0 +1,58 @@
1
+ // src/native/ffi/constants.ts — caps / sizing heuristics / self-test
2
+ // vectors for the bun:ffi transport (pure data, no logic).
3
+ //
4
+ // The caps mirror the Rust napi layer (decompression-bomb guard, JSON-patch
5
+ // output bound). The sizing heuristics are ALLOCATION caps only — `growExact`
6
+ // in the core covers any residual miss with one exact-size retry, so a guess
7
+ // that is too small costs one extra native pass, never a wrong result.
8
+
9
+ // ── Caps mirrored from the Rust napi layer ────────────────────────
10
+ /** rust/payload/compress.rs DEFAULT_MAX_DECOMPRESSED (64 MiB decompression-bomb
11
+ * guard — must stay in sync; do not raise without benchmarking). */
12
+ export const MAX_DECOMPRESSED = 64 * 1024 * 1024
13
+ /** rust/json/json_patch_ops.rs MAX_JSON_PATCH_OUTPUT (128 MiB). */
14
+ export const MAX_JSON_PATCH_OUTPUT = 128 * 1024 * 1024
15
+
16
+ // ── Output-buffer sizing heuristics (measured) ─────────────────────
17
+ // These are ALLOCATION caps only, not correctness bounds: `growExact` covers
18
+ // any residual miss with at most one exact-size retry (no re-run loop), so a
19
+ // guess that is too small costs one extra native pass, never a wrong result.
20
+ //
21
+ // Compress: a 75 KiB input compresses to <1 KiB, so a 16 KiB initial is
22
+ // plenty and single-pass; the 1 MiB ceiling bounds incompressible data.
23
+ /** gzip/brotli compress: initial output-buffer size (bytes). */
24
+ export const COMPRESS_INITIAL_CAP = 16 * 1024
25
+ /** gzip/brotli compress: ceiling that bounds incompressible input (bytes). */
26
+ export const COMPRESS_MAX_CAP = 1024 * 1024
27
+ /** gzip/brotli compress: small-input slack added above `data.length` (bytes). */
28
+ export const COMPRESS_HEADROOM = 64
29
+ // Decompress (no trailer / expensive trailer): typical JSON/text ratios.
30
+ /** gzip decompress: output-size guess multiplier over the input length. */
31
+ export const DECOMPRESS_GUESS_MULTIPLIER_GZIP = 16
32
+ /** brotli decompress: output-size guess multiplier over the input length. */
33
+ export const DECOMPRESS_GUESS_MULTIPLIER_BROTLI = 32
34
+ /** decompress: 4 MiB over-alloc bound used as a last-resort initial size. */
35
+ export const DECOMPRESS_FALLBACK_CAP = 4 * 1024 * 1024
36
+ /** decompress: minimum initial output size (bytes). */
37
+ export const DECOMPRESS_MIN_INITIAL = 1024
38
+ // JWT: token ≈ header(~36) + payload(≈4/3× claims) + sig(~43) + 2 dots. The
39
+ // old `claims.length + 128` under-sized a typical token (measured 168 B for a
40
+ // 30 B claim → grow-retry double-run, making ffi slower than napi). 2×+128
41
+ // with a 256-byte floor covers typical claims in one pass.
42
+ /** jwt sign: claims-length multiplier for the initial output-size guess. */
43
+ export const JWT_INITIAL_MULTIPLIER = 2
44
+ /** jwt sign: fixed byte slack added to the claims-length guess. */
45
+ export const JWT_INITIAL_EXTRA = 128
46
+ /** jwt sign: minimum initial output size (bytes). */
47
+ export const JWT_INITIAL_FLOOR = 256
48
+
49
+ // ── Known-good vectors for the bind-time self-test ───────────────
50
+ // These mirror the Rust `#[cfg(test)]` vectors in rust/ffi.rs.
51
+ /** Self-test vector: ASCII "hello" (hex-encodes to `68656c6c6f`). */
52
+ export const SELFTEST_HEX = new Uint8Array([0x68, 0x65, 0x6c, 0x6c, 0x6f]) // "hello" -> 68656c6c6f
53
+ /** Self-test vector: JSON `{"a":1}` (validates via the packed JSON ops). */
54
+ export const SELFTEST_JSON = new Uint8Array([0x7b, 0x22, 0x61, 0x22, 0x3a, 0x31, 0x7d]) // "{\"a\":1}"
55
+
56
+ /** Empty view for `null` body slots in (ptr, len) pairs — the C side treats
57
+ * len 0 as "no body" regardless of the pointer value. */
58
+ export const EMPTY_VIEW = new Uint8Array(0)