@beignet/core 0.0.25 → 0.0.27
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/CHANGELOG.md +15 -0
- package/README.md +49 -5
- package/dist/ports/rate-limit.d.ts.map +1 -1
- package/dist/ports/rate-limit.js +12 -0
- package/dist/ports/rate-limit.js.map +1 -1
- package/dist/server/fixtures/run-service-context-script.fixture.d.ts +12 -0
- package/dist/server/fixtures/run-service-context-script.fixture.d.ts.map +1 -0
- package/dist/server/fixtures/run-service-context-script.fixture.js +36 -0
- package/dist/server/fixtures/run-service-context-script.fixture.js.map +1 -0
- package/dist/server/hooks/rate-limit.d.ts +17 -3
- package/dist/server/hooks/rate-limit.d.ts.map +1 -1
- package/dist/server/hooks/rate-limit.js +40 -4
- package/dist/server/hooks/rate-limit.js.map +1 -1
- package/dist/server/http.d.ts +12 -0
- package/dist/server/http.d.ts.map +1 -1
- package/dist/server/request-context.d.ts +9 -0
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/request-context.js +11 -0
- package/dist/server/request-context.js.map +1 -1
- package/dist/server/server.d.ts +19 -0
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +36 -1
- package/dist/server/server.js.map +1 -1
- package/dist/tasks/index.d.ts +22 -0
- package/dist/tasks/index.d.ts.map +1 -1
- package/dist/tasks/index.js.map +1 -1
- package/package.json +1 -1
- package/skills/app-architecture/SKILL.md +13 -3
- package/src/ports/rate-limit.ts +12 -0
- package/src/server/fixtures/run-service-context-script.fixture.ts +45 -0
- package/src/server/hooks/rate-limit.ts +59 -7
- package/src/server/http.ts +10 -0
- package/src/server/request-context.ts +15 -0
- package/src/server/server.ts +68 -0
- package/src/tasks/index.ts +23 -0
package/src/server/server.ts
CHANGED
|
@@ -71,6 +71,7 @@ import {
|
|
|
71
71
|
enterActiveRequestContext,
|
|
72
72
|
readContextActor,
|
|
73
73
|
readContextTenant,
|
|
74
|
+
runWithActiveRequestContext,
|
|
74
75
|
setActiveRequestIdentity,
|
|
75
76
|
} from "./request-context.js";
|
|
76
77
|
import type {
|
|
@@ -428,10 +429,31 @@ export interface ServerInstance<
|
|
|
428
429
|
* tasks, and background work.
|
|
429
430
|
*
|
|
430
431
|
* Requires `context.service` to be declared in `createServer(...)`.
|
|
432
|
+
*
|
|
433
|
+
* Only call this from long-lived runtimes such as servers, workers, and
|
|
434
|
+
* `bun test`. It enters the ambient correlation context with
|
|
435
|
+
* `AsyncLocalStorage.enterWith`, and resuming that frame across top-level
|
|
436
|
+
* await crashes Bun 1.3.x in plain scripts. Seeds and one-off scripts must
|
|
437
|
+
* use `runServiceContext(...)` instead.
|
|
431
438
|
*/
|
|
432
439
|
createServiceContext: (
|
|
433
440
|
...args: ServiceContextInputArgs<ServiceInput>
|
|
434
441
|
) => Promise<Ctx>;
|
|
442
|
+
/**
|
|
443
|
+
* Build a service context and run `fn` inside a scoped ambient correlation
|
|
444
|
+
* frame, returning its result.
|
|
445
|
+
*
|
|
446
|
+
* This is the script-safe counterpart to `createServiceContext(...)`: the
|
|
447
|
+
* ambient frame is entered with `AsyncLocalStorage.run`, so plain scripts
|
|
448
|
+
* such as seeds and one-off maintenance work stay safe under top-level
|
|
449
|
+
* await. Requires `context.service` to be declared in `createServer(...)`.
|
|
450
|
+
*/
|
|
451
|
+
runServiceContext: <T>(
|
|
452
|
+
...args: [
|
|
453
|
+
...ServiceContextInputArgs<ServiceInput>,
|
|
454
|
+
fn: (ctx: Ctx) => T | Promise<T>,
|
|
455
|
+
]
|
|
456
|
+
) => Promise<T>;
|
|
435
457
|
/**
|
|
436
458
|
* Contract configs registered through the `routes` option.
|
|
437
459
|
*/
|
|
@@ -2032,6 +2054,11 @@ export async function createServer<
|
|
|
2032
2054
|
];
|
|
2033
2055
|
const contracts = options.routes ? contractsFromRoutes(options.routes) : [];
|
|
2034
2056
|
|
|
2057
|
+
// Fail startup on hook misconfiguration before provider setup runs.
|
|
2058
|
+
for (const hook of hooks) {
|
|
2059
|
+
hook.validate?.({ contracts });
|
|
2060
|
+
}
|
|
2061
|
+
|
|
2035
2062
|
const resolvedContext = resolveServerContext<Ctx, FinalPorts, ServiceInput>(
|
|
2036
2063
|
options.context,
|
|
2037
2064
|
);
|
|
@@ -2089,6 +2116,46 @@ export async function createServer<
|
|
|
2089
2116
|
ambient.tenant = readContextTenant(ctx);
|
|
2090
2117
|
return ctx;
|
|
2091
2118
|
};
|
|
2119
|
+
const runServiceContext = async <T>(
|
|
2120
|
+
...args: [
|
|
2121
|
+
...ServiceContextInputArgs<ServiceInput>,
|
|
2122
|
+
fn: (ctx: Ctx) => T | Promise<T>,
|
|
2123
|
+
]
|
|
2124
|
+
): Promise<T> => {
|
|
2125
|
+
const serviceFactory = resolvedContext.service;
|
|
2126
|
+
if (!serviceFactory) {
|
|
2127
|
+
throw new Error(
|
|
2128
|
+
"Define context.service in createServer(...) to create service contexts.",
|
|
2129
|
+
);
|
|
2130
|
+
}
|
|
2131
|
+
|
|
2132
|
+
const fn = args[args.length - 1] as (ctx: Ctx) => T | Promise<T>;
|
|
2133
|
+
const input = (args.length > 1 ? args[0] : undefined) as ServiceInput;
|
|
2134
|
+
const { requestId, trace } = instrumentation.createServiceCorrelation();
|
|
2135
|
+
const ambient: ActiveRequestContext = {
|
|
2136
|
+
requestId,
|
|
2137
|
+
traceId: trace.traceId,
|
|
2138
|
+
spanId: trace.spanId,
|
|
2139
|
+
parentSpanId: trace.parentSpanId,
|
|
2140
|
+
traceparent: trace.traceparent,
|
|
2141
|
+
};
|
|
2142
|
+
// AsyncLocalStorage.run scopes the ambient frame to this callback, so the
|
|
2143
|
+
// caller's continuation never resumes through an enterWith frame — the
|
|
2144
|
+
// pattern that crashes Bun 1.3.x in plain scripts under top-level await.
|
|
2145
|
+
return runWithActiveRequestContext(ambient, async () => {
|
|
2146
|
+
const ctx = finalizeContext(
|
|
2147
|
+
await serviceFactory({
|
|
2148
|
+
ports: finalPorts,
|
|
2149
|
+
input,
|
|
2150
|
+
requestId,
|
|
2151
|
+
trace,
|
|
2152
|
+
}),
|
|
2153
|
+
);
|
|
2154
|
+
ambient.actor = readContextActor(ctx);
|
|
2155
|
+
ambient.tenant = readContextTenant(ctx);
|
|
2156
|
+
return await fn(ctx);
|
|
2157
|
+
});
|
|
2158
|
+
};
|
|
2092
2159
|
const contextRuntime = {
|
|
2093
2160
|
createRequestContext,
|
|
2094
2161
|
finalizeContext,
|
|
@@ -2426,6 +2493,7 @@ export async function createServer<
|
|
|
2426
2493
|
},
|
|
2427
2494
|
createRequestContext: (req) => createRequestContext(req),
|
|
2428
2495
|
createServiceContext,
|
|
2496
|
+
runServiceContext,
|
|
2429
2497
|
contracts,
|
|
2430
2498
|
stop,
|
|
2431
2499
|
ports: finalPorts,
|
package/src/tasks/index.ts
CHANGED
|
@@ -121,6 +121,29 @@ export interface RunTaskOptions<Ctx> {
|
|
|
121
121
|
ctx: Ctx;
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Arguments `beignet task run` passes to the app's `createTaskContext` and
|
|
126
|
+
* `stopTaskContext` exports in `server/tasks.ts`.
|
|
127
|
+
*/
|
|
128
|
+
export interface TaskRunContextArgs<T extends TaskDef = TaskDef> {
|
|
129
|
+
/**
|
|
130
|
+
* Task definition being run.
|
|
131
|
+
*/
|
|
132
|
+
task: T;
|
|
133
|
+
/**
|
|
134
|
+
* Stable task name being run.
|
|
135
|
+
*/
|
|
136
|
+
taskName: string;
|
|
137
|
+
/**
|
|
138
|
+
* Schema-parsed task input.
|
|
139
|
+
*/
|
|
140
|
+
input: unknown;
|
|
141
|
+
/**
|
|
142
|
+
* Tenant id or slug from `--tenant`, resolved by the app.
|
|
143
|
+
*/
|
|
144
|
+
tenant?: string;
|
|
145
|
+
}
|
|
146
|
+
|
|
124
147
|
/**
|
|
125
148
|
* Context-bound operational task helper factory.
|
|
126
149
|
*/
|