bunderstack 0.18.0 → 0.19.1

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 (110) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/access.js.map +1 -1
  3. package/dist/api/builder.js.map +1 -1
  4. package/dist/api/context.js.map +1 -1
  5. package/dist/api/crud-router.d.ts +121 -0
  6. package/dist/api/crud-router.d.ts.map +1 -1
  7. package/dist/api/crud-router.js +110 -4
  8. package/dist/api/crud-router.js.map +1 -1
  9. package/dist/api/list-input-schema.d.ts +15 -0
  10. package/dist/api/list-input-schema.d.ts.map +1 -1
  11. package/dist/api/list-input-schema.js +16 -0
  12. package/dist/api/list-input-schema.js.map +1 -1
  13. package/dist/api/list-spec.js.map +1 -1
  14. package/dist/api/live-view.d.ts +14 -0
  15. package/dist/api/live-view.d.ts.map +1 -0
  16. package/dist/api/live-view.js +42 -0
  17. package/dist/api/live-view.js.map +1 -0
  18. package/dist/api/live-window.d.ts +40 -0
  19. package/dist/api/live-window.d.ts.map +1 -0
  20. package/dist/api/live-window.js +83 -0
  21. package/dist/api/live-window.js.map +1 -0
  22. package/dist/api/openapi.js.map +1 -1
  23. package/dist/api/realtime-router.js.map +1 -1
  24. package/dist/api/registry.js.map +1 -1
  25. package/dist/api/router.js.map +1 -1
  26. package/dist/api/storage-router.js.map +1 -1
  27. package/dist/api/types.d.ts +1 -1
  28. package/dist/api/types.d.ts.map +1 -1
  29. package/dist/api/types.js.map +1 -1
  30. package/dist/auth.js.map +1 -1
  31. package/dist/blueprint-generator.js.map +1 -1
  32. package/dist/blueprint.js.map +1 -1
  33. package/dist/cli-skills.js.map +1 -1
  34. package/dist/cli.js.map +1 -1
  35. package/dist/config.js.map +1 -1
  36. package/dist/cron.js.map +1 -1
  37. package/dist/crud-operations.js.map +1 -1
  38. package/dist/database/adapter.js.map +1 -1
  39. package/dist/database/bun-sql.js.map +1 -1
  40. package/dist/database/libsql.js.map +1 -1
  41. package/dist/database/pglite.js.map +1 -1
  42. package/dist/database/postgres-js.js.map +1 -1
  43. package/dist/db.js.map +1 -1
  44. package/dist/dialect.js.map +1 -1
  45. package/dist/email/smtp.js.map +1 -1
  46. package/dist/email.js.map +1 -1
  47. package/dist/env.js.map +1 -1
  48. package/dist/errors.js.map +1 -1
  49. package/dist/handler.js.map +1 -1
  50. package/dist/idempotency.js.map +1 -1
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +1 -0
  53. package/dist/index.js.map +1 -1
  54. package/dist/internal-tables-pg.js.map +1 -1
  55. package/dist/internal-tables.js.map +1 -1
  56. package/dist/jobs/cron.js.map +1 -1
  57. package/dist/jobs/define.js.map +1 -1
  58. package/dist/jobs/index.js.map +1 -1
  59. package/dist/jobs/queue.js.map +1 -1
  60. package/dist/jobs/runtime.js.map +1 -1
  61. package/dist/jobs/slots.js.map +1 -1
  62. package/dist/jobs/worker.js.map +1 -1
  63. package/dist/lifecycle.js.map +1 -1
  64. package/dist/list-query.js.map +1 -1
  65. package/dist/live/apply.d.ts +13 -0
  66. package/dist/live/apply.d.ts.map +1 -0
  67. package/dist/live/apply.js +32 -0
  68. package/dist/live/apply.js.map +1 -0
  69. package/dist/live/index.d.ts +48 -0
  70. package/dist/live/index.d.ts.map +1 -0
  71. package/dist/live/index.js +108 -0
  72. package/dist/live/index.js.map +1 -0
  73. package/dist/live/protocol.d.ts +44 -0
  74. package/dist/live/protocol.d.ts.map +1 -0
  75. package/dist/live/protocol.js +12 -0
  76. package/dist/live/protocol.js.map +1 -0
  77. package/dist/live/sse.d.ts +22 -0
  78. package/dist/live/sse.d.ts.map +1 -0
  79. package/dist/live/sse.js +41 -0
  80. package/dist/live/sse.js.map +1 -0
  81. package/dist/manifest.js.map +1 -1
  82. package/dist/provision-internals.js.map +1 -1
  83. package/dist/provision.js.map +1 -1
  84. package/dist/rate-limit.js.map +1 -1
  85. package/dist/realtime/facade.js.map +1 -1
  86. package/dist/realtime/filter.d.ts +34 -5
  87. package/dist/realtime/filter.d.ts.map +1 -1
  88. package/dist/realtime/filter.js +62 -25
  89. package/dist/realtime/filter.js.map +1 -1
  90. package/dist/realtime/heartbeat.js.map +1 -1
  91. package/dist/realtime/publisher.js.map +1 -1
  92. package/dist/schema-export-pg.js.map +1 -1
  93. package/dist/schema-export.js.map +1 -1
  94. package/dist/scope.js.map +1 -1
  95. package/dist/standard-schema.js.map +1 -1
  96. package/dist/storage/buckets.js.map +1 -1
  97. package/dist/storage/delete.js.map +1 -1
  98. package/dist/storage/file-meta.js.map +1 -1
  99. package/dist/storage/index.js.map +1 -1
  100. package/dist/storage/local.js.map +1 -1
  101. package/dist/storage/operations.js.map +1 -1
  102. package/dist/storage/registry.js.map +1 -1
  103. package/dist/storage/s3.js.map +1 -1
  104. package/dist/storage/sweep.js.map +1 -1
  105. package/dist/storage/thumbnails.js.map +1 -1
  106. package/dist/testing.js.map +1 -1
  107. package/dist/typeid-pg.js.map +1 -1
  108. package/dist/typeid.js.map +1 -1
  109. package/llms.txt +3 -3
  110. package/package.json +6 -2
package/CHANGELOG.md CHANGED
@@ -4,6 +4,30 @@ All notable changes to `bunderstack` will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.19.1] - 2026-08-23
8
+
9
+ ### Fixed
10
+
11
+ - **Inline source maps in published packages.** `tsconfig.build.json` enables
12
+ `inlineSources: true` across all packages, embedding TypeScript source code
13
+ into `.js.map` files. This prevents bundlers and dev servers (like Vite) from
14
+ emitting warnings about missing source files when consuming packages whose
15
+ `src/` directory is omitted from npm tarballs.
16
+
17
+ ## [0.19.0] - 2026-08-23
18
+
19
+ ### Added
20
+
21
+ - **Live views.** `GET /api/live/{table}` streams one list query: a snapshot of
22
+ the result, then only the changes that belong to it. The server evaluates the
23
+ view's filters per record and places each row (`afterId`), so a client keeps
24
+ the view current without a cache, without invalidation, and without repeating
25
+ the sort. Every connection opens with a snapshot, which makes a reconnect its
26
+ own resynchronisation. The new `bunderstack/live` subpath holds a
27
+ dependency-free browser client (`createLiveView`) built on `subscribe` plus
28
+ `getRows`. Reading a live view needs the table's `list` right, which also
29
+ gates every delivered change.
30
+
7
31
  ## [0.18.0] - 2026-08-20
8
32
 
9
33
  ### Fixed
@@ -1 +1 @@
1
- {"version":3,"file":"access.js","sourceRoot":"","sources":["../src/access.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"access.js","sourceRoot":"","sources":["../src/access.ts"],"names":[],"mappings":"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","sourcesContent":["import { getTableColumns, getTableName, isTable } from 'drizzle-orm'\n\nimport { INTERNAL_TABLE_NAMES } from './internal-tables'\n\nexport const AUTH_TABLE_NAMES = new Set([\n 'user',\n 'session',\n 'account',\n 'verification',\n])\n\nconst EXPOSEABLE_AUTH_TABLES = new Set(['user'])\n\nexport type AccessUser = {\n id: string\n email: string\n name?: string\n role?: string\n}\n\nexport type AccessContext = {\n user: AccessUser | null\n request: Request\n row?: Record<string, unknown>\n body?: Record<string, unknown>\n session?: { activeOrganizationId: string | null } | null\n}\n\nexport type OperationRule =\n | 'public'\n | 'authenticated'\n | 'owner'\n | 'deny'\n | ((ctx: AccessContext) => boolean | Promise<boolean>)\n\nexport type ScopeMap = Record<string, string | string[]>\nexport type ScopeResolver = (ctx: AccessContext) => ScopeMap\n\nexport type CrudOperation = 'list' | 'get' | 'create' | 'update' | 'delete'\n\nexport type SortOrder = 'asc' | 'desc'\n\nexport type DefaultSort = {\n column: string\n order: SortOrder\n}\n\nexport type TableAccessInput = {\n crud?: boolean\n /** Opt the BetterAuth `user` table into auto-CRUD (read profiles, owner-update image). */\n exposeAuthTable?: boolean\n ownerColumn?: string\n list?: OperationRule\n get?: OperationRule\n create?: OperationRule\n update?: OperationRule\n delete?: OperationRule\n /** Explicit write allowlist. Entries override matching system-readonly\n * defaults such as `updatedAt`; `id` remains immutable on update. */\n writableColumns?: string[]\n readonlyColumns?: string[]\n /** Columns matched by `?q=` on list — opt-in; omitted columns are never searched. */\n searchableColumns?: string[]\n /** Columns filterable via flat `?column=value` query params. */\n filterableColumns?: string[]\n /** Columns allowed in `?sort=`. Defaults to `['id']`. */\n sortableColumns?: string[]\n /** Default list ordering when `?sort` is omitted. Defaults to `{ column: 'id', order: 'desc' }`. */\n defaultSort?: DefaultSort\n scope?: {\n read?: ScopeResolver\n write?: ScopeResolver\n }\n}\n\nexport type ResolvedTableAccess = {\n tableKey: string\n tableName: string\n enabled: boolean\n ownerColumn?: string\n list: OperationRule\n get: OperationRule\n create: OperationRule\n update: OperationRule\n delete: OperationRule\n writableColumns?: string[]\n readonlyColumns: string[]\n searchableColumns?: string[]\n filterableColumns: string[]\n sortableColumns: string[]\n defaultSort: DefaultSort\n readScope?: ScopeResolver\n writeScope?: ScopeResolver\n}\n\nexport type ResolvedAccess = Map<string, ResolvedTableAccess>\n\n/**\n * Look up a table's resolved access by its physical table name.\n *\n * `ResolvedAccess` is keyed by schema export name, not table name, so every\n * consumer that starts from a physical name needs this scan. It lives here so\n * CRUD, realtime, and route validation cannot drift apart on which tables they\n * consider enabled.\n */\nexport function tableEntryForName(\n access: ResolvedAccess,\n tableName: string,\n): ResolvedTableAccess | undefined {\n for (const entry of access.values()) {\n if (entry.tableName === tableName) return entry\n }\n return undefined\n}\n\nconst DEFAULT_READONLY = [\n 'id',\n 'createdAt',\n 'updatedAt',\n 'created_at',\n 'updated_at',\n]\n\nfunction getSchemaTables<TSchema extends Record<string, unknown>>(\n schema: TSchema,\n) {\n const tables: {\n key: string\n table: Parameters<typeof getTableName>[0]\n name: string\n columns: string[]\n }[] = []\n for (const [key, value] of Object.entries(schema)) {\n if (!isTable(value)) continue\n const name = getTableName(value)\n const columns = Object.keys(getTableColumns(value))\n tables.push({ key, table: value, name, columns })\n }\n return tables\n}\n\nfunction resolveListAccess(\n input: TableAccessInput,\n columns: string[],\n): Pick<\n ResolvedTableAccess,\n 'filterableColumns' | 'sortableColumns' | 'defaultSort'\n> {\n const sortableColumns =\n input.sortableColumns ?? (columns.includes('id') ? ['id'] : [])\n const defaultSort: DefaultSort = input.defaultSort ?? {\n column: sortableColumns[0] ?? 'id',\n order: 'desc',\n }\n\n if (!columns.includes(defaultSort.column)) {\n throw new Error(\n `[bunderstack] defaultSort.column \"${defaultSort.column}\" is not a column on this table`,\n )\n }\n if (!sortableColumns.includes(defaultSort.column)) {\n throw new Error(\n `[bunderstack] defaultSort.column \"${defaultSort.column}\" must be listed in sortableColumns`,\n )\n }\n\n const filterableColumns = input.filterableColumns ?? []\n for (const col of filterableColumns) {\n if (!columns.includes(col)) {\n throw new Error(\n `[bunderstack] filterableColumns references unknown column \"${col}\"`,\n )\n }\n }\n\n for (const col of sortableColumns) {\n if (!columns.includes(col)) {\n throw new Error(\n `[bunderstack] sortableColumns references unknown column \"${col}\"`,\n )\n }\n }\n\n return { filterableColumns, sortableColumns, defaultSort }\n}\n\nfunction resolveDefaults(\n input: TableAccessInput,\n ownerColumn: string | undefined,\n columns: string[],\n): Omit<ResolvedTableAccess, 'tableKey' | 'tableName' | 'enabled'> {\n const listAccess = resolveListAccess(input, columns)\n const explicitlyWritable = new Set(input.writableColumns ?? [])\n return {\n ownerColumn,\n list: input.list ?? 'public',\n get: input.get ?? 'public',\n create: input.create ?? 'public',\n update: input.update ?? (ownerColumn ? 'owner' : 'deny'),\n delete: input.delete ?? (ownerColumn ? 'owner' : 'deny'),\n writableColumns: input.writableColumns,\n readonlyColumns: [\n ...DEFAULT_READONLY.filter(\n (column) => column === 'id' || !explicitlyWritable.has(column),\n ),\n ...(input.readonlyColumns ?? []),\n ...(ownerColumn ? [ownerColumn] : []),\n ],\n searchableColumns: input.searchableColumns,\n readScope: input.scope?.read,\n writeScope: input.scope?.write,\n ...listAccess,\n }\n}\n\nfunction detectOwnerColumn(\n columns: string[],\n input?: TableAccessInput,\n): string | undefined {\n if (input?.ownerColumn) return input.ownerColumn\n if (columns.includes('userId')) return 'userId'\n return undefined\n}\n\nexport function validateAndResolveAccess<\n TSchema extends Record<string, unknown>,\n>(\n schema: TSchema,\n accessInput?: Record<string, TableAccessInput>,\n): ResolvedAccess {\n const tables = getSchemaTables(schema)\n const tableByKey = new Map(tables.map((t) => [t.key, t]))\n const resolved: ResolvedAccess = new Map()\n\n if (accessInput) {\n for (const key of Object.keys(accessInput)) {\n if (!tableByKey.has(key)) {\n throw new Error(\n `[bunderstack] access.${key} does not match any table in schema`,\n )\n }\n const tableName = tableByKey.get(key)!.name\n const input = accessInput[key]\n if (AUTH_TABLE_NAMES.has(tableName)) {\n if (input?.crud === false) continue\n if (!EXPOSEABLE_AUTH_TABLES.has(tableName) || !input?.exposeAuthTable) {\n throw new Error(\n `[bunderstack] access.${key} cannot target auth table \"${tableName}\" — use { crud: false } to silence, or exposeAuthTable on user`,\n )\n }\n }\n }\n }\n\n for (const { key, name, columns } of tables) {\n const input = accessInput?.[key]\n if (input?.crud === false) continue\n if (INTERNAL_TABLE_NAMES.has(name)) continue\n\n if (AUTH_TABLE_NAMES.has(name)) {\n if (!input?.exposeAuthTable || !EXPOSEABLE_AUTH_TABLES.has(name)) continue\n\n const ownerColumn = input.ownerColumn ?? 'id'\n if (!columns.includes(ownerColumn)) {\n throw new Error(\n `[bunderstack] access.${key}.ownerColumn \"${ownerColumn}\" is not a column on table \"${name}\"`,\n )\n }\n\n const defaults = resolveDefaults(\n {\n ...input,\n create: input.create ?? 'deny',\n delete: input.delete ?? 'deny',\n },\n ownerColumn,\n columns,\n )\n\n const existingReadonly = defaults.readonlyColumns.filter((col) =>\n columns.includes(col),\n )\n const resolvedReadonly = [...new Set(existingReadonly)]\n\n for (const col of [\n ...(defaults.writableColumns ?? []),\n ...(defaults.searchableColumns ?? []),\n ...defaults.filterableColumns,\n ...defaults.sortableColumns,\n ...resolvedReadonly,\n ]) {\n if (!columns.includes(col)) {\n throw new Error(\n `[bunderstack] access.${key} references unknown column \"${col}\" on table \"${name}\"`,\n )\n }\n }\n\n resolved.set(key, {\n tableKey: key,\n tableName: name,\n enabled: true,\n ...defaults,\n readonlyColumns: resolvedReadonly,\n })\n continue\n }\n\n const ownerColumn = detectOwnerColumn(columns, input)\n const hasExplicitRules = input !== undefined\n const hasConventionOwner =\n ownerColumn !== undefined &&\n input?.ownerColumn === undefined &&\n columns.includes('userId')\n\n if (!hasExplicitRules && !hasConventionOwner) continue\n if (\n !ownerColumn &&\n input?.crud !== true &&\n !input?.scope?.read &&\n !input?.scope?.write\n )\n continue\n\n if (input?.ownerColumn && !columns.includes(input.ownerColumn)) {\n throw new Error(\n `[bunderstack] access.${key}.ownerColumn \"${input.ownerColumn}\" is not a column on table \"${name}\"`,\n )\n }\n\n const defaults = resolveDefaults(input ?? {}, ownerColumn, columns)\n const existingReadonly = defaults.readonlyColumns.filter((col) =>\n columns.includes(col),\n )\n const resolvedReadonly = [...new Set(existingReadonly)]\n\n for (const col of [\n ...(defaults.writableColumns ?? []),\n ...(defaults.searchableColumns ?? []),\n ...defaults.filterableColumns,\n ...defaults.sortableColumns,\n ...resolvedReadonly,\n ]) {\n if (!columns.includes(col)) {\n throw new Error(\n `[bunderstack] access.${key} references unknown column \"${col}\" on table \"${name}\"`,\n )\n }\n }\n\n const needsOwner = [defaults.update, defaults.delete].some(\n (r) => r === 'owner',\n )\n if (needsOwner && !ownerColumn) {\n throw new Error(\n `[bunderstack] access.${key} requires ownerColumn for owner-based update/delete rules`,\n )\n }\n\n resolved.set(key, {\n tableKey: key,\n tableName: name,\n enabled: true,\n ...defaults,\n readonlyColumns: resolvedReadonly,\n })\n }\n\n return resolved\n}\n\nexport function defineAccess<\n TSchema extends Record<string, unknown>,\n const TRules extends Record<string, TableAccessInput>,\n>(schema: TSchema, rules: TRules): TRules {\n validateAndResolveAccess(schema, rules)\n return rules\n}\n\nexport function rowMatchesScope(\n row: Record<string, unknown>,\n scope: ScopeMap,\n): boolean {\n for (const [col, expected] of Object.entries(scope)) {\n const actual = row[col]\n if (actual == null) return false\n if (Array.isArray(expected)) {\n if (!expected.map(String).includes(String(actual))) return false\n } else if (String(actual) !== String(expected)) {\n return false\n }\n }\n return true\n}\n\nexport function stampScope(\n values: Record<string, unknown>,\n scope: ScopeMap,\n): Record<string, unknown> {\n const out = { ...values }\n for (const [col, expected] of Object.entries(scope)) {\n if (!Array.isArray(expected)) out[col] = expected\n }\n return out\n}\n\nexport function checkAccessSync(\n rule: Exclude<\n OperationRule,\n (ctx: AccessContext) => boolean | Promise<boolean>\n >,\n ctx: AccessContext,\n ownerColumn?: string,\n): { allowed: boolean } {\n if (rule === 'deny') return { allowed: false }\n if (rule === 'public') return { allowed: true }\n if (!ctx.user) return { allowed: false }\n if (rule === 'authenticated') return { allowed: true }\n if (rule === 'owner') {\n if (!ownerColumn) return { allowed: false }\n const owner = ctx.row?.[ownerColumn]\n return { allowed: owner != null && String(owner) === ctx.user.id }\n }\n return { allowed: false }\n}\n\nexport async function checkAccess(\n rule: OperationRule,\n ctx: AccessContext,\n ownerColumn?: string,\n): Promise<{ allowed: boolean; status: 401 | 403 }> {\n if (rule === 'deny') return { allowed: false, status: 403 }\n\n if (typeof rule === 'function') {\n return (await rule(ctx))\n ? { allowed: true, status: 403 }\n : { allowed: false, status: 403 }\n }\n\n if (rule === 'public') return { allowed: true, status: 403 }\n\n if (!ctx.user) return { allowed: false, status: 401 }\n\n if (rule === 'authenticated') return { allowed: true, status: 403 }\n\n if (rule === 'owner') {\n if (!ownerColumn) return { allowed: false, status: 403 }\n const rowOwner = ctx.row?.[ownerColumn] ?? ctx.body?.[ownerColumn]\n if (rowOwner == null) return { allowed: false, status: 403 }\n if (String(rowOwner) !== ctx.user.id) return { allowed: false, status: 403 }\n return { allowed: true, status: 403 }\n }\n\n return { allowed: false, status: 403 }\n}\n\nexport function sanitizeWriteBody(\n body: Record<string, unknown>,\n access: ResolvedTableAccess,\n mode: 'create' | 'update',\n userId: string | null,\n): Record<string, unknown> {\n const out: Record<string, unknown> = {}\n const readonly = new Set(access.readonlyColumns)\n\n for (const [key, value] of Object.entries(body)) {\n // On create, allow client-supplied `id` even if it appears in readonlyColumns,\n // but still respect an explicit writableColumns allowlist if provided.\n if (mode === 'create' && key === 'id') {\n if (access.writableColumns && !access.writableColumns.includes(key))\n continue\n out[key] = value\n continue\n }\n if (readonly.has(key)) continue\n if (access.writableColumns && !access.writableColumns.includes(key))\n continue\n out[key] = value\n }\n\n if (mode === 'create' && access.ownerColumn) {\n out[access.ownerColumn] = userId ?? null\n }\n\n if (mode === 'update' && access.ownerColumn) {\n delete out[access.ownerColumn]\n }\n\n return out\n}\n\nexport type AuthSessionResolver = {\n api: {\n getSession: (opts: { headers: Headers }) => Promise<{\n user: { id: string; email: string; name?: string; role?: string } | null\n session?: { activeOrganizationId?: string | null } | null\n } | null>\n }\n}\n\nexport async function resolveAccessUser(\n auth: AuthSessionResolver | undefined,\n headers: Headers,\n): Promise<AccessUser | null> {\n if (!auth) return null\n const session = await auth.api.getSession({ headers })\n if (!session?.user) return null\n return {\n id: session.user.id,\n email: session.user.email,\n name: session.user.name,\n role: session.user.role,\n }\n}\n\nexport async function resolveSession(\n auth: AuthSessionResolver | undefined,\n headers: Headers,\n): Promise<{ user: AccessUser | null; activeOrganizationId: string | null }> {\n if (!auth) return { user: null, activeOrganizationId: null }\n const session = await auth.api.getSession({ headers })\n if (!session?.user) return { user: null, activeOrganizationId: null }\n return {\n user: {\n id: session.user.id,\n email: session.user.email,\n name: session.user.name,\n role: session.user.role,\n },\n activeOrganizationId: session.session?.activeOrganizationId ?? null,\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"builder.js","sourceRoot":"","sources":["../../src/api/builder.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,EAAE,GAKH,MAAM,cAAc,CAAA;AAKrB,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,WAAW,CAAA;AAGlB,MAAM,UAAU,gBAAgB;IAI9B,MAAM,IAAI,GAAG,EAAE;SACZ,QAAQ,EAA6B;SACrC,MAAM,CAAC,kBAAkB,CAAC;SAC1B,GAAG,CAAC,oBAAoB,CAAC,CAAA;IAE5B,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE;QACzD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,EAAE,CAAA;QAC1C,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClB,MAAM,IAAI,gBAAgB,CAAC,cAAc,EAAE,yBAAyB,CAAC,CAAA;QACvE,CAAC;QACD,OAAO,IAAI,CAAC;YACV,OAAO,EAAE;gBACP,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,OAAO,EAAE;oBACP,oBAAoB,EAAE,OAAO,CAAC,oBAAoB;iBACnD;aACF;SACF,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,OAAO;QACL,MAAM,EAAE,IAAI;QACZ,SAAS,EAAE,aAAa;QACxB,OAAO,EAAE,IAAI;QACb;;;;;;;WAOG;QACH,UAAU,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAQnB;KACnB,CAAA;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAGvB,QAAyC;IACzC,OAAO,gBAAgB,EAA+B,CAAA;AACxD,CAAC"}
1
+ {"version":3,"file":"builder.js","sourceRoot":"","sources":["../../src/api/builder.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,EAAE,GAKH,MAAM,cAAc,CAAA;AAKrB,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,WAAW,CAAA;AAGlB,MAAM,UAAU,gBAAgB;IAI9B,MAAM,IAAI,GAAG,EAAE;SACZ,QAAQ,EAA6B;SACrC,MAAM,CAAC,kBAAkB,CAAC;SAC1B,GAAG,CAAC,oBAAoB,CAAC,CAAA;IAE5B,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE;QACzD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,EAAE,CAAA;QAC1C,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClB,MAAM,IAAI,gBAAgB,CAAC,cAAc,EAAE,yBAAyB,CAAC,CAAA;QACvE,CAAC;QACD,OAAO,IAAI,CAAC;YACV,OAAO,EAAE;gBACP,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,OAAO,EAAE;oBACP,oBAAoB,EAAE,OAAO,CAAC,oBAAoB;iBACnD;aACF;SACF,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,OAAO;QACL,MAAM,EAAE,IAAI;QACZ,SAAS,EAAE,aAAa;QACxB,OAAO,EAAE,IAAI;QACb;;;;;;;WAOG;QACH,UAAU,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAQnB;KACnB,CAAA;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAGvB,QAAyC;IACzC,OAAO,gBAAgB,EAA+B,CAAA;AACxD,CAAC","sourcesContent":["import {\n os,\n type AnyMiddleware,\n type AnyRouter,\n type Context,\n type Middleware,\n} from '@orpc/server'\n\nimport type { EnvConfigInput, ValidatedEnv } from '../env'\nimport type { ApiContext } from './context'\n\nimport {\n BUNDERSTACK_ERRORS,\n BunderstackError,\n mapBunderstackErrors,\n} from '../errors'\nexport type { ProtectedContextAdditions } from './types'\n\nexport function createApiBuilder<\n TSchema extends Record<string, unknown> = Record<string, unknown>,\n TEnv = Record<string, unknown>,\n>() {\n const base = os\n .$context<ApiContext<TSchema, TEnv>>()\n .errors(BUNDERSTACK_ERRORS)\n .use(mapBunderstackErrors)\n\n const protectedProc = base.use(async ({ context, next }) => {\n const session = await context.getSession()\n if (!session.user) {\n throw new BunderstackError('UNAUTHORIZED', 'Authentication required')\n }\n return next({\n context: {\n user: session.user,\n session: {\n activeOrganizationId: session.activeOrganizationId,\n },\n },\n })\n })\n\n return {\n public: base,\n protected: protectedProc,\n webhook: base,\n /**\n * Declares a standalone middleware over the base context. Use it for\n * `createBunderstack({ middleware })`, which reaches every procedure in\n * the graph, and for `.use(...)` on any base declared here.\n *\n * The annotation is explicit because the inferred `DecoratedMiddleware`\n * is internal to `@orpc/server` and cannot be named in the emitted types.\n */\n middleware: base.middleware.bind(base) as <TOutContext extends Context>(\n middleware: Middleware<\n ApiContext<TSchema, TEnv>,\n TOutContext,\n unknown,\n unknown,\n typeof BUNDERSTACK_ERRORS\n >,\n ) => AnyMiddleware,\n }\n}\n\n/**\n * Same builder as `createApiBuilder`, but the generics come from the values an\n * application already has. It reads nothing at runtime, so a module can call it\n * at import time and export the bases that its router modules import.\n */\nexport function defineApi<\n TSchema extends Record<string, unknown>,\n TEnv extends EnvConfigInput | undefined = undefined,\n>(_options: { schema: TSchema; env?: TEnv }) {\n return createApiBuilder<TSchema, ValidatedEnv<TEnv>>()\n}\n\nexport type BunderstackApiBuilder<\n TSchema extends Record<string, unknown>,\n TEnv = Record<string, unknown>,\n> = ReturnType<typeof createApiBuilder<TSchema, TEnv>>\n\nexport type ApiFactory<\n TSchema extends Record<string, unknown>,\n TEnv,\n TCustomApiRouter extends AnyRouter,\n> = (builder: BunderstackApiBuilder<TSchema, TEnv>) => TCustomApiRouter\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/api/context.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AA6C1C,MAAM,UAAU,gBAAgB,CAI9B,IAAmC,EACnC,OAAgB;IAEhB,uEAAuE;IACvE,MAAM,cAAc,GAAG,OAAO,CAAC,KAAK,EAAE,CAAA;IACtC,IAAI,cAA2C,CAAA;IAC/C,IAAI,cAES,CAAA;IAEb,IAAI,cAES,CAAA;IAEb,MAAM,UAAU,GAAG,GAAG,EAAE;QACtB,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,cAAc,GAAG,cAAc,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CACtE,CAAC,OAAO,EAAE,EAAE;gBACV,cAAc,GAAG,OAAO,CAAA;gBACxB,OAAO,OAAO,CAAA;YAChB,CAAC,CACF,CAAA;QACH,CAAC;QACD,OAAO,cAAc,CAAA;IACvB,CAAC,CAAA;IAED,MAAM,WAAW,GAAG,GAAG,EAAE,CAAC,cAAc,CAAA;IAExC,MAAM,UAAU,GAAG,GAAG,EAAE;QACtB,IAAI,CAAC,cAAc;YAAE,cAAc,GAAG,cAAc,CAAC,IAAI,EAAE,CAAA;QAC3D,OAAO,cAAc,CAAA;IACvB,CAAC,CAAA;IAED,OAAO;QACL,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,OAAO;QACP,UAAU,EAAE,IAAI,OAAO,EAAE;QACzB,UAAU;QACV,UAAU;QACV,WAAW;KACZ,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/api/context.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AA6C1C,MAAM,UAAU,gBAAgB,CAI9B,IAAmC,EACnC,OAAgB;IAEhB,uEAAuE;IACvE,MAAM,cAAc,GAAG,OAAO,CAAC,KAAK,EAAE,CAAA;IACtC,IAAI,cAA2C,CAAA;IAC/C,IAAI,cAES,CAAA;IAEb,IAAI,cAES,CAAA;IAEb,MAAM,UAAU,GAAG,GAAG,EAAE;QACtB,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,cAAc,GAAG,cAAc,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CACtE,CAAC,OAAO,EAAE,EAAE;gBACV,cAAc,GAAG,OAAO,CAAA;gBACxB,OAAO,OAAO,CAAA;YAChB,CAAC,CACF,CAAA;QACH,CAAC;QACD,OAAO,cAAc,CAAA;IACvB,CAAC,CAAA;IAED,MAAM,WAAW,GAAG,GAAG,EAAE,CAAC,cAAc,CAAA;IAExC,MAAM,UAAU,GAAG,GAAG,EAAE;QACtB,IAAI,CAAC,cAAc;YAAE,cAAc,GAAG,cAAc,CAAC,IAAI,EAAE,CAAA;QAC3D,OAAO,cAAc,CAAA;IACvB,CAAC,CAAA;IAED,OAAO;QACL,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,OAAO;QACP,UAAU,EAAE,IAAI,OAAO,EAAE;QACzB,UAAU;QACV,UAAU;QACV,WAAW;KACZ,CAAA;AACH,CAAC","sourcesContent":["import type { AccessUser, AuthSessionResolver } from '../access'\nimport type { DbFor } from '../db'\nimport type { EmailFacade } from '../email'\nimport type { AuthInstance, StorageFacade } from '../index'\nimport type { JobsRuntimeFacade } from '../jobs/define'\nimport type { RealtimeFacade } from '../realtime/facade'\n\nimport { resolveSession } from '../access'\n\nexport interface ApiContextDeps<\n TSchema extends Record<string, unknown> = Record<string, unknown>,\n TEnv = Record<string, unknown>,\n> {\n db: DbFor<TSchema>\n env: TEnv\n storage: StorageFacade\n email: EmailFacade\n jobs: JobsRuntimeFacade\n realtime: RealtimeFacade<TSchema>\n auth: AuthInstance\n authResolver?: AuthSessionResolver\n}\n\nexport interface ApiContext<\n TSchema extends Record<string, unknown> = Record<string, unknown>,\n TEnv = Record<string, unknown>,\n> {\n db: DbFor<TSchema>\n env: TEnv\n storage: StorageFacade\n email: EmailFacade\n jobs: JobsRuntimeFacade\n realtime: RealtimeFacade<TSchema>\n auth: AuthInstance\n request: Request\n resHeaders: Headers\n getRawBody: () => Promise<string>\n getSession: () => Promise<{\n user: AccessUser | null\n activeOrganizationId: string | null\n }>\n /**\n * The session that some earlier code already resolved, or `undefined`.\n * Never starts a resolution, so a global middleware can log the caller\n * without removing the lazy session behavior that signed webhooks rely on.\n * Use it for observability only. Never use it for authorization.\n */\n peekSession: () =>\n | { user: AccessUser | null; activeOrganizationId: string | null }\n | undefined\n}\n\nexport function createApiContext<\n TSchema extends Record<string, unknown> = Record<string, unknown>,\n TEnv = Record<string, unknown>,\n>(\n deps: ApiContextDeps<TSchema, TEnv>,\n request: Request,\n): ApiContext<TSchema, TEnv> {\n // Reserve the body stream before a transport codec consumes `request`.\n const rawBodyRequest = request.clone()\n let rawBodyPromise: Promise<string> | undefined\n let sessionPromise:\n | Promise<{ user: AccessUser | null; activeOrganizationId: string | null }>\n | undefined\n\n let settledSession:\n | { user: AccessUser | null; activeOrganizationId: string | null }\n | undefined\n\n const getSession = () => {\n if (!sessionPromise) {\n sessionPromise = resolveSession(deps.authResolver, request.headers).then(\n (session) => {\n settledSession = session\n return session\n },\n )\n }\n return sessionPromise\n }\n\n const peekSession = () => settledSession\n\n const getRawBody = () => {\n if (!rawBodyPromise) rawBodyPromise = rawBodyRequest.text()\n return rawBodyPromise\n }\n\n return {\n db: deps.db,\n env: deps.env,\n storage: deps.storage,\n email: deps.email,\n jobs: deps.jobs,\n realtime: deps.realtime,\n auth: deps.auth,\n request,\n resHeaders: new Headers(),\n getRawBody,\n getSession,\n peekSession,\n }\n}\n"]}
@@ -4,6 +4,7 @@ import * as v from 'valibot';
4
4
  import type { AnyDb } from '../dialect.js';
5
5
  import type { IdempotencyConfig } from '../idempotency.js';
6
6
  import type { RealtimeFacade } from '../realtime/facade.js';
7
+ import type { RealtimePublisher } from '../realtime/publisher.js';
7
8
  import type { CrudApiRouterFor } from './types.js';
8
9
  import { type ResolvedAccess, type ResolvedTableAccess, type TableAccessInput } from '../access.js';
9
10
  import { type CrudOperations } from '../crud-operations.js';
@@ -12,6 +13,12 @@ export type CrudApiRouterOptions<TSchema extends Record<string, unknown> = Recor
12
13
  access: ResolvedAccess;
13
14
  idempotency?: boolean | IdempotencyConfig;
14
15
  realtime?: RealtimeFacade<TSchema>;
16
+ /**
17
+ * The raw realtime publisher, present when realtime is enabled. The CRUD
18
+ * router subscribes on behalf of live views (`GET /{table}:live`);
19
+ * publishing stays behind the facade.
20
+ */
21
+ livePublisher?: RealtimePublisher;
15
22
  };
16
23
  type CrudUpdate<TTable extends Table> = Partial<Omit<TTable['$inferInsert'], 'id'>>;
17
24
  /** A filter accepts one value (`=`), a list (`IN`), or null (`IS NULL`). */
@@ -34,11 +41,25 @@ export type ListInputFor<TTable extends Table, TFilterable extends string, TSort
34
41
  count?: boolean;
35
42
  filters?: ListFilters<TTable, TFilterable>;
36
43
  } | undefined;
44
+ /**
45
+ * The live-view input as callers see it: the list contract narrowed to what a
46
+ * stream can honor — no text search, no pagination.
47
+ */
48
+ export type LiveInputFor<TTable extends Table, TFilterable extends string, TSortable extends string> = {
49
+ limit?: number;
50
+ sort?: TSortable;
51
+ order?: 'asc' | 'desc';
52
+ filters?: ListFilters<TTable, TFilterable>;
53
+ } | undefined;
37
54
  export type BuildTableCrudProceduresArgs<TSchema extends Record<string, unknown>, TTable extends Table> = {
38
55
  table: TTable;
39
56
  operations: CrudOperations;
40
57
  builder: ReturnType<typeof createApiBuilder<TSchema>>;
41
58
  access: ResolvedTableAccess;
59
+ /** The schema key events are published under. */
60
+ schemaKey: string;
61
+ /** Present when realtime is enabled; without it no live procedure is built. */
62
+ livePublisher?: RealtimePublisher;
42
63
  };
43
64
  export declare function buildTableCrudProcedures<TSchema extends Record<string, unknown>, TTable extends Table, TFilterable extends string = string, TSortable extends string = string>(args: BuildTableCrudProceduresArgs<TSchema, TTable>): {
44
65
  list: import("@orpc/server").DecoratedProcedure<import("./context.js").ApiContext<TSchema, Record<string, unknown>> & object, object, v.GenericSchema<ListInputFor<TTable, TFilterable, TSortable>, ListInputFor<TTable, TFilterable, TSortable>>, v.StrictObjectSchema<{
@@ -353,6 +374,106 @@ export declare function buildTableCrudProcedures<TSchema extends Record<string,
353
374
  }>;
354
375
  };
355
376
  }, never>;
377
+ live: import("@orpc/server").DecoratedProcedure<import("./context.js").ApiContext<TSchema, Record<string, unknown>> & object, object, v.GenericSchema<LiveInputFor<TTable, TFilterable, TSortable>, LiveInputFor<TTable, TFilterable, TSortable>>, import("@orpc/contract").Schema<AsyncIteratorObject<{
378
+ type: "snapshot";
379
+ items: {
380
+ [x: string]: unknown;
381
+ }[];
382
+ sort: string;
383
+ order: "asc" | "desc";
384
+ limit: number;
385
+ hasMore: boolean;
386
+ } | {
387
+ type: "upsert";
388
+ record: {
389
+ [x: string]: unknown;
390
+ };
391
+ afterId: string | null;
392
+ } | {
393
+ type: "remove";
394
+ id: string;
395
+ } | {
396
+ type: "heartbeat";
397
+ intervalMs: number;
398
+ }, unknown, void>, import("@orpc/server").AsyncIteratorClass<{
399
+ type: "snapshot";
400
+ items: {
401
+ [x: string]: unknown;
402
+ }[];
403
+ sort: string;
404
+ order: "asc" | "desc";
405
+ limit: number;
406
+ hasMore: boolean;
407
+ } | {
408
+ type: "upsert";
409
+ record: {
410
+ [x: string]: unknown;
411
+ };
412
+ afterId: string | null;
413
+ } | {
414
+ type: "remove";
415
+ id: string;
416
+ } | {
417
+ type: "heartbeat";
418
+ intervalMs: number;
419
+ }, unknown, void>>, {
420
+ readonly BAD_REQUEST: {
421
+ readonly data: v.OptionalSchema<v.StrictObjectSchema<{
422
+ readonly code: v.OptionalSchema<v.LiteralSchema<"BAD_REQUEST", undefined>, "BAD_REQUEST">;
423
+ readonly details: v.OptionalSchema<v.UnknownSchema, undefined>;
424
+ }, undefined>, {
425
+ readonly code: "BAD_REQUEST";
426
+ }>;
427
+ };
428
+ readonly UNAUTHORIZED: {
429
+ readonly data: v.OptionalSchema<v.StrictObjectSchema<{
430
+ readonly code: v.OptionalSchema<v.LiteralSchema<"UNAUTHORIZED", undefined>, "UNAUTHORIZED">;
431
+ readonly details: v.OptionalSchema<v.UnknownSchema, undefined>;
432
+ }, undefined>, {
433
+ readonly code: "UNAUTHORIZED";
434
+ }>;
435
+ };
436
+ readonly FORBIDDEN: {
437
+ readonly data: v.OptionalSchema<v.StrictObjectSchema<{
438
+ readonly code: v.OptionalSchema<v.LiteralSchema<"FORBIDDEN", undefined>, "FORBIDDEN">;
439
+ readonly details: v.OptionalSchema<v.UnknownSchema, undefined>;
440
+ }, undefined>, {
441
+ readonly code: "FORBIDDEN";
442
+ }>;
443
+ };
444
+ readonly NOT_FOUND: {
445
+ readonly data: v.OptionalSchema<v.StrictObjectSchema<{
446
+ readonly code: v.OptionalSchema<v.LiteralSchema<"NOT_FOUND", undefined>, "NOT_FOUND">;
447
+ readonly details: v.OptionalSchema<v.UnknownSchema, undefined>;
448
+ }, undefined>, {
449
+ readonly code: "NOT_FOUND";
450
+ }>;
451
+ };
452
+ readonly CONFLICT: {
453
+ readonly data: v.OptionalSchema<v.StrictObjectSchema<{
454
+ readonly code: v.OptionalSchema<v.LiteralSchema<"CONFLICT", undefined>, "CONFLICT">;
455
+ readonly details: v.OptionalSchema<v.UnknownSchema, undefined>;
456
+ }, undefined>, {
457
+ readonly code: "CONFLICT";
458
+ }>;
459
+ };
460
+ readonly PAYLOAD_TOO_LARGE: {
461
+ readonly data: v.OptionalSchema<v.StrictObjectSchema<{
462
+ readonly code: v.OptionalSchema<v.LiteralSchema<"PAYLOAD_TOO_LARGE", undefined>, "PAYLOAD_TOO_LARGE">;
463
+ readonly details: v.OptionalSchema<v.UnknownSchema, undefined>;
464
+ }, undefined>, {
465
+ readonly code: "PAYLOAD_TOO_LARGE";
466
+ }>;
467
+ };
468
+ readonly TOO_MANY_REQUESTS: {
469
+ readonly data: v.OptionalSchema<v.StrictObjectSchema<{
470
+ readonly code: v.OptionalSchema<v.LiteralSchema<"TOO_MANY_REQUESTS", undefined>, "TOO_MANY_REQUESTS">;
471
+ readonly details: v.OptionalSchema<v.UnknownSchema, undefined>;
472
+ }, undefined>, {
473
+ readonly code: "TOO_MANY_REQUESTS";
474
+ }>;
475
+ };
476
+ }, never>;
356
477
  };
357
478
  export type TableCrudProcedures<TTable extends Table, TFilterable extends string = string, TSortable extends string = string> = ReturnType<typeof buildTableCrudProcedures<Record<string, unknown>, TTable, TFilterable, TSortable>>;
358
479
  export declare function buildCrudApiRouter<TSchema extends Record<string, unknown>, TAccess extends Record<string, TableAccessInput> | undefined = undefined>(schema: TSchema, db: AnyDb, options: CrudApiRouterOptions<TSchema>): CrudApiRouterFor<TSchema, TAccess>;
@@ -1 +1 @@
1
- {"version":3,"file":"crud-router.d.ts","sourceRoot":"","sources":["../../src/api/crud-router.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"crud-router.d.ts","sourceRoot":"","sources":["../../src/api/crud-router.ts"],"names":[],"mappings":"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"}
@@ -1,16 +1,20 @@
1
1
  import { getTableColumns, getTableName, isTable } from 'drizzle-orm';
2
2
  import { createInsertSchema, createSelectSchema, createUpdateSchema, } from 'drizzle-valibot';
3
3
  import '@orpc/openapi/extensions/route';
4
+ import { eventIterator } from '@orpc/server';
4
5
  import * as v from 'valibot';
5
6
  import { tableEntryForName, } from '../access.js';
6
7
  import { createCrudOperations } from '../crud-operations.js';
8
+ import { filterTableChanges } from '../realtime/filter.js';
9
+ import { REALTIME_HEARTBEAT_INTERVAL_MS, withRealtimeHeartbeat, } from '../realtime/heartbeat.js';
7
10
  import { createApiBuilder } from './builder.js';
8
- import { buildListInputSchema } from './list-input-schema.js';
11
+ import { createLiveWindow } from './live-window.js';
12
+ import { buildListInputSchema, buildLiveInputSchema } from './list-input-schema.js';
9
13
  function strictObject(schema) {
10
14
  return v.strictObject(schema.entries);
11
15
  }
12
16
  export function buildTableCrudProcedures(args) {
13
- const { table, operations, builder, access } = args;
17
+ const { table, operations, builder, access, schemaKey, livePublisher } = args;
14
18
  const name = getTableName(table);
15
19
  // drizzle-valibot infers its schemas through internal generics. Left as-is,
16
20
  // declaration emit inlines those generics by name into the published `.d.ts`,
@@ -185,16 +189,116 @@ export function buildTableCrudProcedures(args) {
185
189
  await operations.delete(name, input.id, execCtx);
186
190
  return undefined;
187
191
  });
188
- return {
192
+ // 6. LIVE procedure — one list query as a stream. A snapshot first, then the
193
+ // changes this view cares about, placed by the server. Every connection
194
+ // opens with a snapshot, so a reconnect is its own recovery: no client-side
195
+ // event buffer, no Last-Event-ID bookkeeping, and no refetch path.
196
+ const liveQuerySchema = buildLiveInputSchema(table, {
197
+ filterableColumns: access.filterableColumns,
198
+ sortableColumns: access.sortableColumns,
199
+ });
200
+ const recordSchema = v.record(v.string(), v.unknown());
201
+ const liveFrameSchema = v.union([
202
+ v.strictObject({
203
+ type: v.literal('snapshot'),
204
+ items: v.array(recordSchema),
205
+ sort: v.string(),
206
+ order: v.picklist(['asc', 'desc']),
207
+ limit: v.number(),
208
+ hasMore: v.boolean(),
209
+ }),
210
+ v.strictObject({
211
+ type: v.literal('upsert'),
212
+ record: recordSchema,
213
+ afterId: v.union([v.string(), v.null()]),
214
+ }),
215
+ v.strictObject({ type: v.literal('remove'), id: v.string() }),
216
+ v.strictObject({ type: v.literal('heartbeat'), intervalMs: v.number() }),
217
+ ]);
218
+ const live = builder.public
219
+ .route({
220
+ method: 'GET',
221
+ // A path of its own, not a child of the table: `/{table}/live`
222
+ // would make the id "live" unreachable on the get route, and a
223
+ // colon suffix is a wildcard parameter in the oRPC matcher.
224
+ path: `/api/live/${name}`,
225
+ summary: `Live view of ${name}`,
226
+ tags: [name],
227
+ // Filters arrive as one URL-encoded JSON value, so no per-key query
228
+ // parsing rule is needed.
229
+ queryStyles: { filters: 'json' },
230
+ })
231
+ .input(liveQuerySchema)
232
+ .output(eventIterator(liveFrameSchema))
233
+ .handler(({ input, context, signal }) => {
234
+ if (!livePublisher) {
235
+ throw new Error(`Realtime is not enabled for live view of ${name}`);
236
+ }
237
+ // Subscribe before anything awaits, so no change slips between the
238
+ // snapshot read and the start of the stream; events that arrive
239
+ // during the query buffer in the publisher and replay on first pull.
240
+ const changes = filterTableChanges(livePublisher.subscribe('change', { signal }), {
241
+ tableName: schemaKey,
242
+ entry: access,
243
+ rule: access.list,
244
+ request: context.request,
245
+ getSession: context.getSession,
246
+ });
247
+ return withRealtimeHeartbeat((async function* () {
248
+ const session = await context.getSession();
249
+ const execCtx = {
250
+ request: context.request,
251
+ user: session.user,
252
+ session: { activeOrganizationId: session.activeOrganizationId },
253
+ };
254
+ let view;
255
+ const readSnapshot = async () => {
256
+ const result = await operations.list(name, input ?? {}, execCtx);
257
+ view = createLiveWindow({
258
+ sort: result.sort,
259
+ order: result.order,
260
+ limit: result.limit,
261
+ filters: input?.filters,
262
+ });
263
+ view.reset(result.items, result.hasMore);
264
+ return {
265
+ type: 'snapshot',
266
+ items: result.items,
267
+ sort: result.sort,
268
+ order: result.order,
269
+ limit: result.limit,
270
+ hasMore: result.hasMore,
271
+ };
272
+ };
273
+ yield await readSnapshot();
274
+ for await (const change of changes) {
275
+ const outcome = view.apply(change);
276
+ if (outcome.type === 'none')
277
+ continue;
278
+ if (outcome.type === 'resnapshot') {
279
+ yield await readSnapshot();
280
+ continue;
281
+ }
282
+ for (const frame of outcome.frames)
283
+ yield frame;
284
+ }
285
+ })(), { intervalMs: REALTIME_HEARTBEAT_INTERVAL_MS, signal });
286
+ });
287
+ const procedures = {
189
288
  list,
190
289
  get,
191
290
  create,
192
291
  update,
193
292
  delete: deleteProc,
293
+ live,
194
294
  };
295
+ if (!livePublisher) {
296
+ delete procedures.live;
297
+ }
298
+ return procedures;
195
299
  }
196
300
  export function buildCrudApiRouter(schema, db, options) {
197
- const { access, realtime, idempotency } = options;
301
+ const { access, realtime, idempotency, livePublisher } = options;
198
302
  const builder = createApiBuilder();
199
303
  const operations = createCrudOperations({
200
304
  schema,
@@ -219,6 +323,8 @@ export function buildCrudApiRouter(schema, db, options) {
219
323
  operations,
220
324
  builder,
221
325
  access: tableAccess,
326
+ schemaKey: tableKey,
327
+ livePublisher,
222
328
  });
223
329
  routerObj[tableKey] = procedures;
224
330
  }
@@ -1 +1 @@
1
- {"version":3,"file":"crud-router.js","sourceRoot":"","sources":["../../src/api/crud-router.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"crud-router.js","sourceRoot":"","sources":["../../src/api/crud-router.ts"],"names":[],"mappings":"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","sourcesContent":["import { getTableColumns, getTableName, isTable, type Table } from 'drizzle-orm'\nimport {\n createInsertSchema,\n createSelectSchema,\n createUpdateSchema,\n} from 'drizzle-valibot'\nimport '@orpc/openapi/extensions/route'\nimport { eventIterator } from '@orpc/server'\nimport * as v from 'valibot'\n\nimport type { AnyDb } from '../dialect'\nimport type { IdempotencyConfig } from '../idempotency'\nimport type { LiveSnapshotFrame } from '../live/protocol'\nimport type { RealtimeFacade } from '../realtime/facade'\nimport type { RealtimePublisher } from '../realtime/publisher'\nimport type { CrudApiRouterFor } from './types'\n\nimport {\n tableEntryForName,\n type ResolvedAccess,\n type ResolvedTableAccess,\n type TableAccessInput,\n} from '../access'\nimport { createCrudOperations, type CrudOperations } from '../crud-operations'\nimport { filterTableChanges } from '../realtime/filter'\nimport {\n REALTIME_HEARTBEAT_INTERVAL_MS,\n withRealtimeHeartbeat,\n} from '../realtime/heartbeat'\nimport { createApiBuilder } from './builder'\nimport { createLiveWindow } from './live-window'\nimport { buildListInputSchema, buildLiveInputSchema } from './list-input-schema'\n\nexport type CrudApiRouterOptions<\n TSchema extends Record<string, unknown> = Record<string, unknown>,\n> = {\n access: ResolvedAccess\n idempotency?: boolean | IdempotencyConfig\n realtime?: RealtimeFacade<TSchema>\n /**\n * The raw realtime publisher, present when realtime is enabled. The CRUD\n * router subscribes on behalf of live views (`GET /{table}:live`);\n * publishing stays behind the facade.\n */\n livePublisher?: RealtimePublisher\n}\n\nfunction strictObject<TEntries extends v.ObjectEntries>(schema: {\n entries: TEntries\n}) {\n return v.strictObject(schema.entries)\n}\n\ntype CrudInsert<TTable extends Table> = Partial<TTable['$inferInsert']>\ntype CrudUpdate<TTable extends Table> = Partial<\n Omit<TTable['$inferInsert'], 'id'>\n>\n\n/** A filter accepts one value (`=`), a list (`IN`), or null (`IS NULL`). */\nexport type ListFilterValue<T> = T | readonly T[] | null | 'null'\n\nexport type ListFilters<TTable extends Table, TFilterable extends string> = {\n [K in Extract<keyof TTable['$inferSelect'], TFilterable>]?: ListFilterValue<\n TTable['$inferSelect'][K]\n >\n}\n\n/**\n * The `list` input as callers see it. Filter columns and sortable columns come\n * from the table's `access` entry, so `filters` autocompletes to real columns\n * and rejects wrong value types at compile time.\n */\nexport type ListInputFor<\n TTable extends Table,\n TFilterable extends string,\n TSortable extends string,\n> =\n | {\n limit?: number\n offset?: number\n cursor?: string\n sort?: TSortable\n order?: 'asc' | 'desc'\n q?: string\n count?: boolean\n filters?: ListFilters<TTable, TFilterable>\n }\n | undefined\n\n/**\n * The live-view input as callers see it: the list contract narrowed to what a\n * stream can honor — no text search, no pagination.\n */\nexport type LiveInputFor<\n TTable extends Table,\n TFilterable extends string,\n TSortable extends string,\n> =\n | {\n limit?: number\n sort?: TSortable\n order?: 'asc' | 'desc'\n filters?: ListFilters<TTable, TFilterable>\n }\n | undefined\n\nexport type BuildTableCrudProceduresArgs<\n TSchema extends Record<string, unknown>,\n TTable extends Table,\n> = {\n table: TTable\n operations: CrudOperations\n builder: ReturnType<typeof createApiBuilder<TSchema>>\n access: ResolvedTableAccess\n /** The schema key events are published under. */\n schemaKey: string\n /** Present when realtime is enabled; without it no live procedure is built. */\n livePublisher?: RealtimePublisher\n}\n\nexport function buildTableCrudProcedures<\n TSchema extends Record<string, unknown>,\n TTable extends Table,\n TFilterable extends string = string,\n TSortable extends string = string,\n>(args: BuildTableCrudProceduresArgs<TSchema, TTable>) {\n const { table, operations, builder, access, schemaKey, livePublisher } =\n args\n const name = getTableName(table)\n\n // drizzle-valibot infers its schemas through internal generics. Left as-is,\n // declaration emit inlines those generics by name into the published `.d.ts`,\n // where they are unbound — every column silently becomes optional for the\n // consumer. Restating the type keeps the runtime schema and makes the emitted\n // one both correct and readable.\n const selectSchema = strictObject(\n createSelectSchema(table),\n ) as unknown as v.GenericSchema<\n TTable['$inferSelect'],\n TTable['$inferSelect']\n >\n const generatedInsertSchema = strictObject(createInsertSchema(table))\n const generatedColumns = Object.keys(generatedInsertSchema.entries)\n const columns = getTableColumns(table)\n const serverManagedColumns = [\n ...access.readonlyColumns,\n ...(access.writeScope && generatedColumns.includes('organizationId')\n ? ['organizationId']\n : []),\n ...Object.entries(columns)\n .filter(([, column]) => !column.notNull || column.hasDefault)\n .map(([column]) => column),\n ].filter((column) => generatedColumns.includes(column))\n const insertEntries: Record<\n string,\n v.BaseSchema<unknown, unknown, v.BaseIssue<unknown>>\n > = {\n ...generatedInsertSchema.entries,\n }\n for (const column of serverManagedColumns) {\n const schema = insertEntries[column]\n if (schema) insertEntries[column] = v.optional(schema)\n }\n const insertSchema = v.strictObject(\n insertEntries,\n ) as unknown as v.GenericSchema<CrudInsert<TTable>, CrudInsert<TTable>>\n const generatedUpdateSchema = createUpdateSchema(table)\n const updateBodySchema = v.omit(generatedUpdateSchema, [\n 'id' as keyof typeof generatedUpdateSchema.entries,\n ])\n const updateInputSchema = v.strictObject({\n params: v.strictObject({ id: v.string() }),\n query: v.optional(v.record(v.string(), v.unknown()), {}),\n headers: v.optional(v.record(v.string(), v.unknown()), {}),\n // Same reason as `selectSchema`: state the type instead of letting\n // declaration emit inline drizzle-valibot's generics.\n body: strictObject(updateBodySchema) as unknown as v.GenericSchema<\n CrudUpdate<TTable>,\n CrudUpdate<TTable>\n >,\n })\n\n // One filter field per allowed column, typed by the column itself: a scalar\n // for `=`, a list for `IN`, and `null` for `IS NULL`. Query strings are\n // coerced to these types by SmartCoercionHandlerPlugin, so REST and RPC share\n // one contract and nothing has to re-read the raw URL.\n // The cast restates the schema with the literals the caller's `access`\n // config carries, which the runtime column lists cannot name on their own.\n const listQuerySchema = buildListInputSchema(table, {\n filterableColumns: access.filterableColumns,\n sortableColumns: access.sortableColumns,\n }) as unknown as v.GenericSchema<\n ListInputFor<TTable, TFilterable, TSortable>,\n ListInputFor<TTable, TFilterable, TSortable>\n >\n\n const listOutputSchema = v.strictObject({\n items: v.array(selectSchema),\n nextCursor: v.optional(v.string()),\n hasMore: v.boolean(),\n total: v.optional(v.number()),\n limit: v.optional(v.number()),\n offset: v.optional(v.number()),\n cursor: v.optional(v.string()),\n q: v.optional(v.string()),\n sort: v.optional(v.string()),\n order: v.optional(v.string()),\n })\n\n // 1. LIST procedure\n const list = builder.public\n .route({\n method: 'GET',\n path: `/api/${name}`,\n summary: `List ${name}`,\n tags: [name],\n })\n .input(listQuerySchema)\n .output(listOutputSchema)\n .handler(async ({ input, context }) => {\n const session = await context.getSession()\n const execCtx = {\n request: context.request,\n user: session.user,\n session: { activeOrganizationId: session.activeOrganizationId },\n }\n const result = await operations.list(name, input ?? {}, execCtx)\n return {\n ...result,\n items: result.items as TTable['$inferSelect'][],\n }\n })\n\n // 2. GET procedure\n const get = builder.public\n .route({\n method: 'GET',\n path: `/api/${name}/{id}`,\n summary: `Get ${name} by ID`,\n tags: [name],\n })\n .input(v.strictObject({ id: v.string() }))\n .output(selectSchema)\n .handler(async ({ input, context }) => {\n const session = await context.getSession()\n const execCtx = {\n request: context.request,\n user: session.user,\n session: { activeOrganizationId: session.activeOrganizationId },\n }\n return (await operations.get(\n name,\n input.id,\n execCtx,\n )) as TTable['$inferSelect']\n })\n\n // 3. CREATE procedure\n const create = builder.public\n .route({\n method: 'POST',\n path: `/api/${name}`,\n summary: `Create ${name}`,\n tags: [name],\n successStatus: 201,\n })\n .input(insertSchema)\n .output(selectSchema)\n .handler(async ({ input, context }) => {\n const session = await context.getSession()\n const execCtx = {\n request: context.request,\n user: session.user,\n session: { activeOrganizationId: session.activeOrganizationId },\n }\n const idempotencyKey = context.request.headers\n .get('Idempotency-Key')\n ?.trim()\n const rawBody = await context.getRawBody()\n\n const res = await operations.create(\n name,\n input,\n rawBody,\n idempotencyKey,\n execCtx,\n )\n if (res.type === 'replay') {\n context.resHeaders.set('Idempotency-Replayed', 'true')\n return res.record as TTable['$inferSelect']\n }\n return res.record as TTable['$inferSelect']\n })\n\n // 4. UPDATE procedure\n const update = builder.public\n .route({\n method: 'PATCH',\n path: `/api/${name}/{id}`,\n summary: `Update ${name}`,\n tags: [name],\n inputStructure: 'detailed',\n })\n .input(updateInputSchema)\n .output(selectSchema)\n .handler(async ({ input, context }) => {\n const session = await context.getSession()\n const execCtx = {\n request: context.request,\n user: session.user,\n session: { activeOrganizationId: session.activeOrganizationId },\n }\n\n return (await operations.update(\n name,\n input.params.id,\n input.body,\n execCtx,\n )) as TTable['$inferSelect']\n })\n\n // 5. DELETE procedure\n const deleteProc = builder.public\n .route({\n method: 'DELETE',\n path: `/api/${name}/{id}`,\n summary: `Delete ${name}`,\n tags: [name],\n successStatus: 204,\n })\n .input(v.strictObject({ id: v.string() }))\n .output(v.undefined())\n .handler(async ({ input, context }) => {\n const session = await context.getSession()\n const execCtx = {\n request: context.request,\n user: session.user,\n session: { activeOrganizationId: session.activeOrganizationId },\n }\n await operations.delete(name, input.id, execCtx)\n return undefined\n })\n\n // 6. LIVE procedure — one list query as a stream. A snapshot first, then the\n // changes this view cares about, placed by the server. Every connection\n // opens with a snapshot, so a reconnect is its own recovery: no client-side\n // event buffer, no Last-Event-ID bookkeeping, and no refetch path.\n const liveQuerySchema = buildLiveInputSchema(table, {\n filterableColumns: access.filterableColumns,\n sortableColumns: access.sortableColumns,\n }) as unknown as v.GenericSchema<\n LiveInputFor<TTable, TFilterable, TSortable>,\n LiveInputFor<TTable, TFilterable, TSortable>\n >\n\n const recordSchema = v.record(v.string(), v.unknown())\n const liveFrameSchema = v.union([\n v.strictObject({\n type: v.literal('snapshot'),\n items: v.array(recordSchema),\n sort: v.string(),\n order: v.picklist(['asc', 'desc']),\n limit: v.number(),\n hasMore: v.boolean(),\n }),\n v.strictObject({\n type: v.literal('upsert'),\n record: recordSchema,\n afterId: v.union([v.string(), v.null()]),\n }),\n v.strictObject({ type: v.literal('remove'), id: v.string() }),\n v.strictObject({ type: v.literal('heartbeat'), intervalMs: v.number() }),\n ])\n\n const live = builder.public\n .route({\n method: 'GET',\n // A path of its own, not a child of the table: `/{table}/live`\n // would make the id \"live\" unreachable on the get route, and a\n // colon suffix is a wildcard parameter in the oRPC matcher.\n path: `/api/live/${name}`,\n summary: `Live view of ${name}`,\n tags: [name],\n // Filters arrive as one URL-encoded JSON value, so no per-key query\n // parsing rule is needed.\n queryStyles: { filters: 'json' },\n })\n .input(liveQuerySchema)\n .output(eventIterator(liveFrameSchema))\n .handler(({ input, context, signal }) => {\n if (!livePublisher) {\n throw new Error(`Realtime is not enabled for live view of ${name}`)\n }\n // Subscribe before anything awaits, so no change slips between the\n // snapshot read and the start of the stream; events that arrive\n // during the query buffer in the publisher and replay on first pull.\n const changes = filterTableChanges(\n livePublisher.subscribe('change', { signal }),\n {\n tableName: schemaKey,\n entry: access,\n rule: access.list,\n request: context.request,\n getSession: context.getSession,\n },\n )\n\n return withRealtimeHeartbeat(\n (async function* () {\n const session = await context.getSession()\n const execCtx = {\n request: context.request,\n user: session.user,\n session: { activeOrganizationId: session.activeOrganizationId },\n }\n let view: ReturnType<typeof createLiveWindow> | undefined\n\n const readSnapshot = async (): Promise<LiveSnapshotFrame> => {\n const result = await operations.list(name, input ?? {}, execCtx)\n view = createLiveWindow({\n sort: result.sort,\n order: result.order,\n limit: result.limit,\n filters: input?.filters as\n | Record<string, unknown>\n | undefined,\n })\n view.reset(result.items, result.hasMore)\n return {\n type: 'snapshot',\n items: result.items,\n sort: result.sort,\n order: result.order,\n limit: result.limit,\n hasMore: result.hasMore,\n }\n }\n\n yield await readSnapshot()\n\n for await (const change of changes) {\n const outcome = view!.apply(change)\n if (outcome.type === 'none') continue\n if (outcome.type === 'resnapshot') {\n yield await readSnapshot()\n continue\n }\n for (const frame of outcome.frames) yield frame\n }\n })(),\n { intervalMs: REALTIME_HEARTBEAT_INTERVAL_MS, signal },\n )\n })\n\n const procedures = {\n list,\n get,\n create,\n update,\n delete: deleteProc,\n live,\n }\n\n if (!livePublisher) {\n delete (procedures as { live?: unknown }).live\n }\n\n return procedures\n}\n\nexport type TableCrudProcedures<\n TTable extends Table,\n TFilterable extends string = string,\n TSortable extends string = string,\n> = ReturnType<\n typeof buildTableCrudProcedures<\n Record<string, unknown>,\n TTable,\n TFilterable,\n TSortable\n >\n>\n\nexport function buildCrudApiRouter<\n TSchema extends Record<string, unknown>,\n TAccess extends Record<string, TableAccessInput> | undefined = undefined,\n>(\n schema: TSchema,\n db: AnyDb,\n options: CrudApiRouterOptions<TSchema>,\n): CrudApiRouterFor<TSchema, TAccess> {\n const { access, realtime, idempotency, livePublisher } = options\n const builder = createApiBuilder<TSchema>()\n const operations = createCrudOperations({\n schema,\n db,\n access,\n idempotency,\n realtime,\n })\n\n const routerObj: Record<string, unknown> = {}\n\n for (const [tableKey, table] of Object.entries(schema)) {\n if (!isTable(table)) continue\n\n const name = getTableName(table)\n const tableAccess = tableEntryForName(access, name)\n if (!tableAccess?.enabled) continue\n\n const idCol = getTableColumns(table)['id']\n if (!idCol) continue\n\n const procedures = buildTableCrudProcedures({\n table: table as Table,\n operations,\n builder,\n access: tableAccess,\n schemaKey: tableKey,\n livePublisher,\n })\n\n routerObj[tableKey] = procedures\n }\n\n return routerObj as CrudApiRouterFor<TSchema, TAccess>\n}\n"]}
@@ -19,4 +19,19 @@ export declare function buildListInputSchema(table: Table, options: {
19
19
  readonly count: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
20
20
  readonly filters: v.OptionalSchema<v.StrictObjectSchema<v.ObjectEntries, undefined>, undefined>;
21
21
  }, undefined>, undefined>;
22
+ /**
23
+ * The input contract of a live view (`GET /api/{table}:live`): the list
24
+ * contract narrowed to what a stream can honor. No text search, no pagination
25
+ * — membership is decided per streamed record on the server, which only
26
+ * equality-style filters allow.
27
+ */
28
+ export declare function buildLiveInputSchema(table: Table, options: {
29
+ filterableColumns: readonly string[];
30
+ sortableColumns: readonly string[];
31
+ }): v.OptionalSchema<v.StrictObjectSchema<{
32
+ readonly limit: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>]>, undefined>;
33
+ readonly sort: v.OptionalSchema<v.PicklistSchema<string[], undefined>, undefined>;
34
+ readonly order: v.OptionalSchema<v.PicklistSchema<["asc", "desc"], undefined>, undefined>;
35
+ readonly filters: v.OptionalSchema<v.StrictObjectSchema<v.ObjectEntries, undefined>, undefined>;
36
+ }, undefined>, undefined>;
22
37
  //# sourceMappingURL=list-input-schema.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"list-input-schema.d.ts","sourceRoot":"","sources":["../../src/api/list-input-schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAGxC,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AAsC5B;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE;IACP,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAA;IACpC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAA;CACnC;;;;;;;;;0BAiBF"}
1
+ {"version":3,"file":"list-input-schema.d.ts","sourceRoot":"","sources":["../../src/api/list-input-schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAGxC,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AAsC5B;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE;IACP,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAA;IACpC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAA;CACnC;;;;;;;;;0BAiBF;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE;IACP,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAA;IACpC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAA;CACnC;;;;;0BAaF"}
@@ -44,4 +44,20 @@ export function buildListInputSchema(table, options) {
44
44
  filters: v.optional(v.strictObject(filterEntries)),
45
45
  }));
46
46
  }
47
+ /**
48
+ * The input contract of a live view (`GET /api/{table}:live`): the list
49
+ * contract narrowed to what a stream can honor. No text search, no pagination
50
+ * — membership is decided per streamed record on the server, which only
51
+ * equality-style filters allow.
52
+ */
53
+ export function buildLiveInputSchema(table, options) {
54
+ const filterEntries = buildFilterEntries(table, options.filterableColumns);
55
+ return v.optional(v.strictObject({
56
+ limit: v.optional(v.pipe(v.number(), v.integer(), v.minValue(1))),
57
+ sort: v.optional(v.picklist(options.sortableColumns)),
58
+ order: v.optional(v.picklist(['asc', 'desc'])),
59
+ // Always present, even with no filterable columns: clients send `{}`.
60
+ filters: v.optional(v.strictObject(filterEntries)),
61
+ }));
62
+ }
47
63
  //# sourceMappingURL=list-input-schema.js.map