castrum 0.9.3 → 0.9.6
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.
- package/Cargo.lock +2242 -0
- package/Cargo.toml +155 -0
- package/README.md +14 -6
- package/build.rs +5 -0
- package/castrum.darwin-arm64.node +0 -0
- package/castrum.darwin-x64.node +0 -0
- package/castrum.linux-arm64-gnu.node +0 -0
- package/castrum.linux-arm64-musl.node +0 -0
- package/castrum.linux-x64-gnu.node +0 -0
- package/castrum.linux-x64-musl.node +0 -0
- package/castrum.linux-x64-v3-gnu.node +0 -0
- package/castrum.win32-x64-msvc.node +0 -0
- package/dist/index.d.ts +1508 -1291
- package/dist/index.js +3391 -2069
- package/docs/API.md +2 -1
- package/docs/ARCHITECTURE.md +3 -2
- package/docs/CASE_STUDY.md +5 -3
- package/docs/ENVIRONMENT.md +25 -2
- package/docs/FFI_BUN_GUIDE.md +242 -14
- package/docs/HOW_TO_ADD_AN_OP.md +10 -0
- package/docs/REPO_MAP.md +17 -6
- package/docs/RND-CONCURRENCY.md +772 -0
- package/docs/bun-builtins-decision-matrix.md +4 -1
- package/index.ts +24 -25
- package/package.json +173 -156
- package/rust/crypto/aead.rs +378 -0
- package/rust/crypto/argon2.rs +265 -0
- package/rust/crypto/base64.rs +420 -0
- package/rust/crypto/bcrypt.rs +89 -0
- package/rust/crypto/cookie_sign.rs +169 -0
- package/rust/crypto/csrf.rs +106 -0
- package/rust/crypto/ed25519.rs +215 -0
- package/rust/crypto/hashing.rs +140 -0
- package/rust/crypto/hmac_sha256.rs +88 -0
- package/rust/crypto/jwt/api.rs +286 -0
- package/rust/crypto/jwt/mod.rs +22 -0
- package/rust/crypto/jwt/tests.rs +312 -0
- package/rust/crypto/jwt/token.rs +360 -0
- package/rust/crypto/mod.rs +27 -0
- package/rust/crypto/pbkdf2.rs +105 -0
- package/rust/crypto/random_token.rs +85 -0
- package/rust/crypto/session.rs +222 -0
- package/rust/ffi/crypto.rs +708 -0
- package/rust/ffi/hashing.rs +285 -0
- package/rust/ffi/http.rs +752 -0
- package/rust/ffi/ingress.rs +303 -0
- package/rust/ffi/json.rs +517 -0
- package/rust/ffi/jwt.rs +419 -0
- package/rust/ffi/metrics.rs +373 -0
- package/rust/ffi/mod.rs +69 -0
- package/rust/ffi/payload.rs +275 -0
- package/rust/ffi/probe.rs +60 -0
- package/rust/ffi/rate_limit.rs +77 -0
- package/rust/ffi/route.rs +85 -0
- package/rust/ffi/task.rs +172 -0
- package/rust/ffi/tests.rs +2333 -0
- package/rust/ffi/util.rs +152 -0
- package/rust/ffi/validators.rs +123 -0
- package/rust/http/accept.rs +606 -0
- package/rust/http/cookie_parser.rs +140 -0
- package/rust/http/etag.rs +289 -0
- package/rust/http/form.rs +136 -0
- package/rust/http/headers.rs +267 -0
- package/rust/http/http_date.rs +286 -0
- package/rust/http/http_parser.rs +252 -0
- package/rust/http/media_type.rs +355 -0
- package/rust/http/method.rs +200 -0
- package/rust/http/mime_lookup.rs +130 -0
- package/rust/http/mod.rs +32 -0
- package/rust/http/multipart.rs +685 -0
- package/rust/http/query_parser.rs +211 -0
- package/rust/http/url_codec.rs +296 -0
- package/rust/http/url_join.rs +324 -0
- package/rust/ingress/api.rs +355 -0
- package/rust/ingress/cors.rs +403 -0
- package/rust/ingress/ingress_constants.rs +209 -0
- package/rust/ingress/ip_trust.rs +312 -0
- package/rust/ingress/mod.rs +48 -0
- package/rust/ingress/native_route.rs +770 -0
- package/rust/ingress/options.rs +176 -0
- package/rust/ingress/output.rs +406 -0
- package/rust/ingress/packed.rs +191 -0
- package/rust/ingress/pipeline.rs +534 -0
- package/rust/ingress/proxy.rs +138 -0
- package/rust/ingress/rate_limit.rs +538 -0
- package/rust/ingress/terminal.rs +114 -0
- package/rust/ingress/tests.rs +567 -0
- package/rust/ingress/time.rs +70 -0
- package/rust/json/fast_schema/capture.rs +336 -0
- package/rust/json/fast_schema/compile.rs +556 -0
- package/rust/json/fast_schema/cursor.rs +368 -0
- package/rust/json/fast_schema/email.rs +282 -0
- package/rust/json/fast_schema/errors.rs +247 -0
- package/rust/json/fast_schema/mod.rs +57 -0
- package/rust/json/fast_schema/tests.rs +1143 -0
- package/rust/json/fast_schema/types.rs +140 -0
- package/rust/json/fast_schema/validate.rs +931 -0
- package/rust/json/json_ops.rs +121 -0
- package/rust/json/json_schema.rs +837 -0
- package/rust/json/json_ser.rs +883 -0
- package/rust/json/mod.rs +19 -0
- package/rust/json/napi_marshal.rs +318 -0
- package/rust/json/patch/api.rs +60 -0
- package/rust/json/patch/engine.rs +153 -0
- package/rust/json/patch/mod.rs +47 -0
- package/rust/json/patch/ops.rs +270 -0
- package/rust/json/patch/pointer.rs +49 -0
- package/rust/json/patch/tests.rs +499 -0
- package/rust/lib.rs +73 -0
- package/rust/metrics/api.rs +148 -0
- package/rust/metrics/mod.rs +21 -0
- package/rust/metrics/registry.rs +961 -0
- package/rust/panic_safety.rs +40 -0
- package/rust/payload/compress.rs +512 -0
- package/rust/payload/mod.rs +13 -0
- package/rust/payload/sse.rs +214 -0
- package/rust/payload/template.rs +253 -0
- package/rust/payload/websocket.rs +69 -0
- package/rust/payload/ws_frames.rs +354 -0
- package/rust/proptest_suite.rs +139 -0
- package/rust/selection.rs +95 -0
- package/rust/src/bin/native-bench.rs +495 -0
- package/rust/task/completion.rs +119 -0
- package/rust/task/mod.rs +65 -0
- package/rust/task/ops.rs +503 -0
- package/rust/task/runtime.rs +220 -0
- package/rust/task/tests.rs +231 -0
- package/rust/test_support.rs +71 -0
- package/rust/util/batch/api.rs +266 -0
- package/rust/util/batch/core.rs +473 -0
- package/rust/util/batch/mod.rs +23 -0
- package/rust/util/batch/tests.rs +445 -0
- package/rust/util/batch_core.rs +184 -0
- package/rust/util/bytes.rs +594 -0
- package/rust/util/mod.rs +34 -0
- package/rust/util/packed.rs +473 -0
- package/rust/util/text.rs +130 -0
- package/rust/util/threadpool.rs +128 -0
- package/rust/util/validation.rs +419 -0
- package/rust-toolchain.toml +17 -0
- package/scripts/postinstall.mjs +199 -0
- package/src/ingress/constants.ts +1 -1
- package/src/ingress/context.ts +2 -2
- package/src/ingress/decode/baked-result.ts +13 -13
- package/src/ingress/decode/fast-result.ts +17 -17
- package/src/ingress/errors.ts +7 -7
- package/src/ingress/headers/baked-templates.ts +1 -1
- package/src/ingress/headers/fast-templates.ts +3 -3
- package/src/ingress/health.ts +1 -2
- package/src/ingress/index.ts +1 -1
- package/src/ingress/native-route.ts +9 -5
- package/src/ingress/options.ts +1 -1
- package/src/ingress/packing/gather-raw-headers.ts +1 -1
- package/src/ingress/packing/route-wire.ts +1 -5
- package/src/ingress/response/error-bodies.ts +5 -5
- package/src/ingress/response/terminal.ts +1 -1
- package/src/ingress/routes/echo.ts +4 -4
- package/src/ingress/routes/fallback.ts +2 -2
- package/src/ingress/routes/head.ts +2 -2
- package/src/ingress/routes/native.ts +2 -1
- package/src/ingress/routes/options.ts +1 -1
- package/src/ingress/routes/read.ts +2 -2
- package/src/ingress/server.ts +10 -6
- package/src/ingress/status.ts +7 -7
- package/src/integration/batch.ts +1 -1
- package/src/integration/index.ts +9 -9
- package/src/integration/pipeline.ts +6 -6
- package/src/integration/websocket.ts +2 -2
- package/src/loader/index.ts +1 -5
- package/src/loader/ops.ts +1 -1
- package/src/native/ffi/build/codecs.ts +130 -12
- package/src/native/ffi/build/compress.ts +22 -10
- package/src/native/ffi/build/instances.ts +46 -4
- package/src/native/ffi/build/metrics.ts +247 -0
- package/src/native/ffi/build/parse.ts +59 -23
- package/src/native/ffi/build/task.ts +79 -0
- package/src/native/ffi/build/util.ts +32 -1
- package/src/native/ffi/build.ts +4 -0
- package/src/native/ffi/selftest.ts +12 -3
- package/src/native/ffi/types.ts +151 -9
- package/src/native/ffi.ts +160 -15
- package/src/native/index.ts +1 -1
- package/src/native/loader.ts +55 -5
- package/src/native/types/instances.ts +34 -0
- package/src/native/types.ts +11 -0
- package/src/runtime/codec.ts +53 -9
- package/src/runtime/types.ts +7 -0
- package/src/rust-ffi/batch/build.ts +16 -9
- package/src/rust-ffi/index.ts +7 -6
- package/src/rust-ffi/options.ts +1 -3
- package/src/rust-ffi/proven.ts +3 -3
- package/src/rust-ffi/scalar/crypto.ts +1 -1
- package/src/rust-ffi/scalar/factories.ts +73 -0
- package/src/rust-ffi/scalar/hashing.ts +1 -1
- package/src/rust-ffi/scalar/http.ts +71 -27
- package/src/rust-ffi/scalar/index.ts +2 -0
- package/src/rust-ffi/scalar/interface.ts +20 -0
- package/src/rust-ffi/scalar/payload.ts +11 -3
- package/src/rust-ffi/scalar/validation.ts +121 -0
- package/src/rust-ffi/text.ts +25 -3
- package/src/selection.ts +1 -1
- package/src/shared/bytes.ts +24 -4
- package/src/shared/codec.ts +18 -3
- package/src/task/index.ts +24 -0
- package/src/task/op.ts +171 -0
- package/src/task/runtime.ts +568 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// scripts/postinstall.mjs — cross-platform native addon fallback builder.
|
|
3
|
+
//
|
|
4
|
+
// castrum ships PREBUILT addons for every `napi.targets` platform (the CI
|
|
5
|
+
// "build" job compiles them per-platform and the "publish" job stages all of
|
|
6
|
+
// them into one tarball), so on a supported platform this script is a fast
|
|
7
|
+
// no-op. It exists to keep the core CROSS-COMPATIBLE when that prebuilt path
|
|
8
|
+
// is NOT available:
|
|
9
|
+
//
|
|
10
|
+
// - the host platform / libc is not in napi.targets (e.g. linux-armv7,
|
|
11
|
+
// freebsd, android, x86 32-bit, …),
|
|
12
|
+
// - a partial tarball shipped without this platform's artifact
|
|
13
|
+
// (CASTRUM_PUBLISH_ALLOW_PARTIAL local publish), or
|
|
14
|
+
// - the artifact failed to load and the user wants a matching rebuild.
|
|
15
|
+
//
|
|
16
|
+
// In those cases it compiles the addon FROM SOURCE in the consumer's
|
|
17
|
+
// node_modules (`cargo build --release`), so the core keeps working anywhere a
|
|
18
|
+
// Rust toolchain exists.
|
|
19
|
+
//
|
|
20
|
+
// Behaviour (in order):
|
|
21
|
+
// 1. If a loadable artifact for this host already exists next to the script
|
|
22
|
+
// (a shipped prebuilt), do nothing — installs stay fast. Forced rebuild
|
|
23
|
+
// with `npm install --build-from-source`.
|
|
24
|
+
// 2. Else if CASTRUM_SKIP_BUILD is set, or CI is detected (GitHub Actions
|
|
25
|
+
// builds the addon explicitly), warn and skip.
|
|
26
|
+
// 3. Else if no `cargo`/`rustc` is on PATH, warn and skip (the runtime
|
|
27
|
+
// loader then fails with a clear "build it" error if the addon is needed).
|
|
28
|
+
// 4. Else run `cargo build --release` and copy the resulting cdylib to every
|
|
29
|
+
// artifact name the loader probes for this host, so whichever libc/name
|
|
30
|
+
// variant it tries first, it finds a correct file.
|
|
31
|
+
//
|
|
32
|
+
// CASTRUM_REQUIRE_BUILD=1 turns every "warn and skip" above into a hard install
|
|
33
|
+
// failure — for strict environments that must guarantee a loadable addon.
|
|
34
|
+
//
|
|
35
|
+
// No dependency on the `@napi-rs/cli`: `build.rs` runs `napi_build::setup()`
|
|
36
|
+
// during a plain `cargo build`, and the produced cdylib IS the `.node` file the
|
|
37
|
+
// napi CLI would rename — so this works in a consumer's node_modules where the
|
|
38
|
+
// CLI (a devDependency) is not installed.
|
|
39
|
+
//
|
|
40
|
+
// The pure helpers are exported for tests (test/unit/native/postinstall.test.ts);
|
|
41
|
+
// the script only auto-runs when invoked directly (npm/bun postinstall hook).
|
|
42
|
+
|
|
43
|
+
import { spawnSync } from 'node:child_process'
|
|
44
|
+
import { copyFileSync, existsSync, statSync } from 'node:fs'
|
|
45
|
+
import { dirname, join } from 'node:path'
|
|
46
|
+
import { fileURLToPath, pathToFileURL } from 'node:url'
|
|
47
|
+
|
|
48
|
+
const ROOT = dirname(dirname(fileURLToPath(import.meta.url)))
|
|
49
|
+
const IS_MAIN = process.argv[1] != null && import.meta.url === pathToFileURL(process.argv[1]).href
|
|
50
|
+
|
|
51
|
+
const log = (msg) => console.log(`postinstall: ${msg}`)
|
|
52
|
+
const warn = (msg) => console.warn(`postinstall: WARNING: ${msg}`)
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Artifact names `src/native/loader.ts` probes for a host, mirroring its
|
|
56
|
+
* `libcVariants` logic. A source build always produces the portable BASELINE
|
|
57
|
+
* (not the optional x86-64-v3 SIMD variant), so this omits the v3 name — the
|
|
58
|
+
* loader falls through from the absent v3 file to the baseline names below.
|
|
59
|
+
*
|
|
60
|
+
* @param platform `process.platform`-style value ('linux' | 'darwin' | 'win32' | …)
|
|
61
|
+
* @param arch `process.arch`-style value ('x64' | 'arm64' | …)
|
|
62
|
+
* @returns artifact file names, in loader probe order
|
|
63
|
+
*/
|
|
64
|
+
export function napiArtifactCandidates(platform, arch) {
|
|
65
|
+
const libcVariants =
|
|
66
|
+
platform === 'win32' ? ['msvc', 'gnu'] : platform === 'linux' ? ['gnu', 'musl'] : ['']
|
|
67
|
+
const names = libcVariants.map(
|
|
68
|
+
(libc) => `castrum.${platform}-${arch}${libc ? `-${libc}` : ''}.node`,
|
|
69
|
+
)
|
|
70
|
+
names.push('castrum.node')
|
|
71
|
+
return names
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Path of the cdylib `cargo build --release` produces for the current host
|
|
76
|
+
* (crate [lib] name = "castrum"; build.rs runs napi_build::setup()).
|
|
77
|
+
*
|
|
78
|
+
* @param root package root directory
|
|
79
|
+
* @param platform `process.platform`-style value
|
|
80
|
+
* @returns absolute path to the built cdylib
|
|
81
|
+
*/
|
|
82
|
+
export function cdylibArtifact(root, platform) {
|
|
83
|
+
const release = join(root, 'target', 'release')
|
|
84
|
+
if (platform === 'win32') return join(release, 'castrum.dll')
|
|
85
|
+
if (platform === 'darwin') return join(release, 'libcastrum.dylib')
|
|
86
|
+
return join(release, 'libcastrum.so')
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function commandExists(cmd, env) {
|
|
90
|
+
const probe =
|
|
91
|
+
process.platform === 'win32'
|
|
92
|
+
? spawnSync('where', [cmd], { stdio: 'ignore', env })
|
|
93
|
+
: spawnSync('which', [cmd], { stdio: 'ignore', env })
|
|
94
|
+
return probe.status === 0
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Ensure a loadable native addon exists for this host, building from source as
|
|
99
|
+
* a fallback when no prebuilt ships. Pure-ish and testable: every input
|
|
100
|
+
* (`root`, `platform`, `arch`, `env`) can be injected, and `cargo` is only ever
|
|
101
|
+
* invoked after all short-circuit checks pass.
|
|
102
|
+
*
|
|
103
|
+
* @param root package root (where the .node artifacts live / where to build)
|
|
104
|
+
* @param opts overrides for testability: `{ platform, arch, env }`
|
|
105
|
+
* @returns `{ status: 'skip', reason }` or `{ status: 'built', candidates }`
|
|
106
|
+
*/
|
|
107
|
+
export function ensureNativeAddon(root = ROOT, opts = {}) {
|
|
108
|
+
const platform = opts.platform ?? process.platform
|
|
109
|
+
const arch = opts.arch ?? process.arch
|
|
110
|
+
const env = opts.env ?? process.env
|
|
111
|
+
|
|
112
|
+
const candidates = napiArtifactCandidates(platform, arch)
|
|
113
|
+
const prebuilt = candidates.find((name) => {
|
|
114
|
+
try {
|
|
115
|
+
return statSync(join(root, name)).size > 0
|
|
116
|
+
} catch {
|
|
117
|
+
return false
|
|
118
|
+
}
|
|
119
|
+
})
|
|
120
|
+
const force = env.npm_config_build_from_source === 'true'
|
|
121
|
+
|
|
122
|
+
if (prebuilt && !force) {
|
|
123
|
+
log(`prebuilt addon present (${prebuilt}) — nothing to build`)
|
|
124
|
+
return { status: 'skip', reason: 'prebuilt' }
|
|
125
|
+
}
|
|
126
|
+
if (force) log('npm_config_build_from_source set — forcing a source rebuild')
|
|
127
|
+
|
|
128
|
+
if (env.CASTRUM_SKIP_BUILD) {
|
|
129
|
+
warn(
|
|
130
|
+
'CASTRUM_SKIP_BUILD is set — skipping the source build. If no prebuilt ' +
|
|
131
|
+
'ships for this platform the native addon will be missing at runtime.',
|
|
132
|
+
)
|
|
133
|
+
return { status: 'skip', reason: 'env' }
|
|
134
|
+
}
|
|
135
|
+
if (env.CI) {
|
|
136
|
+
// GitHub Actions etc. install deps first, then build the addon explicitly
|
|
137
|
+
// (bun run build / napi build) — don't double-build during bun install.
|
|
138
|
+
if (!prebuilt) {
|
|
139
|
+
warn('CI detected — skipping the source build (CI builds the addon explicitly).')
|
|
140
|
+
}
|
|
141
|
+
return { status: 'skip', reason: 'ci' }
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (!commandExists('cargo', env) || !commandExists('rustc', env)) {
|
|
145
|
+
const msg =
|
|
146
|
+
`no Rust toolchain (cargo/rustc) found — cannot build the castrum addon for ` +
|
|
147
|
+
`${platform}/${arch}. Install Rust from https://rustup.rs and re-run ` +
|
|
148
|
+
`npm install, or set CASTRUM_SKIP_BUILD=1 to silence this warning.`
|
|
149
|
+
if (env.CASTRUM_REQUIRE_BUILD) throw new Error(msg)
|
|
150
|
+
warn(msg)
|
|
151
|
+
return { status: 'skip', reason: 'no-toolchain' }
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
log(
|
|
155
|
+
`no prebuilt addon for ${platform}/${arch} — building from source ` +
|
|
156
|
+
'(cargo build --release; requires network to crates.io, a few minutes on first run)',
|
|
157
|
+
)
|
|
158
|
+
// Windows needs the shell so `cargo` resolves via PATH/PATHEXT (cargo.exe).
|
|
159
|
+
const run =
|
|
160
|
+
process.platform === 'win32'
|
|
161
|
+
? spawnSync('cargo build --release', { cwd: root, stdio: 'inherit', shell: true })
|
|
162
|
+
: spawnSync('cargo', ['build', '--release'], { cwd: root, stdio: 'inherit' })
|
|
163
|
+
if (run.status !== 0) {
|
|
164
|
+
const msg =
|
|
165
|
+
`cargo build --release failed (exit ${run.status ?? 'unknown'}); the castrum ` +
|
|
166
|
+
`native addon could not be built for ${platform}/${arch}.`
|
|
167
|
+
if (env.CASTRUM_REQUIRE_BUILD) throw new Error(msg)
|
|
168
|
+
warn(msg)
|
|
169
|
+
return { status: 'skip', reason: 'build-failed' }
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const built = cdylibArtifact(root, platform)
|
|
173
|
+
if (!existsSync(built)) {
|
|
174
|
+
const msg = `build finished but no cdylib found at ${built}`
|
|
175
|
+
if (env.CASTRUM_REQUIRE_BUILD) throw new Error(msg)
|
|
176
|
+
warn(msg)
|
|
177
|
+
return { status: 'skip', reason: 'artifact-missing' }
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Copy the SAME correctly-built binary to every candidate name the loader
|
|
181
|
+
// probes. Only one is ever loaded (the first existing candidate), and since
|
|
182
|
+
// the file was built on this exact host its content always matches — so a
|
|
183
|
+
// glibc build copied under the musl name is still the right binary for this
|
|
184
|
+
// machine, and the loader finds a working file regardless of its probe order.
|
|
185
|
+
for (const name of candidates) {
|
|
186
|
+
copyFileSync(built, join(root, name))
|
|
187
|
+
}
|
|
188
|
+
log(`built + staged native addon for ${platform}/${arch}: ${candidates.join(', ')}`)
|
|
189
|
+
return { status: 'built', candidates }
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (IS_MAIN) {
|
|
193
|
+
try {
|
|
194
|
+
ensureNativeAddon()
|
|
195
|
+
} catch (err) {
|
|
196
|
+
console.error(`\npostinstall: ERROR: ${err instanceof Error ? err.message : String(err)}\n`)
|
|
197
|
+
process.exit(1)
|
|
198
|
+
}
|
|
199
|
+
}
|
package/src/ingress/constants.ts
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// they cannot drift.
|
|
12
12
|
|
|
13
13
|
import { getAddon } from '../native'
|
|
14
|
-
import {
|
|
14
|
+
import { type BunFFI, getBunFFI } from '../native/ffi'
|
|
15
15
|
|
|
16
16
|
// Transport: bun:ffi is PRIMARY on Bun, so the layout is read through the
|
|
17
17
|
// C-ABI blob WITHOUT dlopening the napi addon. Node — or forced
|
package/src/ingress/context.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// src/ingress/context.ts — Result snapshotting + synthetic/error context
|
|
2
2
|
// builders for the async ingress API.
|
|
3
3
|
|
|
4
|
+
import { ERR_CODE_INTERNAL, ERR_CODE_RATE_LIMITED, HV_CORS_SIMPLE, HV_JSON } from './constants'
|
|
4
5
|
import type { ResponseBuildContext } from './headers/fast-templates'
|
|
5
6
|
import { buildTerminalResponse } from './response/terminal'
|
|
6
|
-
import {
|
|
7
|
-
import type { IngressOptions, IngressResult, IngressContext } from './types'
|
|
7
|
+
import type { IngressContext, IngressOptions, IngressResult } from './types'
|
|
8
8
|
|
|
9
9
|
const EMPTY_BODY = new Uint8Array(0)
|
|
10
10
|
|
|
@@ -11,27 +11,27 @@
|
|
|
11
11
|
// via ./result-base.ts.
|
|
12
12
|
|
|
13
13
|
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
OUT_RATE_LIMIT,
|
|
17
|
-
OUT_RATE_REMAINING,
|
|
18
|
-
OUT_COOKIES_JSON_LEN,
|
|
19
|
-
OUT_QUERY_JSON_LEN,
|
|
20
|
-
OUT_HEADER_VARIANT,
|
|
21
|
-
OUT_BODY_JSON_LEN,
|
|
22
|
-
OUT_DATA_START,
|
|
14
|
+
ERR_CODE_INTERNAL as ERROR_CODE_INTERNAL,
|
|
15
|
+
FLAG_BODY_TRUNCATED,
|
|
23
16
|
FLAG_BODY_VALID_JSON,
|
|
24
|
-
FLAG_SCHEMA_VALID,
|
|
25
17
|
FLAG_CORS_ALLOWED,
|
|
26
18
|
FLAG_IS_PREFLIGHT,
|
|
27
19
|
FLAG_RATE_LIMITED,
|
|
20
|
+
FLAG_SCHEMA_VALID,
|
|
28
21
|
FLAG_TRUSTED_PROXY,
|
|
29
|
-
FLAG_BODY_TRUNCATED,
|
|
30
22
|
HV_JSON,
|
|
31
|
-
|
|
23
|
+
OUT_BODY_JSON_LEN,
|
|
24
|
+
OUT_COOKIES_JSON_LEN,
|
|
25
|
+
OUT_DATA_START,
|
|
26
|
+
OUT_FLAGS,
|
|
27
|
+
OUT_HEADER_VARIANT,
|
|
28
|
+
OUT_QUERY_JSON_LEN,
|
|
29
|
+
OUT_RATE_LIMIT,
|
|
30
|
+
OUT_RATE_REMAINING,
|
|
31
|
+
OUT_VERDICT,
|
|
32
32
|
} from '../constants'
|
|
33
|
-
import { sectionLayout } from './packed-sections'
|
|
34
33
|
import { isValidResponseStatus } from '../status'
|
|
34
|
+
import { sectionLayout } from './packed-sections'
|
|
35
35
|
import { IngressResultBase } from './result-base'
|
|
36
36
|
|
|
37
37
|
/** Zero-alloc, reusable result decoder for the pre-baked handler path. */
|
|
@@ -12,28 +12,28 @@
|
|
|
12
12
|
|
|
13
13
|
import { viewForArrayBuffer } from '../../shared/bytes'
|
|
14
14
|
import {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
OUT_STATUS,
|
|
18
|
-
OUT_FLAGS,
|
|
19
|
-
OUT_RATE_LIMIT,
|
|
20
|
-
OUT_RATE_REMAINING,
|
|
21
|
-
OUT_COOKIES_JSON_LEN,
|
|
22
|
-
OUT_QUERY_JSON_LEN,
|
|
23
|
-
OUT_HEADER_VARIANT,
|
|
24
|
-
OUT_BODY_JSON_LEN,
|
|
25
|
-
OUT_DATA_START,
|
|
26
|
-
FLAG_HAS_COOKIES,
|
|
27
|
-
FLAG_HAS_QUERY,
|
|
15
|
+
ERR_CODE_INTERNAL,
|
|
16
|
+
FLAG_BODY_TRUNCATED,
|
|
28
17
|
FLAG_BODY_VALID_JSON,
|
|
29
|
-
FLAG_SCHEMA_VALID,
|
|
30
18
|
FLAG_CORS_ALLOWED,
|
|
19
|
+
FLAG_HAS_COOKIES,
|
|
20
|
+
FLAG_HAS_QUERY,
|
|
21
|
+
FLAG_HTTPS,
|
|
31
22
|
FLAG_IS_PREFLIGHT,
|
|
32
23
|
FLAG_RATE_LIMITED,
|
|
33
|
-
|
|
24
|
+
FLAG_SCHEMA_VALID,
|
|
34
25
|
FLAG_TRUSTED_PROXY,
|
|
35
|
-
|
|
36
|
-
|
|
26
|
+
OUT_BODY_JSON_LEN,
|
|
27
|
+
OUT_COOKIES_JSON_LEN,
|
|
28
|
+
OUT_DATA_START,
|
|
29
|
+
OUT_ERROR_CODE,
|
|
30
|
+
OUT_FLAGS,
|
|
31
|
+
OUT_HEADER_VARIANT,
|
|
32
|
+
OUT_QUERY_JSON_LEN,
|
|
33
|
+
OUT_RATE_LIMIT,
|
|
34
|
+
OUT_RATE_REMAINING,
|
|
35
|
+
OUT_STATUS,
|
|
36
|
+
OUT_VERDICT,
|
|
37
37
|
} from '../constants'
|
|
38
38
|
import { normalizeResponseStatus } from '../status'
|
|
39
39
|
import { sectionLayout } from './packed-sections'
|
package/src/ingress/errors.ts
CHANGED
|
@@ -5,16 +5,16 @@
|
|
|
5
5
|
// the two mappings are intentionally not unified (see AGENTS.md).
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
|
-
|
|
9
|
-
ERR_CODE_CORS_PREFLIGHT,
|
|
10
|
-
ERR_CODE_RATE_LIMITED,
|
|
8
|
+
ERR_CODE_BAD_REQUEST,
|
|
11
9
|
ERR_CODE_BODY_TOO_LARGE,
|
|
10
|
+
ERR_CODE_CORS_PREFLIGHT,
|
|
11
|
+
ERR_CODE_INTERNAL,
|
|
12
12
|
ERR_CODE_INVALID_JSON,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
ERR_CODE_REQUEST_TOO_LARGE,
|
|
13
|
+
ERR_CODE_NONE,
|
|
14
|
+
ERR_CODE_RATE_LIMITED,
|
|
16
15
|
ERR_CODE_REQUEST_TIMEOUT,
|
|
17
|
-
|
|
16
|
+
ERR_CODE_REQUEST_TOO_LARGE,
|
|
17
|
+
ERR_CODE_SCHEMA_VALIDATION,
|
|
18
18
|
} from './constants'
|
|
19
19
|
|
|
20
20
|
/** Map a native error code to its stable string name. */
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// builder (./fast-templates.ts) with a different wire format (x-ratelimit-*) —
|
|
9
9
|
// do not unify them (see AGENTS.md).
|
|
10
10
|
|
|
11
|
-
import {
|
|
11
|
+
import { HV_CORS_PREFLIGHT, HV_CORS_SIMPLE, HV_JSON, HV_RATE_ACTIVE } from '../constants'
|
|
12
12
|
|
|
13
13
|
/** Inputs needed to build the pre-baked header templates. */
|
|
14
14
|
export interface BakedTemplateParams {
|
|
@@ -9,15 +9,15 @@
|
|
|
9
9
|
// a different wire format — do not unify them (see AGENTS.md).
|
|
10
10
|
|
|
11
11
|
import {
|
|
12
|
-
HV_COUNT,
|
|
13
|
-
HV_CORS_SIMPLE,
|
|
14
12
|
HV_CORS_PREFLIGHT,
|
|
13
|
+
HV_CORS_SIMPLE,
|
|
14
|
+
HV_COUNT,
|
|
15
15
|
HV_RATE_ACTIVE,
|
|
16
16
|
HV_RATE_LIMITED,
|
|
17
17
|
} from '../constants'
|
|
18
|
+
import { secondsFromMs } from '../shared'
|
|
18
19
|
import { buildCorsStaticStrings, type CorsOptions, type CorsStaticStrings } from './cors'
|
|
19
20
|
import { buildHstsValue, buildSecurityPairs, type SecurityHeadersOptions } from './hsts'
|
|
20
|
-
import { secondsFromMs } from '../shared'
|
|
21
21
|
|
|
22
22
|
/** A single precomputed header-variant template. */
|
|
23
23
|
export interface HeaderTemplate {
|
package/src/ingress/health.ts
CHANGED
|
@@ -49,10 +49,9 @@ export function readinessHandler(check?: () => boolean | Promise<boolean>) {
|
|
|
49
49
|
return ok
|
|
50
50
|
? jsonResponse(200, { status: 'ready' })
|
|
51
51
|
: jsonResponse(503, { status: 'not_ready' })
|
|
52
|
-
} catch (
|
|
52
|
+
} catch (_err) {
|
|
53
53
|
return jsonResponse(503, {
|
|
54
54
|
status: 'not_ready',
|
|
55
|
-
error: err instanceof Error ? err.message : String(err),
|
|
56
55
|
})
|
|
57
56
|
}
|
|
58
57
|
}
|
package/src/ingress/index.ts
CHANGED
|
@@ -36,9 +36,9 @@ export type { IngressMetrics } from './metrics'
|
|
|
36
36
|
export { createIngressMetrics, metricsHandler } from './metrics'
|
|
37
37
|
export type { NativeRoute, NativeRoutePlan } from './native-route'
|
|
38
38
|
export { createNativeRoute } from './native-route'
|
|
39
|
+
export type { IngressFastHandler, IngressFastOptions } from './options'
|
|
39
40
|
// ── Route-wire v3 byte contract (PURE wire helpers) ───────────────
|
|
40
41
|
export * from './packing/route-wire'
|
|
41
|
-
export type { IngressFastHandler, IngressFastOptions } from './options'
|
|
42
42
|
export { buildTerminalResponse } from './response/terminal'
|
|
43
43
|
export type { CreateIngressRouterOptions, IngressRouter, RouterRouteSpec } from './router'
|
|
44
44
|
export { createIngressRouter } from './router'
|
|
@@ -14,15 +14,15 @@
|
|
|
14
14
|
// `handlers.ts`/`server.ts`; the byte wire helpers it uses are the PURE
|
|
15
15
|
// `src/ingress/packing/route-wire.ts`.
|
|
16
16
|
|
|
17
|
-
import { getBunFFI } from '../native/ffi'
|
|
18
17
|
import { getAddon } from '../native'
|
|
18
|
+
import { getBunFFI } from '../native/ffi'
|
|
19
19
|
import type { BunFFI } from '../native/ffi/types'
|
|
20
20
|
import {
|
|
21
|
-
ROUTE_PART,
|
|
22
|
-
ROUTE_STAGE,
|
|
23
21
|
decodeRouteResult,
|
|
24
22
|
encodeRouteDescriptor,
|
|
25
23
|
packRouteFrame,
|
|
24
|
+
ROUTE_PART,
|
|
25
|
+
ROUTE_STAGE,
|
|
26
26
|
type RouteStageTag,
|
|
27
27
|
type RouteWireLimits,
|
|
28
28
|
type RouteWireResult,
|
|
@@ -168,9 +168,13 @@ function compileFfi(bunFFI: BunFFI, descriptor: Uint8Array): number {
|
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
/** Compile through the napi `Route` class (Node / fallback transport). */
|
|
171
|
-
function compileNapi(
|
|
171
|
+
function compileNapi(
|
|
172
|
+
descriptor: Uint8Array,
|
|
173
|
+
): { run: (frame: Uint8Array, out: Uint8Array) => number } | null {
|
|
172
174
|
const addon = getAddon()
|
|
173
|
-
const Route = (
|
|
175
|
+
const Route = (
|
|
176
|
+
addon as { Route?: new (d: Uint8Array) => { run: (f: Uint8Array, o: Uint8Array) => number } }
|
|
177
|
+
).Route
|
|
174
178
|
if (typeof Route !== 'function') {
|
|
175
179
|
return null // addon without the route stack (pre-rebuild) — caller falls back
|
|
176
180
|
}
|
package/src/ingress/options.ts
CHANGED
|
@@ -78,9 +78,9 @@ export interface IngressFastHandler {
|
|
|
78
78
|
*/
|
|
79
79
|
export type IngressHandlerOptions = Omit<IngressFastOptions, 'onError'>
|
|
80
80
|
|
|
81
|
+
import type { FastIngressResult } from './decode/fast-result'
|
|
81
82
|
import type { CorsOptions } from './headers/cors'
|
|
82
83
|
import type { SecurityHeadersOptions } from './headers/hsts'
|
|
83
|
-
import type { FastIngressResult } from './decode/fast-result'
|
|
84
84
|
|
|
85
85
|
const KNOWN_INGRESS_OPTION_KEYS: ReadonlySet<string> = new Set([
|
|
86
86
|
'trustProxy',
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
import type { HeaderPlan } from '../shared'
|
|
10
10
|
import { METHOD_KIND } from '../shared'
|
|
11
11
|
import { writeHeaderPair } from './header-packing'
|
|
12
|
-
import { forEachSelectedHeader, HDR_ORIGIN } from './select-headers'
|
|
13
12
|
import { getHeaderBuf, MAX_SMALL_HEADER_BYTES } from './scratch'
|
|
13
|
+
import { forEachSelectedHeader, HDR_ORIGIN } from './select-headers'
|
|
14
14
|
|
|
15
15
|
// Shared per-header size guards (single source of truth in scratch.ts).
|
|
16
16
|
// Re-exported for back-compat with imports that referenced them here.
|
|
@@ -112,11 +112,7 @@ export function encodeRouteDescriptor(
|
|
|
112
112
|
* Encode a request frame: `[flags u32][qLen][query][cLen][cookie]([bLen][body])`.
|
|
113
113
|
* The `flags` word currently only carries `ROUTE_FRAME_FLAG_HAS_BODY`.
|
|
114
114
|
*/
|
|
115
|
-
export function packRouteFrame(
|
|
116
|
-
query: string,
|
|
117
|
-
cookie: string,
|
|
118
|
-
body: Uint8Array | null,
|
|
119
|
-
): Uint8Array {
|
|
115
|
+
export function packRouteFrame(query: string, cookie: string, body: Uint8Array | null): Uint8Array {
|
|
120
116
|
const q = encoder.encode(query)
|
|
121
117
|
const c = encoder.encode(cookie)
|
|
122
118
|
const hasBody = body !== null && body.byteLength > 0
|
|
@@ -8,14 +8,14 @@
|
|
|
8
8
|
|
|
9
9
|
import { encoder } from '../../shared/bytes'
|
|
10
10
|
import {
|
|
11
|
-
|
|
12
|
-
ERR_CODE_RATE_LIMITED,
|
|
11
|
+
ERR_CODE_BAD_REQUEST,
|
|
13
12
|
ERR_CODE_BODY_TOO_LARGE,
|
|
13
|
+
ERR_CODE_CORS_PREFLIGHT,
|
|
14
|
+
ERR_CODE_INTERNAL,
|
|
14
15
|
ERR_CODE_INVALID_JSON,
|
|
15
|
-
|
|
16
|
-
ERR_CODE_BAD_REQUEST,
|
|
16
|
+
ERR_CODE_RATE_LIMITED,
|
|
17
17
|
ERR_CODE_REQUEST_TOO_LARGE,
|
|
18
|
-
|
|
18
|
+
ERR_CODE_SCHEMA_VALIDATION,
|
|
19
19
|
} from '../constants'
|
|
20
20
|
|
|
21
21
|
function staticErrorBody(code: string, message: string): Uint8Array {
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
// the pre-baked path has its own builders (see ./handlers.ts) — do not unify
|
|
7
7
|
// them (see AGENTS.md).
|
|
8
8
|
|
|
9
|
+
import { errorCodeName, errorMessage } from '../errors'
|
|
9
10
|
import { headersForResult, type ResponseBuildContext } from '../headers/fast-templates'
|
|
10
11
|
import { safeTerminalStatus } from '../status'
|
|
11
|
-
import { errorCodeName, errorMessage } from '../errors'
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Build a terminal response for a result, or `null` when the result is not
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// src/ingress/routes/echo.ts — Pre-baked echo handler.
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
import { resolveIp, type BakedHandlerOptions } from './common'
|
|
5
|
-
import { DEFAULT_MAX_BODY_BYTES, DEFAULT_BODY_TIMEOUT_MS, secondsFromMs } from '../shared'
|
|
3
|
+
import { readBodyWithLimit } from '../body'
|
|
6
4
|
import { HV_JSON } from '../constants'
|
|
7
5
|
import { ERROR_BODIES } from '../response/error-bodies'
|
|
8
|
-
import {
|
|
6
|
+
import { DEFAULT_BODY_TIMEOUT_MS, DEFAULT_MAX_BODY_BYTES, secondsFromMs } from '../shared'
|
|
7
|
+
import type { OptimizedIngressHandler } from '../types'
|
|
8
|
+
import { type BakedHandlerOptions, resolveIp } from './common'
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Pre-baked echo handler: streams the request body back with the client's
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// src/ingress/routes/fallback.ts — Pre-baked fallback handler.
|
|
2
2
|
|
|
3
|
-
import type { BakedContext, OptimizedIngressHandler } from '../types'
|
|
4
3
|
import type { BakedIngressResult } from '../decode/baked-result'
|
|
5
|
-
import {
|
|
4
|
+
import type { BakedContext, OptimizedIngressHandler } from '../types'
|
|
5
|
+
import { type BakedHandlerOptions, runBaked } from './common'
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Pre-baked fallback handler: 404 for unmatched routes / OPTIONS.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// src/ingress/routes/head.ts — Pre-baked HEAD read handler.
|
|
2
2
|
|
|
3
|
-
import type { BakedContext, OptimizedIngressHandler } from '../types'
|
|
4
3
|
import type { BakedIngressResult } from '../decode/baked-result'
|
|
5
|
-
import {
|
|
4
|
+
import type { BakedContext, OptimizedIngressHandler } from '../types'
|
|
5
|
+
import { type BakedHandlerOptions, buildSuccessInit, runBaked } from './common'
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Pre-baked HEAD read handler: headers only, no body.
|
|
@@ -23,6 +23,7 @@ import { decoder } from '../../shared/bytes'
|
|
|
23
23
|
import { generateRequestId } from '../../shared/request-id'
|
|
24
24
|
import { readBodyWithLimit } from '../body'
|
|
25
25
|
import type { NativeRoute } from '../native-route'
|
|
26
|
+
import type { RouteWireResult } from '../packing/route-wire'
|
|
26
27
|
import type { RouteHandler } from '../server'
|
|
27
28
|
import { DEFAULT_BODY_TIMEOUT_MS, DEFAULT_MAX_BODY_BYTES } from '../shared'
|
|
28
29
|
import type { NativeRequestContext, NativeResponder } from '../types'
|
|
@@ -97,7 +98,7 @@ export function nativeRouteHandler(
|
|
|
97
98
|
const queryStr = qIndex >= 0 ? url.slice(qIndex + 1) : ''
|
|
98
99
|
const cookieStr = req.headers.get('cookie') ?? ''
|
|
99
100
|
|
|
100
|
-
let result
|
|
101
|
+
let result: RouteWireResult
|
|
101
102
|
try {
|
|
102
103
|
result = route.run(queryStr, cookieStr, body)
|
|
103
104
|
} catch {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/ingress/routes/options.ts — Pre-baked OPTIONS handler (CORS preflight).
|
|
2
2
|
|
|
3
3
|
import type { OptimizedIngressHandler } from '../types'
|
|
4
|
-
import { buildSuccessInit, resolveIp
|
|
4
|
+
import { type BakedHandlerOptions, buildSuccessInit, resolveIp } from './common'
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Pre-baked OPTIONS handler: serves the native pipeline's CORS preflight
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// src/ingress/routes/read.ts — Pre-baked GET read handler.
|
|
2
2
|
|
|
3
|
-
import type { BakedContext, OptimizedIngressHandler } from '../types'
|
|
4
3
|
import type { BakedIngressResult } from '../decode/baked-result'
|
|
5
|
-
import {
|
|
4
|
+
import type { BakedContext, OptimizedIngressHandler } from '../types'
|
|
5
|
+
import { type BakedHandlerOptions, buildSuccessInit, runBaked } from './common'
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Pre-baked GET read handler: returns the ingress body JSON on success.
|
package/src/ingress/server.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// src/ingress/server.ts — Bun.serve builder over pre-baked route handlers.
|
|
2
2
|
|
|
3
3
|
import { isBun } from '../shared/runtime'
|
|
4
|
+
import type { NativeRoutePlan } from './native-route'
|
|
5
|
+
import { createNativeRoute } from './native-route'
|
|
4
6
|
import {
|
|
5
7
|
deleteHandler,
|
|
6
8
|
echoHandler,
|
|
@@ -13,8 +15,6 @@ import {
|
|
|
13
15
|
import type { BakedHandlerOptions } from './routes/common'
|
|
14
16
|
import { nativeRouteHandler } from './routes/native'
|
|
15
17
|
import { nativeResponderRoute } from './routes/responder'
|
|
16
|
-
import { createNativeRoute } from './native-route'
|
|
17
|
-
import type { NativeRoutePlan } from './native-route'
|
|
18
18
|
import type { NativeResponder, OptimizedIngressHandler, TerminalStyle } from './types'
|
|
19
19
|
|
|
20
20
|
/** Server-level default for the socket request-body cap (16 MiB). */
|
|
@@ -304,10 +304,14 @@ export function buildRouteHandlers(options: BuildRouteHandlersOptions): {
|
|
|
304
304
|
// LEAN native-stack responder route: route-wire v3 stack, no envelope.
|
|
305
305
|
// The compiled route is injected into the pure route factory (DI across
|
|
306
306
|
// the purity boundary — the compile touches the dlopen layer here).
|
|
307
|
-
const nativeRoute = nativeRouteHandler(
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
307
|
+
const nativeRoute = nativeRouteHandler(
|
|
308
|
+
createNativeRoute(spec.native.plan),
|
|
309
|
+
spec.native.handler,
|
|
310
|
+
{
|
|
311
|
+
...routeOpts,
|
|
312
|
+
readBody: spec.native.readBody,
|
|
313
|
+
},
|
|
314
|
+
)
|
|
311
315
|
const nativeMethods = spec.native.methods ?? ['GET']
|
|
312
316
|
for (const m of nativeMethods) {
|
|
313
317
|
methods[m] = nativeRoute
|
package/src/ingress/status.ts
CHANGED
|
@@ -6,16 +6,16 @@
|
|
|
6
6
|
// ./constants.ts, so they live in one place and cannot drift.
|
|
7
7
|
|
|
8
8
|
import {
|
|
9
|
-
|
|
10
|
-
ERR_CODE_CORS_PREFLIGHT,
|
|
11
|
-
ERR_CODE_RATE_LIMITED,
|
|
9
|
+
ERR_CODE_BAD_REQUEST,
|
|
12
10
|
ERR_CODE_BODY_TOO_LARGE,
|
|
11
|
+
ERR_CODE_CORS_PREFLIGHT,
|
|
12
|
+
ERR_CODE_INTERNAL,
|
|
13
13
|
ERR_CODE_INVALID_JSON,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
ERR_CODE_REQUEST_TOO_LARGE,
|
|
14
|
+
ERR_CODE_NONE,
|
|
15
|
+
ERR_CODE_RATE_LIMITED,
|
|
17
16
|
ERR_CODE_REQUEST_TIMEOUT,
|
|
18
|
-
|
|
17
|
+
ERR_CODE_REQUEST_TOO_LARGE,
|
|
18
|
+
ERR_CODE_SCHEMA_VALIDATION,
|
|
19
19
|
} from './constants'
|
|
20
20
|
|
|
21
21
|
/**
|
package/src/integration/batch.ts
CHANGED
|
@@ -13,12 +13,12 @@
|
|
|
13
13
|
// checks) — exactly the pattern these helpers exist for.
|
|
14
14
|
|
|
15
15
|
import {
|
|
16
|
-
loader,
|
|
17
16
|
type LoaderBulk,
|
|
18
17
|
type LoaderBulkArgs,
|
|
19
18
|
type LoaderOpArgs,
|
|
20
19
|
type LoaderOpName,
|
|
21
20
|
type LoaderScalar,
|
|
21
|
+
loader,
|
|
22
22
|
} from '../loader'
|
|
23
23
|
import type { SchemaValidator } from '../shared/packed'
|
|
24
24
|
|