@lunora/runtime 1.0.0-alpha.37 → 1.0.0-alpha.39
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 +359 -8
- package/dist/index.d.ts +359 -8
- package/dist/index.mjs +1 -22
- package/dist/packem_shared/DEFAULT_LOG_COLUMNS-CpZ9kd-q.mjs +1 -0
- package/dist/packem_shared/DEFAULT_REGISTRY_CACHE_TTL_MS-BBf3mNrD.mjs +1 -0
- package/dist/packem_shared/GET_AUTH_AUDIT_LOG_OP-DmxHQbZT.mjs +1 -0
- package/dist/packem_shared/HEALTH_PATH-DiZqjEGp.mjs +1 -0
- package/dist/packem_shared/LOG_ARCHIVE_NOT_CONFIGURED-CDpi4yFD.mjs +1 -0
- package/dist/packem_shared/LOG_ARCHIVE_PATH-e8U3ftfM.mjs +1 -0
- package/dist/packem_shared/LunoraError-C08OP5Uq.mjs +1 -0
- package/dist/packem_shared/NOOP_EXECUTION_CONTEXT-YmXqH-jH.mjs +1 -0
- package/dist/packem_shared/analyticsEngineSink-DOoyBx4o.mjs +1 -0
- package/dist/packem_shared/applyJurisdiction-uRQLx282.mjs +1 -0
- package/dist/packem_shared/argsFromQuery-0KrWTkNx.mjs +1 -0
- package/dist/packem_shared/composeIdentityResolvers-DlBbYmBJ.mjs +1 -0
- package/dist/packem_shared/composeWorker-D7Zi6kZR.mjs +6 -0
- package/dist/packem_shared/createCrossShardRelationCapabilities-B2EKbSEs.mjs +1 -0
- package/dist/packem_shared/createKvCursorStore-C24tEuYk.mjs +3 -0
- package/dist/packem_shared/createQueryCoordinator-DLsrcOkB.mjs +1 -0
- package/dist/packem_shared/createShardClient-62qcYKGl.mjs +1 -0
- package/dist/packem_shared/decorateResponse-C6TZSzID.mjs +1 -0
- package/dist/packem_shared/emitLogEvent-CEbCh6FQ.mjs +1 -0
- package/dist/packem_shared/memoizeIdentity-DRYIK1yT.mjs +1 -0
- package/dist/packem_shared/method-guard-BbuR0VfS.mjs +1 -0
- package/dist/packem_shared/observability-B0MYwNDB.mjs +1 -0
- package/dist/packem_shared/otlp-resource-cAjGEywx.mjs +1 -0
- package/dist/packem_shared/pipeline-log-reader-tDuvc_Ty.mjs +1 -0
- package/dist/packem_shared/toAirbyteMessages-DBTuFjb5.mjs +1 -0
- package/package.json +1 -1
- package/dist/packem_shared/DEFAULT_LOG_COLUMNS-B7H3YdJ3.mjs +0 -2
- package/dist/packem_shared/DEFAULT_REGISTRY_CACHE_TTL_MS-B3pA7aXp.mjs +0 -79
- package/dist/packem_shared/HEALTH_PATH-e5J_NHBx.mjs +0 -150
- package/dist/packem_shared/LOG_ARCHIVE_NOT_CONFIGURED-acNcguqc.mjs +0 -3
- package/dist/packem_shared/LOG_ARCHIVE_PATH-CNs0bznX.mjs +0 -125
- package/dist/packem_shared/LunoraError-Bpb9EFJ3.mjs +0 -22
- package/dist/packem_shared/NOOP_EXECUTION_CONTEXT-CCTu0Bf1.mjs +0 -8
- package/dist/packem_shared/analyticsEngineSink-yLFNjHDt.mjs +0 -429
- package/dist/packem_shared/applyJurisdiction-BkZtTkct.mjs +0 -20
- package/dist/packem_shared/argsFromQuery-c-U1WRy-.mjs +0 -121
- package/dist/packem_shared/composeIdentityResolvers-XGjO7V1J.mjs +0 -55
- package/dist/packem_shared/composeWorker-DiWwOXXt.mjs +0 -3738
- package/dist/packem_shared/createCrossShardRelationCapabilities-CbcWjkAn.mjs +0 -63
- package/dist/packem_shared/createKvCursorStore-g8aA6B4L.mjs +0 -165
- package/dist/packem_shared/createQueryCoordinator-DNCJzOZE.mjs +0 -847
- package/dist/packem_shared/decorateResponse-DRWQFNhF.mjs +0 -273
- package/dist/packem_shared/emitLogEvent-BlGMnKZK.mjs +0 -1
- package/dist/packem_shared/method-guard-Qzw99aCj.mjs +0 -3
- package/dist/packem_shared/observability--NOFYBFc.mjs +0 -47
- package/dist/packem_shared/otlp-resource-Dow6-F_u.mjs +0 -163
- package/dist/packem_shared/pipeline-log-reader-BXULGNC3.mjs +0 -135
- package/dist/packem_shared/toAirbyteMessages-DrHdplb4.mjs +0 -39
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import { m as methodGuard } from './method-guard-Qzw99aCj.mjs';
|
|
2
|
-
|
|
3
|
-
const REST_PATH_PREFIX = "/_lunora/rest";
|
|
4
|
-
const splitFunctionPath = (functionPath) => {
|
|
5
|
-
const colon = functionPath.indexOf(":");
|
|
6
|
-
if (colon <= 0 || colon >= functionPath.length - 1 || functionPath.indexOf(":", colon + 1) !== -1) {
|
|
7
|
-
return void 0;
|
|
8
|
-
}
|
|
9
|
-
return { name: functionPath.slice(colon + 1), namespace: functionPath.slice(0, colon) };
|
|
10
|
-
};
|
|
11
|
-
const restPathForFunction = (functionPath) => {
|
|
12
|
-
const parts = splitFunctionPath(functionPath);
|
|
13
|
-
if (parts === void 0) {
|
|
14
|
-
return void 0;
|
|
15
|
-
}
|
|
16
|
-
return `${REST_PATH_PREFIX}/${parts.namespace}/${parts.name}`;
|
|
17
|
-
};
|
|
18
|
-
const restMethodForKind = (kind) => kind === "query" ? "GET" : "POST";
|
|
19
|
-
const describeRestSurface = (procedures) => {
|
|
20
|
-
const entries = [];
|
|
21
|
-
for (const procedure of procedures) {
|
|
22
|
-
if (procedure.exposure?.rest !== true || procedure.kind === "stream") {
|
|
23
|
-
continue;
|
|
24
|
-
}
|
|
25
|
-
const parts = splitFunctionPath(procedure.functionPath);
|
|
26
|
-
const path = restPathForFunction(procedure.functionPath);
|
|
27
|
-
if (parts === void 0 || path === void 0) {
|
|
28
|
-
continue;
|
|
29
|
-
}
|
|
30
|
-
entries.push({
|
|
31
|
-
functionPath: procedure.functionPath,
|
|
32
|
-
kind: procedure.kind,
|
|
33
|
-
method: restMethodForKind(procedure.kind),
|
|
34
|
-
name: parts.name,
|
|
35
|
-
namespace: parts.namespace,
|
|
36
|
-
path
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
entries.sort((a, b) => a.path.localeCompare(b.path));
|
|
40
|
-
return entries;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
const registryToSurfaceInput = (functions) => Object.entries(functions).map(([functionPath, entry]) => {
|
|
44
|
-
return { exposure: entry.expose, functionPath, kind: entry.kind };
|
|
45
|
-
});
|
|
46
|
-
const restSurfaceFromRegistry = (functions) => describeRestSurface(registryToSurfaceInput(functions));
|
|
47
|
-
const readShardKey = (url, request) => {
|
|
48
|
-
const fromQuery = url.searchParams.get("shardKey");
|
|
49
|
-
if (fromQuery !== null && fromQuery !== "") {
|
|
50
|
-
return fromQuery;
|
|
51
|
-
}
|
|
52
|
-
const fromHeader = request.headers.get("x-lunora-shard-key");
|
|
53
|
-
return fromHeader === null || fromHeader === "" ? void 0 : fromHeader;
|
|
54
|
-
};
|
|
55
|
-
const argsFromQuery = (url) => {
|
|
56
|
-
const args = {};
|
|
57
|
-
for (const [key, value] of url.searchParams.entries()) {
|
|
58
|
-
if (key === "shardKey") {
|
|
59
|
-
continue;
|
|
60
|
-
}
|
|
61
|
-
try {
|
|
62
|
-
args[key] = JSON.parse(value);
|
|
63
|
-
} catch {
|
|
64
|
-
args[key] = value;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
return args;
|
|
68
|
-
};
|
|
69
|
-
const buildRestRoutes = (deps) => {
|
|
70
|
-
const { functions, invoke, rateLimit, readJsonBody } = deps;
|
|
71
|
-
const routes = {};
|
|
72
|
-
for (const entry of restSurfaceFromRegistry(functions)) {
|
|
73
|
-
const allowed = entry.kind === "query" ? ["GET", "POST"] : ["POST"];
|
|
74
|
-
routes[entry.path] = async (request, env, _url, context) => {
|
|
75
|
-
const wrongMethod = methodGuard(request, allowed);
|
|
76
|
-
if (wrongMethod) {
|
|
77
|
-
return wrongMethod;
|
|
78
|
-
}
|
|
79
|
-
const url = new URL(request.url);
|
|
80
|
-
if (rateLimit) {
|
|
81
|
-
const limited = await rateLimit(request, entry.functionPath);
|
|
82
|
-
if (limited) {
|
|
83
|
-
return limited;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
let args;
|
|
87
|
-
if (request.method === "GET") {
|
|
88
|
-
args = argsFromQuery(url);
|
|
89
|
-
} else {
|
|
90
|
-
args = request.body === null ? {} : await readJsonBody(request);
|
|
91
|
-
}
|
|
92
|
-
const shardKey = readShardKey(url, request);
|
|
93
|
-
return invoke({
|
|
94
|
-
args,
|
|
95
|
-
env,
|
|
96
|
-
functionPath: entry.functionPath,
|
|
97
|
-
request,
|
|
98
|
-
...shardKey === void 0 ? {} : { shardKey },
|
|
99
|
-
...context?.waitUntil === void 0 ? {} : { waitUntil: (promise) => context.waitUntil?.(promise) }
|
|
100
|
-
});
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
return routes;
|
|
104
|
-
};
|
|
105
|
-
const createRestRateLimit = (limiter, options) => async (request, functionPath) => {
|
|
106
|
-
const key = options.key ? options.key(request, functionPath) : request.headers.get("cf-connecting-ip") ?? void 0;
|
|
107
|
-
const status = await limiter.limit(options.name, key === void 0 ? {} : { key });
|
|
108
|
-
if (status.ok) {
|
|
109
|
-
return void 0;
|
|
110
|
-
}
|
|
111
|
-
const retryAfterSeconds = Math.max(1, Math.ceil(status.retryAfter / 1e3));
|
|
112
|
-
return Response.json(
|
|
113
|
-
{ error: { code: "RATE_LIMITED", message: "Rate limit exceeded" } },
|
|
114
|
-
{
|
|
115
|
-
headers: { "content-type": "application/json", "retry-after": String(retryAfterSeconds) },
|
|
116
|
-
status: 429
|
|
117
|
-
}
|
|
118
|
-
);
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
export { argsFromQuery, buildRestRoutes, createRestRateLimit, readShardKey, restSurfaceFromRegistry };
|
|
@@ -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 };
|