@base44/functions-compiler 0.1.0

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 (81) hide show
  1. package/README.md +137 -0
  2. package/lib/dist/activation-shim.mjs +237 -0
  3. package/lib/dist/actor.mjs +1129 -0
  4. package/lib/dist/deno-shim.mjs +2347 -0
  5. package/lib/src/actor-compat.d.ts +24 -0
  6. package/lib/src/actor-compat.js +302 -0
  7. package/lib/src/actor-compat.js.map +1 -0
  8. package/lib/src/bundler.d.ts +51 -0
  9. package/lib/src/bundler.js +321 -0
  10. package/lib/src/bundler.js.map +1 -0
  11. package/lib/src/contracts.d.ts +108 -0
  12. package/lib/src/contracts.js +39 -0
  13. package/lib/src/contracts.js.map +1 -0
  14. package/lib/src/deno-bundle.d.ts +30 -0
  15. package/lib/src/deno-bundle.js +146 -0
  16. package/lib/src/deno-bundle.js.map +1 -0
  17. package/lib/src/errors.d.ts +16 -0
  18. package/lib/src/errors.js +11 -0
  19. package/lib/src/errors.js.map +1 -0
  20. package/lib/src/esbuild/deno-resolver.d.ts +26 -0
  21. package/lib/src/esbuild/deno-resolver.js +436 -0
  22. package/lib/src/esbuild/deno-resolver.js.map +1 -0
  23. package/lib/src/esbuild/node-builtin-require.d.ts +2 -0
  24. package/lib/src/esbuild/node-builtin-require.js +33 -0
  25. package/lib/src/esbuild/node-builtin-require.js.map +1 -0
  26. package/lib/src/esbuild/private-data-sources-virtual.d.ts +3 -0
  27. package/lib/src/esbuild/private-data-sources-virtual.js +127 -0
  28. package/lib/src/esbuild/private-data-sources-virtual.js.map +1 -0
  29. package/lib/src/esbuild/runtime-context-virtual.d.ts +3 -0
  30. package/lib/src/esbuild/runtime-context-virtual.js +42 -0
  31. package/lib/src/esbuild/runtime-context-virtual.js.map +1 -0
  32. package/lib/src/esbuild/runtime-virtual.d.ts +2 -0
  33. package/lib/src/esbuild/runtime-virtual.js +52 -0
  34. package/lib/src/esbuild/runtime-virtual.js.map +1 -0
  35. package/lib/src/esbuild/user-files.d.ts +15 -0
  36. package/lib/src/esbuild/user-files.js +73 -0
  37. package/lib/src/esbuild/user-files.js.map +1 -0
  38. package/lib/src/fetch-guard.d.ts +26 -0
  39. package/lib/src/fetch-guard.js +67 -0
  40. package/lib/src/fetch-guard.js.map +1 -0
  41. package/lib/src/index.d.ts +12 -0
  42. package/lib/src/index.js +11 -0
  43. package/lib/src/index.js.map +1 -0
  44. package/lib/src/log.d.ts +7 -0
  45. package/lib/src/log.js +39 -0
  46. package/lib/src/log.js.map +1 -0
  47. package/lib/src/private-data-sources/build-http.ts +51 -0
  48. package/lib/src/private-data-sources/elasticsearch.ts +8 -0
  49. package/lib/src/private-data-sources/http-url.ts +23 -0
  50. package/lib/src/private-data-sources/http.ts +6 -0
  51. package/lib/src/private-data-sources/hyperdrive.ts +48 -0
  52. package/lib/src/private-data-sources/ioredis-adapter.ts +229 -0
  53. package/lib/src/private-data-sources/manifest.ts +150 -0
  54. package/lib/src/private-data-sources/mariadb.ts +8 -0
  55. package/lib/src/private-data-sources/mongodb.ts +70 -0
  56. package/lib/src/private-data-sources/mysql.ts +8 -0
  57. package/lib/src/private-data-sources/node-net-adapter.ts +244 -0
  58. package/lib/src/private-data-sources/postgres.ts +8 -0
  59. package/lib/src/private-data-sources/redis-auth.ts +83 -0
  60. package/lib/src/private-data-sources/redis.ts +47 -0
  61. package/lib/src/private-data-sources/runtime-environment.ts +4 -0
  62. package/lib/src/private-data-sources/runtime-manifest-store.ts +32 -0
  63. package/lib/src/private-data-sources/sqlserver.ts +22 -0
  64. package/lib/src/private-data-sources/tcp.ts +86 -0
  65. package/lib/src/private-data-sources/tedious-adapter.ts +67 -0
  66. package/lib/src/private-data-sources/types.ts +29 -0
  67. package/lib/src/runtime/index.ts +30 -0
  68. package/lib/src/runtime-context.ts +29 -0
  69. package/lib/src/static-egress-marker.d.ts +1 -0
  70. package/lib/src/static-egress-marker.js +7 -0
  71. package/lib/src/static-egress-marker.js.map +1 -0
  72. package/lib/src/telemetry.d.ts +32 -0
  73. package/lib/src/telemetry.js +84 -0
  74. package/lib/src/telemetry.js.map +1 -0
  75. package/lib/src/tracing.d.ts +9 -0
  76. package/lib/src/tracing.js +21 -0
  77. package/lib/src/tracing.js.map +1 -0
  78. package/lib/src/worker-entry.d.ts +36 -0
  79. package/lib/src/worker-entry.js +320 -0
  80. package/lib/src/worker-entry.js.map +1 -0
  81. package/package.json +43 -0
package/README.md ADDED
@@ -0,0 +1,137 @@
1
+ # @base44/functions-compiler
2
+
3
+ Production compiler for Base44 backend functions. Takes function sources as
4
+ data and returns a single Cloudflare Workers module — the generated worker
5
+ entry, the Deno shim, the runtime and private-data-source modules, and npm/jsr
6
+ dependency resolution through `@deno/loader` + esbuild.
7
+
8
+ Two consumers share this one engine:
9
+
10
+ - the **Base44 CLI**, which compiles locally (and inside the platform's build
11
+ sandbox) with no network service in the path;
12
+ - apper's **`base44-userapp-bundler`** HTTP service, which keeps its own
13
+ endpoints, auth, worker pool and telemetry around it.
14
+
15
+ ## Status and scope
16
+
17
+ Internal to Base44 — published **public** so apper's bundler service can install
18
+ it, but it is not a supported public API: the CLI bundles it at build time so
19
+ end users never install it, and it carries no compatibility promise to anyone
20
+ outside this repo. It compiles functions and nothing else: shard planning, size
21
+ splitting, artifact writing, version creation and deploy all live above it.
22
+
23
+ The package carries no credentials and reads no configuration of its own. It
24
+ names the environment variables and headers the generated worker will use at
25
+ runtime (`BASE44_*`, `X-Base44-*`) but holds none of their values, and the code
26
+ it ships is the same code already compiled into every deployed user worker.
27
+
28
+ ## What is missing: shards, and whole-app CFW bundles
29
+
30
+ Today this package compiles **one module per call**. It does not decide which
31
+ functions belong in which module, how large the result may be, or what to do
32
+ when it is too large. That work is still Python in apper's
33
+ `backend/app/cloudflare_functions/` and moves here next — it is what turns
34
+ "compile this set of sources" into "produce the deployable Cloudflare Workers
35
+ bundles for this app".
36
+
37
+ | Missing piece | Where it lives today | What it has to do |
38
+ |---|---|---|
39
+ | Source assembly | `function_bundle.py` — `cfw_bundle_input`, `collect_reachable_backend_files` | Turn a function's directory plus the shared files it reaches into the `entry` + `files` this package takes, keeping the flat single-file case and the refusal to escape into the frontend tree |
40
+ | Fresh shard planning | `shard_planning.py` — `full_repartition`, `target_shard_count` | Group an app's functions into shards deterministically, and refuse a set that exceeds the supplied product capacity |
41
+ | Size measurement | `cloudflare_wfp_runtime.py` — `measure_bundle_bytes`, `judge_bundle_size` | Raw UTF-8 bytes and level-6 gzip, against Cloudflare's 64 MiB uncompressed limit and our compressed cap |
42
+ | Split on overflow | `cloudflare_wfp_runtime.py` — `_build_shard_with_split` | Halve an oversized multi-function shard deterministically and recompile; fail the build when one function alone is too big |
43
+ | Whole-build validation | apper PR #23460 | Reject a partial result: every declared function in exactly one successful shard, or no build at all |
44
+
45
+ Only the **fresh-build** slice comes across. Everything that remembers a
46
+ previous deploy stays in apper: incremental shard reuse (it needs the previous
47
+ deployment map), the per-app `shard_size_override` ratchet, entitlement and
48
+ settings reads, provider upload, binding resolution and secret delivery. Policy
49
+ numbers — shard size, shard count, the gzip cap, whether the gate is enforced —
50
+ arrive as inputs; the package never reads them itself.
51
+
52
+ Two details from the Python that must survive the port, both verified against
53
+ the current code:
54
+
55
+ - The single-shard path builds in caller order while the multi-shard path sorts
56
+ by name. Function order changes the emitted bytes, so both branches carry
57
+ over as they are — normalising them is a byte change dressed as a cleanup.
58
+ - Capacity is judged at the *global* shard size while packing may use a smaller
59
+ ratcheted one, so a legal plan can hold more shards than `max_shards`. A
60
+ final "shard count ≤ max_shards" assertion would lock out apps that deploy
61
+ fine today.
62
+
63
+ Also deliberately out of scope for the new lane: Deno deployment targets,
64
+ existing-Worker reuse, incremental deploy state, and actors — though the engine
65
+ keeps its actor support for the legacy service that still uses it.
66
+
67
+ ## Using it
68
+
69
+ ```ts
70
+ import { bundle, bundleApp } from "@base44/functions-compiler";
71
+
72
+ const result = await bundle({
73
+ entry: "main.ts",
74
+ files: { "main.ts": "export default { fetch: () => new Response('hi') }" },
75
+ });
76
+ if (result.ok) console.log(result.module);
77
+ ```
78
+
79
+ `bundleApp` compiles several functions into one combined module and reports
80
+ per-function status; a successful response can still contain failed functions,
81
+ so a caller that needs a whole-app build must reject those itself.
82
+
83
+ ### Process isolation
84
+
85
+ `installFetchGuard()` blocks outbound `fetch` other than the dependency
86
+ resolution the compiler itself performs. Install it in the worker or child
87
+ process that runs a compile — not in a process that later needs the network.
88
+
89
+ ### Diagnostics
90
+
91
+ The compiler ships no tracer and no service credentials. Hosts that want spans
92
+ or structured logs register their own, in the thread that runs the compile:
93
+
94
+ ```ts
95
+ import { setCompilerTracer, setLogSink } from "@base44/functions-compiler";
96
+
97
+ setCompilerTracer({ withSpan, setSpanTags }); // e.g. a dd-trace adapter
98
+ setLogSink((level, event, fields) => myLogger[level](event, fields));
99
+ ```
100
+
101
+ Without a sink, `logEvent` writes the Datadog-shaped JSON line it always has.
102
+
103
+ ## Layout
104
+
105
+ | Path | What it is |
106
+ |---|---|
107
+ | `src/bundler.ts` | Single-function and combined-app compilation, error attribution |
108
+ | `src/deno-bundle.ts`, `src/esbuild/` | esbuild execution and the resolver/virtual-module plugins |
109
+ | `src/worker-entry.ts`, `src/actor-compat.ts` | Generated worker entry and the Actor wrapper |
110
+ | `src/shim/`, `src/static-egress.ts` | Shim sources — esbuild inputs for `build:shim`, never imported |
111
+ | `src/runtime/`, `src/runtime-context.ts`, `src/private-data-sources/` | Compile-time assets read as **text** and injected into the user bundle |
112
+
113
+ The compile-time assets must stay TypeScript: the virtual plugins load them
114
+ with esbuild's `ts` loader. `scripts/copy-assets.ts` copies them into `lib/`
115
+ next to the compiled JS so the published package resolves them the same way.
116
+
117
+ **Do not reformat an asset.** Their text goes into the user's bundle, so
118
+ whitespace is part of the emitted worker bytes — running Biome over
119
+ `src/shim/`, `src/private-data-sources/`, `src/runtime/`, `runtime-context.ts`,
120
+ `static-egress.ts` or `static-egress-marker.ts` changes what every compiled
121
+ function hashes to. `biome.json` excludes those paths for that reason. The
122
+ `test/` directory is likewise held byte-identical to apper's copy until that
123
+ copy is deleted; it sits outside the repo's `packages/*/src` lint glob.
124
+
125
+ ## Commands
126
+
127
+ ```bash
128
+ bun run build:shim # regenerate dist/{deno-shim,activation-shim,actor}.mjs
129
+ bun run test # vitest (builds the shims first)
130
+ bun run typecheck # tsc --noEmit over src/, test/, scripts/
131
+ bun run build # shims + tsc -> lib/ + assets; what gets published
132
+ ```
133
+
134
+ `exports` points only at `lib/`, so anything consuming this package — including
135
+ a sibling workspace — needs `bun run build` here first. There is deliberately
136
+ no source-resolving export condition: the tarball ships `lib/` alone, and a
137
+ second resolution path would mean two answers to "which code ran".
@@ -0,0 +1,237 @@
1
+ // GENERATED by scripts/build-shim.ts from src/shim/activation.ts — do not edit.
2
+ // Regenerate with `npm run build:shim`.
3
+
4
+ // src/shim/activation.ts
5
+ import { inflateSync } from "node:zlib";
6
+ import { setRuntimeManifest } from "base44:private-data-sources/runtime-manifest-store";
7
+ var NEEDS_ACTIVATION_HEADER = "X-Base44-Needs-Activation";
8
+ var RUNTIME_SECRETS_HEADER = "Base44-Runtime-Secrets";
9
+ var HKDF_INFO = "base44-runtime-secrets-v1";
10
+ var BACKEND_PUBKEY_LEN = 65;
11
+ var NONCE_LEN = 12;
12
+ var DATA_KEY_LEN = 32;
13
+ var WRAP_BLOCK_LEN = NONCE_LEN + DATA_KEY_LEN + 16;
14
+ var BLOB_BINDING_PREFIX = "BASE44_SECRETS_BLOB";
15
+ var BLOB_KEY_ID_LEN = 1;
16
+ var MANIFEST_KEY = "BASE44_PRIVATE_DATA_SOURCES";
17
+ var _subtle = crypto.subtle;
18
+ var _subtleGenerateKey = _subtle.generateKey.bind(_subtle);
19
+ var _subtleExportKey = _subtle.exportKey.bind(_subtle);
20
+ var _subtleImportKey = _subtle.importKey.bind(_subtle);
21
+ var _subtleDeriveBits = _subtle.deriveBits.bind(_subtle);
22
+ var _subtleDecrypt = _subtle.decrypt.bind(_subtle);
23
+ var _JSONparse = JSON.parse;
24
+ var _TextDecoder = TextDecoder;
25
+ var _TextEncoder = TextEncoder;
26
+ var _decodeUtf8 = TextDecoder.prototype.decode;
27
+ var _encodeUtf8 = TextEncoder.prototype.encode;
28
+ var _Uint8Array = Uint8Array;
29
+ var _atob = atob;
30
+ var _btoa = btoa;
31
+ var _DOMException = DOMException;
32
+ var _ObjectEntries = Object.entries;
33
+ var _Headers = Headers;
34
+ var _Request = Request;
35
+ var _Response = Response;
36
+ var _headersGet = Headers.prototype.get;
37
+ var _headersAppend = Headers.prototype.append;
38
+ var _headersEntries = Headers.prototype.entries;
39
+ var _iterNext = Object.getPrototypeOf(new Headers().entries()).next;
40
+ function accessor(proto, name) {
41
+ for (let o = proto; o; o = Object.getPrototypeOf(o)) {
42
+ const d = Object.getOwnPropertyDescriptor(o, name);
43
+ if (d?.get) return d.get;
44
+ }
45
+ return void 0;
46
+ }
47
+ var _reqHeaders = accessor(Request.prototype, "headers");
48
+ var _resHeaders = accessor(Response.prototype, "headers");
49
+ var _resStatus = accessor(Response.prototype, "status");
50
+ var _resStatusText = accessor(Response.prototype, "statusText");
51
+ var _resBody = accessor(Response.prototype, "body");
52
+ var _resWebSocket = accessor(Response.prototype, "webSocket");
53
+ var NEEDS_ACTIVATION_HEADER_LC = "x-base44-needs-activation";
54
+ var RUNTIME_SECRETS_HEADER_LC = "base44-runtime-secrets";
55
+ function headersWithout(src, dropLowercased) {
56
+ const out = new _Headers();
57
+ const it = _headersEntries.call(src);
58
+ for (; ; ) {
59
+ const step = _iterNext.call(it);
60
+ if (step.done) break;
61
+ if (step.value[0] !== dropLowercased) _headersAppend.call(out, step.value[0], step.value[1]);
62
+ }
63
+ return out;
64
+ }
65
+ var keyPairPromise = null;
66
+ var installed = false;
67
+ var pendingInstall = null;
68
+ var installChain = Promise.resolve();
69
+ function getKeyPair() {
70
+ keyPairPromise ??= _subtleGenerateKey(
71
+ { name: "ECDH", namedCurve: "P-256" },
72
+ false,
73
+ ["deriveBits"]
74
+ ).catch((e) => {
75
+ keyPairPromise = null;
76
+ throw e;
77
+ });
78
+ return keyPairPromise;
79
+ }
80
+ async function needsActivationResponse() {
81
+ const { publicKey } = await getKeyPair();
82
+ const raw = await _subtleExportKey("raw", publicKey);
83
+ return new Response(null, {
84
+ status: 503,
85
+ headers: {
86
+ [NEEDS_ACTIVATION_HEADER]: toBase64Url(new _Uint8Array(raw)),
87
+ "Cache-Control": "no-store"
88
+ }
89
+ });
90
+ }
91
+ async function install(envelopeB64, env) {
92
+ const envelope = fromBase64Url(envelopeB64);
93
+ const backendPub = envelope.slice(0, BACKEND_PUBKEY_LEN);
94
+ const recipientCount = envelope[BACKEND_PUBKEY_LEN];
95
+ const { privateKey } = await getKeyPair();
96
+ const peer = await _subtleImportKey(
97
+ "raw",
98
+ backendPub,
99
+ { name: "ECDH", namedCurve: "P-256" },
100
+ false,
101
+ []
102
+ );
103
+ const shared = await _subtleDeriveBits({ name: "ECDH", public: peer }, privateKey, 256);
104
+ const hkdfKey = await _subtleImportKey("raw", shared, "HKDF", false, ["deriveBits"]);
105
+ const keyBits = await _subtleDeriveBits(
106
+ {
107
+ name: "HKDF",
108
+ hash: "SHA-256",
109
+ salt: new _Uint8Array(0),
110
+ info: _encodeUtf8.call(new _TextEncoder(), HKDF_INFO)
111
+ },
112
+ hkdfKey,
113
+ 256
114
+ );
115
+ const kek = await _subtleImportKey("raw", keyBits, "AES-GCM", false, ["decrypt"]);
116
+ const appId = env?.BASE44_APP_ID;
117
+ const aad = _encodeUtf8.call(new _TextEncoder(), typeof appId === "string" ? appId : "");
118
+ let dataKeyBytes = null;
119
+ for (let i = 0; i < recipientCount && dataKeyBytes === null; i++) {
120
+ const blockStart = BACKEND_PUBKEY_LEN + 1 + i * WRAP_BLOCK_LEN;
121
+ const wrapNonce = envelope.slice(blockStart, blockStart + NONCE_LEN);
122
+ const wrapped = envelope.slice(blockStart + NONCE_LEN, blockStart + WRAP_BLOCK_LEN);
123
+ try {
124
+ dataKeyBytes = await _subtleDecrypt(
125
+ { name: "AES-GCM", iv: wrapNonce, additionalData: aad },
126
+ kek,
127
+ wrapped
128
+ );
129
+ } catch {
130
+ }
131
+ }
132
+ if (dataKeyBytes === null) {
133
+ throw new _DOMException("no wrap block for this isolate", "OperationError");
134
+ }
135
+ const bindings = env ?? {};
136
+ let blobB64 = "";
137
+ for (let i = 0; ; i++) {
138
+ const part = bindings[`${BLOB_BINDING_PREFIX}_${i}`];
139
+ if (typeof part !== "string") break;
140
+ blobB64 += part;
141
+ }
142
+ if (blobB64 === "") {
143
+ throw new _DOMException("no secret blob bindings on this script", "OperationError");
144
+ }
145
+ const blob = fromBase64Url(blobB64);
146
+ const blobNonce = blob.slice(BLOB_KEY_ID_LEN, BLOB_KEY_ID_LEN + NONCE_LEN);
147
+ const blobCiphertext = blob.slice(BLOB_KEY_ID_LEN + NONCE_LEN);
148
+ const dataKey = await _subtleImportKey("raw", dataKeyBytes, "AES-GCM", false, ["decrypt"]);
149
+ const plaintext = await _subtleDecrypt(
150
+ { name: "AES-GCM", iv: blobNonce, additionalData: aad },
151
+ dataKey,
152
+ blobCiphertext
153
+ );
154
+ const payload = _JSONparse(
155
+ _decodeUtf8.call(new _TextDecoder(), inflateSync(new _Uint8Array(plaintext)))
156
+ );
157
+ const secrets = payload && typeof payload === "object" && payload.secrets ? payload.secrets : {};
158
+ const manifestValue = secrets[MANIFEST_KEY];
159
+ setRuntimeManifest(typeof manifestValue === "string" ? manifestValue : "");
160
+ for (const [key, value] of _ObjectEntries(secrets)) {
161
+ if (key !== MANIFEST_KEY && typeof value === "string") process.env[key] = value;
162
+ }
163
+ installed = true;
164
+ }
165
+ function installOnce(envelopeB64, env) {
166
+ if (installed) return Promise.resolve();
167
+ const afterPrevious = installChain.then(void 0, () => {
168
+ });
169
+ const run = afterPrevious.then(() => installed ? void 0 : install(envelopeB64, env));
170
+ installChain = run.then(void 0, () => {
171
+ });
172
+ pendingInstall = run;
173
+ const clear = () => {
174
+ if (pendingInstall === run) pendingInstall = null;
175
+ };
176
+ run.then(clear, clear);
177
+ return run;
178
+ }
179
+ async function ensureActivation(request, env) {
180
+ const header = _headersGet.call(_reqHeaders.call(request), RUNTIME_SECRETS_HEADER);
181
+ if (header) {
182
+ try {
183
+ await installOnce(header, env);
184
+ return null;
185
+ } catch (e) {
186
+ console.error(
187
+ `Base44 runtime-secrets activation failed, re-signaling: ${e?.name ?? "error"}`
188
+ );
189
+ return needsActivationResponse();
190
+ }
191
+ }
192
+ if (installed) return null;
193
+ if (pendingInstall) {
194
+ try {
195
+ await pendingInstall;
196
+ } catch {
197
+ }
198
+ if (installed) return null;
199
+ }
200
+ return needsActivationResponse();
201
+ }
202
+ function withoutRuntimeSecretsHeader(request) {
203
+ const raw = _reqHeaders.call(request);
204
+ if (_headersGet.call(raw, RUNTIME_SECRETS_HEADER) === null) return request;
205
+ return new _Request(request, { headers: headersWithout(raw, RUNTIME_SECRETS_HEADER_LC) });
206
+ }
207
+ function withoutActivationSignal(response) {
208
+ const raw = _resHeaders.call(response);
209
+ if (_headersGet.call(raw, NEEDS_ACTIVATION_HEADER) === null) return response;
210
+ return new _Response(_resBody.call(response), {
211
+ status: _resStatus.call(response),
212
+ statusText: _resStatusText.call(response),
213
+ headers: headersWithout(raw, NEEDS_ACTIVATION_HEADER_LC),
214
+ // Preserved or a 101 upgrade would fail to reconstruct.
215
+ webSocket: _resWebSocket ? _resWebSocket.call(response) : void 0
216
+ });
217
+ }
218
+ function toBase64Url(bytes) {
219
+ let bin = "";
220
+ for (const b of bytes) bin += String.fromCharCode(b);
221
+ return _btoa(bin).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
222
+ }
223
+ function fromBase64Url(value) {
224
+ const b64 = value.replace(/-/g, "+").replace(/_/g, "/");
225
+ const padded = b64 + "=".repeat((4 - b64.length % 4) % 4);
226
+ const bin = _atob(padded);
227
+ const bytes = new _Uint8Array(bin.length);
228
+ for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);
229
+ return bytes;
230
+ }
231
+ export {
232
+ NEEDS_ACTIVATION_HEADER,
233
+ RUNTIME_SECRETS_HEADER,
234
+ ensureActivation,
235
+ withoutActivationSignal,
236
+ withoutRuntimeSecretsHeader
237
+ };