feat: deliver module database ABI by manifest
CI / verify (pull_request) Successful in 1m0s
CI / infrastructure-smoke (pull_request) Successful in 36s
CI / migration-smoke (pull_request) Successful in 1m53s
CI / image-build (pull_request) Successful in 23s
CI / deploy-smoke (same-origin) (pull_request) Successful in 50s
CI / deploy-smoke (split) (pull_request) Successful in 1m30s
CI / verify (pull_request) Successful in 1m0s
CI / infrastructure-smoke (pull_request) Successful in 36s
CI / migration-smoke (pull_request) Successful in 1m53s
CI / image-build (pull_request) Successful in 23s
CI / deploy-smoke (same-origin) (pull_request) Successful in 50s
CI / deploy-smoke (split) (pull_request) Successful in 1m30s
This commit is contained in:
@@ -2,7 +2,8 @@ import { z } from "zod";
|
||||
import { type ModuleId, type PermissionId, permissionIdSchema } from "./identifiers.js";
|
||||
import type { EkklesiaPrincipal } from "./identity.js";
|
||||
import type { ModuleConfiguration } from "./module-configuration.js";
|
||||
import type { ModuleRuntimeServices } from "./module-database.js";
|
||||
import type { ModuleDatabase, ModuleRuntimeServices } from "./module-database.js";
|
||||
import type { ModuleDatabaseExecutor } from "./module-database-abi.js";
|
||||
import type { ModuleRealtimePublisher } from "./module-realtime.js";
|
||||
import type { ModuleStorage } from "./module-storage.js";
|
||||
|
||||
@@ -271,7 +272,9 @@ export function moduleRoutesOverlap(
|
||||
* behavior, and uncaught-handler sanitization; permission enforcement always completes before a
|
||||
* handler — and therefore any parameter validation it performs — can run.
|
||||
*/
|
||||
export interface ModuleRouteHandlerContext {
|
||||
export interface ModuleRouteHandlerContext<
|
||||
Database extends ModuleDatabase | ModuleDatabaseExecutor = ModuleDatabase,
|
||||
> {
|
||||
readonly moduleId: ModuleId;
|
||||
readonly principal: EkklesiaPrincipal;
|
||||
readonly params: Readonly<Record<string, string>>;
|
||||
@@ -279,7 +282,7 @@ export interface ModuleRouteHandlerContext {
|
||||
* object, not a re-resolved one (ADR 0030). This is what lets a module stream an object straight
|
||||
* into a `Response` without the browser ever learning that object storage exists. */
|
||||
readonly storage: ModuleStorage;
|
||||
readonly services: ModuleRuntimeServices;
|
||||
readonly services: ModuleRuntimeServices<Database>;
|
||||
/** The identical module-scoped realtime publisher used by lifecycle hooks. */
|
||||
readonly realtime: ModuleRealtimePublisher;
|
||||
/** The identical frozen configuration snapshot this module's `start`/`stop` hooks received — the
|
||||
@@ -293,10 +296,9 @@ export interface ModuleRouteHandlerContext {
|
||||
/** A framework-neutral Fetch handler: standard `Request` in, standard `Response` out. The full
|
||||
* query string remains available through `Request.url`; there is no competing query or body
|
||||
* abstraction. */
|
||||
export type ModuleRouteHandler = (
|
||||
request: Request,
|
||||
context: ModuleRouteHandlerContext,
|
||||
) => Awaitable<Response>;
|
||||
export type ModuleRouteHandler<
|
||||
Database extends ModuleDatabase | ModuleDatabaseExecutor = ModuleDatabase,
|
||||
> = (request: Request, context: ModuleRouteHandlerContext<Database>) => Awaitable<Response>;
|
||||
|
||||
/**
|
||||
* What a module passes to `http.route(...)` during `register`. `permission` is a plain string here
|
||||
@@ -311,7 +313,9 @@ export type ModuleRouteHandler = (
|
||||
* path, CORS/origin policy, authentication behavior, grant/platform-owner state, middleware, audit
|
||||
* metadata, another module's namespace, or an unprotected/no-permission route.
|
||||
*/
|
||||
export interface ModuleRouteDefinitionInput {
|
||||
export interface ModuleRouteDefinitionInput<
|
||||
Database extends ModuleDatabase | ModuleDatabaseExecutor = ModuleDatabase,
|
||||
> {
|
||||
readonly method: ModuleHttpMethod;
|
||||
readonly path: string;
|
||||
readonly permission: string;
|
||||
@@ -322,12 +326,14 @@ export interface ModuleRouteDefinitionInput {
|
||||
* existed meant, so adding this field changed no existing route's behaviour.
|
||||
*/
|
||||
readonly bodyMode?: ModuleRouteBodyMode;
|
||||
readonly handler: ModuleRouteHandler;
|
||||
readonly handler: ModuleRouteHandler<Database>;
|
||||
}
|
||||
|
||||
/** The validated, canonical form of a `ModuleRouteDefinitionInput` — what `http.route` produces
|
||||
* only after every field passes its own grammar. */
|
||||
export interface ModuleRouteDefinition {
|
||||
export interface ModuleRouteDefinition<
|
||||
Database extends ModuleDatabase | ModuleDatabaseExecutor = ModuleDatabase,
|
||||
> {
|
||||
readonly method: ModuleHttpMethod;
|
||||
readonly path: ModuleRoutePath;
|
||||
readonly permission: PermissionId;
|
||||
@@ -335,13 +341,15 @@ export interface ModuleRouteDefinition {
|
||||
/** Always present in the canonical form, defaulted to `buffered`, so no consumer downstream has
|
||||
* to re-apply the default and none of them can disagree about it. */
|
||||
readonly bodyMode: ModuleRouteBodyMode;
|
||||
readonly handler: ModuleRouteHandler;
|
||||
readonly handler: ModuleRouteHandler<Database>;
|
||||
}
|
||||
|
||||
/** The Fetch-based registrar exposed as `context.http` during `register` only — never on
|
||||
* `ModuleRuntimeContext`, so `start`/`stop` cannot register a route after the fact. */
|
||||
export interface ModuleHttpRouteRegistrar {
|
||||
route(definition: ModuleRouteDefinitionInput): void;
|
||||
export interface ModuleHttpRouteRegistrar<
|
||||
Database extends ModuleDatabase | ModuleDatabaseExecutor = ModuleDatabase,
|
||||
> {
|
||||
route(definition: ModuleRouteDefinitionInput<Database>): void;
|
||||
}
|
||||
|
||||
/** One published route in `StartedModuleRuntime`'s immutable route snapshot — the same validated
|
||||
@@ -355,6 +363,8 @@ export interface RegisteredModuleHttpRoute {
|
||||
readonly permission: PermissionId;
|
||||
readonly maxBodyBytes: number;
|
||||
readonly bodyMode: ModuleRouteBodyMode;
|
||||
/** Runtime-erased callback. Module authors get the database-mode-specific handler type through
|
||||
* `ModuleHttpRouteRegistrar`; Core stores the validated callback opaquely in this snapshot. */
|
||||
readonly handler: ModuleRouteHandler;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user