@pramen/server 0.0.48 → 0.0.50
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/auth.d.ts +4 -3
- package/dist/cli.js +17 -30
- package/dist/dev.d.ts +1 -0
- package/dist/dev.js +9 -0
- package/dist/durable-object.d.ts +1 -0
- package/dist/durable-object.js +13 -6
- package/dist/index.d.ts +7 -5
- package/dist/index.js +6 -2
- package/dist/pramen.d.ts +4 -2
- package/dist/runtime/acl.d.ts +14 -5
- package/dist/runtime/acl.js +1 -5
- package/dist/runtime/db.d.ts +3 -2
- package/dist/runtime/dev-token.d.ts +4 -0
- package/dist/runtime/dev-token.js +34 -0
- package/dist/runtime/dispatch.d.ts +3 -1
- package/dist/runtime/dispatch.js +2 -0
- package/dist/runtime/driver.d.ts +8 -5
- package/dist/runtime/errors.d.ts +6 -0
- package/dist/runtime/errors.js +8 -0
- package/dist/runtime/mail.d.ts +2 -1
- package/dist/runtime/protocol.d.ts +4 -3
- package/dist/runtime/queue-consumer.d.ts +4 -2
- package/dist/runtime/queue.d.ts +3 -2
- package/dist/runtime/read-engine.d.ts +11 -9
- package/dist/runtime/read-engine.js +4 -1
- package/dist/runtime/registry.d.ts +4 -1
- package/dist/runtime/registry.js +0 -3
- package/dist/runtime/schema-diff.d.ts +6 -6
- package/dist/runtime/schema-diff.js +4 -4
- package/dist/runtime/storage.d.ts +4 -4
- package/dist/runtime/storage.js +8 -63
- package/dist/runtime/token.d.ts +22 -0
- package/dist/runtime/token.js +88 -0
- package/dist/sdk/acl.d.ts +18 -11
- package/dist/sdk/handlers.d.ts +16 -3
- package/dist/sdk/infer.d.ts +17 -0
- package/dist/worker.d.ts +2 -1
- package/dist/worker.js +20 -10
- package/package.json +13 -3
- package/src/auth.ts +7 -6
- package/src/cli.ts +22 -36
- package/src/dev.ts +10 -0
- package/src/durable-object.ts +18 -9
- package/src/index.ts +14 -4
- package/src/pramen.ts +4 -2
- package/src/runtime/acl.ts +45 -31
- package/src/runtime/db.ts +14 -12
- package/src/runtime/dev-token.ts +36 -0
- package/src/runtime/dispatch.ts +7 -3
- package/src/runtime/driver.ts +11 -7
- package/src/runtime/errors.ts +9 -0
- package/src/runtime/mail.ts +2 -1
- package/src/runtime/migrate.ts +2 -1
- package/src/runtime/outbox.ts +2 -1
- package/src/runtime/protocol.ts +5 -3
- package/src/runtime/queue-consumer.ts +4 -2
- package/src/runtime/queue.ts +4 -2
- package/src/runtime/read-engine.ts +27 -21
- package/src/runtime/registry.ts +5 -1
- package/src/runtime/schema-diff.ts +14 -14
- package/src/runtime/storage.ts +14 -62
- package/src/runtime/token.ts +94 -0
- package/src/sdk/acl.ts +29 -14
- package/src/sdk/handlers.ts +17 -3
- package/src/sdk/infer.ts +21 -0
- package/src/worker.ts +24 -11
package/src/worker.ts
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
import { authorizeTenant, HmacStrategy, isAdmin, JwksStrategy, resolveIdentity, type VerifyOptions, type VerifyStrategy } from "./auth";
|
|
8
8
|
import { dispatch, tasksFacade, bindTasks } from "./runtime/dispatch";
|
|
9
|
+
import type { EnvBag } from "./sdk/handlers";
|
|
10
|
+
import type { JsonValue } from "./sdk/infer";
|
|
9
11
|
import { ensureOutbox, drainOutbox, listTasks } from "./runtime/outbox";
|
|
10
12
|
import { createMail } from "./runtime/mail";
|
|
11
13
|
import { createQueue, type QueueProducerBinding } from "./runtime/queue";
|
|
@@ -23,6 +25,11 @@ import type { HandlerContext } from "./sdk/handlers";
|
|
|
23
25
|
import { DEFAULT_PARTITION, partitionsOf } from "./sdk/schema";
|
|
24
26
|
import type { PramenApp } from "./pramen";
|
|
25
27
|
|
|
28
|
+
/** Widen the closed `Env` interface to the open `EnvBag` handlers and services see.
|
|
29
|
+
* Spreading yields an anonymous object type, which TypeScript gives an implicit index
|
|
30
|
+
* signature — so this needs no type assertion. */
|
|
31
|
+
const envBag = (env: Env): EnvBag => ({ ...env });
|
|
32
|
+
|
|
26
33
|
export interface Env {
|
|
27
34
|
PRAMEN: DurableObjectNamespace;
|
|
28
35
|
/** Project KV — tenant registry (`tenant:` keys) + handler ctx.kv (`app:` keys). */
|
|
@@ -149,7 +156,7 @@ function partitionStubFor(env: Env, tenant: string, partition: string = DEFAULT_
|
|
|
149
156
|
* DO's JSON response (`{ ok, result }` / `{ ok: false, … }`). */
|
|
150
157
|
export async function callPrivileged(
|
|
151
158
|
env: Env,
|
|
152
|
-
opts: { name: string; input?:
|
|
159
|
+
opts: { name: string; input?: JsonValue; tenant?: string; roles?: string[]; partition?: string },
|
|
153
160
|
): Promise<Response> {
|
|
154
161
|
const tenant = opts.tenant ?? "main";
|
|
155
162
|
const partition = opts.partition ?? DEFAULT_PARTITION;
|
|
@@ -235,7 +242,10 @@ export function makeWorker(app: PramenApp) {
|
|
|
235
242
|
const files = createFiles({ tenant: "main", secret: filesSecret(env), adapter: new R2Adapter(env.FILES) });
|
|
236
243
|
const db = new Db(driver, { acl: d1Acl, identity, system: true, schema: app.schema, suppressTriggers: true }, app.schema);
|
|
237
244
|
const kv = new Kv(env.KV);
|
|
238
|
-
|
|
245
|
+
const bag = envBag(env);
|
|
246
|
+
// The D1 store is not per-tenant addressed (one shared database, no DO), so the
|
|
247
|
+
// task context runs as the default tenant — matching the `files` scope just above.
|
|
248
|
+
return { db, kv, files, env: bag, identity, tenant: "main", store: "d1", tasks: tasksFacade(driver), mail: createMail(bag, kv), queue: createQueue(bag) };
|
|
239
249
|
};
|
|
240
250
|
|
|
241
251
|
/** Drain the D1 outbox in the Worker (no DO/alarm on this path) — called by the
|
|
@@ -281,7 +291,7 @@ export function makeWorker(app: PramenApp) {
|
|
|
281
291
|
for (const r of app.routes ?? []) {
|
|
282
292
|
if (request.method === r.method && url.pathname === r.path) {
|
|
283
293
|
const routeCtx = { callPrivileged: (opts: Parameters<typeof callPrivileged>[1]) => callPrivileged(env, opts) };
|
|
284
|
-
return r.handler(request, env
|
|
294
|
+
return r.handler(request, envBag(env), routeCtx);
|
|
285
295
|
}
|
|
286
296
|
}
|
|
287
297
|
|
|
@@ -473,8 +483,9 @@ export function makeWorker(app: PramenApp) {
|
|
|
473
483
|
}
|
|
474
484
|
// (isLive is excluded by useD1Store — live always routes to the DO below.)
|
|
475
485
|
const name = url.pathname.replace(/^\/rpc\//, "");
|
|
476
|
-
|
|
477
|
-
|
|
486
|
+
// The RPC body is JSON — parse it into the domain type once, here at the boundary.
|
|
487
|
+
let input: JsonValue = null;
|
|
488
|
+
if (request.method === "POST") input = ((await request.json().catch(() => null)) ?? null) as JsonValue;
|
|
478
489
|
|
|
479
490
|
// Pick where the D1 session may start its first read. A mutation ALWAYS pins the
|
|
480
491
|
// primary (`first-primary` is a superset of read-your-writes) so a read-modify-write
|
|
@@ -489,10 +500,12 @@ export function makeWorker(app: PramenApp) {
|
|
|
489
500
|
|
|
490
501
|
const driver = new D1Driver(env.DB, { start });
|
|
491
502
|
const files = createFiles({ tenant, secret: filesSecret(env), adapter: new R2Adapter(env.FILES) });
|
|
492
|
-
const
|
|
503
|
+
const bag = envBag(env);
|
|
493
504
|
try {
|
|
494
505
|
await ensureD1Migrated(driver, env.PRAMEN_ALLOW_DESTRUCTIVE === "true");
|
|
495
|
-
|
|
506
|
+
// `tenant` matters here: a handler minting a tenant-scoped capability (a signed
|
|
507
|
+
// preview link) would otherwise stamp it "main" while reading acme's rows.
|
|
508
|
+
const { result, enqueued } = await dispatch(app.handlers, app.schema, driver, new Kv(env.KV), files, bag, { acl: d1Acl, identity, tenant, store: "d1" }, name, input);
|
|
496
509
|
// Kick an immediate drain in the request tail when this handler enqueued tasks
|
|
497
510
|
// (e.g. sendMagicLinkEmail). Without this, tasks wait for the next Cron trigger
|
|
498
511
|
// — up to a full minute. `waitUntil` lets the response return now while the
|
|
@@ -567,13 +580,13 @@ export function makeWorker(app: PramenApp) {
|
|
|
567
580
|
// handler (ACK on success / RETRY on throw, per message). A consumer is Worker-level
|
|
568
581
|
// (no tenant DO): its ctx carries env/kv/mail/queue + callPrivileged to reach a DO.
|
|
569
582
|
async queue(batch: QueueBatch, env: Env): Promise<void> {
|
|
570
|
-
const
|
|
583
|
+
const bag = envBag(env);
|
|
571
584
|
const kv = new Kv(env.KV);
|
|
572
585
|
const ctx: QueueContext = {
|
|
573
|
-
env:
|
|
586
|
+
env: bag,
|
|
574
587
|
kv,
|
|
575
|
-
mail: createMail(
|
|
576
|
-
queue: createQueue(
|
|
588
|
+
mail: createMail(bag, kv),
|
|
589
|
+
queue: createQueue(bag),
|
|
577
590
|
callPrivileged: (opts) => callPrivileged(env, opts),
|
|
578
591
|
};
|
|
579
592
|
await dispatchQueueBatch(app.queues ?? {}, ctx, batch);
|