bunderstack 0.19.2 → 0.20.0

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 (39) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/api/crud-router.d.ts +19 -24
  3. package/dist/api/crud-router.d.ts.map +1 -1
  4. package/dist/api/crud-router.js +39 -18
  5. package/dist/api/crud-router.js.map +1 -1
  6. package/dist/api/live-window.d.ts.map +1 -1
  7. package/dist/api/live-window.js +13 -3
  8. package/dist/api/live-window.js.map +1 -1
  9. package/dist/api/realtime-router.d.ts +2 -0
  10. package/dist/api/realtime-router.d.ts.map +1 -1
  11. package/dist/api/realtime-router.js +1 -0
  12. package/dist/api/realtime-router.js.map +1 -1
  13. package/dist/api/types.d.ts +2 -2
  14. package/dist/api/types.d.ts.map +1 -1
  15. package/dist/api/types.js.map +1 -1
  16. package/dist/codegen.d.ts +36 -0
  17. package/dist/codegen.d.ts.map +1 -0
  18. package/dist/codegen.js +235 -0
  19. package/dist/codegen.js.map +1 -0
  20. package/dist/crud-operations.d.ts.map +1 -1
  21. package/dist/crud-operations.js +7 -3
  22. package/dist/crud-operations.js.map +1 -1
  23. package/dist/index.d.ts +9 -4
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js.map +1 -1
  26. package/dist/live/protocol.d.ts +3 -0
  27. package/dist/live/protocol.d.ts.map +1 -1
  28. package/dist/live/protocol.js.map +1 -1
  29. package/dist/realtime/facade.d.ts +3 -1
  30. package/dist/realtime/facade.d.ts.map +1 -1
  31. package/dist/realtime/facade.js +2 -1
  32. package/dist/realtime/facade.js.map +1 -1
  33. package/dist/realtime/filter.d.ts.map +1 -1
  34. package/dist/realtime/filter.js +1 -0
  35. package/dist/realtime/filter.js.map +1 -1
  36. package/dist/realtime/publisher.d.ts +2 -0
  37. package/dist/realtime/publisher.d.ts.map +1 -1
  38. package/dist/realtime/publisher.js.map +1 -1
  39. package/package.json +5 -1
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AnyRouter as AnyORPCRouter } from '@orpc/server'\n// src/index.ts\n\nimport { SmartCoercionHandlerPlugin } from '@orpc/json-schema'\nimport { OpenAPIGenerator, OpenAPIGeneratorError } from '@orpc/openapi'\nimport { OpenAPIHandler } from '@orpc/openapi/fetch'\nimport { RPCHandler } from '@orpc/server/fetch'\nimport { ValibotToJsonSchemaConverter } from '@orpc/valibot'\n\nimport type { TableAccessInput } from './access'\nimport type { BunderstackApiBuilder } from './api/builder'\nimport type { RealtimeApiRouter } from './api/realtime-router'\nimport type {\n CrudApiRouterFor,\n MergeApiRouterTypes,\n UnifiedApiRouter,\n} from './api/types'\nimport type { DbFor } from './db'\nimport type {\n BunderstackJobsBuilder,\n EnqueueOptions,\n JobsDefs,\n JobsFacade,\n StartWorkerOptions,\n WorkerHandle,\n} from './jobs/index'\nimport type { StorageConfigInput } from './storage/buckets'\nimport type { StorageAdapter } from './storage/index'\n\nimport { validateAndResolveAccess } from './access'\nimport { createApiBuilder } from './api/builder'\nimport { createApiContext } from './api/context'\nimport { buildCrudApiRouter } from './api/crud-router'\nimport { mergeOpenAPISpecs } from './api/openapi'\nimport { buildRealtimeApiRouter } from './api/realtime-router'\nimport { buildApiRegistry, normalizeForeignOpenAPISpec } from './api/registry'\nimport { buildApiRouter } from './api/router'\nimport { buildStorageApiRouter } from './api/storage-router'\nimport {\n createAuth,\n toAuthSessionResolver,\n withEmailAuthDefaults,\n} from './auth'\nimport { resolveConfig, type BunderstackConfig } from './config'\nimport { resolveAuthConfig, resolveRealtimeRedisUrl } from './config'\nimport { createDb } from './db'\nimport { detectDialect } from './dialect'\nimport { createEmail, emailProviderTag, type EmailFacade } from './email'\nimport { validateEnv, type EnvConfigInput, type ValidatedEnv } from './env'\nimport { buildHandler } from './handler'\nimport { withInternalTables } from './internal-tables'\nimport {\n createJobsBuilder,\n createJobRunner,\n enqueueJob,\n startJobWorker,\n validateJobsDefs,\n} from './jobs/index'\nimport { Lifecycle, type LifecycleStatus } from './lifecycle'\nimport { buildManifest, type BunderstackManifest } from './manifest'\nimport {\n PROVISION_INTERNALS,\n type WithProvisionInternals,\n} from './provision-internals'\nimport {\n createRealtimeFacade,\n type RealtimeFacade,\n type RealtimeTransport,\n} from './realtime/facade'\nimport {\n createMemoryRealtimePublisher,\n createRedisRealtimePublisher,\n} from './realtime/publisher'\nimport { deleteFileWithDerivatives } from './storage/delete'\nimport { deleteFileMetaRow, insertReadyFile } from './storage/file-meta'\nimport { createStorageOperations } from './storage/operations'\nimport { createBucketStorages } from './storage/registry'\nimport { sweepOrphans } from './storage/sweep'\n\nexport type AuthInstance = ReturnType<typeof createAuth>\n\nfunction waitForWorkerShutdown(\n signal: AbortSignal,\n installProcessListeners: boolean,\n): Promise<void> {\n if (signal.aborted) return Promise.resolve()\n\n return new Promise((resolve) => {\n const done = () => {\n signal.removeEventListener('abort', done)\n if (installProcessListeners) {\n process.removeListener('SIGINT', done)\n process.removeListener('SIGTERM', done)\n }\n resolve()\n }\n signal.addEventListener('abort', done, { once: true })\n if (installProcessListeners) {\n process.once('SIGINT', done)\n process.once('SIGTERM', done)\n }\n })\n}\n\n/** Default age before an unconfirmed `pending` file is treated as an orphan. */\nconst DEFAULT_PENDING_TTL_MS = 30 * 60_000\n/**\n * Public storage facade exposed as `app.storage`. Object-level operations live\n * on the per-bucket adapters; this surface offers the app-wide deletes that\n * must also clean the file-meta row.\n */\nexport interface StorageFacade {\n /** Delete a file row and purge all underlying storage derivatives. */\n delete(fileId: string): Promise<void>\n /** Low-level access to the underlying storage adapter for a bucket. */\n bucket(name: string): StorageAdapter | undefined\n /**\n * Reap stale `pending` uploads older than `olderThanMs` (default 30m). Runs\n * only when explicitly invoked by the host or local scheduler. Returns\n * the count reaped.\n */\n sweep(olderThanMs?: number): Promise<number>\n /**\n * Get a public or presigned download URL for a file key.\n * Returns a presigned S3 URL when S3 is configured, or local proxy route `/api/files/...` in development.\n */\n getUrl(\n key: string,\n opts?: { bucket?: string; expiresIn?: number },\n ): Promise<string>\n /**\n * Upload bytes as a ready file and register it in file_meta so it is\n * accessible via `GET /api/files/<key>`. Use this for server-generated\n * files (e.g. generated PDFs) that are not uploaded by end-users.\n */\n upload(\n key: string,\n body: ArrayBuffer | Uint8Array,\n contentType: string,\n opts?: { ownerId?: string; filename?: string },\n ): Promise<void>\n}\n\nexport type AppStartWorkerOptions = Omit<StartWorkerOptions, 'tick'>\nexport type AppRunWorkerOptions = AppStartWorkerOptions & {\n /**\n * Permit process-local realtime in a standalone worker.\n *\n * Use only when job handlers never call ctx.realtime.publish(). Publications\n * made through the memory broker cannot reach SSE clients in another process.\n */\n allowProcessLocalRealtime?: boolean\n}\n/** Bucket names declared in a storage config; `string` when unknowable. */\nexport type BucketNamesOf<TStorage> = TStorage extends {\n buckets: infer B extends Record<string, unknown>\n}\n ? keyof B & string\n : string\n\nexport type BunderstackApp<\n TSchema extends Record<string, unknown>,\n TAccess extends Record<string, TableAccessInput> | undefined = undefined,\n TBuckets extends string = string,\n TEnv extends EnvConfigInput | undefined = undefined,\n TJobsDefs extends JobsDefs | undefined = undefined,\n TCustomApiRouter extends AnyORPCRouter | undefined = undefined,\n> = {\n handler: (req: Request) => Promise<Response>\n db: DbFor<TSchema>\n auth: AuthInstance\n storage: StorageFacade\n /** Validated env: bunderstack's base vars plus the config's `env` extension. */\n env: ValidatedEnv<TEnv>\n /** Email facade; always present — send() throws when email isn't configured. */\n email: EmailFacade\n /** Job queue facade; always present — enqueue throws when jobs aren't configured. */\n jobs: JobsFacade<\n TJobsDefs extends JobsDefs ? TJobsDefs : Record<never, never>\n >\n /** Typed custom row publication; enabled=false/no-op when realtime is off. */\n realtime: RealtimeFacade<TSchema>\n startWorker(options?: AppStartWorkerOptions): Promise<WorkerHandle>\n /** Run a queue worker until aborted, then close the application. */\n runWorker(options?: AppRunWorkerOptions): Promise<void>\n close(): Promise<void>\n /** True when this process is running the background tick loop. */\n readonly backgroundRunning: boolean\n readonly status: LifecycleStatus\n readonly signal: AbortSignal\n /** Deploy-time introspection: what this app needs provisioned. */\n manifest: BunderstackManifest\n /**\n * Type-only carrier for client inference (`createClient<typeof app>()`).\n * Never assigned at runtime.\n */\n readonly $inferClient?: {\n schema: TSchema\n access: TAccess\n buckets: TBuckets\n api: MergeApiRouterTypes<\n UnifiedApiRouter<CrudApiRouterFor<TSchema, TAccess>, TCustomApiRouter>,\n RealtimeApiRouter\n >\n }\n}\n\nexport function createBunderstack<\n TSchema extends Record<string, unknown>,\n const TAccess extends Record<string, TableAccessInput> | undefined =\n undefined,\n const TStorage extends StorageConfigInput | undefined = undefined,\n const TEnv extends EnvConfigInput | undefined = undefined,\n const TJobsDefs extends JobsDefs | undefined = undefined,\n TCustomApiRouter extends AnyORPCRouter | undefined = undefined,\n>(\n options: BunderstackConfig<\n TSchema,\n TAccess,\n TStorage,\n TEnv,\n TCustomApiRouter\n > & {\n jobs?:\n | TJobsDefs\n | ((j: BunderstackJobsBuilder<TSchema, ValidatedEnv<TEnv>>) => TJobsDefs)\n },\n): Promise<\n BunderstackApp<\n TSchema,\n TAccess,\n BucketNamesOf<TStorage>,\n TEnv,\n TJobsDefs,\n TCustomApiRouter\n >\n>\nexport async function createBunderstack<\n TSchema extends Record<string, unknown>,\n const TAccess extends Record<string, TableAccessInput> | undefined =\n undefined,\n const TStorage extends StorageConfigInput | undefined = undefined,\n const TEnv extends EnvConfigInput | undefined = undefined,\n TCustomApiRouter extends AnyORPCRouter | undefined = undefined,\n>(\n options: BunderstackConfig<\n TSchema,\n TAccess,\n TStorage,\n TEnv,\n TCustomApiRouter\n > & {\n jobs?:\n | JobsDefs\n | ((j: BunderstackJobsBuilder<TSchema, ValidatedEnv<TEnv>>) => JobsDefs)\n },\n): Promise<\n BunderstackApp<\n TSchema,\n TAccess,\n BucketNamesOf<TStorage>,\n TEnv,\n JobsDefs | undefined,\n TCustomApiRouter\n >\n> {\n const dialect = detectDialect(options.schema)\n const jobsDefs: JobsDefs | undefined = options.jobs\n ? typeof options.jobs === 'function'\n ? options.jobs(createJobsBuilder<TSchema, ValidatedEnv<TEnv>>())\n : (options.jobs as JobsDefs)\n : undefined\n if (jobsDefs) validateJobsDefs(jobsDefs)\n // Env is validated FIRST: the app refuses to boot on missing/invalid vars,\n // and everything downstream consumes the result.\n const env = validateEnv(options.env, {\n emailProvider:\n options.processEnv?.BUNDERSTACK_EMAIL_PROVIDER ??\n emailProviderTag(options.email),\n defaultDatabaseUrl:\n dialect === 'pg' ? 'file:./data.pglite' : 'file:./data.db',\n source: options.processEnv,\n })\n const config = resolveConfig(options, env, options.processEnv)\n // Adapters use Drizzle mocks during deployment introspection, so the database\n // and Redis below never touch external services.\n const introspect = process.env.BUNDERSTACK_INTROSPECT === '1'\n // Merge bunderstack's internal tables (file-meta, idempotency) into the\n // schema used for the db client + provisioning. CRUD/access stay on the USER\n // schema so internal tables never get a CRUD route.\n const mergedSchema = withInternalTables(options.schema)\n const lifecycle = new Lifecycle()\n const {\n db,\n driver,\n close: closeDatabase,\n } = await createDb(mergedSchema, {\n ...config.database,\n dialect,\n introspect,\n })\n const email = createEmail(options.email, { env, db })\n if (closeDatabase) lifecycle.add(closeDatabase)\n try {\n // `db` is typed with the merged schema (user tables + internal tables) so the\n // storage/idempotency code can query the internal tables. The public surface\n // and CRUD only expose the USER schema. TS can widen the merged-schema db type\n // on its own (storage/auth pass `db` directly), but it can't *narrow* a\n // generic schema view, so this single intentional cast produces the\n // user-facing, per-dialect db type. See `app.db` / crud below.\n const userDb = db as unknown as DbFor<TSchema>\n // An `auth` builder gets the user-facing db, so better-auth hooks in another\n // file can write through the app's own connection without importing the app.\n const authConfig = resolveAuthConfig(config.auth, { db: userDb, env })\n const auth = createAuth(\n db,\n withEmailAuthDefaults(authConfig, email, Boolean(options.email)),\n dialect,\n options.schema as Record<string, unknown>,\n )\n // Internal routers consume the narrow AuthSessionResolver contract, not the\n // raw better-auth instance. app.auth still exposes `auth` unchanged.\n const authResolver = options.authResolver ?? toAuthSessionResolver(auth)\n const resolvedAccess = validateAndResolveAccess(\n options.schema,\n options.access,\n )\n const realtimeBufferSize =\n typeof config.realtime === 'object'\n ? config.realtime.bufferSize\n : undefined\n const realtimeResumeSeconds =\n typeof config.realtime === 'object'\n ? config.realtime.resumeSeconds\n : undefined\n const configuredRedisUrl = config.realtime\n ? resolveRealtimeRedisUrl(config.realtime, env)\n : undefined\n const redisUrl = introspect ? undefined : configuredRedisUrl\n const publisher = config.realtime\n ? redisUrl\n ? (() => {\n const redis = new Bun.RedisClient(redisUrl)\n const subscriber = redis.duplicate()\n lifecycle.add(async () => {\n redis.close()\n ;(await subscriber).close()\n })\n return createRedisRealtimePublisher(redis, subscriber, {\n prefix: process.env.BUNDERSTACK_REALTIME_PREFIX ?? 'bunderstack:',\n maxBufferedEvents: realtimeBufferSize,\n resumeSeconds: realtimeResumeSeconds,\n })\n })()\n : createMemoryRealtimePublisher({\n maxBufferedEvents: realtimeBufferSize,\n resumeSeconds: realtimeResumeSeconds,\n })\n : undefined\n const runtimeRealtimeTransport: RealtimeTransport = !publisher\n ? 'disabled'\n : redisUrl\n ? 'redis'\n : 'memory'\n const realtime = createRealtimeFacade<TSchema>(\n publisher,\n runtimeRealtimeTransport,\n options.schema,\n )\n const registry = createBucketStorages(config.storage)\n const storageOperations = createStorageOperations({\n registry,\n db,\n })\n const storageApiRouter = buildStorageApiRouter(registry, storageOperations)\n const realtimeApiRouter = buildRealtimeApiRouter(publisher, resolvedAccess)\n const storage: StorageFacade = {\n async delete(fileId) {\n const bucketName = fileId.split('/')[0] ?? ''\n const entry = registry.get(bucketName)\n if (entry) {\n await deleteFileWithDerivatives(entry.adapter, db, fileId)\n } else {\n // Unknown bucket: no adapter to clean, but still drop the meta row.\n await deleteFileMetaRow(db, fileId)\n }\n },\n bucket(name) {\n return registry.get(name)?.adapter\n },\n sweep(olderThanMs = DEFAULT_PENDING_TTL_MS) {\n return sweepOrphans(registry, db, olderThanMs)\n },\n async getUrl(key, opts = {}) {\n const bucketName =\n opts.bucket ?? key.split('/')[0] ?? config.storage.defaultBucket\n const adapter = registry.get(bucketName)?.adapter\n if (adapter?.presignGet) {\n return adapter.presignGet(key, {\n expiresIn: opts.expiresIn ?? 3600,\n })\n }\n return `/api/files/${key}`\n },\n async upload(key, body, contentType, opts = {}) {\n const bucketName = key.split('/')[0] ?? ''\n const adapter = registry.get(bucketName)?.adapter\n if (!adapter) throw new Error(`Unknown bucket: ${bucketName}`)\n const u8 = body instanceof Uint8Array ? body : new Uint8Array(body)\n const buf: ArrayBuffer = u8.buffer.slice(\n u8.byteOffset,\n u8.byteOffset + u8.byteLength,\n ) as ArrayBuffer\n await adapter.upload(key, buf, contentType)\n await insertReadyFile(db, {\n fileId: key,\n bucket: bucketName,\n ownerId: opts.ownerId ?? null,\n scopeJson: null,\n filename: opts.filename ?? key.split('/').at(-1) ?? null,\n contentType,\n size: buf.byteLength,\n })\n },\n }\n const storageConfigured = Boolean(options.storage)\n // The storage sweep used to be a hardcoded maintenance route. It is an\n // ordinary cron now, so it inherits retries, timeout and onFailed.\n const resolvedDefs: JobsDefs | undefined = storageConfigured\n ? {\n ...jobsDefs,\n 'bunderstack:storage-sweep': {\n kind: 'cron',\n schedule: '0 4 * * *',\n handler: async () => {\n await storage.sweep()\n },\n },\n }\n : jobsDefs\n\n const jobRunner = resolvedDefs\n ? createJobRunner({\n db,\n defs: resolvedDefs,\n ctx: { db: userDb, env, email, storage, realtime },\n })\n : undefined\n const jobs = {\n async enqueue(name: string, input?: unknown, opts?: EnqueueOptions) {\n if (!resolvedDefs) {\n throw new Error(\n '[bunderstack] no jobs configured — add a `jobs` key to createBunderstack',\n )\n }\n const result = await enqueueJob(db, resolvedDefs, name, input, opts)\n return result\n },\n tick(now?: number) {\n return jobRunner\n ? jobRunner.tick(now)\n : Promise.resolve({ claimed: 0, ran: 0, failed: 0 })\n },\n }\n if (jobRunner) jobRunner.setJobsFacade(jobs)\n const startWorker = async (\n options: AppStartWorkerOptions = {},\n ): Promise<WorkerHandle> => {\n if (introspect) {\n return { closed: Promise.resolve(), close: async () => {} }\n }\n if (!jobRunner) {\n throw new Error('[bunderstack] no queue jobs configured')\n }\n if (lifecycle.status !== 'ready') {\n throw new Error('[bunderstack] application lifecycle is closed')\n }\n const signal = options.signal\n ? AbortSignal.any([lifecycle.signal, options.signal])\n : lifecycle.signal\n const handle = startJobWorker({\n ...options,\n signal,\n // The runtime loop only cares that a tick completed; TickResult is for\n // callers that invoke tick() directly.\n tick: async (now) => {\n await jobRunner.tick(now)\n },\n })\n const unregister = lifecycle.add(() => handle.close())\n void handle.closed.finally(unregister)\n return handle\n }\n const runWorker = async (\n options: AppRunWorkerOptions = {},\n ): Promise<void> => {\n if (introspect) return\n if (\n realtime.transport === 'memory' &&\n !options.allowProcessLocalRealtime\n ) {\n throw new Error(\n '[bunderstack] runWorker() cannot deliver realtime events through the in-memory broker. Configure REDIS_URL or realtime.redis, embed the worker with startWorker(), or pass allowProcessLocalRealtime: true only when jobs never publish realtime.',\n )\n }\n const {\n allowProcessLocalRealtime: _allowProcessLocalRealtime,\n ...workerOptions\n } = options\n const handle = await startWorker(workerOptions)\n try {\n const signal = workerOptions.signal\n ? AbortSignal.any([lifecycle.signal, workerOptions.signal])\n : lifecycle.signal\n await waitForWorkerShutdown(signal, !workerOptions.signal)\n } finally {\n await handle.close()\n await lifecycle.close()\n }\n }\n const crudApiRouter = buildCrudApiRouter(options.schema, userDb, {\n access: resolvedAccess,\n idempotency: options.idempotency,\n realtime,\n livePublisher: publisher,\n })\n\n const customApiRouter =\n typeof options.api === 'function'\n ? (\n options.api as (\n builder: BunderstackApiBuilder<TSchema, ValidatedEnv<TEnv>>,\n ) => TCustomApiRouter\n )(createApiBuilder<TSchema, ValidatedEnv<TEnv>>())\n : options.api\n\n const nativeRouter = buildApiRouter({\n crud: crudApiRouter as Record<string, unknown>,\n storage: storageApiRouter as Record<string, unknown>,\n realtime: realtimeApiRouter as Record<string, unknown> | undefined,\n custom: customApiRouter as Record<string, unknown> | undefined,\n middleware: options.middleware,\n }) as any\n\n const authOpenAPISpecRaw =\n options.openapi &&\n auth.api &&\n 'generateOpenAPISchema' in auth.api &&\n typeof auth.api.generateOpenAPISchema === 'function'\n ? await auth.api.generateOpenAPISchema()\n : undefined\n\n const authOpenAPISpec = authOpenAPISpecRaw\n ? normalizeForeignOpenAPISpec(authOpenAPISpecRaw, {\n prefix: '/api/auth',\n source: 'auth',\n })\n : undefined\n\n await buildApiRegistry({\n nativeRouter,\n foreignSpecs: authOpenAPISpec ? [authOpenAPISpec] : [],\n reservedCoreHandles: new Set([\n 'health',\n ...(publisher ? ['realtime.changes'] : []),\n ...[...registry.keys()].flatMap((name) =>\n [\n 'prepareUpload',\n 'upload',\n 'confirmUpload',\n 'download',\n 'delete',\n ].map((operation) => `files.${name}.${operation}`),\n ),\n ]),\n })\n\n const valibotConverter = new ValibotToJsonSchemaConverter()\n\n const combinedOpenAPISpec = options.openapi\n ? mergeOpenAPISpecs({\n nativeSpec: await new OpenAPIGenerator({\n converters: [\n valibotConverter,\n {\n condition: (schema: any) =>\n Boolean(\n schema?.['~standard'] && !schema['~standard'].jsonSchema,\n ),\n convert: (schema: any) => {\n const vendor = schema?.['~standard']?.vendor ?? 'unknown'\n throw new OpenAPIGeneratorError(\n `No JSON Schema converter is configured for Standard Schema vendor \"${vendor}\"`,\n )\n },\n },\n ],\n }).generate(nativeRouter),\n authSpec: authOpenAPISpec,\n })\n : undefined\n\n const openapiHandler = new OpenAPIHandler(nativeRouter, {\n // Query strings and form bodies are strings; this coerces them to the\n // types each procedure's input schema declares, so schemas stay honest\n // (`v.number()`, not a string-union pipe) and REST matches RPC.\n plugins: [\n new SmartCoercionHandlerPlugin({ converters: [valibotConverter] }),\n ],\n customErrorResponseBodyEncoder: (error: any) => {\n if (\n error?.code === 'INTERNAL_SERVER_ERROR' ||\n !error?.status ||\n error.status >= 500\n ) {\n console.error(\n '[bunderstack-api] 500 Internal Server Error:',\n error?.cause ?? error,\n )\n }\n return {\n error: error.message,\n code: error.data?.code ?? error.code,\n // oRPC reports schema failures as `data.issues`; forwarding them tells\n // the client which field was rejected instead of just \"invalid\".\n ...(error.data?.details !== undefined\n ? { details: error.data.details }\n : error.data?.issues !== undefined\n ? { details: error.data.issues }\n : {}),\n }\n },\n fetchInterceptors: [\n async (options) => {\n const res = await options.next()\n if (res.matched && options.context.resHeaders) {\n options.context.resHeaders.forEach((v: string, k: string) =>\n res.response.headers.set(k, v),\n )\n }\n return res\n },\n ],\n })\n // No custom error encoding here: the RPC protocol owns its error body, and\n // `mapBunderstackErrors` already logs unhandled procedure errors for every\n // transport before rethrowing them.\n const rpcHandler = new RPCHandler(nativeRouter)\n\n const apiHandler = async (req: Request): Promise<Response | null> => {\n const urlString = typeof req === 'string' ? (req as string) : req.url\n if (!urlString) return null\n const url = new URL(urlString, 'http://localhost')\n if (\n combinedOpenAPISpec &&\n url.pathname === '/api/openapi.json' &&\n req.method === 'GET'\n ) {\n return new Response(JSON.stringify(combinedOpenAPISpec), {\n headers: { 'Content-Type': 'application/json' },\n })\n }\n\n const apiCtx = createApiContext(\n {\n db: userDb,\n env,\n storage,\n email,\n jobs,\n realtime,\n auth,\n authResolver,\n },\n req,\n )\n\n if (url.pathname.startsWith('/api/rpc')) {\n const res = await rpcHandler.handle(req, {\n prefix: '/api/rpc',\n context: apiCtx,\n })\n if (res.matched) return res.response\n }\n\n const openapiRes = await openapiHandler.handle(req, { context: apiCtx })\n if (openapiRes.matched) return openapiRes.response\n\n return null\n }\n\n const handler = buildHandler({\n authHandler: (req) => auth.handler(req),\n apiHandler,\n rateLimit: options.rateLimit,\n })\n\n // Topology is a deployment concern: the role decides whether this process\n // runs background work, so application code never has to.\n const roleWantsWorker =\n env.BUNDERSTACK_ROLE === 'all' || env.BUNDERSTACK_ROLE === 'worker'\n const autoStart =\n options.background?.autoStart ??\n (roleWantsWorker && !introspect && resolvedDefs !== undefined)\n let backgroundRunning = false\n if (autoStart) {\n await startWorker()\n backgroundRunning = true\n }\n\n const app: BunderstackApp<\n TSchema,\n TAccess,\n BucketNamesOf<TStorage>,\n TEnv,\n JobsDefs | undefined,\n TCustomApiRouter\n > = {\n handler,\n // Internal tables live on the runtime db but stay out of the public type.\n db: userDb,\n auth,\n storage,\n env,\n email,\n realtime,\n // Runtime facade is untyped (JobsRuntimeFacade); the generic-typed field\n // narrows `enqueue` per-app from the declared job defs — same relationship\n // as `userDb` above.\n jobs: jobs as never,\n startWorker,\n runWorker,\n close: () => lifecycle.close(),\n backgroundRunning,\n get status() {\n return lifecycle.status\n },\n signal: lifecycle.signal,\n manifest: buildManifest({\n schema: options.schema,\n dialect,\n migrationsDirectory: config.database.migrations,\n storage: config.storage,\n envConfig: options.env as EnvConfigInput | undefined,\n emailProvider: emailProviderTag(options.email),\n realtime: Boolean(config.realtime),\n jobs: resolvedDefs,\n }),\n }\n\n // Hidden handle for the optional `bunderstack/provision` entry. Kept off the\n // public type so provisioning stays opt-in (and drizzle-kit out of this\n // module graph).\n ;(app as WithProvisionInternals)[PROVISION_INTERNALS] = {\n db,\n schema: mergedSchema,\n databaseUrl: config.database.url,\n migrationsFolder: config.database.migrations,\n dialect,\n driver,\n adapter: config.database.adapter,\n }\n\n return app\n } catch (cause) {\n try {\n await lifecycle.close()\n } catch (cleanupCause) {\n throw new AggregateError(\n [cause, cleanupCause],\n '[bunderstack] application initialization failed and cleanup failed',\n )\n }\n throw cause\n }\n}\n\nexport { listSpec } from './api/list-spec'\nexport type { ListSpecOptions } from './api/list-spec'\nexport type { BunderstackDb, BunderstackTx } from './db'\nexport { MAX_LIST_LIMIT } from './list-query'\nexport { BunderstackError } from './errors'\nexport type { BunderstackErrorCode } from './errors'\nexport { resolveConfig, resolveAuthConfig, defineAuth } from './config'\nexport type {\n AuthConfigContext,\n AuthConfigFactory,\n AuthConfigInput,\n BetterAuthConfig,\n BunderstackConfig,\n ResolvedConfig,\n} from './config'\nexport { validateEnv, createClientEnv, BunderstackEnvError } from './env'\nexport type { EnvConfigInput, BaseEnv, ValidatedEnv } from './env'\nexport { buildManifest, parseManifest } from './manifest'\nexport type { BunderstackManifest, ManifestEnvVar } from './manifest'\nexport { createEmail } from './email'\nexport type {\n EmailMessage,\n EmailAdapter,\n EmailConfigInput,\n EmailFacade,\n} from './email'\nexport { createJobsBuilder } from './jobs/index'\nexport type {\n BunderstackJobContext,\n BunderstackJobsBuilder,\n BackgroundDefinition,\n BackgroundDefs,\n CronDefinition,\n CronInvocation,\n EnqueueOptions,\n JobContext,\n JobDefinition,\n JobsDefs,\n JobsFacade,\n JobsRuntimeFacade,\n QueueJobDefinition,\n QueueJobKeys,\n RunWorkerOptions,\n StartWorkerOptions,\n WorkerHandle,\n} from './jobs/index'\nexport {\n defineAccess,\n validateAndResolveAccess,\n checkAccess,\n AUTH_TABLE_NAMES,\n} from './access'\nexport type {\n TableAccessInput,\n OperationRule,\n AccessContext,\n AccessUser,\n} from './access'\nexport {\n typeid,\n generate as generateTypeId,\n parse as parseTypeId,\n asTypeId,\n} from './typeid'\nexport type { TypeId } from './typeid'\nexport type {\n DatabaseAdapter,\n DatabaseConnectOptions,\n DatabaseConnection,\n DatabaseConnectionResult,\n} from './database/adapter'\nexport type { StorageAdapter } from './storage/index'\nexport type {\n StorageConfigInput,\n BucketConfigInput,\n ResolvedBucket,\n} from './storage/buckets'\n// StorageFacade is declared+exported inline above.\nexport type { TransformSpec } from './storage/thumbnails'\nexport { mockAuthSession } from './testing'\n\nexport type { RealtimeAction } from './realtime/publisher'\nexport { createRealtimeFacade } from './realtime/facade'\nexport type {\n RealtimeFacade,\n RealtimeTransport,\n SchemaTable,\n} from './realtime/facade'\n\nexport { createApiBuilder, defineApi } from './api/builder'\nexport type { BunderstackApiBuilder, ApiFactory } from './api/builder'\n// Needed to declare shared middleware over the app's context, e.g.\n// `os.$context<ApiContext<typeof schema>>().middleware(...)`.\nexport type { ApiContext } from './api/context'\nexport type {\n CrudApiRouterFor,\n ExposedApiTables,\n MergeApiRouterTypes,\n UnifiedApiRouter,\n} from './api/types'\nexport type { TableCrudProcedures } from './api/crud-router'\nexport {\n buildApiRegistry,\n mergeApiRoutersStrict,\n normalizeApiPath,\n normalizeForeignOpenAPISpec,\n} from './api/registry'\nexport { mergeOpenAPISpecs } from './api/openapi'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AnyRouter as AnyORPCRouter } from '@orpc/server'\n// src/index.ts\n\nimport { SmartCoercionHandlerPlugin } from '@orpc/json-schema'\nimport { OpenAPIGenerator, OpenAPIGeneratorError } from '@orpc/openapi'\nimport { OpenAPIHandler } from '@orpc/openapi/fetch'\nimport { RPCHandler } from '@orpc/server/fetch'\nimport { ValibotToJsonSchemaConverter } from '@orpc/valibot'\n\nimport type { TableAccessInput } from './access'\nimport type { BunderstackApiBuilder } from './api/builder'\nimport type { RealtimeApiRouter } from './api/realtime-router'\nimport type {\n CrudApiRouterFor,\n MergeApiRouterTypes,\n UnifiedApiRouter,\n} from './api/types'\nimport type { DbFor } from './db'\nimport type {\n BunderstackJobsBuilder,\n EnqueueOptions,\n JobsDefs,\n JobsFacade,\n StartWorkerOptions,\n WorkerHandle,\n} from './jobs/index'\nimport type { StorageConfigInput } from './storage/buckets'\nimport type { StorageAdapter } from './storage/index'\n\nimport { validateAndResolveAccess } from './access'\nimport { createApiBuilder } from './api/builder'\nimport { createApiContext } from './api/context'\nimport { buildCrudApiRouter } from './api/crud-router'\nimport { mergeOpenAPISpecs } from './api/openapi'\nimport { buildRealtimeApiRouter } from './api/realtime-router'\nimport { buildApiRegistry, normalizeForeignOpenAPISpec } from './api/registry'\nimport { buildApiRouter } from './api/router'\nimport { buildStorageApiRouter } from './api/storage-router'\nimport {\n createAuth,\n toAuthSessionResolver,\n withEmailAuthDefaults,\n} from './auth'\nimport { resolveConfig, type BunderstackConfig } from './config'\nimport { resolveAuthConfig, resolveRealtimeRedisUrl } from './config'\nimport { createDb } from './db'\nimport { detectDialect } from './dialect'\nimport { createEmail, emailProviderTag, type EmailFacade } from './email'\nimport { validateEnv, type EnvConfigInput, type ValidatedEnv } from './env'\nimport { buildHandler } from './handler'\nimport { withInternalTables } from './internal-tables'\nimport {\n createJobsBuilder,\n createJobRunner,\n enqueueJob,\n startJobWorker,\n validateJobsDefs,\n} from './jobs/index'\nimport { Lifecycle, type LifecycleStatus } from './lifecycle'\nimport { buildManifest, type BunderstackManifest } from './manifest'\nimport {\n PROVISION_INTERNALS,\n type WithProvisionInternals,\n} from './provision-internals'\nimport {\n createRealtimeFacade,\n type RealtimeFacade,\n type RealtimeTransport,\n} from './realtime/facade'\nimport {\n createMemoryRealtimePublisher,\n createRedisRealtimePublisher,\n} from './realtime/publisher'\nimport { deleteFileWithDerivatives } from './storage/delete'\nimport { deleteFileMetaRow, insertReadyFile } from './storage/file-meta'\nimport { createStorageOperations } from './storage/operations'\nimport { createBucketStorages } from './storage/registry'\nimport { sweepOrphans } from './storage/sweep'\n\nexport type AuthInstance = ReturnType<typeof createAuth>\n\nfunction waitForWorkerShutdown(\n signal: AbortSignal,\n installProcessListeners: boolean,\n): Promise<void> {\n if (signal.aborted) return Promise.resolve()\n\n return new Promise((resolve) => {\n const done = () => {\n signal.removeEventListener('abort', done)\n if (installProcessListeners) {\n process.removeListener('SIGINT', done)\n process.removeListener('SIGTERM', done)\n }\n resolve()\n }\n signal.addEventListener('abort', done, { once: true })\n if (installProcessListeners) {\n process.once('SIGINT', done)\n process.once('SIGTERM', done)\n }\n })\n}\n\n/** Default age before an unconfirmed `pending` file is treated as an orphan. */\nconst DEFAULT_PENDING_TTL_MS = 30 * 60_000\n/**\n * Public storage facade exposed as `app.storage`. Object-level operations live\n * on the per-bucket adapters; this surface offers the app-wide deletes that\n * must also clean the file-meta row.\n */\nexport interface StorageFacade {\n /** Delete a file row and purge all underlying storage derivatives. */\n delete(fileId: string): Promise<void>\n /** Low-level access to the underlying storage adapter for a bucket. */\n bucket(name: string): StorageAdapter | undefined\n /**\n * Reap stale `pending` uploads older than `olderThanMs` (default 30m). Runs\n * only when explicitly invoked by the host or local scheduler. Returns\n * the count reaped.\n */\n sweep(olderThanMs?: number): Promise<number>\n /**\n * Get a public or presigned download URL for a file key.\n * Returns a presigned S3 URL when S3 is configured, or local proxy route `/api/files/...` in development.\n */\n getUrl(\n key: string,\n opts?: { bucket?: string; expiresIn?: number },\n ): Promise<string>\n /**\n * Upload bytes as a ready file and register it in file_meta so it is\n * accessible via `GET /api/files/<key>`. Use this for server-generated\n * files (e.g. generated PDFs) that are not uploaded by end-users.\n */\n upload(\n key: string,\n body: ArrayBuffer | Uint8Array,\n contentType: string,\n opts?: { ownerId?: string; filename?: string },\n ): Promise<void>\n}\n\nexport type AppStartWorkerOptions = Omit<StartWorkerOptions, 'tick'>\nexport type AppRunWorkerOptions = AppStartWorkerOptions & {\n /**\n * Permit process-local realtime in a standalone worker.\n *\n * Use only when job handlers never call ctx.realtime.publish(). Publications\n * made through the memory broker cannot reach SSE clients in another process.\n */\n allowProcessLocalRealtime?: boolean\n}\n/** Bucket names declared in a storage config; `string` when unknowable. */\nexport type BucketNamesOf<TStorage> = TStorage extends {\n buckets: infer B extends Record<string, unknown>\n}\n ? keyof B & string\n : string\n\nexport type BunderstackApp<\n TSchema extends Record<string, unknown>,\n TAccess extends Record<string, TableAccessInput> | undefined = undefined,\n TBuckets extends string = string,\n TEnv extends EnvConfigInput | undefined = undefined,\n TJobsDefs extends JobsDefs | undefined = undefined,\n TCustomApiRouter extends AnyORPCRouter | undefined = undefined,\n TRealtime = undefined,\n> = {\n handler: (req: Request) => Promise<Response>\n db: DbFor<TSchema>\n auth: AuthInstance\n storage: StorageFacade\n /** Validated env: bunderstack's base vars plus the config's `env` extension. */\n env: ValidatedEnv<TEnv>\n /** Email facade; always present — send() throws when email isn't configured. */\n email: EmailFacade\n /** Job queue facade; always present — enqueue throws when jobs aren't configured. */\n jobs: JobsFacade<\n TJobsDefs extends JobsDefs ? TJobsDefs : Record<never, never>\n >\n /** Typed custom row publication; enabled=false/no-op when realtime is off. */\n realtime: RealtimeFacade<TSchema>\n startWorker(options?: AppStartWorkerOptions): Promise<WorkerHandle>\n /** Run a queue worker until aborted, then close the application. */\n runWorker(options?: AppRunWorkerOptions): Promise<void>\n close(): Promise<void>\n /** True when this process is running the background tick loop. */\n readonly backgroundRunning: boolean\n readonly status: LifecycleStatus\n readonly signal: AbortSignal\n /** Deploy-time introspection: what this app needs provisioned. */\n manifest: BunderstackManifest\n /**\n * Type-only carrier for client inference (`createClient<typeof app>()`).\n * Never assigned at runtime.\n */\n readonly $inferClient?: {\n schema: TSchema\n access: TAccess\n buckets: TBuckets\n api: MergeApiRouterTypes<\n UnifiedApiRouter<\n CrudApiRouterFor<\n TSchema,\n TAccess,\n [TRealtime] extends [false | undefined] ? false : true\n >,\n TCustomApiRouter\n >,\n [TRealtime] extends [false | undefined] ? {} : RealtimeApiRouter\n >\n }\n}\n\nexport function createBunderstack<\n TSchema extends Record<string, unknown>,\n const TAccess extends Record<string, TableAccessInput> | undefined =\n undefined,\n const TStorage extends StorageConfigInput | undefined = undefined,\n const TEnv extends EnvConfigInput | undefined = undefined,\n const TJobsDefs extends JobsDefs | undefined = undefined,\n TCustomApiRouter extends AnyORPCRouter | undefined = undefined,\n const TRealtime extends BunderstackConfig<\n TSchema,\n TAccess,\n TStorage,\n TEnv,\n TCustomApiRouter\n >['realtime'] = undefined,\n>(\n options: BunderstackConfig<\n TSchema,\n TAccess,\n TStorage,\n TEnv,\n TCustomApiRouter\n > & {\n realtime?: TRealtime\n jobs?:\n | TJobsDefs\n | ((j: BunderstackJobsBuilder<TSchema, ValidatedEnv<TEnv>>) => TJobsDefs)\n },\n): Promise<\n BunderstackApp<\n TSchema,\n TAccess,\n BucketNamesOf<TStorage>,\n TEnv,\n TJobsDefs,\n TCustomApiRouter,\n TRealtime\n >\n>\nexport async function createBunderstack<\n TSchema extends Record<string, unknown>,\n const TAccess extends Record<string, TableAccessInput> | undefined =\n undefined,\n const TStorage extends StorageConfigInput | undefined = undefined,\n const TEnv extends EnvConfigInput | undefined = undefined,\n TCustomApiRouter extends AnyORPCRouter | undefined = undefined,\n const TRealtime extends BunderstackConfig<\n TSchema,\n TAccess,\n TStorage,\n TEnv,\n TCustomApiRouter\n >['realtime'] = undefined,\n>(\n options: BunderstackConfig<\n TSchema,\n TAccess,\n TStorage,\n TEnv,\n TCustomApiRouter\n > & {\n realtime?: TRealtime\n jobs?:\n | JobsDefs\n | ((j: BunderstackJobsBuilder<TSchema, ValidatedEnv<TEnv>>) => JobsDefs)\n },\n): Promise<\n BunderstackApp<\n TSchema,\n TAccess,\n BucketNamesOf<TStorage>,\n TEnv,\n JobsDefs | undefined,\n TCustomApiRouter,\n TRealtime\n >\n> {\n const dialect = detectDialect(options.schema)\n const jobsDefs: JobsDefs | undefined = options.jobs\n ? typeof options.jobs === 'function'\n ? options.jobs(createJobsBuilder<TSchema, ValidatedEnv<TEnv>>())\n : (options.jobs as JobsDefs)\n : undefined\n if (jobsDefs) validateJobsDefs(jobsDefs)\n // Env is validated FIRST: the app refuses to boot on missing/invalid vars,\n // and everything downstream consumes the result.\n const env = validateEnv(options.env, {\n emailProvider:\n options.processEnv?.BUNDERSTACK_EMAIL_PROVIDER ??\n emailProviderTag(options.email),\n defaultDatabaseUrl:\n dialect === 'pg' ? 'file:./data.pglite' : 'file:./data.db',\n source: options.processEnv,\n })\n const config = resolveConfig(options, env, options.processEnv)\n // Adapters use Drizzle mocks during deployment introspection, so the database\n // and Redis below never touch external services.\n const introspect = process.env.BUNDERSTACK_INTROSPECT === '1'\n // Merge bunderstack's internal tables (file-meta, idempotency) into the\n // schema used for the db client + provisioning. CRUD/access stay on the USER\n // schema so internal tables never get a CRUD route.\n const mergedSchema = withInternalTables(options.schema)\n const lifecycle = new Lifecycle()\n const {\n db,\n driver,\n close: closeDatabase,\n } = await createDb(mergedSchema, {\n ...config.database,\n dialect,\n introspect,\n })\n const email = createEmail(options.email, { env, db })\n if (closeDatabase) lifecycle.add(closeDatabase)\n try {\n // `db` is typed with the merged schema (user tables + internal tables) so the\n // storage/idempotency code can query the internal tables. The public surface\n // and CRUD only expose the USER schema. TS can widen the merged-schema db type\n // on its own (storage/auth pass `db` directly), but it can't *narrow* a\n // generic schema view, so this single intentional cast produces the\n // user-facing, per-dialect db type. See `app.db` / crud below.\n const userDb = db as unknown as DbFor<TSchema>\n // An `auth` builder gets the user-facing db, so better-auth hooks in another\n // file can write through the app's own connection without importing the app.\n const authConfig = resolveAuthConfig(config.auth, { db: userDb, env })\n const auth = createAuth(\n db,\n withEmailAuthDefaults(authConfig, email, Boolean(options.email)),\n dialect,\n options.schema as Record<string, unknown>,\n )\n // Internal routers consume the narrow AuthSessionResolver contract, not the\n // raw better-auth instance. app.auth still exposes `auth` unchanged.\n const authResolver = options.authResolver ?? toAuthSessionResolver(auth)\n const resolvedAccess = validateAndResolveAccess(\n options.schema,\n options.access,\n )\n const realtimeBufferSize =\n typeof config.realtime === 'object'\n ? config.realtime.bufferSize\n : undefined\n const realtimeResumeSeconds =\n typeof config.realtime === 'object'\n ? config.realtime.resumeSeconds\n : undefined\n const configuredRedisUrl = config.realtime\n ? resolveRealtimeRedisUrl(config.realtime, env)\n : undefined\n const redisUrl = introspect ? undefined : configuredRedisUrl\n const publisher = config.realtime\n ? redisUrl\n ? (() => {\n const redis = new Bun.RedisClient(redisUrl)\n const subscriber = redis.duplicate()\n lifecycle.add(async () => {\n redis.close()\n ;(await subscriber).close()\n })\n return createRedisRealtimePublisher(redis, subscriber, {\n prefix: process.env.BUNDERSTACK_REALTIME_PREFIX ?? 'bunderstack:',\n maxBufferedEvents: realtimeBufferSize,\n resumeSeconds: realtimeResumeSeconds,\n })\n })()\n : createMemoryRealtimePublisher({\n maxBufferedEvents: realtimeBufferSize,\n resumeSeconds: realtimeResumeSeconds,\n })\n : undefined\n const runtimeRealtimeTransport: RealtimeTransport = !publisher\n ? 'disabled'\n : redisUrl\n ? 'redis'\n : 'memory'\n const realtime = createRealtimeFacade<TSchema>(\n publisher,\n runtimeRealtimeTransport,\n options.schema,\n )\n const registry = createBucketStorages(config.storage)\n const storageOperations = createStorageOperations({\n registry,\n db,\n })\n const storageApiRouter = buildStorageApiRouter(registry, storageOperations)\n const realtimeApiRouter = buildRealtimeApiRouter(publisher, resolvedAccess)\n const storage: StorageFacade = {\n async delete(fileId) {\n const bucketName = fileId.split('/')[0] ?? ''\n const entry = registry.get(bucketName)\n if (entry) {\n await deleteFileWithDerivatives(entry.adapter, db, fileId)\n } else {\n // Unknown bucket: no adapter to clean, but still drop the meta row.\n await deleteFileMetaRow(db, fileId)\n }\n },\n bucket(name) {\n return registry.get(name)?.adapter\n },\n sweep(olderThanMs = DEFAULT_PENDING_TTL_MS) {\n return sweepOrphans(registry, db, olderThanMs)\n },\n async getUrl(key, opts = {}) {\n const bucketName =\n opts.bucket ?? key.split('/')[0] ?? config.storage.defaultBucket\n const adapter = registry.get(bucketName)?.adapter\n if (adapter?.presignGet) {\n return adapter.presignGet(key, {\n expiresIn: opts.expiresIn ?? 3600,\n })\n }\n return `/api/files/${key}`\n },\n async upload(key, body, contentType, opts = {}) {\n const bucketName = key.split('/')[0] ?? ''\n const adapter = registry.get(bucketName)?.adapter\n if (!adapter) throw new Error(`Unknown bucket: ${bucketName}`)\n const u8 = body instanceof Uint8Array ? body : new Uint8Array(body)\n const buf: ArrayBuffer = u8.buffer.slice(\n u8.byteOffset,\n u8.byteOffset + u8.byteLength,\n ) as ArrayBuffer\n await adapter.upload(key, buf, contentType)\n await insertReadyFile(db, {\n fileId: key,\n bucket: bucketName,\n ownerId: opts.ownerId ?? null,\n scopeJson: null,\n filename: opts.filename ?? key.split('/').at(-1) ?? null,\n contentType,\n size: buf.byteLength,\n })\n },\n }\n const storageConfigured = Boolean(options.storage)\n // The storage sweep used to be a hardcoded maintenance route. It is an\n // ordinary cron now, so it inherits retries, timeout and onFailed.\n const resolvedDefs: JobsDefs | undefined = storageConfigured\n ? {\n ...jobsDefs,\n 'bunderstack:storage-sweep': {\n kind: 'cron',\n schedule: '0 4 * * *',\n handler: async () => {\n await storage.sweep()\n },\n },\n }\n : jobsDefs\n\n const jobRunner = resolvedDefs\n ? createJobRunner({\n db,\n defs: resolvedDefs,\n ctx: { db: userDb, env, email, storage, realtime },\n })\n : undefined\n const jobs = {\n async enqueue(name: string, input?: unknown, opts?: EnqueueOptions) {\n if (!resolvedDefs) {\n throw new Error(\n '[bunderstack] no jobs configured — add a `jobs` key to createBunderstack',\n )\n }\n const result = await enqueueJob(db, resolvedDefs, name, input, opts)\n return result\n },\n tick(now?: number) {\n return jobRunner\n ? jobRunner.tick(now)\n : Promise.resolve({ claimed: 0, ran: 0, failed: 0 })\n },\n }\n if (jobRunner) jobRunner.setJobsFacade(jobs)\n const startWorker = async (\n options: AppStartWorkerOptions = {},\n ): Promise<WorkerHandle> => {\n if (introspect) {\n return { closed: Promise.resolve(), close: async () => {} }\n }\n if (!jobRunner) {\n throw new Error('[bunderstack] no queue jobs configured')\n }\n if (lifecycle.status !== 'ready') {\n throw new Error('[bunderstack] application lifecycle is closed')\n }\n const signal = options.signal\n ? AbortSignal.any([lifecycle.signal, options.signal])\n : lifecycle.signal\n const handle = startJobWorker({\n ...options,\n signal,\n // The runtime loop only cares that a tick completed; TickResult is for\n // callers that invoke tick() directly.\n tick: async (now) => {\n await jobRunner.tick(now)\n },\n })\n const unregister = lifecycle.add(() => handle.close())\n void handle.closed.finally(unregister)\n return handle\n }\n const runWorker = async (\n options: AppRunWorkerOptions = {},\n ): Promise<void> => {\n if (introspect) return\n if (\n realtime.transport === 'memory' &&\n !options.allowProcessLocalRealtime\n ) {\n throw new Error(\n '[bunderstack] runWorker() cannot deliver realtime events through the in-memory broker. Configure REDIS_URL or realtime.redis, embed the worker with startWorker(), or pass allowProcessLocalRealtime: true only when jobs never publish realtime.',\n )\n }\n const {\n allowProcessLocalRealtime: _allowProcessLocalRealtime,\n ...workerOptions\n } = options\n const handle = await startWorker(workerOptions)\n try {\n const signal = workerOptions.signal\n ? AbortSignal.any([lifecycle.signal, workerOptions.signal])\n : lifecycle.signal\n await waitForWorkerShutdown(signal, !workerOptions.signal)\n } finally {\n await handle.close()\n await lifecycle.close()\n }\n }\n const crudApiRouter = buildCrudApiRouter<\n TSchema,\n TAccess,\n [TRealtime] extends [false | undefined] ? false : true\n >(options.schema, userDb, {\n access: resolvedAccess,\n idempotency: options.idempotency,\n realtime,\n livePublisher: publisher,\n })\n\n const customApiRouter =\n typeof options.api === 'function'\n ? (\n options.api as (\n builder: BunderstackApiBuilder<TSchema, ValidatedEnv<TEnv>>,\n ) => TCustomApiRouter\n )(createApiBuilder<TSchema, ValidatedEnv<TEnv>>())\n : options.api\n\n const nativeRouter = buildApiRouter({\n crud: crudApiRouter as Record<string, unknown>,\n storage: storageApiRouter as Record<string, unknown>,\n realtime: realtimeApiRouter as Record<string, unknown> | undefined,\n custom: customApiRouter as Record<string, unknown> | undefined,\n middleware: options.middleware,\n }) as any\n\n const authOpenAPISpecRaw =\n options.openapi &&\n auth.api &&\n 'generateOpenAPISchema' in auth.api &&\n typeof auth.api.generateOpenAPISchema === 'function'\n ? await auth.api.generateOpenAPISchema()\n : undefined\n\n const authOpenAPISpec = authOpenAPISpecRaw\n ? normalizeForeignOpenAPISpec(authOpenAPISpecRaw, {\n prefix: '/api/auth',\n source: 'auth',\n })\n : undefined\n\n await buildApiRegistry({\n nativeRouter,\n foreignSpecs: authOpenAPISpec ? [authOpenAPISpec] : [],\n reservedCoreHandles: new Set([\n 'health',\n ...(publisher ? ['realtime.changes'] : []),\n ...[...registry.keys()].flatMap((name) =>\n [\n 'prepareUpload',\n 'upload',\n 'confirmUpload',\n 'download',\n 'delete',\n ].map((operation) => `files.${name}.${operation}`),\n ),\n ]),\n })\n\n const valibotConverter = new ValibotToJsonSchemaConverter()\n\n const combinedOpenAPISpec = options.openapi\n ? mergeOpenAPISpecs({\n nativeSpec: await new OpenAPIGenerator({\n converters: [\n valibotConverter,\n {\n condition: (schema: any) =>\n Boolean(\n schema?.['~standard'] && !schema['~standard'].jsonSchema,\n ),\n convert: (schema: any) => {\n const vendor = schema?.['~standard']?.vendor ?? 'unknown'\n throw new OpenAPIGeneratorError(\n `No JSON Schema converter is configured for Standard Schema vendor \"${vendor}\"`,\n )\n },\n },\n ],\n }).generate(nativeRouter),\n authSpec: authOpenAPISpec,\n })\n : undefined\n\n const openapiHandler = new OpenAPIHandler(nativeRouter, {\n // Query strings and form bodies are strings; this coerces them to the\n // types each procedure's input schema declares, so schemas stay honest\n // (`v.number()`, not a string-union pipe) and REST matches RPC.\n plugins: [\n new SmartCoercionHandlerPlugin({ converters: [valibotConverter] }),\n ],\n customErrorResponseBodyEncoder: (error: any) => {\n if (\n error?.code === 'INTERNAL_SERVER_ERROR' ||\n !error?.status ||\n error.status >= 500\n ) {\n console.error(\n '[bunderstack-api] 500 Internal Server Error:',\n error?.cause ?? error,\n )\n }\n return {\n error: error.message,\n code: error.data?.code ?? error.code,\n // oRPC reports schema failures as `data.issues`; forwarding them tells\n // the client which field was rejected instead of just \"invalid\".\n ...(error.data?.details !== undefined\n ? { details: error.data.details }\n : error.data?.issues !== undefined\n ? { details: error.data.issues }\n : {}),\n }\n },\n fetchInterceptors: [\n async (options) => {\n const res = await options.next()\n if (res.matched && options.context.resHeaders) {\n options.context.resHeaders.forEach((v: string, k: string) =>\n res.response.headers.set(k, v),\n )\n }\n return res\n },\n ],\n })\n // No custom error encoding here: the RPC protocol owns its error body, and\n // `mapBunderstackErrors` already logs unhandled procedure errors for every\n // transport before rethrowing them.\n const rpcHandler = new RPCHandler(nativeRouter)\n\n const apiHandler = async (req: Request): Promise<Response | null> => {\n const urlString = typeof req === 'string' ? (req as string) : req.url\n if (!urlString) return null\n const url = new URL(urlString, 'http://localhost')\n if (\n combinedOpenAPISpec &&\n url.pathname === '/api/openapi.json' &&\n req.method === 'GET'\n ) {\n return new Response(JSON.stringify(combinedOpenAPISpec), {\n headers: { 'Content-Type': 'application/json' },\n })\n }\n\n const apiCtx = createApiContext(\n {\n db: userDb,\n env,\n storage,\n email,\n jobs,\n realtime,\n auth,\n authResolver,\n },\n req,\n )\n\n if (url.pathname.startsWith('/api/rpc')) {\n const res = await rpcHandler.handle(req, {\n prefix: '/api/rpc',\n context: apiCtx,\n })\n if (res.matched) return res.response\n }\n\n const openapiRes = await openapiHandler.handle(req, { context: apiCtx })\n if (openapiRes.matched) return openapiRes.response\n\n return null\n }\n\n const handler = buildHandler({\n authHandler: (req) => auth.handler(req),\n apiHandler,\n rateLimit: options.rateLimit,\n })\n\n // Topology is a deployment concern: the role decides whether this process\n // runs background work, so application code never has to.\n const roleWantsWorker =\n env.BUNDERSTACK_ROLE === 'all' || env.BUNDERSTACK_ROLE === 'worker'\n const autoStart =\n options.background?.autoStart ??\n (roleWantsWorker && !introspect && resolvedDefs !== undefined)\n let backgroundRunning = false\n if (autoStart) {\n await startWorker()\n backgroundRunning = true\n }\n\n const app: BunderstackApp<\n TSchema,\n TAccess,\n BucketNamesOf<TStorage>,\n TEnv,\n JobsDefs | undefined,\n TCustomApiRouter,\n TRealtime\n > = {\n handler,\n // Internal tables live on the runtime db but stay out of the public type.\n db: userDb,\n auth,\n storage,\n env,\n email,\n realtime,\n // Runtime facade is untyped (JobsRuntimeFacade); the generic-typed field\n // narrows `enqueue` per-app from the declared job defs — same relationship\n // as `userDb` above.\n jobs: jobs as never,\n startWorker,\n runWorker,\n close: () => lifecycle.close(),\n backgroundRunning,\n get status() {\n return lifecycle.status\n },\n signal: lifecycle.signal,\n manifest: buildManifest({\n schema: options.schema,\n dialect,\n migrationsDirectory: config.database.migrations,\n storage: config.storage,\n envConfig: options.env as EnvConfigInput | undefined,\n emailProvider: emailProviderTag(options.email),\n realtime: Boolean(config.realtime),\n jobs: resolvedDefs,\n }),\n }\n\n // Hidden handle for the optional `bunderstack/provision` entry. Kept off the\n // public type so provisioning stays opt-in (and drizzle-kit out of this\n // module graph).\n ;(app as WithProvisionInternals)[PROVISION_INTERNALS] = {\n db,\n schema: mergedSchema,\n databaseUrl: config.database.url,\n migrationsFolder: config.database.migrations,\n dialect,\n driver,\n adapter: config.database.adapter,\n }\n\n return app\n } catch (cause) {\n try {\n await lifecycle.close()\n } catch (cleanupCause) {\n throw new AggregateError(\n [cause, cleanupCause],\n '[bunderstack] application initialization failed and cleanup failed',\n )\n }\n throw cause\n }\n}\n\nexport { listSpec } from './api/list-spec'\nexport type { ListSpecOptions } from './api/list-spec'\nexport type { BunderstackDb, BunderstackTx } from './db'\nexport { MAX_LIST_LIMIT } from './list-query'\nexport { BunderstackError } from './errors'\nexport type { BunderstackErrorCode } from './errors'\nexport { resolveConfig, resolveAuthConfig, defineAuth } from './config'\nexport type {\n AuthConfigContext,\n AuthConfigFactory,\n AuthConfigInput,\n BetterAuthConfig,\n BunderstackConfig,\n ResolvedConfig,\n} from './config'\nexport { validateEnv, createClientEnv, BunderstackEnvError } from './env'\nexport type { EnvConfigInput, BaseEnv, ValidatedEnv } from './env'\nexport { buildManifest, parseManifest } from './manifest'\nexport type { BunderstackManifest, ManifestEnvVar } from './manifest'\nexport { createEmail } from './email'\nexport type {\n EmailMessage,\n EmailAdapter,\n EmailConfigInput,\n EmailFacade,\n} from './email'\nexport { createJobsBuilder } from './jobs/index'\nexport type {\n BunderstackJobContext,\n BunderstackJobsBuilder,\n BackgroundDefinition,\n BackgroundDefs,\n CronDefinition,\n CronInvocation,\n EnqueueOptions,\n JobContext,\n JobDefinition,\n JobsDefs,\n JobsFacade,\n JobsRuntimeFacade,\n QueueJobDefinition,\n QueueJobKeys,\n RunWorkerOptions,\n StartWorkerOptions,\n WorkerHandle,\n} from './jobs/index'\nexport {\n defineAccess,\n validateAndResolveAccess,\n checkAccess,\n AUTH_TABLE_NAMES,\n} from './access'\nexport type {\n TableAccessInput,\n OperationRule,\n AccessContext,\n AccessUser,\n} from './access'\nexport {\n typeid,\n generate as generateTypeId,\n parse as parseTypeId,\n asTypeId,\n} from './typeid'\nexport type { TypeId } from './typeid'\nexport type {\n DatabaseAdapter,\n DatabaseConnectOptions,\n DatabaseConnection,\n DatabaseConnectionResult,\n} from './database/adapter'\nexport type { StorageAdapter } from './storage/index'\nexport type {\n StorageConfigInput,\n BucketConfigInput,\n ResolvedBucket,\n} from './storage/buckets'\n// StorageFacade is declared+exported inline above.\nexport type { TransformSpec } from './storage/thumbnails'\nexport { mockAuthSession } from './testing'\n\nexport type { RealtimeAction } from './realtime/publisher'\nexport { createRealtimeFacade } from './realtime/facade'\nexport type {\n RealtimeFacade,\n RealtimeTransport,\n SchemaTable,\n} from './realtime/facade'\n\nexport { createApiBuilder, defineApi } from './api/builder'\nexport type { BunderstackApiBuilder, ApiFactory } from './api/builder'\n// Needed to declare shared middleware over the app's context, e.g.\n// `os.$context<ApiContext<typeof schema>>().middleware(...)`.\nexport type { ApiContext } from './api/context'\nexport type {\n CrudApiRouterFor,\n ExposedApiTables,\n MergeApiRouterTypes,\n UnifiedApiRouter,\n} from './api/types'\nexport type { TableCrudProcedures } from './api/crud-router'\nexport {\n buildApiRegistry,\n mergeApiRoutersStrict,\n normalizeApiPath,\n normalizeForeignOpenAPISpec,\n} from './api/registry'\nexport { mergeOpenAPISpecs } from './api/openapi'\n"]}
@@ -11,6 +11,7 @@
11
11
  export type LiveSnapshotFrame<TRow = Record<string, unknown>> = {
12
12
  type: 'snapshot';
13
13
  items: TRow[];
14
+ operationId?: string;
14
15
  /** The values the server resolved, not the values the caller sent. */
15
16
  sort: string;
16
17
  order: 'asc' | 'desc';
@@ -21,12 +22,14 @@ export type LiveSnapshotFrame<TRow = Record<string, unknown>> = {
21
22
  export type LiveUpsertFrame<TRow = Record<string, unknown>> = {
22
23
  type: 'upsert';
23
24
  record: TRow;
25
+ operationId?: string;
24
26
  /** The id this row follows in the view; `null` means the head. */
25
27
  afterId: string | null;
26
28
  };
27
29
  export type LiveRemoveFrame = {
28
30
  type: 'remove';
29
31
  id: string;
32
+ operationId?: string;
30
33
  };
31
34
  export type LiveHeartbeatFrame = {
32
35
  type: 'heartbeat';
@@ -1 +1 @@
1
- {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/live/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,MAAM,iBAAiB,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IAC9D,IAAI,EAAE,UAAU,CAAA;IAChB,KAAK,EAAE,IAAI,EAAE,CAAA;IACb,sEAAsE;IACtE,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,KAAK,GAAG,MAAM,CAAA;IACrB,KAAK,EAAE,MAAM,CAAA;IACb,6CAA6C;IAC7C,OAAO,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,eAAe,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IAC5D,IAAI,EAAE,QAAQ,CAAA;IACd,MAAM,EAAE,IAAI,CAAA;IACZ,kEAAkE;IAClE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAA;AAE5D,MAAM,MAAM,kBAAkB,GAAG;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAA;AAE1E,MAAM,MAAM,cAAc,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IACrD,eAAe,CAAC,IAAI,CAAC,GACrB,eAAe,CAAA;AAEnB,MAAM,MAAM,SAAS,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAChD,iBAAiB,CAAC,IAAI,CAAC,GACvB,cAAc,CAAC,IAAI,CAAC,GACpB,kBAAkB,CAAA;AAEtB,2EAA2E;AAC3E,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,CAAA;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAClC,CAAA"}
1
+ {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/live/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,MAAM,iBAAiB,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IAC9D,IAAI,EAAE,UAAU,CAAA;IAChB,KAAK,EAAE,IAAI,EAAE,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,sEAAsE;IACtE,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,KAAK,GAAG,MAAM,CAAA;IACrB,KAAK,EAAE,MAAM,CAAA;IACb,6CAA6C;IAC7C,OAAO,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,eAAe,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IAC5D,IAAI,EAAE,QAAQ,CAAA;IACd,MAAM,EAAE,IAAI,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,kEAAkE;IAClE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,QAAQ,CAAA;IACd,EAAE,EAAE,MAAM,CAAA;IACV,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAA;AAE1E,MAAM,MAAM,cAAc,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IACrD,eAAe,CAAC,IAAI,CAAC,GACrB,eAAe,CAAA;AAEnB,MAAM,MAAM,SAAS,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAChD,iBAAiB,CAAC,IAAI,CAAC,GACvB,cAAc,CAAC,IAAI,CAAC,GACpB,kBAAkB,CAAA;AAEtB,2EAA2E;AAC3E,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,CAAA;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAClC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/live/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG","sourcesContent":["/**\n * The wire frames of a live view (`GET /api/{table}:live`).\n *\n * A live view is one SSE stream that opens with a snapshot of a list query and\n * then delivers only what that view cares about. The server decides membership\n * and placement, so a client applies frames without knowing the filter or sort\n * rules, and a reconnect replays a fresh snapshot instead of a refetch.\n *\n * Types only: both the browser client and the server import this module.\n */\n\nexport type LiveSnapshotFrame<TRow = Record<string, unknown>> = {\n type: 'snapshot'\n items: TRow[]\n /** The values the server resolved, not the values the caller sent. */\n sort: string\n order: 'asc' | 'desc'\n limit: number\n /** True when rows exist below the window. */\n hasMore: boolean\n}\n\nexport type LiveUpsertFrame<TRow = Record<string, unknown>> = {\n type: 'upsert'\n record: TRow\n /** The id this row follows in the view; `null` means the head. */\n afterId: string | null\n}\n\nexport type LiveRemoveFrame = { type: 'remove'; id: string }\n\nexport type LiveHeartbeatFrame = { type: 'heartbeat'; intervalMs: number }\n\nexport type LiveDeltaFrame<TRow = Record<string, unknown>> =\n | LiveUpsertFrame<TRow>\n | LiveRemoveFrame\n\nexport type LiveFrame<TRow = Record<string, unknown>> =\n | LiveSnapshotFrame<TRow>\n | LiveDeltaFrame<TRow>\n | LiveHeartbeatFrame\n\n/** The query a live view accepts: the list contract a stream can honor. */\nexport type LiveInput = {\n limit?: number\n sort?: string\n order?: 'asc' | 'desc'\n filters?: Record<string, unknown>\n}\n"]}
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/live/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG","sourcesContent":["/**\n * The wire frames of a live view (`GET /api/{table}:live`).\n *\n * A live view is one SSE stream that opens with a snapshot of a list query and\n * then delivers only what that view cares about. The server decides membership\n * and placement, so a client applies frames without knowing the filter or sort\n * rules, and a reconnect replays a fresh snapshot instead of a refetch.\n *\n * Types only: both the browser client and the server import this module.\n */\n\nexport type LiveSnapshotFrame<TRow = Record<string, unknown>> = {\n type: 'snapshot'\n items: TRow[]\n operationId?: string\n /** The values the server resolved, not the values the caller sent. */\n sort: string\n order: 'asc' | 'desc'\n limit: number\n /** True when rows exist below the window. */\n hasMore: boolean\n}\n\nexport type LiveUpsertFrame<TRow = Record<string, unknown>> = {\n type: 'upsert'\n record: TRow\n operationId?: string\n /** The id this row follows in the view; `null` means the head. */\n afterId: string | null\n}\n\nexport type LiveRemoveFrame = {\n type: 'remove'\n id: string\n operationId?: string\n}\n\nexport type LiveHeartbeatFrame = { type: 'heartbeat'; intervalMs: number }\n\nexport type LiveDeltaFrame<TRow = Record<string, unknown>> =\n | LiveUpsertFrame<TRow>\n | LiveRemoveFrame\n\nexport type LiveFrame<TRow = Record<string, unknown>> =\n | LiveSnapshotFrame<TRow>\n | LiveDeltaFrame<TRow>\n | LiveHeartbeatFrame\n\n/** The query a live view accepts: the list contract a stream can honor. */\nexport type LiveInput = {\n limit?: number\n sort?: string\n order?: 'asc' | 'desc'\n filters?: Record<string, unknown>\n}\n"]}
@@ -5,7 +5,9 @@ export type SchemaTable<TSchema extends Record<string, unknown>> = Extract<TSche
5
5
  export interface RealtimeFacade<TSchema extends Record<string, unknown> = Record<string, unknown>> {
6
6
  readonly enabled: boolean;
7
7
  readonly transport: RealtimeTransport;
8
- publish<TTable extends SchemaTable<TSchema>>(table: TTable, action: RealtimeAction, record: InferSelectModel<TTable>): Promise<void>;
8
+ publish<TTable extends SchemaTable<TSchema>>(table: TTable, action: RealtimeAction, record: InferSelectModel<TTable>, metadata?: {
9
+ operationId?: string;
10
+ }): Promise<void>;
9
11
  }
10
12
  /**
11
13
  * One name for a table everywhere: events, subscriptions, and the CRUD router
@@ -1 +1 @@
1
- {"version":3,"file":"facade.d.ts","sourceRoot":"","sources":["../../src/realtime/facade.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,KAAK,EACX,MAAM,aAAa,CAAA;AAEpB,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAEpE,MAAM,MAAM,iBAAiB,GAAG,UAAU,GAAG,QAAQ,GAAG,OAAO,CAAA;AAE/D,MAAM,MAAM,WAAW,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,OAAO,CACxE,OAAO,CAAC,MAAM,OAAO,CAAC,EACtB,KAAK,CACN,CAAA;AAED,MAAM,WAAW,cAAc,CAC7B,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAEjE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAA;IAErC,OAAO,CAAC,MAAM,SAAS,WAAW,CAAC,OAAO,CAAC,EACzC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,gBAAgB,CAAC,MAAM,CAAC,GAC/B,OAAO,CAAC,IAAI,CAAC,CAAA;CACjB;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC1E,SAAS,CAAC,EAAE,iBAAiB,EAC7B,SAAS,GAAE,iBAAqD,EAChE,MAAM,CAAC,EAAE,OAAO,GACf,cAAc,CAAC,OAAO,CAAC,CA8BzB"}
1
+ {"version":3,"file":"facade.d.ts","sourceRoot":"","sources":["../../src/realtime/facade.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,KAAK,EACX,MAAM,aAAa,CAAA;AAEpB,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAEpE,MAAM,MAAM,iBAAiB,GAAG,UAAU,GAAG,QAAQ,GAAG,OAAO,CAAA;AAE/D,MAAM,MAAM,WAAW,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,OAAO,CACxE,OAAO,CAAC,MAAM,OAAO,CAAC,EACtB,KAAK,CACN,CAAA;AAED,MAAM,WAAW,cAAc,CAC7B,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAEjE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAA;IAErC,OAAO,CAAC,MAAM,SAAS,WAAW,CAAC,OAAO,CAAC,EACzC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,gBAAgB,CAAC,MAAM,CAAC,EAChC,QAAQ,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAClC,OAAO,CAAC,IAAI,CAAC,CAAA;CACjB;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC1E,SAAS,CAAC,EAAE,iBAAiB,EAC7B,SAAS,GAAE,iBAAqD,EAChE,MAAM,CAAC,EAAE,OAAO,GACf,cAAc,CAAC,OAAO,CAAC,CA+BzB"}
@@ -21,7 +21,7 @@ export function createRealtimeFacade(publisher, transport = publisher ? 'memory'
21
21
  return {
22
22
  enabled: publisher !== undefined,
23
23
  transport,
24
- async publish(table, action, record) {
24
+ async publish(table, action, record, metadata) {
25
25
  if (!publisher)
26
26
  return;
27
27
  const tableName = getTableName(table);
@@ -29,6 +29,7 @@ export function createRealtimeFacade(publisher, transport = publisher ? 'memory'
29
29
  table: keyByTableName.get(tableName) ?? tableName,
30
30
  action,
31
31
  record: record,
32
+ ...(metadata?.operationId ? { operationId: metadata.operationId } : {}),
32
33
  });
33
34
  },
34
35
  };
@@ -1 +1 @@
1
- {"version":3,"file":"facade.js","sourceRoot":"","sources":["../../src/realtime/facade.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,OAAO,GAGR,MAAM,aAAa,CAAA;AAwBpB;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAClC,SAA6B,EAC7B,YAA+B,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,EAChE,MAAgB;IAEhB,IAAI,CAAC,SAAS,IAAI,SAAS,KAAK,UAAU,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CACb,kEAAkE,CACnE,CAAA;IACH,CAAC;IACD,IAAI,SAAS,IAAI,SAAS,KAAK,UAAU,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CACb,sEAAsE,CACvE,CAAA;IACH,CAAC;IAED,MAAM,cAAc,GAAG,IAAI,GAAG,EAAkB,CAAA;IAChD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,CAAC;QACxD,IAAI,OAAO,CAAC,KAAK,CAAC;YAAE,cAAc,CAAC,GAAG,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAA;IAClE,CAAC;IAED,OAAO;QACL,OAAO,EAAE,SAAS,KAAK,SAAS;QAChC,SAAS;QACT,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM;YACjC,IAAI,CAAC,SAAS;gBAAE,OAAM;YACtB,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,CAAA;YACrC,MAAM,SAAS,CAAC,OAAO,CAAC,QAAQ,EAAE;gBAChC,KAAK,EAAE,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,SAAS;gBACjD,MAAM;gBACN,MAAM,EAAE,MAA4C;aACrD,CAAC,CAAA;QACJ,CAAC;KACF,CAAA;AACH,CAAC","sourcesContent":["import {\n getTableName,\n isTable,\n type InferSelectModel,\n type Table,\n} from 'drizzle-orm'\n\nimport type { RealtimeAction, RealtimePublisher } from './publisher'\n\nexport type RealtimeTransport = 'disabled' | 'memory' | 'redis'\n\nexport type SchemaTable<TSchema extends Record<string, unknown>> = Extract<\n TSchema[keyof TSchema],\n Table\n>\n\nexport interface RealtimeFacade<\n TSchema extends Record<string, unknown> = Record<string, unknown>,\n> {\n readonly enabled: boolean\n readonly transport: RealtimeTransport\n\n publish<TTable extends SchemaTable<TSchema>>(\n table: TTable,\n action: RealtimeAction,\n record: InferSelectModel<TTable>,\n ): Promise<void>\n}\n\n/**\n * One name for a table everywhere: events, subscriptions, and the CRUD router\n * all use the schema key. Pass the schema so a key like `creditBalances` is not\n * published as its SQL name `credit_balances` — clients subscribe with the key\n * they call procedures with. Without a schema, the SQL name is the only name\n * available and is used as-is.\n */\nexport function createRealtimeFacade<TSchema extends Record<string, unknown>>(\n publisher?: RealtimePublisher,\n transport: RealtimeTransport = publisher ? 'memory' : 'disabled',\n schema?: TSchema,\n): RealtimeFacade<TSchema> {\n if (!publisher && transport !== 'disabled') {\n throw new Error(\n '[bunderstack] an enabled realtime transport requires a publisher',\n )\n }\n if (publisher && transport === 'disabled') {\n throw new Error(\n '[bunderstack] a realtime publisher cannot use the disabled transport',\n )\n }\n\n const keyByTableName = new Map<string, string>()\n for (const [key, value] of Object.entries(schema ?? {})) {\n if (isTable(value)) keyByTableName.set(getTableName(value), key)\n }\n\n return {\n enabled: publisher !== undefined,\n transport,\n async publish(table, action, record) {\n if (!publisher) return\n const tableName = getTableName(table)\n await publisher.publish('change', {\n table: keyByTableName.get(tableName) ?? tableName,\n action,\n record: record as unknown as Record<string, unknown>,\n })\n },\n }\n}\n"]}
1
+ {"version":3,"file":"facade.js","sourceRoot":"","sources":["../../src/realtime/facade.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,OAAO,GAGR,MAAM,aAAa,CAAA;AAyBpB;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAClC,SAA6B,EAC7B,YAA+B,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,EAChE,MAAgB;IAEhB,IAAI,CAAC,SAAS,IAAI,SAAS,KAAK,UAAU,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CACb,kEAAkE,CACnE,CAAA;IACH,CAAC;IACD,IAAI,SAAS,IAAI,SAAS,KAAK,UAAU,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CACb,sEAAsE,CACvE,CAAA;IACH,CAAC;IAED,MAAM,cAAc,GAAG,IAAI,GAAG,EAAkB,CAAA;IAChD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,CAAC;QACxD,IAAI,OAAO,CAAC,KAAK,CAAC;YAAE,cAAc,CAAC,GAAG,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAA;IAClE,CAAC;IAED,OAAO;QACL,OAAO,EAAE,SAAS,KAAK,SAAS;QAChC,SAAS;QACT,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ;YAC3C,IAAI,CAAC,SAAS;gBAAE,OAAM;YACtB,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,CAAA;YACrC,MAAM,SAAS,CAAC,OAAO,CAAC,QAAQ,EAAE;gBAChC,KAAK,EAAE,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,SAAS;gBACjD,MAAM;gBACN,MAAM,EAAE,MAA4C;gBACpD,GAAG,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACxE,CAAC,CAAA;QACJ,CAAC;KACF,CAAA;AACH,CAAC","sourcesContent":["import {\n getTableName,\n isTable,\n type InferSelectModel,\n type Table,\n} from 'drizzle-orm'\n\nimport type { RealtimeAction, RealtimePublisher } from './publisher'\n\nexport type RealtimeTransport = 'disabled' | 'memory' | 'redis'\n\nexport type SchemaTable<TSchema extends Record<string, unknown>> = Extract<\n TSchema[keyof TSchema],\n Table\n>\n\nexport interface RealtimeFacade<\n TSchema extends Record<string, unknown> = Record<string, unknown>,\n> {\n readonly enabled: boolean\n readonly transport: RealtimeTransport\n\n publish<TTable extends SchemaTable<TSchema>>(\n table: TTable,\n action: RealtimeAction,\n record: InferSelectModel<TTable>,\n metadata?: { operationId?: string },\n ): Promise<void>\n}\n\n/**\n * One name for a table everywhere: events, subscriptions, and the CRUD router\n * all use the schema key. Pass the schema so a key like `creditBalances` is not\n * published as its SQL name `credit_balances` — clients subscribe with the key\n * they call procedures with. Without a schema, the SQL name is the only name\n * available and is used as-is.\n */\nexport function createRealtimeFacade<TSchema extends Record<string, unknown>>(\n publisher?: RealtimePublisher,\n transport: RealtimeTransport = publisher ? 'memory' : 'disabled',\n schema?: TSchema,\n): RealtimeFacade<TSchema> {\n if (!publisher && transport !== 'disabled') {\n throw new Error(\n '[bunderstack] an enabled realtime transport requires a publisher',\n )\n }\n if (publisher && transport === 'disabled') {\n throw new Error(\n '[bunderstack] a realtime publisher cannot use the disabled transport',\n )\n }\n\n const keyByTableName = new Map<string, string>()\n for (const [key, value] of Object.entries(schema ?? {})) {\n if (isTable(value)) keyByTableName.set(getTableName(value), key)\n }\n\n return {\n enabled: publisher !== undefined,\n transport,\n async publish(table, action, record, metadata) {\n if (!publisher) return\n const tableName = getTableName(table)\n await publisher.publish('change', {\n table: keyByTableName.get(tableName) ?? tableName,\n action,\n record: record as unknown as Record<string, unknown>,\n ...(metadata?.operationId ? { operationId: metadata.operationId } : {}),\n })\n },\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../src/realtime/filter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,UAAU,EACV,aAAa,EACb,cAAc,EACd,mBAAmB,EACpB,MAAM,WAAW,CAAA;AAClB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAIjD,KAAK,UAAU,GAAG,MAAM,OAAO,CAAC;IAC9B,IAAI,EAAE,UAAU,GAAG,IAAI,CAAA;IACvB,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAA;CACpC,CAAC,CAAA;AAEF,MAAM,WAAW,4BAA4B;IAC3C,aAAa,EAAE,SAAS,MAAM,EAAE,CAAA;IAChC,MAAM,EAAE,cAAc,CAAA;IACtB,OAAO,EAAE,OAAO,CAAA;IAChB,UAAU,EAAE,UAAU,CAAA;CACvB;AAED,MAAM,WAAW,yBAAyB;IACxC,+EAA+E;IAC/E,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,mBAAmB,CAAA;IAC1B;;;OAGG;IACH,IAAI,EAAE,aAAa,CAAA;IACnB,OAAO,EAAE,OAAO,CAAA;IAChB,UAAU,EAAE,UAAU,CAAA;CACvB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,mBAAmB,EAC1B,OAAO,EAAE;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,UAAU,CAAA;CAAE,GACzE,CAAC,MAAM,EAAE,cAAc,KAAK,OAAO,CAAC,OAAO,CAAC,CA6B9C;AAaD,wBAAuB,qBAAqB,CAC1C,MAAM,EAAE,aAAa,CAAC,cAAc,CAAC,EACrC,OAAO,EAAE,4BAA4B,GACpC,cAAc,CAAC,cAAc,EAAE,IAAI,EAAE,IAAI,CAAC,CAiC5C;AAED;;;GAGG;AACH,wBAAuB,kBAAkB,CACvC,MAAM,EAAE,aAAa,CAAC,cAAc,CAAC,EACrC,OAAO,EAAE,yBAAyB,GACjC,cAAc,CAAC,cAAc,EAAE,IAAI,EAAE,IAAI,CAAC,CAO5C"}
1
+ {"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../src/realtime/filter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,UAAU,EACV,aAAa,EACb,cAAc,EACd,mBAAmB,EACpB,MAAM,WAAW,CAAA;AAClB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAIjD,KAAK,UAAU,GAAG,MAAM,OAAO,CAAC;IAC9B,IAAI,EAAE,UAAU,GAAG,IAAI,CAAA;IACvB,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAA;CACpC,CAAC,CAAA;AAEF,MAAM,WAAW,4BAA4B;IAC3C,aAAa,EAAE,SAAS,MAAM,EAAE,CAAA;IAChC,MAAM,EAAE,cAAc,CAAA;IACtB,OAAO,EAAE,OAAO,CAAA;IAChB,UAAU,EAAE,UAAU,CAAA;CACvB;AAED,MAAM,WAAW,yBAAyB;IACxC,+EAA+E;IAC/E,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,mBAAmB,CAAA;IAC1B;;;OAGG;IACH,IAAI,EAAE,aAAa,CAAA;IACnB,OAAO,EAAE,OAAO,CAAA;IAChB,UAAU,EAAE,UAAU,CAAA;CACvB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,mBAAmB,EAC1B,OAAO,EAAE;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,UAAU,CAAA;CAAE,GACzE,CAAC,MAAM,EAAE,cAAc,KAAK,OAAO,CAAC,OAAO,CAAC,CA+B9C;AAcD,wBAAuB,qBAAqB,CAC1C,MAAM,EAAE,aAAa,CAAC,cAAc,CAAC,EACrC,OAAO,EAAE,4BAA4B,GACpC,cAAc,CAAC,cAAc,EAAE,IAAI,EAAE,IAAI,CAAC,CAiC5C;AAED;;;GAGG;AACH,wBAAuB,kBAAkB,CACvC,MAAM,EAAE,aAAa,CAAC,cAAc,CAAC,EACrC,OAAO,EAAE,yBAAyB,GACjC,cAAc,CAAC,cAAc,EAAE,IAAI,EAAE,IAAI,CAAC,CAO5C"}
@@ -37,6 +37,7 @@ function project(change) {
37
37
  table: change.table,
38
38
  action: change.action,
39
39
  record: change.record,
40
+ ...(change.operationId ? { operationId: change.operationId } : {}),
40
41
  };
41
42
  const meta = getEventMeta(change);
42
43
  return meta ? withEventMeta(projected, meta) : projected;
@@ -1 +1 @@
1
- {"version":3,"file":"filter.js","sourceRoot":"","sources":["../../src/realtime/filter.ts"],"names":[],"mappings":"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","sourcesContent":["import { getEventMeta, withEventMeta } from '@orpc/server'\n\nimport type {\n AccessUser,\n OperationRule,\n ResolvedAccess,\n ResolvedTableAccess,\n} from '../access'\nimport type { RealtimeChange } from './publisher'\n\nimport { checkAccess, rowMatchesScope, tableEntryForName } from '../access'\n\ntype GetSession = () => Promise<{\n user: AccessUser | null\n activeOrganizationId: string | null\n}>\n\nexport interface FilterRealtimeChangesOptions {\n subscriptions: readonly string[]\n access: ResolvedAccess\n request: Request\n getSession: GetSession\n}\n\nexport interface FilterTableChangesOptions {\n /** Events arrive under this name — the schema key they were published with. */\n tableName: string\n entry: ResolvedTableAccess\n /**\n * The operation right this stream reads under: `get` for a subscription to\n * rows, `list` for a live view of a query.\n */\n rule: OperationRule\n request: Request\n getSession: GetSession\n}\n\n/**\n * Whether one change may reach this subscriber: the given right plus the read\n * scope of the row, evaluated against the caller's session. The session\n * resolves at most once per stream.\n */\nexport function createChangeGuard(\n entry: ResolvedTableAccess,\n options: { rule: OperationRule; request: Request; getSession: GetSession },\n): (change: RealtimeChange) => Promise<boolean> {\n let sessionPromise: ReturnType<GetSession> | undefined\n const getSession = () => (sessionPromise ??= options.getSession())\n\n return async (change) => {\n if (!entry.enabled || options.rule === 'deny') return false\n\n const needsSession =\n options.rule !== 'public' || entry.readScope !== undefined\n const session = needsSession\n ? await getSession()\n : { user: null, activeOrganizationId: null }\n const context = {\n request: options.request,\n user: session.user,\n row: change.record,\n session: { activeOrganizationId: session.activeOrganizationId },\n }\n if (!(await checkAccess(options.rule, context, entry.ownerColumn)).allowed) {\n return false\n }\n if (\n entry.readScope &&\n !rowMatchesScope(change.record, entry.readScope(context))\n ) {\n return false\n }\n return true\n }\n}\n\n/** Preserve publisher event metadata (ids) across the projection. */\nfunction project(change: RealtimeChange): RealtimeChange {\n const projected: RealtimeChange = {\n table: change.table,\n action: change.action,\n record: change.record,\n }\n const meta = getEventMeta(change)\n return meta ? withEventMeta(projected, meta) : projected\n}\n\nexport async function* filterRealtimeChanges(\n source: AsyncIterable<RealtimeChange>,\n options: FilterRealtimeChangesOptions,\n): AsyncGenerator<RealtimeChange, void, void> {\n const subscriptions = new Set(options.subscriptions)\n // One guard — and therefore one cached session — per table entry.\n const guards = new Map<\n ResolvedTableAccess,\n ReturnType<typeof createChangeGuard>\n >()\n\n for await (const change of source) {\n // Events name tables by schema key; the SQL-name lookup stays as a fallback\n // for publishers outside the CRUD path that only know the physical name.\n const entry =\n options.access.get(change.table) ??\n tableEntryForName(options.access, change.table)\n if (!entry?.enabled) continue\n\n const recordId = change.record.id\n if (\n !subscriptions.has(change.table) &&\n (recordId == null ||\n !subscriptions.has(`${change.table}/${String(recordId)}`))\n ) {\n continue\n }\n\n let guard = guards.get(entry)\n if (!guard) {\n guard = createChangeGuard(entry, { ...options, rule: entry.get })\n guards.set(entry, guard)\n }\n if (!(await guard(change))) continue\n yield project(change)\n }\n}\n\n/**\n * The same stream narrowed to one table with its access entry known up front —\n * what a live view (`GET /{table}:live`) consumes.\n */\nexport async function* filterTableChanges(\n source: AsyncIterable<RealtimeChange>,\n options: FilterTableChangesOptions,\n): AsyncGenerator<RealtimeChange, void, void> {\n const guard = createChangeGuard(options.entry, options)\n for await (const change of source) {\n if (change.table !== options.tableName) continue\n if (!(await guard(change))) continue\n yield project(change)\n }\n}\n"]}
1
+ {"version":3,"file":"filter.js","sourceRoot":"","sources":["../../src/realtime/filter.ts"],"names":[],"mappings":"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","sourcesContent":["import { getEventMeta, withEventMeta } from '@orpc/server'\n\nimport type {\n AccessUser,\n OperationRule,\n ResolvedAccess,\n ResolvedTableAccess,\n} from '../access'\nimport type { RealtimeChange } from './publisher'\n\nimport { checkAccess, rowMatchesScope, tableEntryForName } from '../access'\n\ntype GetSession = () => Promise<{\n user: AccessUser | null\n activeOrganizationId: string | null\n}>\n\nexport interface FilterRealtimeChangesOptions {\n subscriptions: readonly string[]\n access: ResolvedAccess\n request: Request\n getSession: GetSession\n}\n\nexport interface FilterTableChangesOptions {\n /** Events arrive under this name — the schema key they were published with. */\n tableName: string\n entry: ResolvedTableAccess\n /**\n * The operation right this stream reads under: `get` for a subscription to\n * rows, `list` for a live view of a query.\n */\n rule: OperationRule\n request: Request\n getSession: GetSession\n}\n\n/**\n * Whether one change may reach this subscriber: the given right plus the read\n * scope of the row, evaluated against the caller's session. The session\n * resolves at most once per stream.\n */\nexport function createChangeGuard(\n entry: ResolvedTableAccess,\n options: { rule: OperationRule; request: Request; getSession: GetSession },\n): (change: RealtimeChange) => Promise<boolean> {\n let sessionPromise: ReturnType<GetSession> | undefined\n const getSession = () => (sessionPromise ??= options.getSession())\n\n return async (change) => {\n if (!entry.enabled || options.rule === 'deny') return false\n\n const needsSession =\n options.rule !== 'public' || entry.readScope !== undefined\n const session = needsSession\n ? await getSession()\n : { user: null, activeOrganizationId: null }\n const context = {\n request: options.request,\n user: session.user,\n row: change.record,\n session: { activeOrganizationId: session.activeOrganizationId },\n }\n if (\n !(await checkAccess(options.rule, context, entry.ownerColumn)).allowed\n ) {\n return false\n }\n if (\n entry.readScope &&\n !rowMatchesScope(change.record, entry.readScope(context))\n ) {\n return false\n }\n return true\n }\n}\n\n/** Preserve publisher event metadata (ids) across the projection. */\nfunction project(change: RealtimeChange): RealtimeChange {\n const projected: RealtimeChange = {\n table: change.table,\n action: change.action,\n record: change.record,\n ...(change.operationId ? { operationId: change.operationId } : {}),\n }\n const meta = getEventMeta(change)\n return meta ? withEventMeta(projected, meta) : projected\n}\n\nexport async function* filterRealtimeChanges(\n source: AsyncIterable<RealtimeChange>,\n options: FilterRealtimeChangesOptions,\n): AsyncGenerator<RealtimeChange, void, void> {\n const subscriptions = new Set(options.subscriptions)\n // One guard — and therefore one cached session — per table entry.\n const guards = new Map<\n ResolvedTableAccess,\n ReturnType<typeof createChangeGuard>\n >()\n\n for await (const change of source) {\n // Events name tables by schema key; the SQL-name lookup stays as a fallback\n // for publishers outside the CRUD path that only know the physical name.\n const entry =\n options.access.get(change.table) ??\n tableEntryForName(options.access, change.table)\n if (!entry?.enabled) continue\n\n const recordId = change.record.id\n if (\n !subscriptions.has(change.table) &&\n (recordId == null ||\n !subscriptions.has(`${change.table}/${String(recordId)}`))\n ) {\n continue\n }\n\n let guard = guards.get(entry)\n if (!guard) {\n guard = createChangeGuard(entry, { ...options, rule: entry.get })\n guards.set(entry, guard)\n }\n if (!(await guard(change))) continue\n yield project(change)\n }\n}\n\n/**\n * The same stream narrowed to one table with its access entry known up front —\n * what a live view (`GET /{table}:live`) consumes.\n */\nexport async function* filterTableChanges(\n source: AsyncIterable<RealtimeChange>,\n options: FilterTableChangesOptions,\n): AsyncGenerator<RealtimeChange, void, void> {\n const guard = createChangeGuard(options.entry, options)\n for await (const change of source) {\n if (change.table !== options.tableName) continue\n if (!(await guard(change))) continue\n yield project(change)\n }\n}\n"]}
@@ -5,6 +5,8 @@ export interface RealtimeChange {
5
5
  table: string;
6
6
  action: RealtimeAction;
7
7
  record: Record<string, unknown>;
8
+ /** Correlates this confirmed write with the client operation that caused it. */
9
+ operationId?: string;
8
10
  }
9
11
  export interface RealtimeEvents extends Record<string, object> {
10
12
  change: RealtimeChange;
@@ -1 +1 @@
1
- {"version":3,"file":"publisher.d.ts","sourceRoot":"","sources":["../../src/realtime/publisher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAChD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,KAAK,CAAA;AAKtC,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAE3D,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,cAAc,CAAA;IACtB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAChC;AAED,MAAM,WAAW,cAAe,SAAQ,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAC5D,MAAM,EAAE,cAAc,CAAA;CACvB;AAED,MAAM,MAAM,iBAAiB,GAAG,SAAS,CAAC,cAAc,CAAC,CAAA;AAEzD,MAAM,WAAW,wBAAwB;IACvC,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,wBAAgB,6BAA6B,CAC3C,OAAO,GAAE,wBAA6B,GACrC,iBAAiB,CAKnB;AAED,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,WAAW,EAClB,UAAU,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,EAC9C,OAAO,GAAE,wBAAwB,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GAC3D,iBAAiB,CAOnB"}
1
+ {"version":3,"file":"publisher.d.ts","sourceRoot":"","sources":["../../src/realtime/publisher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAChD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,KAAK,CAAA;AAKtC,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAE3D,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,cAAc,CAAA;IACtB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC/B,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,cAAe,SAAQ,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAC5D,MAAM,EAAE,cAAc,CAAA;CACvB;AAED,MAAM,MAAM,iBAAiB,GAAG,SAAS,CAAC,cAAc,CAAC,CAAA;AAEzD,MAAM,WAAW,wBAAwB;IACvC,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,wBAAgB,6BAA6B,CAC3C,OAAO,GAAE,wBAA6B,GACrC,iBAAiB,CAKnB;AAED,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,WAAW,EAClB,UAAU,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,EAC9C,OAAO,GAAE,wBAAwB,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GAC3D,iBAAiB,CAOnB"}
@@ -1 +1 @@
1
- {"version":3,"file":"publisher.js","sourceRoot":"","sources":["../../src/realtime/publisher.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAqBxD,MAAM,UAAU,6BAA6B,CAC3C,UAAoC,EAAE;IAEtC,OAAO,IAAI,eAAe,CAAiB;QACzC,iBAAiB,EAAE,OAAO,CAAC,iBAAiB;QAC5C,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,aAAa,IAAI,GAAG,EAAE;KACjE,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,UAAU,4BAA4B,CAC1C,KAAkB,EAClB,UAA8C,EAC9C,UAA0D,EAAE;IAE5D,OAAO,IAAI,iBAAiB,CAAiB,KAAK,EAAE;QAClD,UAAU;QACV,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,cAAc;QACxC,iBAAiB,EAAE,OAAO,CAAC,iBAAiB;QAC5C,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,aAAa,IAAI,GAAG,EAAE;KACjE,CAAC,CAAA;AACJ,CAAC","sourcesContent":["import type { Publisher } from '@orpc/publisher'\nimport type { RedisClient } from 'bun'\n\nimport { BunRedisPublisher } from '@orpc/bun'\nimport { MemoryPublisher } from '@orpc/publisher/memory'\n\nexport type RealtimeAction = 'create' | 'update' | 'delete'\n\nexport interface RealtimeChange {\n table: string\n action: RealtimeAction\n record: Record<string, unknown>\n}\n\nexport interface RealtimeEvents extends Record<string, object> {\n change: RealtimeChange\n}\n\nexport type RealtimePublisher = Publisher<RealtimeEvents>\n\nexport interface RealtimePublisherOptions {\n maxBufferedEvents?: number\n resumeSeconds?: number\n}\n\nexport function createMemoryRealtimePublisher(\n options: RealtimePublisherOptions = {},\n): RealtimePublisher {\n return new MemoryPublisher<RealtimeEvents>({\n maxBufferedEvents: options.maxBufferedEvents,\n resume: { enabled: true, seconds: options.resumeSeconds ?? 300 },\n })\n}\n\nexport function createRedisRealtimePublisher(\n redis: RedisClient,\n subscriber: RedisClient | Promise<RedisClient>,\n options: RealtimePublisherOptions & { prefix?: string } = {},\n): RealtimePublisher {\n return new BunRedisPublisher<RealtimeEvents>(redis, {\n subscriber,\n prefix: options.prefix ?? 'bunderstack:',\n maxBufferedEvents: options.maxBufferedEvents,\n resume: { enabled: true, seconds: options.resumeSeconds ?? 300 },\n })\n}\n"]}
1
+ {"version":3,"file":"publisher.js","sourceRoot":"","sources":["../../src/realtime/publisher.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAuBxD,MAAM,UAAU,6BAA6B,CAC3C,UAAoC,EAAE;IAEtC,OAAO,IAAI,eAAe,CAAiB;QACzC,iBAAiB,EAAE,OAAO,CAAC,iBAAiB;QAC5C,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,aAAa,IAAI,GAAG,EAAE;KACjE,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,UAAU,4BAA4B,CAC1C,KAAkB,EAClB,UAA8C,EAC9C,UAA0D,EAAE;IAE5D,OAAO,IAAI,iBAAiB,CAAiB,KAAK,EAAE;QAClD,UAAU;QACV,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,cAAc;QACxC,iBAAiB,EAAE,OAAO,CAAC,iBAAiB;QAC5C,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,aAAa,IAAI,GAAG,EAAE;KACjE,CAAC,CAAA;AACJ,CAAC","sourcesContent":["import type { Publisher } from '@orpc/publisher'\nimport type { RedisClient } from 'bun'\n\nimport { BunRedisPublisher } from '@orpc/bun'\nimport { MemoryPublisher } from '@orpc/publisher/memory'\n\nexport type RealtimeAction = 'create' | 'update' | 'delete'\n\nexport interface RealtimeChange {\n table: string\n action: RealtimeAction\n record: Record<string, unknown>\n /** Correlates this confirmed write with the client operation that caused it. */\n operationId?: string\n}\n\nexport interface RealtimeEvents extends Record<string, object> {\n change: RealtimeChange\n}\n\nexport type RealtimePublisher = Publisher<RealtimeEvents>\n\nexport interface RealtimePublisherOptions {\n maxBufferedEvents?: number\n resumeSeconds?: number\n}\n\nexport function createMemoryRealtimePublisher(\n options: RealtimePublisherOptions = {},\n): RealtimePublisher {\n return new MemoryPublisher<RealtimeEvents>({\n maxBufferedEvents: options.maxBufferedEvents,\n resume: { enabled: true, seconds: options.resumeSeconds ?? 300 },\n })\n}\n\nexport function createRedisRealtimePublisher(\n redis: RedisClient,\n subscriber: RedisClient | Promise<RedisClient>,\n options: RealtimePublisherOptions & { prefix?: string } = {},\n): RealtimePublisher {\n return new BunRedisPublisher<RealtimeEvents>(redis, {\n subscriber,\n prefix: options.prefix ?? 'bunderstack:',\n maxBufferedEvents: options.maxBufferedEvents,\n resume: { enabled: true, seconds: options.resumeSeconds ?? 300 },\n })\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bunderstack",
3
- "version": "0.19.2",
3
+ "version": "0.20.0",
4
4
  "description": "Batteries-included backend framework for Bun: type-safe oRPC APIs, auth, storage, realtime, jobs, email, and validated env from one config.",
5
5
  "keywords": [
6
6
  "backend",
@@ -44,6 +44,10 @@
44
44
  "types": "./dist/access.d.ts",
45
45
  "default": "./dist/access.js"
46
46
  },
47
+ "./codegen": {
48
+ "types": "./dist/codegen.d.ts",
49
+ "default": "./dist/codegen.js"
50
+ },
47
51
  "./database/bun-sql": {
48
52
  "types": "./dist/database/bun-sql.d.ts",
49
53
  "default": "./dist/database/bun-sql.js"