@lunora/runtime 1.0.0-alpha.17 → 1.0.0-alpha.170

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 (55) hide show
  1. package/LICENSE.md +126 -0
  2. package/README.md +59 -0
  3. package/dist/index.d.mts +4398 -1542
  4. package/dist/index.d.ts +4398 -1542
  5. package/dist/index.mjs +1 -16
  6. package/dist/packem_shared/BACKUP_KEY_PREFIX-BOtSu-_3.mjs +1 -0
  7. package/dist/packem_shared/DEFAULT_LOG_COLUMNS-gYMhXLzO.mjs +1 -0
  8. package/dist/packem_shared/DEFAULT_REGISTRY_CACHE_TTL_MS-BSKqUsWS.mjs +1 -0
  9. package/dist/packem_shared/HEALTH_PATH-D0i8LhwT.mjs +1 -0
  10. package/dist/packem_shared/LOG_ARCHIVE_NOT_CONFIGURED-CDpi4yFD.mjs +1 -0
  11. package/dist/packem_shared/LOG_ARCHIVE_PATH-Hmjpz_Ko.mjs +1 -0
  12. package/dist/packem_shared/LunoraError-DksAgIpa.mjs +1 -0
  13. package/dist/packem_shared/NOOP_EXECUTION_CONTEXT-YmXqH-jH.mjs +1 -0
  14. package/dist/packem_shared/STORAGE_UPLOAD_MAX_BODY_BYTES-BIiV5kqV.mjs +1 -0
  15. package/dist/packem_shared/analyticsEngineSink-BlkElAL2.mjs +1 -0
  16. package/dist/packem_shared/applyJurisdiction-C0ddU7Tg.mjs +1 -0
  17. package/dist/packem_shared/applyRestCache-CEcBz3qq.mjs +1 -0
  18. package/dist/packem_shared/argsFromQuery-CGTSmiBb.mjs +1 -0
  19. package/dist/packem_shared/base64-Bl1_r2k1.mjs +1 -0
  20. package/dist/packem_shared/composeIdentityResolvers-BHZ4jH8o.mjs +1 -0
  21. package/dist/packem_shared/composeWorker-0rWJ3MHB.mjs +6 -0
  22. package/dist/packem_shared/createCrossShardRelationCapabilities-BiXSW10v.mjs +1 -0
  23. package/dist/packem_shared/createKvCursorStore-DQXTTD0l.mjs +1 -0
  24. package/dist/packem_shared/createQueryCoordinator-BkZPoV26.mjs +1 -0
  25. package/dist/packem_shared/createShardClient-BrzRLSs9.mjs +1 -0
  26. package/dist/packem_shared/declareAppJurisdiction-DEba2p42.mjs +1 -0
  27. package/dist/packem_shared/decorateResponse-CRrFNW1v.mjs +1 -0
  28. package/dist/packem_shared/emitLogEvent-C4keuLS-.mjs +1 -0
  29. package/dist/packem_shared/evict-oldest-BNXsKx4s.mjs +1 -0
  30. package/dist/packem_shared/export-tap-CAyZ2TWC.mjs +3 -0
  31. package/dist/packem_shared/identity-header-pR617HTs.mjs +1 -0
  32. package/dist/packem_shared/memoizeIdentity-DnOj3QRi.mjs +1 -0
  33. package/dist/packem_shared/method-guard-BG_vJNTl.mjs +1 -0
  34. package/dist/packem_shared/observability-DgurIZIR.mjs +1 -0
  35. package/dist/packem_shared/origin-paywall-B6eOO67m.mjs +1 -0
  36. package/dist/packem_shared/otlp-resource-BI3MvjSy.mjs +1 -0
  37. package/dist/packem_shared/pipeline-log-reader-C-nuWG_e.mjs +1 -0
  38. package/dist/packem_shared/portable-json-BSCiOfqE.mjs +1 -0
  39. package/dist/packem_shared/rest-cache-CmHN871W.mjs +1 -0
  40. package/dist/packem_shared/rest-routes-D3ShCTHh.mjs +1 -0
  41. package/dist/packem_shared/toAirbyteMessages-2d_iJXPf.mjs +1 -0
  42. package/dist/packem_shared/wire-codec-BLvSm5Mn.mjs +1 -0
  43. package/package.json +9 -2
  44. package/dist/packem_shared/DEFAULT_REGISTRY_CACHE_TTL_MS-B3pA7aXp.mjs +0 -79
  45. package/dist/packem_shared/LunoraError-Bpb9EFJ3.mjs +0 -22
  46. package/dist/packem_shared/NOOP_EXECUTION_CONTEXT-CCTu0Bf1.mjs +0 -8
  47. package/dist/packem_shared/analyticsEngineSink-DqEvrQs0.mjs +0 -141
  48. package/dist/packem_shared/applyJurisdiction-BkZtTkct.mjs +0 -20
  49. package/dist/packem_shared/composeIdentityResolvers-XGjO7V1J.mjs +0 -55
  50. package/dist/packem_shared/composeWorker-DU8vDrgA.mjs +0 -2924
  51. package/dist/packem_shared/createCrossShardRelationCapabilities-CbcWjkAn.mjs +0 -63
  52. package/dist/packem_shared/createQueryCoordinator-DNCJzOZE.mjs +0 -847
  53. package/dist/packem_shared/decorateResponse-CsZc49QC.mjs +0 -266
  54. package/dist/packem_shared/emitLogEvent-pEdtqAK8.mjs +0 -20
  55. package/dist/packem_shared/toAirbyteMessages-DrHdplb4.mjs +0 -39
@@ -0,0 +1 @@
1
+ import{a as d,b as E}from"./base64-Bl1_r2k1.mjs";const o="$lunora.wire$",w=64,p=1024,g="__proto__",l={BigInt64Array,BigUint64Array,Float32Array,Float64Array,Int8Array,Int16Array,Int32Array,Uint8Array,Uint8ClampedArray,Uint16Array,Uint32Array},A={Error,EvalError,RangeError,ReferenceError,SyntaxError,TypeError,URIError},O=e=>{if(e===null||typeof e!="object")return!1;const n=Object.getPrototypeOf(e);return n===null||n===Object.prototype},u=(e,n=0)=>{if(n>w)throw new RangeError(`wire-codec: value nesting exceeds the ${w}-level limit`);if(e===void 0)return[o,"undefined"];if(e===null)return null;const b=typeof e;if(b==="bigint")return[o,"bigint",e.toString()];if(b==="number"){const r=e;return Number.isNaN(r)?[o,"nan"]:r===1/0?[o,"inf"]:r===-1/0?[o,"-inf"]:r}if(b!=="object")return e;if(e instanceof Date)return[o,"date",u(e.getTime(),n+1)];if(e instanceof Error){const r=e,t={};for(const i of Object.keys(r)){if(r[i]===void 0)continue;const y=u(r[i],n+1);i===g?Object.defineProperty(t,i,{configurable:!0,enumerable:!0,value:y,writable:!0}):t[i]=y}const s=[o,"error",String(r.name),String(r.message),t];return r.cause!==void 0&&s.push(u(r.cause,n+1)),s}if(e instanceof URL)return[o,"url",e.href];if(e instanceof Map)return[o,"map",[...e.entries()].map(([r,t])=>[u(r,n+1),u(t,n+1)])];if(e instanceof Set)return[o,"set",[...e].map(r=>u(r,n+1))];if(e instanceof ArrayBuffer)return[o,"bytes",d(new Uint8Array(e)),"ArrayBuffer"];if(ArrayBuffer.isView(e)){const r=e,t=r.constructor.name,s=new Uint8Array(r.buffer,r.byteOffset,r.byteLength);return t==="Uint8Array"?[o,"bytes",d(s)]:[o,"bytes",d(s),t]}if(Array.isArray(e)){const r=e.map(t=>u(t,n+1));return r.length>0&&r[0]===o?[o,"arr",r]:r}if(!O(e)){const r=e.constructor?.name??"value";throw new TypeError(`wire-codec: cannot encode a ${r} over the Lunora wire — only plain objects, arrays, and the supported built-ins (Date, Error, URL, Map, Set, ArrayBuffer/typed arrays, bigint) round-trip`)}const c=e,a={};for(const r of Object.keys(c)){const t=c[r];if(t===void 0)continue;const s=u(t,n+1);r===g?Object.defineProperty(a,r,{configurable:!0,enumerable:!0,value:s,writable:!0}):a[r]=s}return a},f=(e,n=0)=>{if(n>w)throw new RangeError(`wire-codec: value nesting exceeds the ${w}-level limit`);if(e===null||typeof e!="object")return e;if(Array.isArray(e)){if(e[0]===o)switch(e[1]){case"-inf":return-1/0;case"arr":return e[2].map(r=>f(r,n+1));case"bigint":{const r=e[2];if(typeof r!="string"||r.length>p||!/^-?\d+$/.test(r))throw new RangeError(`wire-codec: invalid or over-long bigint (max ${p} digits)`);return BigInt(r)}case"date":{const r=f(e[2],n+1);if(typeof r!="number")throw new TypeError("wire-codec: malformed date — epoch must be a number");return new Date(r)}case"map":{const r=e[2];return new Map(r.map(t=>{if(!Array.isArray(t)||t.length!==2)throw new TypeError("wire-codec: malformed map entry — expected a [key, value] pair");return[f(t[0],n+1),f(t[1],n+1)]}))}case"set":return new Set(e[2].map(r=>f(r,n+1)));case"url":{const r=e[2];if(typeof r!="string")throw new TypeError("wire-codec: malformed url — href must be a string");return new URL(r)}case"error":{const r=e[2],t=e[3];if(typeof r!="string"||typeof t!="string")throw new TypeError("wire-codec: malformed error — name and message must be strings");const s=(Object.hasOwn(A,r)?A[r]:void 0)??Error,i=new s(t);i.name!==r&&Object.defineProperty(i,"name",{configurable:!0,value:r,writable:!0});const y=f(e[4],n+1);if(y===null||typeof y!="object"||Array.isArray(y))throw new TypeError("wire-codec: malformed error — props must be an object");for(const m of Object.keys(y))m===g?Object.defineProperty(i,m,{configurable:!0,enumerable:!0,value:y[m],writable:!0}):i[m]=y[m];return e.length>5&&Object.defineProperty(i,"cause",{configurable:!0,value:f(e[5],n+1),writable:!0}),i}case"bytes":{const r=e[2];if(typeof r!="string")throw new TypeError("wire-codec: malformed bytes — payload must be a base64 string");const t=E(r);if(d(t)!==r)throw new TypeError("wire-codec: malformed bytes — payload must be canonical padded base64");const s=e[3]??"Uint8Array";if(s==="ArrayBuffer")return t.buffer.byteLength===t.byteLength?t.buffer:t.slice().buffer;const i=Object.hasOwn(l,s)?l[s]:void 0;return i?new i(t.slice().buffer):t}case"inf":return 1/0;case"nan":return Number.NaN;case"undefined":return;default:return e.map(r=>f(r,n+1))}return e.map(a=>f(a,n+1))}const b=e,c={};for(const a of Object.keys(b)){const r=f(b[a],n+1);a===g?Object.defineProperty(c,a,{configurable:!0,enumerable:!0,value:r,writable:!0}):c[a]=r}return c},T=(e,n,b)=>{try{return u(b)}catch(c){throw new TypeError(`${e}: cannot encode args for '${n}' — ${c instanceof Error?c.message:String(c)}`,c instanceof Error?{cause:c}:void 0)}};export{T as a,f as d,u as e,O as i};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/runtime",
3
- "version": "1.0.0-alpha.17",
3
+ "version": "1.0.0-alpha.170",
4
4
  "description": "Lunora Worker runtime: the RPC router, shard resolver, and query coordinator",
5
5
  "keywords": [
6
6
  "cloudflare",
@@ -46,7 +46,14 @@
46
46
  "access": "public"
47
47
  },
48
48
  "dependencies": {
49
- "@lunora/errors": "1.0.0-alpha.1"
49
+ "@lunora/bindings": "1.0.0-alpha.90",
50
+ "@lunora/errors": "1.0.0-alpha.48",
51
+ "@lunora/observability": "1.0.0-alpha.114",
52
+ "@lunora/platform": "1.0.0-alpha.49"
53
+ },
54
+ "peerDependencies": {
55
+ "@lunora/shard-engine": ">=1.0.0-alpha.24 <2.0.0-0",
56
+ "@lunora/workflow": ">=1.0.0-alpha.24 <2.0.0-0"
50
57
  },
51
58
  "engines": {
52
59
  "node": "^22.15.0 || >=24.11.0"
@@ -1,79 +0,0 @@
1
- import { LunoraError } from './LunoraError-Bpb9EFJ3.mjs';
2
- import { applyJurisdiction } from './applyJurisdiction-BkZtTkct.mjs';
3
-
4
- const SHARD_REGISTRY_DO_NAME = "__lunora_shard_registry__";
5
- const DEFAULT_REGISTRY_CACHE_TTL_MS = 3e4;
6
- const REGISTRY_BASE_URL = "https://shard-registry.internal";
7
- const decodeJson = async (response) => (
8
- // Response.json() throws on non-JSON; the DO always returns JSON so this
9
- // only surfaces if the DO route is misbehaving — let it bubble.
10
- await response.json()
11
- );
12
- const createDynamicShardRegistry = (options) => {
13
- const instanceName = options.instanceName ?? SHARD_REGISTRY_DO_NAME;
14
- const cacheTtlMs = options.cacheTtlMs ?? DEFAULT_REGISTRY_CACHE_TTL_MS;
15
- const cache = /* @__PURE__ */ new Map();
16
- const namespace = applyJurisdiction(options.namespace, options.jurisdiction);
17
- let cachedStub;
18
- const stub = () => {
19
- cachedStub ??= namespace.get(namespace.idFromName(instanceName));
20
- return cachedStub;
21
- };
22
- const post = async (path, body) => stub().fetch(
23
- new Request(`${REGISTRY_BASE_URL}${path}`, {
24
- body: JSON.stringify(body),
25
- headers: { "content-type": "application/json" },
26
- method: "POST"
27
- })
28
- );
29
- const get = async (path) => stub().fetch(new Request(`${REGISTRY_BASE_URL}${path}`, { method: "GET" }));
30
- return {
31
- invalidate(table) {
32
- if (table === void 0) {
33
- cache.clear();
34
- } else {
35
- cache.delete(table);
36
- }
37
- },
38
- async listShardKeys(table) {
39
- const now = Date.now();
40
- const cached = cache.get(table);
41
- if (cached && cached.expiresAt > now) {
42
- return cached.shardKeys;
43
- }
44
- const response = await get(`/list?table=${encodeURIComponent(table)}`);
45
- if (!response.ok) {
46
- throw new LunoraError(`shard registry /list returned ${String(response.status)}`);
47
- }
48
- const { shardKeys } = await decodeJson(response);
49
- if (cacheTtlMs > 0) {
50
- cache.set(table, { expiresAt: now + cacheTtlMs, shardKeys });
51
- }
52
- return shardKeys;
53
- },
54
- async register(table, shardKey) {
55
- const response = await post("/register", { shardKey, table });
56
- if (!response.ok) {
57
- throw new LunoraError(`shard registry /register returned ${String(response.status)}`);
58
- }
59
- cache.delete(table);
60
- },
61
- async snapshot() {
62
- const response = await get("/snapshot");
63
- if (!response.ok) {
64
- throw new LunoraError(`shard registry /snapshot returned ${String(response.status)}`);
65
- }
66
- const { tables } = await decodeJson(response);
67
- return tables;
68
- },
69
- async unregister(table, shardKey) {
70
- const response = await post("/unregister", { shardKey, table });
71
- if (!response.ok) {
72
- throw new LunoraError(`shard registry /unregister returned ${String(response.status)}`);
73
- }
74
- cache.delete(table);
75
- }
76
- };
77
- };
78
-
79
- export { DEFAULT_REGISTRY_CACHE_TTL_MS, SHARD_REGISTRY_DO_NAME, createDynamicShardRegistry };
@@ -1,22 +0,0 @@
1
- import { LunoraError as LunoraError$1, toErrorBody } from '@lunora/errors';
2
-
3
- const toErrorResponse = (error) => {
4
- const { body, redacted, status } = toErrorBody(error, { fallbackCode: "INTERNAL", redactedMessage: "Internal error" });
5
- if (redacted) {
6
- console.error("[lunora] internal error:", error);
7
- }
8
- return Response.json({ error: body }, {
9
- headers: { "content-type": "application/json" },
10
- status
11
- });
12
- };
13
- class LunoraError extends LunoraError$1 {
14
- constructor(message, options) {
15
- super(options?.code ?? "INTERNAL", message, { cause: options?.cause, status: options?.status });
16
- }
17
- toResponse() {
18
- return toErrorResponse(this);
19
- }
20
- }
21
-
22
- export { LunoraError, toErrorResponse };
@@ -1,8 +0,0 @@
1
- const NOOP_EXECUTION_CONTEXT = {
2
- passThroughOnException: () => {
3
- },
4
- waitUntil: () => {
5
- }
6
- };
7
-
8
- export { NOOP_EXECUTION_CONTEXT };
@@ -1,141 +0,0 @@
1
- const shouldSkip = (event, onlyErrors) => onlyErrors === true && event.ok;
2
- const mergeHeaders = (defaults, overrides) => {
3
- if (!overrides) {
4
- return { ...defaults };
5
- }
6
- const merged = {};
7
- const seen = /* @__PURE__ */ new Map();
8
- for (const [name, value] of Object.entries(defaults)) {
9
- const lower = name.toLowerCase();
10
- seen.set(lower, name);
11
- merged[name] = value;
12
- }
13
- for (const [name, value] of Object.entries(overrides)) {
14
- const lower = name.toLowerCase();
15
- const existing = seen.get(lower);
16
- if (existing === void 0) {
17
- seen.set(lower, name);
18
- merged[name] = value;
19
- } else {
20
- merged[existing] = value;
21
- }
22
- }
23
- return merged;
24
- };
25
- const consoleSink = (options = {}) => {
26
- const { onlyErrors } = options;
27
- return {
28
- onLog: (event) => {
29
- if (event.level === "error") {
30
- console.error("[lunora:log]", event.functionPath, event.message);
31
- } else {
32
- console.log("[lunora:log]", event.functionPath, event.message);
33
- }
34
- },
35
- onRpc: (event) => {
36
- if (shouldSkip(event, onlyErrors)) {
37
- return;
38
- }
39
- if (event.ok) {
40
- console.log("[lunora:rpc]", event);
41
- } else {
42
- console.error("[lunora:rpc]", event);
43
- }
44
- }
45
- };
46
- };
47
- const webhookSink = (options) => {
48
- const { headers, onlyErrors, transform, url } = options;
49
- const mergedHeaders = mergeHeaders({ "content-type": "application/json" }, headers);
50
- return {
51
- onRpc: (event, context) => {
52
- if (shouldSkip(event, onlyErrors)) {
53
- return;
54
- }
55
- try {
56
- let payload = event;
57
- if (transform) {
58
- try {
59
- payload = transform(event);
60
- } catch {
61
- return;
62
- }
63
- }
64
- if (payload === null || payload === void 0) {
65
- return;
66
- }
67
- const sent = fetch(url, {
68
- body: JSON.stringify(payload),
69
- headers: mergedHeaders,
70
- method: "POST"
71
- }).catch(() => {
72
- });
73
- if (context?.waitUntil) {
74
- context.waitUntil(sent);
75
- }
76
- } catch {
77
- }
78
- }
79
- };
80
- };
81
- const sentrySink = (options) => {
82
- const { capture } = options;
83
- const onlyErrors = options.onlyErrors ?? true;
84
- return {
85
- onRpc: (event) => {
86
- if (shouldSkip(event, onlyErrors)) {
87
- return;
88
- }
89
- try {
90
- capture(event);
91
- } catch {
92
- }
93
- }
94
- };
95
- };
96
- const analyticsEngineSink = (options) => {
97
- const { dataset, onlyErrors } = options;
98
- return {
99
- onRpc: (event) => {
100
- if (shouldSkip(event, onlyErrors)) {
101
- return;
102
- }
103
- try {
104
- dataset.writeDataPoint({
105
- blobs: [event.functionPath, event.ok ? "ok" : "error", event.shardKey ?? "", event.error?.code ?? "", event.fanOut?.table ?? ""],
106
- doubles: [event.durationMs, event.ok ? 0 : 1, event.fanOut?.shards ?? 0, event.fanOut?.failed ?? 0],
107
- indexes: [event.functionPath]
108
- });
109
- } catch {
110
- }
111
- }
112
- };
113
- };
114
- const combineSinks = (...sinks) => {
115
- return {
116
- onLog: (event, context) => {
117
- for (const sink of sinks) {
118
- if (!sink.onLog) {
119
- continue;
120
- }
121
- try {
122
- sink.onLog(event, context);
123
- } catch {
124
- }
125
- }
126
- },
127
- onRpc: (event, context) => {
128
- for (const sink of sinks) {
129
- if (!sink.onRpc) {
130
- continue;
131
- }
132
- try {
133
- sink.onRpc(event, context);
134
- } catch {
135
- }
136
- }
137
- }
138
- };
139
- };
140
-
141
- export { analyticsEngineSink, combineSinks, consoleSink, sentrySink, webhookSink };
@@ -1,20 +0,0 @@
1
- const applyJurisdiction = (namespace, jurisdiction) => {
2
- if (jurisdiction === void 0) {
3
- return namespace;
4
- }
5
- if (typeof namespace.jurisdiction !== "function") {
6
- throw new TypeError(
7
- `@lunora/runtime: Durable Object namespace does not support jurisdiction("${jurisdiction}") — update @cloudflare/workers-types or remove the jurisdiction option`
8
- );
9
- }
10
- return namespace.jurisdiction(jurisdiction);
11
- };
12
- const resolveShard = (namespace, shardKey) => {
13
- if (typeof namespace.getByName === "function") {
14
- return namespace.getByName(shardKey);
15
- }
16
- const id = namespace.idFromName(shardKey);
17
- return namespace.get(id);
18
- };
19
-
20
- export { applyJurisdiction, resolveShard };
@@ -1,55 +0,0 @@
1
- import { LunoraError } from './LunoraError-Bpb9EFJ3.mjs';
2
-
3
- const composeIdentityResolvers = (resolvers, options = {}) => {
4
- const onError = options.onError ?? "fail-closed";
5
- return async (request, env) => {
6
- for (const resolver of resolvers) {
7
- let resolved;
8
- try {
9
- resolved = await resolver(request, env);
10
- } catch (error) {
11
- if (onError === "skip") {
12
- continue;
13
- }
14
- throw error;
15
- }
16
- if (resolved) {
17
- return resolved;
18
- }
19
- }
20
- return null;
21
- };
22
- };
23
- const routeIdentityResolvers = (routes) => {
24
- const prefixes = Object.keys(routes).filter((key) => key !== "*").toSorted((a, b) => b.length - a.length);
25
- return (request, env) => {
26
- const { pathname } = new URL(request.url);
27
- const matched = prefixes.find((prefix) => pathname === prefix || pathname.startsWith(prefix.endsWith("/") ? prefix : `${prefix}/`));
28
- const resolver = matched === void 0 ? routes["*"] : routes[matched];
29
- if (resolver === void 0) {
30
- return null;
31
- }
32
- return resolver(request, env);
33
- };
34
- };
35
- const wrapResolverWithContract = (baseResolveIdentity, contract) => {
36
- if (contract === void 0 || baseResolveIdentity === void 0) {
37
- return baseResolveIdentity;
38
- }
39
- return async (request, env) => {
40
- const resolved = await baseResolveIdentity(request, env);
41
- if (!resolved) {
42
- return resolved;
43
- }
44
- const result = contract.validate(resolved);
45
- if (result.ok) {
46
- return resolved;
47
- }
48
- if (contract.onInvalid === "reject") {
49
- throw new LunoraError(`identity claims failed the declared contract: ${result.error}`, { code: "UNAUTHENTICATED", status: 401 });
50
- }
51
- return null;
52
- };
53
- };
54
-
55
- export { composeIdentityResolvers, routeIdentityResolvers, wrapResolverWithContract };