@lunora/runtime 1.0.0-alpha.6 → 1.0.0-alpha.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.
package/dist/index.d.mts
CHANGED
|
@@ -110,6 +110,38 @@ declare const toFivetranResponse: (page: ConnectorSyncPage, primaryKey?: Record<
|
|
|
110
110
|
* @param emittedAt epoch-ms stamped on each `RECORD` (default `Date.now()`).
|
|
111
111
|
*/
|
|
112
112
|
declare const toAirbyteMessages: (page: ConnectorSyncPage, emittedAt?: number) => AirbyteMessage[];
|
|
113
|
+
/**
|
|
114
|
+
* The subset of the Cloudflare `ExecutionContext` the Lunora worker entry and
|
|
115
|
+
* the framework mount seams rely on — `waitUntil` for fire-and-forget work that
|
|
116
|
+
* must outlive the response, and `passThroughOnException` for the top-level
|
|
117
|
+
* error posture.
|
|
118
|
+
*
|
|
119
|
+
* It is deliberately **not** a package. `@lunora/runtime` is the leaf server
|
|
120
|
+
* runtime and `@lunora/nuxt` is a framework integration that intentionally does
|
|
121
|
+
* not depend on `@lunora/runtime`'s worker types, yet both need this exact
|
|
122
|
+
* shape: the runtime to build/forward the worker `fetch`, Nuxt to forward an
|
|
123
|
+
* inbound request to the user's composed worker. Each imports this file by
|
|
124
|
+
* relative path and the bundler (packem/rollup) inlines it: no runtime
|
|
125
|
+
* dependency edge is created, the helper is duplicated only in emitted output,
|
|
126
|
+
* never in source. One source of truth, zero deps. See AGENTS.md → "Top-level
|
|
127
|
+
* `shared/` — bundler-inlined source".
|
|
128
|
+
*
|
|
129
|
+
* Both methods are **optional**: a real Cloudflare `ExecutionContext` always
|
|
130
|
+
* supplies them, but a host that mounts Lunora as a sub-handler (Nitro/H3, a
|
|
131
|
+
* non-Cloudflare preview, a unit test) may hand over a partial context or none
|
|
132
|
+
* at all. Callers therefore invoke them defensively (`ctx.waitUntil?.(…)`) or
|
|
133
|
+
* fall back to {@link NOOP_EXECUTION_CONTEXT}.
|
|
134
|
+
*/
|
|
135
|
+
interface ExecutionContextLike {
|
|
136
|
+
passThroughOnException?: () => void;
|
|
137
|
+
waitUntil?: (promise: Promise<unknown>) => void;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* No-op `ExecutionContext` used when the host runtime didn't supply one (a
|
|
141
|
+
* non-Cloudflare preview, or a unit test), so the worker's `fetch` always
|
|
142
|
+
* receives a valid third argument.
|
|
143
|
+
*/
|
|
144
|
+
declare const NOOP_EXECUTION_CONTEXT: ExecutionContextLike;
|
|
113
145
|
/** A timestamp as better-auth stores it: epoch-ms, an ISO string, or absent. */
|
|
114
146
|
type AuthTimestamp = null | number | string;
|
|
115
147
|
/**
|
|
@@ -1157,10 +1189,6 @@ interface RpcEnvelope {
|
|
|
1157
1189
|
functionPath: string;
|
|
1158
1190
|
shardKey?: string;
|
|
1159
1191
|
}
|
|
1160
|
-
interface ExecutionContextLike {
|
|
1161
|
-
passThroughOnException: () => void;
|
|
1162
|
-
waitUntil: (promise: Promise<unknown>) => void;
|
|
1163
|
-
}
|
|
1164
1192
|
type Route = (request: Request, env: unknown, context: ExecutionContextLike) => Promise<Response> | Response;
|
|
1165
1193
|
/**
|
|
1166
1194
|
* Context handed to HTTP-action handlers. Built per request by the worker; its
|
|
@@ -2095,12 +2123,6 @@ declare const withFrameworkWorker: (host: FrameworkHostHandler, optionsInput: Fr
|
|
|
2095
2123
|
*/
|
|
2096
2124
|
type LunoraHandlerOptions = ((env: unknown) => FrameworkWorkerOptions) | Partial<FrameworkWorkerOptions>;
|
|
2097
2125
|
/**
|
|
2098
|
-
* No-op `ExecutionContext` used when the host runtime didn't supply one (a
|
|
2099
|
-
* non-Cloudflare preview, or a unit test), so the worker's `fetch` always
|
|
2100
|
-
* receives a valid third argument.
|
|
2101
|
-
*/
|
|
2102
|
-
declare const NOOP_EXECUTION_CONTEXT: ExecutionContextLike;
|
|
2103
|
-
/**
|
|
2104
2126
|
* Resolve per-request Lunora worker options. A factory is called with the
|
|
2105
2127
|
* request `env`; a partial object has its `shardDO` defaulted to `env.SHARD` so
|
|
2106
2128
|
* the common case needs no configuration. Throws a clear error when no shard
|
package/dist/index.d.ts
CHANGED
|
@@ -110,6 +110,38 @@ declare const toFivetranResponse: (page: ConnectorSyncPage, primaryKey?: Record<
|
|
|
110
110
|
* @param emittedAt epoch-ms stamped on each `RECORD` (default `Date.now()`).
|
|
111
111
|
*/
|
|
112
112
|
declare const toAirbyteMessages: (page: ConnectorSyncPage, emittedAt?: number) => AirbyteMessage[];
|
|
113
|
+
/**
|
|
114
|
+
* The subset of the Cloudflare `ExecutionContext` the Lunora worker entry and
|
|
115
|
+
* the framework mount seams rely on — `waitUntil` for fire-and-forget work that
|
|
116
|
+
* must outlive the response, and `passThroughOnException` for the top-level
|
|
117
|
+
* error posture.
|
|
118
|
+
*
|
|
119
|
+
* It is deliberately **not** a package. `@lunora/runtime` is the leaf server
|
|
120
|
+
* runtime and `@lunora/nuxt` is a framework integration that intentionally does
|
|
121
|
+
* not depend on `@lunora/runtime`'s worker types, yet both need this exact
|
|
122
|
+
* shape: the runtime to build/forward the worker `fetch`, Nuxt to forward an
|
|
123
|
+
* inbound request to the user's composed worker. Each imports this file by
|
|
124
|
+
* relative path and the bundler (packem/rollup) inlines it: no runtime
|
|
125
|
+
* dependency edge is created, the helper is duplicated only in emitted output,
|
|
126
|
+
* never in source. One source of truth, zero deps. See AGENTS.md → "Top-level
|
|
127
|
+
* `shared/` — bundler-inlined source".
|
|
128
|
+
*
|
|
129
|
+
* Both methods are **optional**: a real Cloudflare `ExecutionContext` always
|
|
130
|
+
* supplies them, but a host that mounts Lunora as a sub-handler (Nitro/H3, a
|
|
131
|
+
* non-Cloudflare preview, a unit test) may hand over a partial context or none
|
|
132
|
+
* at all. Callers therefore invoke them defensively (`ctx.waitUntil?.(…)`) or
|
|
133
|
+
* fall back to {@link NOOP_EXECUTION_CONTEXT}.
|
|
134
|
+
*/
|
|
135
|
+
interface ExecutionContextLike {
|
|
136
|
+
passThroughOnException?: () => void;
|
|
137
|
+
waitUntil?: (promise: Promise<unknown>) => void;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* No-op `ExecutionContext` used when the host runtime didn't supply one (a
|
|
141
|
+
* non-Cloudflare preview, or a unit test), so the worker's `fetch` always
|
|
142
|
+
* receives a valid third argument.
|
|
143
|
+
*/
|
|
144
|
+
declare const NOOP_EXECUTION_CONTEXT: ExecutionContextLike;
|
|
113
145
|
/** A timestamp as better-auth stores it: epoch-ms, an ISO string, or absent. */
|
|
114
146
|
type AuthTimestamp = null | number | string;
|
|
115
147
|
/**
|
|
@@ -1157,10 +1189,6 @@ interface RpcEnvelope {
|
|
|
1157
1189
|
functionPath: string;
|
|
1158
1190
|
shardKey?: string;
|
|
1159
1191
|
}
|
|
1160
|
-
interface ExecutionContextLike {
|
|
1161
|
-
passThroughOnException: () => void;
|
|
1162
|
-
waitUntil: (promise: Promise<unknown>) => void;
|
|
1163
|
-
}
|
|
1164
1192
|
type Route = (request: Request, env: unknown, context: ExecutionContextLike) => Promise<Response> | Response;
|
|
1165
1193
|
/**
|
|
1166
1194
|
* Context handed to HTTP-action handlers. Built per request by the worker; its
|
|
@@ -2095,12 +2123,6 @@ declare const withFrameworkWorker: (host: FrameworkHostHandler, optionsInput: Fr
|
|
|
2095
2123
|
*/
|
|
2096
2124
|
type LunoraHandlerOptions = ((env: unknown) => FrameworkWorkerOptions) | Partial<FrameworkWorkerOptions>;
|
|
2097
2125
|
/**
|
|
2098
|
-
* No-op `ExecutionContext` used when the host runtime didn't supply one (a
|
|
2099
|
-
* non-Cloudflare preview, or a unit test), so the worker's `fetch` always
|
|
2100
|
-
* receives a valid third argument.
|
|
2101
|
-
*/
|
|
2102
|
-
declare const NOOP_EXECUTION_CONTEXT: ExecutionContextLike;
|
|
2103
|
-
/**
|
|
2104
2126
|
* Resolve per-request Lunora worker options. A factory is called with the
|
|
2105
2127
|
* request `env`; a partial object has its `shardDO` defaulted to `env.SHARD` so
|
|
2106
2128
|
* the common case needs no configuration. Throws a clear error when no shard
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { toAirbyteMessages, toFivetranResponse } from './packem_shared/toAirbyteMessages-DrHdplb4.mjs';
|
|
2
|
-
export {
|
|
2
|
+
export { composeWorker, createLunoraHandler, createWorker, defineRpcEnvelope, resolveLunoraOptions, withFrameworkWorker } from './packem_shared/composeWorker-Y3uASpzc.mjs';
|
|
3
3
|
export { createCrossShardRelationCapabilities } from './packem_shared/createCrossShardRelationCapabilities-C0KOf7er.mjs';
|
|
4
4
|
export { DEFAULT_REGISTRY_CACHE_TTL_MS, SHARD_REGISTRY_DO_NAME, createDynamicShardRegistry } from './packem_shared/DEFAULT_REGISTRY_CACHE_TTL_MS-ocax8v0n.mjs';
|
|
5
5
|
export { LunoraError, toErrorResponse } from './packem_shared/LunoraError-CL0aOtpo.mjs';
|
|
@@ -8,6 +8,7 @@ export { analyticsEngineSink, combineSinks, consoleSink, sentrySink, webhookSink
|
|
|
8
8
|
export { createQueryCoordinator, createStaticShardRegistry, mergeStrategyForAggregate } from './packem_shared/createQueryCoordinator-Cbds9cUI.mjs';
|
|
9
9
|
export { applyJurisdiction, resolveShard } from './packem_shared/applyJurisdiction-BkZtTkct.mjs';
|
|
10
10
|
export { decorateResponse, enforceOrigin, handleCorsPreflight, resolveSecurity } from './packem_shared/decorateResponse-DbISh_Wi.mjs';
|
|
11
|
+
export { NOOP_EXECUTION_CONTEXT } from './packem_shared/NOOP_EXECUTION_CONTEXT-CCTu0Bf1.mjs';
|
|
11
12
|
|
|
12
13
|
const VERSION = "0.0.0";
|
|
13
14
|
|
package/dist/packem_shared/{NOOP_EXECUTION_CONTEXT-Rns-X7RV.mjs → composeWorker-Y3uASpzc.mjs}
RENAMED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { NOOP_EXECUTION_CONTEXT } from './NOOP_EXECUTION_CONTEXT-CCTu0Bf1.mjs';
|
|
1
2
|
import { LunoraError, toErrorResponse, isStructuralLunoraError, isStructuralConflictError } from './LunoraError-CL0aOtpo.mjs';
|
|
2
3
|
import { emitRpcEvent } from './emitLogEvent-pEdtqAK8.mjs';
|
|
3
4
|
import { resolveShard, applyJurisdiction } from './applyJurisdiction-BkZtTkct.mjs';
|
|
@@ -1502,7 +1503,7 @@ const buildWorkflowsAdminRoutes = (deps) => {
|
|
|
1502
1503
|
assertAdmin(request);
|
|
1503
1504
|
const client = resolveWorkflowsClient(env);
|
|
1504
1505
|
if (!client) {
|
|
1505
|
-
return
|
|
1506
|
+
return Response.json({ configured: false, instances: [], page: 1, perPage: 0, totalCount: 0 });
|
|
1506
1507
|
}
|
|
1507
1508
|
const workflowName = requireQuery(url, "name");
|
|
1508
1509
|
const status = toInstanceStatus(url.searchParams.get("status"));
|
|
@@ -1598,6 +1599,8 @@ const resolveForwardContext = async (request, env, resolveIdentity) => {
|
|
|
1598
1599
|
const cookie = request.headers.get("cookie");
|
|
1599
1600
|
const bookmark = request.headers.get("x-d1-bookmark");
|
|
1600
1601
|
const mutationId = request.headers.get("x-lunora-mutation-id");
|
|
1602
|
+
const clientId = request.headers.get("x-lunora-client-id");
|
|
1603
|
+
const clientSeq = request.headers.get("x-lunora-client-seq");
|
|
1601
1604
|
if (authorization) {
|
|
1602
1605
|
headers["authorization"] = authorization;
|
|
1603
1606
|
}
|
|
@@ -1610,6 +1613,12 @@ const resolveForwardContext = async (request, env, resolveIdentity) => {
|
|
|
1610
1613
|
if (mutationId) {
|
|
1611
1614
|
headers["x-lunora-mutation-id"] = mutationId;
|
|
1612
1615
|
}
|
|
1616
|
+
if (clientId) {
|
|
1617
|
+
headers["x-lunora-client-id"] = clientId;
|
|
1618
|
+
}
|
|
1619
|
+
if (clientSeq) {
|
|
1620
|
+
headers["x-lunora-client-seq"] = clientSeq;
|
|
1621
|
+
}
|
|
1613
1622
|
const clientIp = request.headers.get("cf-connecting-ip");
|
|
1614
1623
|
if (clientIp) {
|
|
1615
1624
|
headers["x-lunora-client-ip"] = clientIp;
|
|
@@ -1662,6 +1671,12 @@ const validateFanOut = (fanOut) => {
|
|
|
1662
1671
|
}
|
|
1663
1672
|
return spec;
|
|
1664
1673
|
};
|
|
1674
|
+
const logRpcDebug = (env, envelope) => {
|
|
1675
|
+
if (!env?.LUNORA_DEBUG_RPC) {
|
|
1676
|
+
return;
|
|
1677
|
+
}
|
|
1678
|
+
console.warn(`[lunora:rpc] ${envelope.fanOut ? "fan-out" : `shard=${envelope.shardKey ?? "(root)"}`} ${envelope.functionPath}`);
|
|
1679
|
+
};
|
|
1665
1680
|
const parseEnvelope = async (request) => {
|
|
1666
1681
|
const text = await readBodyTextWithLimit(request);
|
|
1667
1682
|
let body;
|
|
@@ -2149,6 +2164,7 @@ const createWorker = (options) => {
|
|
|
2149
2164
|
throw new LunoraError("RPC endpoint requires POST", { code: "METHOD_NOT_ALLOWED", status: 405 });
|
|
2150
2165
|
}
|
|
2151
2166
|
const envelope = await parseEnvelope(request);
|
|
2167
|
+
logRpcDebug(env, envelope);
|
|
2152
2168
|
if (envelope.fanOut && envelope.shardKey) {
|
|
2153
2169
|
throw new LunoraError("RPC envelope cannot set both `shardKey` and `fanOut`", { code: "BAD_REQUEST", status: 400 });
|
|
2154
2170
|
}
|
|
@@ -2171,7 +2187,7 @@ const createWorker = (options) => {
|
|
|
2171
2187
|
const { observability } = options;
|
|
2172
2188
|
const sinkContext = context ? {
|
|
2173
2189
|
waitUntil: (promise) => {
|
|
2174
|
-
context.waitUntil(promise);
|
|
2190
|
+
context.waitUntil?.(promise);
|
|
2175
2191
|
}
|
|
2176
2192
|
} : void 0;
|
|
2177
2193
|
if (envelope.fanOut) {
|
|
@@ -2375,7 +2391,7 @@ const createWorker = (options) => {
|
|
|
2375
2391
|
}
|
|
2376
2392
|
const basePath = options.authBasePath ?? DEFAULT_AUTH_BASE_PATH;
|
|
2377
2393
|
if (isAuthAttemptPath(url.pathname, basePath)) {
|
|
2378
|
-
context.waitUntil(recordAuthAttempt(env, authResponse.status >= 400 ? "fail" : "ok"));
|
|
2394
|
+
context.waitUntil?.(recordAuthAttempt(env, authResponse.status >= 400 ? "fail" : "ok"));
|
|
2379
2395
|
}
|
|
2380
2396
|
return authResponse;
|
|
2381
2397
|
};
|
|
@@ -2448,7 +2464,7 @@ const createWorker = (options) => {
|
|
|
2448
2464
|
return {
|
|
2449
2465
|
async fetch(request, env, context) {
|
|
2450
2466
|
if (options.passThroughOnException) {
|
|
2451
|
-
context.passThroughOnException();
|
|
2467
|
+
context.passThroughOnException?.();
|
|
2452
2468
|
}
|
|
2453
2469
|
ensureSecurityResolved(env);
|
|
2454
2470
|
resolveAdminTokenFromEnv(env);
|
|
@@ -2505,12 +2521,6 @@ const withFrameworkWorker = (host, optionsInput) => {
|
|
|
2505
2521
|
serverQuery: (request, env, reference, args, options) => build(optionsFactory(env)).serverQuery(request, env, reference, args, options)
|
|
2506
2522
|
};
|
|
2507
2523
|
};
|
|
2508
|
-
const NOOP_EXECUTION_CONTEXT = {
|
|
2509
|
-
passThroughOnException: () => {
|
|
2510
|
-
},
|
|
2511
|
-
waitUntil: () => {
|
|
2512
|
-
}
|
|
2513
|
-
};
|
|
2514
2524
|
const resolveLunoraOptions = (options, env) => {
|
|
2515
2525
|
if (typeof options === "function") {
|
|
2516
2526
|
return options(env);
|