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
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/api/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { AnyRouter } from '@orpc/server'\nimport type { Table } from 'drizzle-orm'\n\nimport type { AccessUser } from '../access'\nimport type { TableCrudProcedures } from './crud-router'\n\nexport interface ProtectedContextAdditions {\n user: AccessUser\n session: {\n activeOrganizationId: string | null\n }\n}\n\ntype AuthTableName = 'user' | 'session' | 'account' | 'verification'\ntype InferSelect<T> = T extends { $inferSelect: infer R } ? R : never\n\ntype DisabledKeys<TAccess> = {\n [K in keyof TAccess & string]: TAccess[K] extends { crud: false } ? K : never\n}[keyof TAccess & string]\n\ntype ExplicitKeys<TSchema, TAccess> = {\n [K in keyof TAccess & keyof TSchema & string]: TAccess[K] extends {\n crud: false\n }\n ? never\n : K extends AuthTableName\n ? TAccess[K] extends { exposeAuthTable: true }\n ? K extends 'user'\n ? K\n : never\n : never\n : K\n}[keyof TAccess & keyof TSchema & string]\n\ntype ConventionKeys<TSchema> = {\n [K in keyof TSchema & string]: K extends AuthTableName\n ? never\n : InferSelect<TSchema[K]> extends { userId: unknown }\n ? K\n : never\n}[keyof TSchema & string]\n\nexport type ExposedApiTables<TSchema, TAccess> = [TAccess] extends [undefined]\n ? ConventionKeys<TSchema>\n :\n | ExplicitKeys<TSchema, TAccess>\n | Exclude<\n ConventionKeys<TSchema>,\n DisabledKeys<TAccess> | (keyof TAccess & string)\n >\n\n/**\n * Column allowlists declared in `access` reach the client as literal unions, so\n * `list` can type `filters` and `sort` per table. Tables that declare nothing\n * get `never` filters and `'id'` sorting, matching the runtime defaults.\n */\ntype FilterableOf<TAccess, K extends string> = K extends keyof TAccess\n ? TAccess[K] extends {\n filterableColumns: readonly (infer F extends string)[]\n }\n ? F\n : never\n : never\n\ntype SortableOf<TAccess, K extends string> = K extends keyof TAccess\n ? TAccess[K] extends { sortableColumns: readonly (infer S extends string)[] }\n ? S\n : 'id'\n : 'id'\n\nexport type CrudApiRouterFor<\n TSchema extends Record<string, unknown>,\n TAccess = undefined,\n> = {\n [K in ExposedApiTables<TSchema, TAccess> as TSchema[K] extends Table\n ? K\n : never]: TableCrudProcedures<\n Extract<TSchema[K], Table>,\n FilterableOf<TAccess, K>,\n SortableOf<TAccess, K>\n >\n}\n\ntype IsProcedure<T> = T extends { '~orpc': unknown } ? true : false\n\nexport type MergeApiRouterTypes<A, B> = {\n [K in keyof A | keyof B]: K extends keyof A\n ? K extends keyof B\n ? IsProcedure<A[K]> extends true\n ? never\n : IsProcedure<B[K]> extends true\n ? never\n : A[K] extends Record<string, unknown>\n ? B[K] extends Record<string, unknown>\n ? MergeApiRouterTypes<A[K], B[K]>\n : never\n : never\n : A[K]\n : K extends keyof B\n ? B[K]\n : never\n}\n\nexport type UnifiedApiRouter<\n TCrud,\n TCustom extends AnyRouter | undefined,\n> = TCustom extends AnyRouter ? MergeApiRouterTypes<TCrud, TCustom> : TCrud\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/api/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { AnyRouter } from '@orpc/server'\nimport type { Table } from 'drizzle-orm'\n\nimport type { AccessUser } from '../access'\nimport type { TableCrudProcedures } from './crud-router'\n\nexport interface ProtectedContextAdditions {\n user: AccessUser\n session: {\n activeOrganizationId: string | null\n }\n}\n\ntype AuthTableName = 'user' | 'session' | 'account' | 'verification'\ntype InferSelect<T> = T extends { $inferSelect: infer R } ? R : never\n\ntype DisabledKeys<TAccess> = {\n [K in keyof TAccess & string]: TAccess[K] extends { crud: false } ? K : never\n}[keyof TAccess & string]\n\ntype ExplicitKeys<TSchema, TAccess> = {\n [K in keyof TAccess & keyof TSchema & string]: TAccess[K] extends {\n crud: false\n }\n ? never\n : K extends AuthTableName\n ? TAccess[K] extends { exposeAuthTable: true }\n ? K extends 'user'\n ? K\n : never\n : never\n : K\n}[keyof TAccess & keyof TSchema & string]\n\ntype ConventionKeys<TSchema> = {\n [K in keyof TSchema & string]: K extends AuthTableName\n ? never\n : InferSelect<TSchema[K]> extends { userId: unknown }\n ? K\n : never\n}[keyof TSchema & string]\n\nexport type ExposedApiTables<TSchema, TAccess> = [TAccess] extends [undefined]\n ? ConventionKeys<TSchema>\n :\n | ExplicitKeys<TSchema, TAccess>\n | Exclude<\n ConventionKeys<TSchema>,\n DisabledKeys<TAccess> | (keyof TAccess & string)\n >\n\n/**\n * Column allowlists declared in `access` reach the client as literal unions, so\n * `list` can type `filters` and `sort` per table. Tables that declare nothing\n * get `never` filters and `'id'` sorting, matching the runtime defaults.\n */\ntype FilterableOf<TAccess, K extends string> = K extends keyof TAccess\n ? TAccess[K] extends {\n filterableColumns: readonly (infer F extends string)[]\n }\n ? F\n : never\n : never\n\ntype SortableOf<TAccess, K extends string> = K extends keyof TAccess\n ? TAccess[K] extends { sortableColumns: readonly (infer S extends string)[] }\n ? S\n : 'id'\n : 'id'\n\nexport type CrudApiRouterFor<\n TSchema extends Record<string, unknown>,\n TAccess = undefined,\n TLive extends boolean = false,\n> = {\n [K in ExposedApiTables<TSchema, TAccess> as TSchema[K] extends Table\n ? K\n : never]: TableCrudProcedures<\n Extract<TSchema[K], Table>,\n FilterableOf<TAccess, K>,\n SortableOf<TAccess, K>,\n TLive\n >\n}\n\ntype IsProcedure<T> = T extends { '~orpc': unknown } ? true : false\n\nexport type MergeApiRouterTypes<A, B> = {\n [K in keyof A | keyof B]: K extends keyof A\n ? K extends keyof B\n ? IsProcedure<A[K]> extends true\n ? never\n : IsProcedure<B[K]> extends true\n ? never\n : A[K] extends Record<string, unknown>\n ? B[K] extends Record<string, unknown>\n ? MergeApiRouterTypes<A[K], B[K]>\n : never\n : never\n : A[K]\n : K extends keyof B\n ? B[K]\n : never\n}\n\nexport type UnifiedApiRouter<\n TCrud,\n TCustom extends AnyRouter | undefined,\n> = TCustom extends AnyRouter ? MergeApiRouterTypes<TCrud, TCustom> : TCrud\n"]}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Typed route-map generation from the app's OpenAPI document.
3
+ *
4
+ * `generateRouteMap` turns `/api/openapi.json` into a small standalone module:
5
+ * an `ApiRoutes` type — one `Op` entry per operation, carrying its method,
6
+ * path literal, query/body/output types and whether it streams — plus a
7
+ * runtime `routes` descriptor object for that same list.
8
+ *
9
+ * The transport itself is deliberately NOT generated: a ~90-line handwritten
10
+ * client (`createRestClient`) consumes any route map. Types change with every API
11
+ * edit and are regenerated; the client never changes at all.
12
+ */
13
+ type JsonSchema = {
14
+ $ref?: string;
15
+ type?: string | string[];
16
+ anyOf?: JsonSchema[];
17
+ oneOf?: JsonSchema[];
18
+ allOf?: JsonSchema[];
19
+ const?: unknown;
20
+ enum?: unknown[];
21
+ items?: JsonSchema;
22
+ properties?: Record<string, JsonSchema>;
23
+ required?: string[];
24
+ additionalProperties?: boolean | JsonSchema;
25
+ };
26
+ /** JSON-schema subset → TypeScript type expression, with $refs inlined. */
27
+ export declare function schemaToType(schema: JsonSchema | undefined, components?: Record<string, JsonSchema>, depth?: number): string;
28
+ /**
29
+ * Deterministic operation names from the path shape:
30
+ * `/api/posts` GET → `postsList`; `/api/posts/{id}` PATCH → `postsUpdate`;
31
+ * `/api/posts/live` GET → `postsLive`; `/api/enrich` POST → `enrichCreate`.
32
+ */
33
+ export declare function operationName(path: string, method: string): string;
34
+ export declare function generateRouteMap(input: unknown): string;
35
+ export {};
36
+ //# sourceMappingURL=codegen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../src/codegen.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,KAAK,UAAU,GAAG;IAChB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IACxB,KAAK,CAAC,EAAE,UAAU,EAAE,CAAA;IACpB,KAAK,CAAC,EAAE,UAAU,EAAE,CAAA;IACpB,KAAK,CAAC,EAAE,UAAU,EAAE,CAAA;IACpB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,IAAI,CAAC,EAAE,OAAO,EAAE,CAAA;IAChB,KAAK,CAAC,EAAE,UAAU,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;IACvC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,oBAAoB,CAAC,EAAE,OAAO,GAAG,UAAU,CAAA;CAC5C,CAAA;AAoCD,2EAA2E;AAC3E,wBAAgB,YAAY,CAC1B,MAAM,EAAE,UAAU,GAAG,SAAS,EAC9B,UAAU,GAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAM,EAC3C,KAAK,SAAI,GACR,MAAM,CA+DR;AAUD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAgBlE;AA+FD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAwDvD"}
@@ -0,0 +1,235 @@
1
+ /**
2
+ * Typed route-map generation from the app's OpenAPI document.
3
+ *
4
+ * `generateRouteMap` turns `/api/openapi.json` into a small standalone module:
5
+ * an `ApiRoutes` type — one `Op` entry per operation, carrying its method,
6
+ * path literal, query/body/output types and whether it streams — plus a
7
+ * runtime `routes` descriptor object for that same list.
8
+ *
9
+ * The transport itself is deliberately NOT generated: a ~90-line handwritten
10
+ * client (`createRestClient`) consumes any route map. Types change with every API
11
+ * edit and are regenerated; the client never changes at all.
12
+ */
13
+ function pascal(value) {
14
+ return value
15
+ .split(/[^a-zA-Z0-9]+/)
16
+ .filter(Boolean)
17
+ .map((part) => part[0].toUpperCase() + part.slice(1))
18
+ .join('');
19
+ }
20
+ function camel(value) {
21
+ const asPascal = pascal(value);
22
+ return asPascal ? asPascal[0].toLowerCase() + asPascal.slice(1) : 'root';
23
+ }
24
+ /** JSON-schema subset → TypeScript type expression, with $refs inlined. */
25
+ export function schemaToType(schema, components = {}, depth = 0) {
26
+ if (!schema || depth > 4)
27
+ return 'unknown';
28
+ if (schema.$ref) {
29
+ const name = schema.$ref.split('/').pop() ?? '';
30
+ return schemaToType(components[name], components, depth + 1);
31
+ }
32
+ if (schema.const !== undefined)
33
+ return JSON.stringify(schema.const);
34
+ if (schema.enum) {
35
+ return [...new Set(schema.enum.map((value) => JSON.stringify(value)))].join(' | ');
36
+ }
37
+ const variants = schema.anyOf ?? schema.oneOf;
38
+ if (variants) {
39
+ const members = [
40
+ ...new Set(variants.map((member) => schemaToType(member, components, depth))),
41
+ ];
42
+ const withoutNull = members.filter((member) => member !== 'null');
43
+ const joined = withoutNull.join(' | ');
44
+ const core = withoutNull.length > 1 ? `(${joined})` : joined || 'unknown';
45
+ return members.length !== withoutNull.length ? `${core} | null` : core;
46
+ }
47
+ if (schema.allOf) {
48
+ return schema.allOf
49
+ .map((member) => schemaToType(member, components, depth))
50
+ .join(' & ');
51
+ }
52
+ if (Array.isArray(schema.type)) {
53
+ return schema.type
54
+ .map((entry) => (entry === 'integer' ? 'number' : entry))
55
+ .join(' | ');
56
+ }
57
+ switch (schema.type) {
58
+ case 'string':
59
+ return 'string';
60
+ case 'integer':
61
+ case 'number':
62
+ return 'number';
63
+ case 'boolean':
64
+ return 'boolean';
65
+ case 'null':
66
+ return 'null';
67
+ case 'array':
68
+ return `${schemaToType(schema.items, components, depth)}[]`;
69
+ case 'object': {
70
+ const properties = schema.properties ?? {};
71
+ const required = new Set(schema.required ?? []);
72
+ if (Object.keys(properties).length === 0) {
73
+ return schema.additionalProperties === false
74
+ ? 'Record<string, never>'
75
+ : 'Record<string, unknown>';
76
+ }
77
+ const fields = Object.entries(properties).map(([key, child]) => {
78
+ const optional = required.has(key) ? '' : '?';
79
+ return `${JSON.stringify(key)}${optional}: ${schemaToType(child, components, depth)}`;
80
+ });
81
+ return `{ ${fields.join('; ')} }`;
82
+ }
83
+ default:
84
+ return 'unknown';
85
+ }
86
+ }
87
+ const METHOD_ACTIONS = {
88
+ get: 'Get',
89
+ post: 'Create',
90
+ patch: 'Update',
91
+ put: 'Update',
92
+ delete: 'Delete',
93
+ };
94
+ /**
95
+ * Deterministic operation names from the path shape:
96
+ * `/api/posts` GET → `postsList`; `/api/posts/{id}` PATCH → `postsUpdate`;
97
+ * `/api/posts/live` GET → `postsLive`; `/api/enrich` POST → `enrichCreate`.
98
+ */
99
+ export function operationName(path, method) {
100
+ const segments = path.split('/').filter(Boolean);
101
+ if (segments[0] === 'api')
102
+ segments.shift();
103
+ const last = segments[segments.length - 1] ?? '';
104
+ const action = METHOD_ACTIONS[method] ?? pascal(method);
105
+ if (last.startsWith('{')) {
106
+ return `${camel(segments.slice(0, -1).join('_'))}${action}`;
107
+ }
108
+ const statics = segments.filter((segment) => !segment.startsWith('{'));
109
+ if (statics.length === 1 && method === 'get')
110
+ return `${camel(last)}List`;
111
+ if (statics.length === 1 && method === 'post')
112
+ return `${camel(last)}Create`;
113
+ // A deeper static path reads as its own name (`/api/posts/live`) — the
114
+ // method suffix would only add noise.
115
+ if (method === 'get')
116
+ return camel(statics.join('_'));
117
+ return `${camel(statics.join('_'))}${action}`;
118
+ }
119
+ const HTTP_METHODS = ['get', 'post', 'patch', 'put', 'delete'];
120
+ function collectOperations(spec) {
121
+ const components = spec.components?.schemas ?? {};
122
+ const operations = [];
123
+ for (const [path, methods] of Object.entries(spec.paths ?? {})) {
124
+ // Better Auth owns its client contract. Keeping auth endpoints out of the
125
+ // generic REST artifact avoids a second, less capable auth API surface.
126
+ if (path === '/api/auth' || path.startsWith('/api/auth/'))
127
+ continue;
128
+ for (const rawMethod of Object.keys(methods)) {
129
+ if (!HTTP_METHODS.includes(rawMethod))
130
+ continue;
131
+ const operation = methods[rawMethod];
132
+ if (!operation)
133
+ continue;
134
+ const parameters = operation.parameters ?? [];
135
+ const queryParameters = parameters.filter((parameter) => parameter.in === 'query');
136
+ let queryType;
137
+ if (queryParameters.length > 0) {
138
+ const fields = queryParameters.map((parameter) => {
139
+ const schema = parameter.schema ?? parameter.content?.['application/json']?.schema;
140
+ return `${JSON.stringify(parameter.name)}?: ${schemaToType(schema, components)}`;
141
+ });
142
+ queryType = `{ ${fields.join('; ')} }`;
143
+ }
144
+ const requestSchema = operation.requestBody?.content?.['application/json']?.schema;
145
+ const rawBodyType = requestSchema
146
+ ? schemaToType(requestSchema, components)
147
+ : undefined;
148
+ // oRPC emits an empty-object request body even for body-less
149
+ // procedures like DELETE; a free-form record there is noise.
150
+ const bodyType = rawBodyType === 'Record<string, unknown>' && rawMethod === 'delete'
151
+ ? undefined
152
+ : rawBodyType;
153
+ const okResponse = operation.responses?.['200'] ?? operation.responses?.['201'];
154
+ const jsonSchema = okResponse?.content?.['application/json']?.schema;
155
+ const eventSchema = okResponse?.content?.['text/event-stream']?.schema;
156
+ let outputType = 'void';
157
+ let isStream = false;
158
+ if (eventSchema) {
159
+ isStream = true;
160
+ // oRPC wraps each SSE data frame as {event, data}; unwrap the payload.
161
+ // Wrapper variants that carry no data (or map to `unknown`) would
162
+ // swallow the whole union, so they are dropped here.
163
+ const wrapper = eventSchema.oneOf ?? eventSchema.anyOf ?? [];
164
+ outputType =
165
+ [
166
+ ...new Set(wrapper
167
+ .map((variant) => variant.properties?.['data'])
168
+ .filter((variant) => Boolean(variant))
169
+ .map((variant) => schemaToType(variant, components))
170
+ .filter((type) => type !== 'unknown')),
171
+ ].join(' | ') || 'void';
172
+ }
173
+ else if (jsonSchema) {
174
+ outputType = schemaToType(jsonSchema, components);
175
+ }
176
+ operations.push({
177
+ name: operationName(path, rawMethod),
178
+ method: rawMethod.toUpperCase(),
179
+ path,
180
+ queryType,
181
+ bodyType,
182
+ outputType,
183
+ isStream,
184
+ });
185
+ }
186
+ }
187
+ return operations;
188
+ }
189
+ export function generateRouteMap(input) {
190
+ const spec = input;
191
+ const operations = collectOperations(spec);
192
+ const lines = [];
193
+ lines.push('// Generated by bunderstack codegen from /api/openapi.json.');
194
+ lines.push('// Regenerate with `bun run gen`; do not edit by hand.');
195
+ lines.push('');
196
+ lines.push('/** One API operation: literals describe the wire, phantoms the shapes. */');
197
+ lines.push('export interface Op<');
198
+ lines.push(' M extends string,');
199
+ lines.push(' P extends string,');
200
+ lines.push(' Query = undefined,');
201
+ lines.push(' Body = undefined,');
202
+ lines.push(' Output = void,');
203
+ lines.push(' Stream extends boolean = false,');
204
+ lines.push('> {');
205
+ lines.push(' method: M');
206
+ lines.push(' path: P');
207
+ lines.push(' stream: Stream');
208
+ lines.push(' query?: Query');
209
+ lines.push(' body?: Body');
210
+ lines.push(' output?: Output');
211
+ lines.push('}');
212
+ lines.push('');
213
+ lines.push('export type ApiRoutes = {');
214
+ const runtimeEntries = [];
215
+ for (const operation of operations) {
216
+ const generics = [
217
+ `'${operation.method}'`,
218
+ `'${operation.path}'`,
219
+ operation.queryType ?? 'undefined',
220
+ operation.bodyType ?? 'undefined',
221
+ operation.isStream ? operation.outputType : operation.outputType,
222
+ String(operation.isStream),
223
+ ].join(', ');
224
+ lines.push(` ${operation.name}: Op<${generics}>`);
225
+ runtimeEntries.push(` ${operation.name}: { method: '${operation.method}', path: '${operation.path}'${operation.isStream ? ', stream: true' : ''} },`);
226
+ }
227
+ lines.push('}');
228
+ lines.push('');
229
+ lines.push('/** Wire descriptors for createRestClient — same keys, runtime values. */');
230
+ lines.push('export const routes = {');
231
+ lines.push(...runtimeEntries);
232
+ lines.push('} as const');
233
+ return lines.join('\n');
234
+ }
235
+ //# sourceMappingURL=codegen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codegen.js","sourceRoot":"","sources":["../src/codegen.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAqCH,SAAS,MAAM,CAAC,KAAa;IAC3B,OAAO,KAAK;SACT,KAAK,CAAC,eAAe,CAAC;SACtB,MAAM,CAAC,OAAO,CAAC;SACf,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SACrD,IAAI,CAAC,EAAE,CAAC,CAAA;AACb,CAAC;AAED,SAAS,KAAK,CAAC,KAAa;IAC1B,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;IAC9B,OAAO,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAA;AAC3E,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,YAAY,CAC1B,MAA8B,EAC9B,aAAyC,EAAE,EAC3C,KAAK,GAAG,CAAC;IAET,IAAI,CAAC,MAAM,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,SAAS,CAAA;IAC1C,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAChB,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAA;QAC/C,OAAO,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,KAAK,GAAG,CAAC,CAAC,CAAA;IAC9D,CAAC;IACD,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IACnE,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAChB,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CACzE,KAAK,CACN,CAAA;IACH,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,CAAA;IAC7C,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,OAAO,GAAG;YACd,GAAG,IAAI,GAAG,CACR,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,CAAC,CAAC,CAClE;SACF,CAAA;QACD,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,KAAK,MAAM,CAAC,CAAA;QACjE,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACtC,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,SAAS,CAAA;QACzE,OAAO,OAAO,CAAC,MAAM,KAAK,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,SAAS,CAAC,CAAC,CAAC,IAAI,CAAA;IACxE,CAAC;IACD,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,OAAO,MAAM,CAAC,KAAK;aAChB,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,CAAC,CAAC;aACxD,IAAI,CAAC,KAAK,CAAC,CAAA;IAChB,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/B,OAAO,MAAM,CAAC,IAAI;aACf,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;aACxD,IAAI,CAAC,KAAK,CAAC,CAAA;IAChB,CAAC;IACD,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,QAAQ;YACX,OAAO,QAAQ,CAAA;QACjB,KAAK,SAAS,CAAC;QACf,KAAK,QAAQ;YACX,OAAO,QAAQ,CAAA;QACjB,KAAK,SAAS;YACZ,OAAO,SAAS,CAAA;QAClB,KAAK,MAAM;YACT,OAAO,MAAM,CAAA;QACf,KAAK,OAAO;YACV,OAAO,GAAG,YAAY,CAAC,MAAM,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,CAAC,IAAI,CAAA;QAC7D,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,EAAE,CAAA;YAC1C,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAA;YAC/C,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzC,OAAO,MAAM,CAAC,oBAAoB,KAAK,KAAK;oBAC1C,CAAC,CAAC,uBAAuB;oBACzB,CAAC,CAAC,yBAAyB,CAAA;YAC/B,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;gBAC7D,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAA;gBAC7C,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,QAAQ,KAAK,YAAY,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,CAAC,EAAE,CAAA;YACvF,CAAC,CAAC,CAAA;YACF,OAAO,KAAK,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAA;QACnC,CAAC;QACD;YACE,OAAO,SAAS,CAAA;IACpB,CAAC;AACH,CAAC;AAED,MAAM,cAAc,GAA2B;IAC7C,GAAG,EAAE,KAAK;IACV,IAAI,EAAE,QAAQ;IACd,KAAK,EAAE,QAAQ;IACf,GAAG,EAAE,QAAQ;IACb,MAAM,EAAE,QAAQ;CACjB,CAAA;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,MAAc;IACxD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IAChD,IAAI,QAAQ,CAAC,CAAC,CAAC,KAAK,KAAK;QAAE,QAAQ,CAAC,KAAK,EAAE,CAAA;IAC3C,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,CAAA;IAChD,MAAM,MAAM,GAAG,cAAc,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,CAAA;IAEvD,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACzB,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,EAAE,CAAA;IAC7D,CAAC;IACD,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAA;IACtE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,KAAK,KAAK;QAAE,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAA;IACzE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,KAAK,MAAM;QAAE,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAA;IAC5E,uEAAuE;IACvE,sCAAsC;IACtC,IAAI,MAAM,KAAK,KAAK;QAAE,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;IACrD,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,EAAE,CAAA;AAC/C,CAAC;AAYD,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAA;AAE9D,SAAS,iBAAiB,CAAC,IAAiB;IAC1C,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,OAAO,IAAI,EAAE,CAAA;IACjD,MAAM,UAAU,GAAuB,EAAE,CAAA;IAEzC,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC;QAC/D,0EAA0E;QAC1E,wEAAwE;QACxE,IAAI,IAAI,KAAK,WAAW,IAAI,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC;YAAE,SAAQ;QACnE,KAAK,MAAM,SAAS,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAC7C,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,SAAS,CAAC;gBAAE,SAAQ;YAC/C,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,CAAA;YACpC,IAAI,CAAC,SAAS;gBAAE,SAAQ;YAExB,MAAM,UAAU,GAAG,SAAS,CAAC,UAAU,IAAI,EAAE,CAAA;YAC7C,MAAM,eAAe,GAAG,UAAU,CAAC,MAAM,CACvC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,KAAK,OAAO,CACxC,CAAA;YAED,IAAI,SAA6B,CAAA;YACjC,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC/B,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE;oBAC/C,MAAM,MAAM,GACV,SAAS,CAAC,MAAM,IAAI,SAAS,CAAC,OAAO,EAAE,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAA;oBACrE,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,YAAY,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,CAAA;gBAClF,CAAC,CAAC,CAAA;gBACF,SAAS,GAAG,KAAK,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAA;YACxC,CAAC;YAED,MAAM,aAAa,GACjB,SAAS,CAAC,WAAW,EAAE,OAAO,EAAE,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAA;YAC9D,MAAM,WAAW,GAAG,aAAa;gBAC/B,CAAC,CAAC,YAAY,CAAC,aAAa,EAAE,UAAU,CAAC;gBACzC,CAAC,CAAC,SAAS,CAAA;YACb,6DAA6D;YAC7D,6DAA6D;YAC7D,MAAM,QAAQ,GACZ,WAAW,KAAK,yBAAyB,IAAI,SAAS,KAAK,QAAQ;gBACjE,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,WAAW,CAAA;YAEjB,MAAM,UAAU,GACd,SAAS,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC,IAAI,SAAS,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC,CAAA;YAC9D,MAAM,UAAU,GAAG,UAAU,EAAE,OAAO,EAAE,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAA;YACpE,MAAM,WAAW,GAAG,UAAU,EAAE,OAAO,EAAE,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAA;YAEtE,IAAI,UAAU,GAAG,MAAM,CAAA;YACvB,IAAI,QAAQ,GAAG,KAAK,CAAA;YACpB,IAAI,WAAW,EAAE,CAAC;gBAChB,QAAQ,GAAG,IAAI,CAAA;gBACf,uEAAuE;gBACvE,kEAAkE;gBAClE,qDAAqD;gBACrD,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,IAAI,WAAW,CAAC,KAAK,IAAI,EAAE,CAAA;gBAC5D,UAAU;oBACR;wBACE,GAAG,IAAI,GAAG,CACR,OAAO;6BACJ,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,MAAM,CAAC,CAAC;6BAC9C,MAAM,CAAC,CAAC,OAAO,EAAyB,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;6BAC5D,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;6BACnD,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,SAAS,CAAC,CACxC;qBACF,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,MAAM,CAAA;YAC3B,CAAC;iBAAM,IAAI,UAAU,EAAE,CAAC;gBACtB,UAAU,GAAG,YAAY,CAAC,UAAU,EAAE,UAAU,CAAC,CAAA;YACnD,CAAC;YAED,UAAU,CAAC,IAAI,CAAC;gBACd,IAAI,EAAE,aAAa,CAAC,IAAI,EAAE,SAAS,CAAC;gBACpC,MAAM,EAAE,SAAS,CAAC,WAAW,EAAE;gBAC/B,IAAI;gBACJ,SAAS;gBACT,QAAQ;gBACR,UAAU;gBACV,QAAQ;aACT,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IACD,OAAO,UAAU,CAAA;AACnB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,MAAM,IAAI,GAAG,KAAoB,CAAA;IACjC,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAA;IAE1C,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,KAAK,CAAC,IAAI,CAAC,6DAA6D,CAAC,CAAA;IACzE,KAAK,CAAC,IAAI,CAAC,wDAAwD,CAAC,CAAA;IACpE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACd,KAAK,CAAC,IAAI,CACR,4EAA4E,CAC7E,CAAA;IACD,KAAK,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAA;IAClC,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAA;IACjC,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAA;IACjC,KAAK,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAA;IAClC,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAA;IACjC,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAA;IAC9B,KAAK,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAA;IAC/C,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACjB,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;IACzB,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;IACvB,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAA;IAC9B,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;IAC7B,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;IAC3B,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAA;IAC/B,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACf,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACd,KAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAA;IAEvC,MAAM,cAAc,GAAa,EAAE,CAAA;IACnC,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,MAAM,QAAQ,GAAG;YACf,IAAI,SAAS,CAAC,MAAM,GAAG;YACvB,IAAI,SAAS,CAAC,IAAI,GAAG;YACrB,SAAS,CAAC,SAAS,IAAI,WAAW;YAClC,SAAS,CAAC,QAAQ,IAAI,WAAW;YACjC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,UAAU;YAChE,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC;SAC3B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACZ,KAAK,CAAC,IAAI,CAAC,KAAK,SAAS,CAAC,IAAI,QAAQ,QAAQ,GAAG,CAAC,CAAA;QAClD,cAAc,CAAC,IAAI,CACjB,KAAK,SAAS,CAAC,IAAI,gBAAgB,SAAS,CAAC,MAAM,aAAa,SAAS,CAAC,IAAI,IAC5E,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAC1C,KAAK,CACN,CAAA;IACH,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACf,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACd,KAAK,CAAC,IAAI,CACR,2EAA2E,CAC5E,CAAA;IACD,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAA;IACrC,KAAK,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,CAAA;IAC7B,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;IAExB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC","sourcesContent":["/**\n * Typed route-map generation from the app's OpenAPI document.\n *\n * `generateRouteMap` turns `/api/openapi.json` into a small standalone module:\n * an `ApiRoutes` type — one `Op` entry per operation, carrying its method,\n * path literal, query/body/output types and whether it streams — plus a\n * runtime `routes` descriptor object for that same list.\n *\n * The transport itself is deliberately NOT generated: a ~90-line handwritten\n * client (`createRestClient`) consumes any route map. Types change with every API\n * edit and are regenerated; the client never changes at all.\n */\n\ntype JsonSchema = {\n $ref?: string\n type?: string | string[]\n anyOf?: JsonSchema[]\n oneOf?: JsonSchema[]\n allOf?: JsonSchema[]\n const?: unknown\n enum?: unknown[]\n items?: JsonSchema\n properties?: Record<string, JsonSchema>\n required?: string[]\n additionalProperties?: boolean | JsonSchema\n}\n\ntype Parameter = {\n in: string\n name: string\n schema?: JsonSchema\n content?: Record<string, { schema: JsonSchema }>\n}\n\ntype Operation = {\n parameters?: Parameter[]\n requestBody?: { content?: Record<string, { schema: JsonSchema }> }\n responses?: Record<\n string,\n { content?: Record<string, { schema: JsonSchema }> }\n >\n}\n\ntype OpenApiSpec = {\n paths?: Record<string, Record<string, Operation | undefined>>\n components?: { schemas?: Record<string, JsonSchema> }\n}\n\nfunction pascal(value: string): string {\n return value\n .split(/[^a-zA-Z0-9]+/)\n .filter(Boolean)\n .map((part) => part[0]!.toUpperCase() + part.slice(1))\n .join('')\n}\n\nfunction camel(value: string): string {\n const asPascal = pascal(value)\n return asPascal ? asPascal[0]!.toLowerCase() + asPascal.slice(1) : 'root'\n}\n\n/** JSON-schema subset → TypeScript type expression, with $refs inlined. */\nexport function schemaToType(\n schema: JsonSchema | undefined,\n components: Record<string, JsonSchema> = {},\n depth = 0,\n): string {\n if (!schema || depth > 4) return 'unknown'\n if (schema.$ref) {\n const name = schema.$ref.split('/').pop() ?? ''\n return schemaToType(components[name], components, depth + 1)\n }\n if (schema.const !== undefined) return JSON.stringify(schema.const)\n if (schema.enum) {\n return [...new Set(schema.enum.map((value) => JSON.stringify(value)))].join(\n ' | ',\n )\n }\n const variants = schema.anyOf ?? schema.oneOf\n if (variants) {\n const members = [\n ...new Set(\n variants.map((member) => schemaToType(member, components, depth)),\n ),\n ]\n const withoutNull = members.filter((member) => member !== 'null')\n const joined = withoutNull.join(' | ')\n const core = withoutNull.length > 1 ? `(${joined})` : joined || 'unknown'\n return members.length !== withoutNull.length ? `${core} | null` : core\n }\n if (schema.allOf) {\n return schema.allOf\n .map((member) => schemaToType(member, components, depth))\n .join(' & ')\n }\n if (Array.isArray(schema.type)) {\n return schema.type\n .map((entry) => (entry === 'integer' ? 'number' : entry))\n .join(' | ')\n }\n switch (schema.type) {\n case 'string':\n return 'string'\n case 'integer':\n case 'number':\n return 'number'\n case 'boolean':\n return 'boolean'\n case 'null':\n return 'null'\n case 'array':\n return `${schemaToType(schema.items, components, depth)}[]`\n case 'object': {\n const properties = schema.properties ?? {}\n const required = new Set(schema.required ?? [])\n if (Object.keys(properties).length === 0) {\n return schema.additionalProperties === false\n ? 'Record<string, never>'\n : 'Record<string, unknown>'\n }\n const fields = Object.entries(properties).map(([key, child]) => {\n const optional = required.has(key) ? '' : '?'\n return `${JSON.stringify(key)}${optional}: ${schemaToType(child, components, depth)}`\n })\n return `{ ${fields.join('; ')} }`\n }\n default:\n return 'unknown'\n }\n}\n\nconst METHOD_ACTIONS: Record<string, string> = {\n get: 'Get',\n post: 'Create',\n patch: 'Update',\n put: 'Update',\n delete: 'Delete',\n}\n\n/**\n * Deterministic operation names from the path shape:\n * `/api/posts` GET → `postsList`; `/api/posts/{id}` PATCH → `postsUpdate`;\n * `/api/posts/live` GET → `postsLive`; `/api/enrich` POST → `enrichCreate`.\n */\nexport function operationName(path: string, method: string): string {\n const segments = path.split('/').filter(Boolean)\n if (segments[0] === 'api') segments.shift()\n const last = segments[segments.length - 1] ?? ''\n const action = METHOD_ACTIONS[method] ?? pascal(method)\n\n if (last.startsWith('{')) {\n return `${camel(segments.slice(0, -1).join('_'))}${action}`\n }\n const statics = segments.filter((segment) => !segment.startsWith('{'))\n if (statics.length === 1 && method === 'get') return `${camel(last)}List`\n if (statics.length === 1 && method === 'post') return `${camel(last)}Create`\n // A deeper static path reads as its own name (`/api/posts/live`) — the\n // method suffix would only add noise.\n if (method === 'get') return camel(statics.join('_'))\n return `${camel(statics.join('_'))}${action}`\n}\n\ntype EmittedOperation = {\n name: string\n method: string\n path: string\n queryType?: string\n bodyType?: string\n outputType: string\n isStream: boolean\n}\n\nconst HTTP_METHODS = ['get', 'post', 'patch', 'put', 'delete']\n\nfunction collectOperations(spec: OpenApiSpec): EmittedOperation[] {\n const components = spec.components?.schemas ?? {}\n const operations: EmittedOperation[] = []\n\n for (const [path, methods] of Object.entries(spec.paths ?? {})) {\n // Better Auth owns its client contract. Keeping auth endpoints out of the\n // generic REST artifact avoids a second, less capable auth API surface.\n if (path === '/api/auth' || path.startsWith('/api/auth/')) continue\n for (const rawMethod of Object.keys(methods)) {\n if (!HTTP_METHODS.includes(rawMethod)) continue\n const operation = methods[rawMethod]\n if (!operation) continue\n\n const parameters = operation.parameters ?? []\n const queryParameters = parameters.filter(\n (parameter) => parameter.in === 'query',\n )\n\n let queryType: string | undefined\n if (queryParameters.length > 0) {\n const fields = queryParameters.map((parameter) => {\n const schema =\n parameter.schema ?? parameter.content?.['application/json']?.schema\n return `${JSON.stringify(parameter.name)}?: ${schemaToType(schema, components)}`\n })\n queryType = `{ ${fields.join('; ')} }`\n }\n\n const requestSchema =\n operation.requestBody?.content?.['application/json']?.schema\n const rawBodyType = requestSchema\n ? schemaToType(requestSchema, components)\n : undefined\n // oRPC emits an empty-object request body even for body-less\n // procedures like DELETE; a free-form record there is noise.\n const bodyType =\n rawBodyType === 'Record<string, unknown>' && rawMethod === 'delete'\n ? undefined\n : rawBodyType\n\n const okResponse =\n operation.responses?.['200'] ?? operation.responses?.['201']\n const jsonSchema = okResponse?.content?.['application/json']?.schema\n const eventSchema = okResponse?.content?.['text/event-stream']?.schema\n\n let outputType = 'void'\n let isStream = false\n if (eventSchema) {\n isStream = true\n // oRPC wraps each SSE data frame as {event, data}; unwrap the payload.\n // Wrapper variants that carry no data (or map to `unknown`) would\n // swallow the whole union, so they are dropped here.\n const wrapper = eventSchema.oneOf ?? eventSchema.anyOf ?? []\n outputType =\n [\n ...new Set(\n wrapper\n .map((variant) => variant.properties?.['data'])\n .filter((variant): variant is JsonSchema => Boolean(variant))\n .map((variant) => schemaToType(variant, components))\n .filter((type) => type !== 'unknown'),\n ),\n ].join(' | ') || 'void'\n } else if (jsonSchema) {\n outputType = schemaToType(jsonSchema, components)\n }\n\n operations.push({\n name: operationName(path, rawMethod),\n method: rawMethod.toUpperCase(),\n path,\n queryType,\n bodyType,\n outputType,\n isStream,\n })\n }\n }\n return operations\n}\n\nexport function generateRouteMap(input: unknown): string {\n const spec = input as OpenApiSpec\n const operations = collectOperations(spec)\n\n const lines: string[] = []\n lines.push('// Generated by bunderstack codegen from /api/openapi.json.')\n lines.push('// Regenerate with `bun run gen`; do not edit by hand.')\n lines.push('')\n lines.push(\n '/** One API operation: literals describe the wire, phantoms the shapes. */',\n )\n lines.push('export interface Op<')\n lines.push(' M extends string,')\n lines.push(' P extends string,')\n lines.push(' Query = undefined,')\n lines.push(' Body = undefined,')\n lines.push(' Output = void,')\n lines.push(' Stream extends boolean = false,')\n lines.push('> {')\n lines.push(' method: M')\n lines.push(' path: P')\n lines.push(' stream: Stream')\n lines.push(' query?: Query')\n lines.push(' body?: Body')\n lines.push(' output?: Output')\n lines.push('}')\n lines.push('')\n lines.push('export type ApiRoutes = {')\n\n const runtimeEntries: string[] = []\n for (const operation of operations) {\n const generics = [\n `'${operation.method}'`,\n `'${operation.path}'`,\n operation.queryType ?? 'undefined',\n operation.bodyType ?? 'undefined',\n operation.isStream ? operation.outputType : operation.outputType,\n String(operation.isStream),\n ].join(', ')\n lines.push(` ${operation.name}: Op<${generics}>`)\n runtimeEntries.push(\n ` ${operation.name}: { method: '${operation.method}', path: '${operation.path}'${\n operation.isStream ? ', stream: true' : ''\n } },`,\n )\n }\n lines.push('}')\n lines.push('')\n lines.push(\n '/** Wire descriptors for createRestClient — same keys, runtime values. */',\n )\n lines.push('export const routes = {')\n lines.push(...runtimeEntries)\n lines.push('} as const')\n\n return lines.join('\\n')\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"crud-operations.d.ts","sourceRoot":"","sources":["../src/crud-operations.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,WAAW,CAAA;AACtC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAEvD,OAAO,EAML,KAAK,UAAU,EACf,KAAK,cAAc,EAGpB,MAAM,UAAU,CAAA;AACjB,OAAO,EACL,gBAAgB,EAIhB,KAAK,cAAc,EACpB,MAAM,UAAU,CAAA;AACjB,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,eAAe,CAAA;AACtB,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,UAAU,EAChB,MAAM,cAAc,CAAA;AAGrB,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAA;IAChB,IAAI,EAAE,UAAU,GAAG,IAAI,CAAA;IACvB,OAAO,EAAE;QAAE,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAA;CACjD;AAYD,qBAAa,kBAAmB,SAAQ,gBAAgB;IAGpD,QAAQ,CAAC,UAAU,EAAE,cAAc;gBADnC,MAAM,EAAE,MAAM,EACL,UAAU,EAAE,cAAc,EACnC,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,OAAO;CAepB;AAED,MAAM,MAAM,kBAAkB,CAC5B,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAC/D;IACF,MAAM,EAAE,OAAO,CAAA;IACf,EAAE,EAAE,KAAK,CAAA;IACT,MAAM,EAAE,cAAc,CAAA;IACtB,WAAW,CAAC,EAAE,OAAO,GAAG,iBAAiB,CAAA;IACzC,QAAQ,CAAC,EAAE,cAAc,CAAC,OAAO,CAAC,CAAA;CACnC,CAAA;AAED,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,GAAG,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GACjE;IACE,IAAI,EAAE,QAAQ,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAChC,CAAA;AAyCL,wBAAgB,oBAAoB,CAClC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjE,IAAI,EAAE,kBAAkB,CAAC,OAAO,CAAC;oBAuClB,MAAM,UACT,eAAe,GAAG,SAAS,OAC9B,oBAAoB,GACxB,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;mBAqClC,MAAM,SACV,MAAM,GAAG,MAAM,OACjB,oBAAoB,GACxB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;sBAgCtB,MAAM,QACX,OAAO,WACJ,MAAM,GAAG,SAAS,kBACX,MAAM,GAAG,SAAS,OAC7B,oBAAoB,GACxB,OAAO,CAAC,YAAY,CAAC;sBAiGX,MAAM,SACV,MAAM,GAAG,MAAM,QAChB,OAAO,OACR,oBAAoB,GACxB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;sBAqEtB,MAAM,SACV,MAAM,GAAG,MAAM,OACjB,oBAAoB,GACxB,OAAO,CAAC,IAAI,CAAC;EAgCnB;AAED,MAAM,MAAM,cAAc,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAA"}
1
+ {"version":3,"file":"crud-operations.d.ts","sourceRoot":"","sources":["../src/crud-operations.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,WAAW,CAAA;AACtC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAEvD,OAAO,EAML,KAAK,UAAU,EACf,KAAK,cAAc,EAGpB,MAAM,UAAU,CAAA;AACjB,OAAO,EACL,gBAAgB,EAIhB,KAAK,cAAc,EACpB,MAAM,UAAU,CAAA;AACjB,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,eAAe,CAAA;AACtB,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,UAAU,EAChB,MAAM,cAAc,CAAA;AAGrB,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAA;IAChB,IAAI,EAAE,UAAU,GAAG,IAAI,CAAA;IACvB,OAAO,EAAE;QAAE,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAA;CACjD;AAiBD,qBAAa,kBAAmB,SAAQ,gBAAgB;IAGpD,QAAQ,CAAC,UAAU,EAAE,cAAc;gBADnC,MAAM,EAAE,MAAM,EACL,UAAU,EAAE,cAAc,EACnC,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,OAAO;CAepB;AAED,MAAM,MAAM,kBAAkB,CAC5B,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAC/D;IACF,MAAM,EAAE,OAAO,CAAA;IACf,EAAE,EAAE,KAAK,CAAA;IACT,MAAM,EAAE,cAAc,CAAA;IACtB,WAAW,CAAC,EAAE,OAAO,GAAG,iBAAiB,CAAA;IACzC,QAAQ,CAAC,EAAE,cAAc,CAAC,OAAO,CAAC,CAAA;CACnC,CAAA;AAED,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,GAAG,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GACjE;IACE,IAAI,EAAE,QAAQ,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAChC,CAAA;AAyCL,wBAAgB,oBAAoB,CAClC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjE,IAAI,EAAE,kBAAkB,CAAC,OAAO,CAAC;oBAuClB,MAAM,UACT,eAAe,GAAG,SAAS,OAC9B,oBAAoB,GACxB,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;mBAqClC,MAAM,SACV,MAAM,GAAG,MAAM,OACjB,oBAAoB,GACxB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;sBAgCtB,MAAM,QACX,OAAO,WACJ,MAAM,GAAG,SAAS,kBACX,MAAM,GAAG,SAAS,OAC7B,oBAAoB,GACxB,OAAO,CAAC,YAAY,CAAC;sBAsGX,MAAM,SACV,MAAM,GAAG,MAAM,QAChB,OAAO,OACR,oBAAoB,GACxB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;sBA0EtB,MAAM,SACV,MAAM,GAAG,MAAM,OACjB,oBAAoB,GACxB,OAAO,CAAC,IAAI,CAAC;EAqCnB;AAED,MAAM,MAAM,cAAc,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAA"}
@@ -4,6 +4,10 @@ import { BunderstackError, ErrorCode, ListQueryError, } from './errors.js';
4
4
  import { lookupIdempotency, resolveIdempotencyConfig, storeIdempotency, } from './idempotency.js';
5
5
  import { executeList, resolveListParams, } from './list-query.js';
6
6
  import { buildScopeWhere } from './scope.js';
7
+ function operationMetadata(request) {
8
+ const operationId = request.headers.get('x-bunderstack-operation-id')?.trim();
9
+ return operationId ? { operationId } : {};
10
+ }
7
11
  function errorCodeForStatus(status) {
8
12
  if (status === 401)
9
13
  return 'UNAUTHORIZED';
@@ -158,7 +162,7 @@ export function createCrudOperations(deps) {
158
162
  throw error;
159
163
  }
160
164
  const created = rows[0];
161
- void realtime?.publish(table, 'create', created);
165
+ void realtime?.publish(table, 'create', created, operationMetadata(ctx.request));
162
166
  if (idempotency && trimmedKey) {
163
167
  await storeIdempotency(db, tableName, trimmedKey, effectiveRawBody, 201, created, idempotency);
164
168
  }
@@ -202,7 +206,7 @@ export function createCrudOperations(deps) {
202
206
  throw new CrudOperationError(404, ErrorCode.NOT_FOUND, 'Not found');
203
207
  }
204
208
  const updated = rows[0];
205
- void realtime?.publish(table, 'update', updated);
209
+ void realtime?.publish(table, 'update', updated, operationMetadata(ctx.request));
206
210
  return updated;
207
211
  },
208
212
  async delete(tableName, rawId, ctx) {
@@ -222,7 +226,7 @@ export function createCrudOperations(deps) {
222
226
  throw new CrudOperationError(denied.status === 401 ? 401 : 403, ErrorCode.FORBIDDEN, 'Forbidden');
223
227
  }
224
228
  await db.delete(table).where(eq(idCol, id));
225
- void realtime?.publish(table, 'delete', existingRow);
229
+ void realtime?.publish(table, 'delete', existingRow, operationMetadata(ctx.request));
226
230
  },
227
231
  };
228
232
  }
@@ -1 +1 @@
1
- {"version":3,"file":"crud-operations.js","sourceRoot":"","sources":["../src/crud-operations.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n eq,\n getTableColumns,\n getTableName,\n isTable,\n type Table,\n} from 'drizzle-orm'\n\nimport type { AnyDb } from './dialect'\nimport type { RealtimeFacade } from './realtime/facade'\n\nimport {\n checkAccess,\n rowMatchesScope,\n sanitizeWriteBody,\n stampScope,\n tableEntryForName,\n type AccessUser,\n type ResolvedAccess,\n type ScopeMap,\n type ScopeResolver,\n} from './access'\nimport {\n BunderstackError,\n ErrorCode,\n ListQueryError,\n type BunderstackErrorCode,\n type ErrorCodeValue,\n} from './errors'\nimport {\n lookupIdempotency,\n resolveIdempotencyConfig,\n storeIdempotency,\n type IdempotencyConfig,\n} from './idempotency'\nimport {\n executeList,\n resolveListParams,\n type ListParamsInput,\n type ListResult,\n} from './list-query'\nimport { buildScopeWhere } from './scope'\n\nexport interface CrudExecutionContext {\n request: Request\n user: AccessUser | null\n session: { activeOrganizationId: string | null }\n}\n\nfunction errorCodeForStatus(status: number): BunderstackErrorCode {\n if (status === 401) return 'UNAUTHORIZED'\n if (status === 403) return 'FORBIDDEN'\n if (status === 404) return 'NOT_FOUND'\n if (status === 409) return 'CONFLICT'\n if (status === 413) return 'PAYLOAD_TOO_LARGE'\n if (status === 429) return 'TOO_MANY_REQUESTS'\n return 'BAD_REQUEST'\n}\n\nexport class CrudOperationError extends BunderstackError {\n constructor(\n status: number,\n readonly legacyCode: ErrorCodeValue,\n message: string,\n details?: unknown,\n ) {\n const code = errorCodeForStatus(status)\n super(\n code,\n message,\n legacyCode === code\n ? details\n : {\n code: legacyCode,\n ...(details === undefined ? {} : { details }),\n },\n )\n this.name = 'CrudOperationError'\n }\n}\n\nexport type CrudOperationsDeps<\n TSchema extends Record<string, unknown> = Record<string, unknown>,\n> = {\n schema: TSchema\n db: AnyDb\n access: ResolvedAccess\n idempotency?: boolean | IdempotencyConfig\n realtime?: RealtimeFacade<TSchema>\n}\n\nexport type CreateResult =\n | { type: 'created'; status: 201; record: Record<string, unknown> }\n | {\n type: 'replay'\n status: number\n body: string\n record: Record<string, unknown>\n }\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction isUniqueConstraintError(error: unknown): boolean {\n const seen = new Set<unknown>()\n let current = error\n\n while (isRecord(current) && !seen.has(current)) {\n seen.add(current)\n const code = current['code']\n if (\n code === '23505' ||\n code === 'SQLITE_CONSTRAINT_UNIQUE' ||\n code === 'SQLITE_CONSTRAINT_PRIMARYKEY'\n ) {\n return true\n }\n\n const message = current['message']\n if (\n typeof message === 'string' &&\n (/duplicate key value violates unique constraint/i.test(message) ||\n /unique constraint failed/i.test(message))\n ) {\n return true\n }\n\n current = current['cause']\n }\n\n return false\n}\n\nfunction coerceId(rawId: string | number): string | number {\n if (typeof rawId === 'number') return rawId\n return isNaN(Number(rawId)) ? rawId : Number(rawId)\n}\n\nexport function createCrudOperations<\n TSchema extends Record<string, unknown> = Record<string, unknown>,\n>(deps: CrudOperationsDeps<TSchema>) {\n const { schema, db, access, realtime } = deps\n const idempotency = resolveIdempotencyConfig(deps.idempotency)\n\n const scopeFor = (\n resolver: ScopeResolver | undefined,\n ctx: {\n user: AccessUser | null\n session: { activeOrganizationId: string | null }\n request: Request\n row?: Record<string, unknown>\n body?: Record<string, unknown>\n },\n ): ScopeMap | undefined => (resolver ? resolver(ctx) : undefined)\n\n function resolveTable(tableName: string) {\n const table = Object.values(schema).find(\n (t) => isTable(t) && getTableName(t) === tableName,\n ) as Table | undefined\n if (!table) {\n throw new CrudOperationError(404, ErrorCode.NOT_FOUND, 'Not found')\n }\n const tableAccess = tableEntryForName(access, tableName)\n if (!tableAccess || !tableAccess.enabled) {\n throw new CrudOperationError(404, ErrorCode.NOT_FOUND, 'Not found')\n }\n const idCol = getTableColumns(table)['id']\n if (!idCol) {\n throw new CrudOperationError(\n 400,\n ErrorCode.BAD_REQUEST,\n `Table ${tableName} has no id column`,\n )\n }\n return { table, tableAccess, idCol }\n }\n\n return {\n async list(\n tableName: string,\n params: ListParamsInput | undefined,\n ctx: CrudExecutionContext,\n ): Promise<ListResult<Record<string, unknown>>> {\n const { table, tableAccess, idCol } = resolveTable(tableName)\n\n const denied = await checkAccess(\n tableAccess.list,\n ctx,\n tableAccess.ownerColumn,\n )\n if (!denied.allowed) {\n throw new CrudOperationError(\n denied.status === 401 ? 401 : 403,\n ErrorCode.FORBIDDEN,\n 'Forbidden',\n )\n }\n\n try {\n const resolved = resolveListParams(params ?? {}, tableAccess)\n const scope = scopeFor(tableAccess.readScope, ctx)\n const scopeWhere = scope ? buildScopeWhere(table, scope) : undefined\n return await executeList(\n db,\n table,\n tableAccess,\n resolved,\n idCol,\n scopeWhere,\n )\n } catch (err) {\n if (err instanceof ListQueryError) {\n throw new CrudOperationError(400, err.code, err.message, err.details)\n }\n throw err\n }\n },\n\n async get(\n tableName: string,\n rawId: string | number,\n ctx: CrudExecutionContext,\n ): Promise<Record<string, unknown>> {\n const { table, tableAccess, idCol } = resolveTable(tableName)\n const id = coerceId(rawId)\n\n const rows = await db.select().from(table).where(eq(idCol, id))\n if (!rows[0]) {\n throw new CrudOperationError(404, ErrorCode.NOT_FOUND, 'Not found')\n }\n const row = rows[0] as Record<string, unknown>\n\n const denied = await checkAccess(\n tableAccess.get,\n { ...ctx, row },\n tableAccess.ownerColumn,\n )\n if (!denied.allowed) {\n throw new CrudOperationError(\n denied.status === 401 ? 401 : 403,\n ErrorCode.FORBIDDEN,\n 'Forbidden',\n )\n }\n\n const scope = scopeFor(tableAccess.readScope, ctx)\n if (scope && !rowMatchesScope(row, scope)) {\n throw new CrudOperationError(404, ErrorCode.NOT_FOUND, 'Not found')\n }\n\n return row\n },\n\n async create(\n tableName: string,\n body: unknown,\n rawBody: string | undefined,\n idempotencyKey: string | undefined,\n ctx: CrudExecutionContext,\n ): Promise<CreateResult> {\n const { table, tableAccess } = resolveTable(tableName)\n\n const denied = await checkAccess(\n tableAccess.create,\n ctx,\n tableAccess.ownerColumn,\n )\n if (!denied.allowed) {\n throw new CrudOperationError(\n denied.status === 401 ? 401 : 403,\n ErrorCode.FORBIDDEN,\n 'Forbidden',\n )\n }\n\n if (!isRecord(body)) {\n throw new CrudOperationError(\n 400,\n ErrorCode.BAD_REQUEST,\n 'Invalid JSON body',\n )\n }\n\n const trimmedKey = idempotencyKey?.trim()\n const effectiveRawBody = rawBody ?? JSON.stringify(body)\n\n if (idempotency && trimmedKey) {\n const lookup = await lookupIdempotency(\n db,\n tableName,\n trimmedKey,\n effectiveRawBody,\n )\n if (lookup.type === 'conflict') {\n throw new CrudOperationError(\n 409,\n ErrorCode.IDEMPOTENCY_CONFLICT,\n 'Idempotency key reused with different body',\n )\n }\n if (lookup.type === 'replay') {\n return {\n type: 'replay',\n status: lookup.status,\n body: lookup.response,\n record: JSON.parse(lookup.response) as Record<string, unknown>,\n }\n }\n }\n\n const values = sanitizeWriteBody(\n body,\n tableAccess,\n 'create',\n ctx.user?.id ?? null,\n )\n\n const scope = scopeFor(tableAccess.writeScope, { ...ctx, body })\n const stamped = scope ? stampScope(values, scope) : values\n\n let rows: Record<string, unknown>[]\n try {\n rows = await db.insert(table).values(stamped).returning()\n } catch (error) {\n if (isUniqueConstraintError(error)) {\n throw new CrudOperationError(\n 409,\n ErrorCode.CONFLICT,\n 'Record already exists',\n )\n }\n throw error\n }\n const created = rows[0] as Record<string, unknown>\n void realtime?.publish(table as never, 'create', created as never)\n\n if (idempotency && trimmedKey) {\n await storeIdempotency(\n db,\n tableName,\n trimmedKey,\n effectiveRawBody,\n 201,\n created,\n idempotency,\n )\n }\n\n return {\n type: 'created',\n status: 201,\n record: created,\n }\n },\n\n async update(\n tableName: string,\n rawId: string | number,\n body: unknown,\n ctx: CrudExecutionContext,\n ): Promise<Record<string, unknown>> {\n const { table, tableAccess, idCol } = resolveTable(tableName)\n const id = coerceId(rawId)\n\n const existing = await db.select().from(table).where(eq(idCol, id))\n if (!existing[0]) {\n throw new CrudOperationError(404, ErrorCode.NOT_FOUND, 'Not found')\n }\n const existingRow = existing[0] as Record<string, unknown>\n\n const readScope = scopeFor(tableAccess.readScope, ctx)\n if (readScope && !rowMatchesScope(existingRow, readScope)) {\n throw new CrudOperationError(404, ErrorCode.NOT_FOUND, 'Not found')\n }\n\n const denied = await checkAccess(\n tableAccess.update,\n { ...ctx, row: existingRow },\n tableAccess.ownerColumn,\n )\n if (!denied.allowed) {\n throw new CrudOperationError(\n denied.status === 401 ? 401 : 403,\n ErrorCode.FORBIDDEN,\n 'Forbidden',\n )\n }\n\n if (!isRecord(body)) {\n throw new CrudOperationError(\n 400,\n ErrorCode.BAD_REQUEST,\n 'Invalid JSON body',\n )\n }\n\n const values = sanitizeWriteBody(\n body,\n tableAccess,\n 'update',\n ctx.user?.id ?? null,\n )\n\n if (Object.keys(values).length === 0) {\n throw new CrudOperationError(\n 400,\n ErrorCode.BAD_REQUEST,\n 'No writable fields to update',\n )\n }\n\n const writeScope = scopeFor(tableAccess.writeScope, { ...ctx, body })\n const stamped = writeScope ? stampScope(values, writeScope) : values\n\n const rows = await db\n .update(table)\n .set(stamped)\n .where(eq(idCol, id))\n .returning()\n\n if (!rows[0]) {\n throw new CrudOperationError(404, ErrorCode.NOT_FOUND, 'Not found')\n }\n const updated = rows[0] as Record<string, unknown>\n void realtime?.publish(table as never, 'update', updated as never)\n return updated\n },\n\n async delete(\n tableName: string,\n rawId: string | number,\n ctx: CrudExecutionContext,\n ): Promise<void> {\n const { table, tableAccess, idCol } = resolveTable(tableName)\n const id = coerceId(rawId)\n\n const existing = await db.select().from(table).where(eq(idCol, id))\n if (!existing[0]) {\n throw new CrudOperationError(404, ErrorCode.NOT_FOUND, 'Not found')\n }\n const existingRow = existing[0] as Record<string, unknown>\n\n const readScope = scopeFor(tableAccess.readScope, ctx)\n if (readScope && !rowMatchesScope(existingRow, readScope)) {\n throw new CrudOperationError(404, ErrorCode.NOT_FOUND, 'Not found')\n }\n\n const denied = await checkAccess(\n tableAccess.delete,\n { ...ctx, row: existingRow },\n tableAccess.ownerColumn,\n )\n if (!denied.allowed) {\n throw new CrudOperationError(\n denied.status === 401 ? 401 : 403,\n ErrorCode.FORBIDDEN,\n 'Forbidden',\n )\n }\n\n await db.delete(table).where(eq(idCol, id))\n void realtime?.publish(table as never, 'delete', existingRow as never)\n },\n }\n}\n\nexport type CrudOperations = ReturnType<typeof createCrudOperations>\n"]}
1
+ {"version":3,"file":"crud-operations.js","sourceRoot":"","sources":["../src/crud-operations.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n eq,\n getTableColumns,\n getTableName,\n isTable,\n type Table,\n} from 'drizzle-orm'\n\nimport type { AnyDb } from './dialect'\nimport type { RealtimeFacade } from './realtime/facade'\n\nimport {\n checkAccess,\n rowMatchesScope,\n sanitizeWriteBody,\n stampScope,\n tableEntryForName,\n type AccessUser,\n type ResolvedAccess,\n type ScopeMap,\n type ScopeResolver,\n} from './access'\nimport {\n BunderstackError,\n ErrorCode,\n ListQueryError,\n type BunderstackErrorCode,\n type ErrorCodeValue,\n} from './errors'\nimport {\n lookupIdempotency,\n resolveIdempotencyConfig,\n storeIdempotency,\n type IdempotencyConfig,\n} from './idempotency'\nimport {\n executeList,\n resolveListParams,\n type ListParamsInput,\n type ListResult,\n} from './list-query'\nimport { buildScopeWhere } from './scope'\n\nexport interface CrudExecutionContext {\n request: Request\n user: AccessUser | null\n session: { activeOrganizationId: string | null }\n}\n\nfunction operationMetadata(request: Request): { operationId?: string } {\n const operationId = request.headers.get('x-bunderstack-operation-id')?.trim()\n return operationId ? { operationId } : {}\n}\n\nfunction errorCodeForStatus(status: number): BunderstackErrorCode {\n if (status === 401) return 'UNAUTHORIZED'\n if (status === 403) return 'FORBIDDEN'\n if (status === 404) return 'NOT_FOUND'\n if (status === 409) return 'CONFLICT'\n if (status === 413) return 'PAYLOAD_TOO_LARGE'\n if (status === 429) return 'TOO_MANY_REQUESTS'\n return 'BAD_REQUEST'\n}\n\nexport class CrudOperationError extends BunderstackError {\n constructor(\n status: number,\n readonly legacyCode: ErrorCodeValue,\n message: string,\n details?: unknown,\n ) {\n const code = errorCodeForStatus(status)\n super(\n code,\n message,\n legacyCode === code\n ? details\n : {\n code: legacyCode,\n ...(details === undefined ? {} : { details }),\n },\n )\n this.name = 'CrudOperationError'\n }\n}\n\nexport type CrudOperationsDeps<\n TSchema extends Record<string, unknown> = Record<string, unknown>,\n> = {\n schema: TSchema\n db: AnyDb\n access: ResolvedAccess\n idempotency?: boolean | IdempotencyConfig\n realtime?: RealtimeFacade<TSchema>\n}\n\nexport type CreateResult =\n | { type: 'created'; status: 201; record: Record<string, unknown> }\n | {\n type: 'replay'\n status: number\n body: string\n record: Record<string, unknown>\n }\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction isUniqueConstraintError(error: unknown): boolean {\n const seen = new Set<unknown>()\n let current = error\n\n while (isRecord(current) && !seen.has(current)) {\n seen.add(current)\n const code = current['code']\n if (\n code === '23505' ||\n code === 'SQLITE_CONSTRAINT_UNIQUE' ||\n code === 'SQLITE_CONSTRAINT_PRIMARYKEY'\n ) {\n return true\n }\n\n const message = current['message']\n if (\n typeof message === 'string' &&\n (/duplicate key value violates unique constraint/i.test(message) ||\n /unique constraint failed/i.test(message))\n ) {\n return true\n }\n\n current = current['cause']\n }\n\n return false\n}\n\nfunction coerceId(rawId: string | number): string | number {\n if (typeof rawId === 'number') return rawId\n return isNaN(Number(rawId)) ? rawId : Number(rawId)\n}\n\nexport function createCrudOperations<\n TSchema extends Record<string, unknown> = Record<string, unknown>,\n>(deps: CrudOperationsDeps<TSchema>) {\n const { schema, db, access, realtime } = deps\n const idempotency = resolveIdempotencyConfig(deps.idempotency)\n\n const scopeFor = (\n resolver: ScopeResolver | undefined,\n ctx: {\n user: AccessUser | null\n session: { activeOrganizationId: string | null }\n request: Request\n row?: Record<string, unknown>\n body?: Record<string, unknown>\n },\n ): ScopeMap | undefined => (resolver ? resolver(ctx) : undefined)\n\n function resolveTable(tableName: string) {\n const table = Object.values(schema).find(\n (t) => isTable(t) && getTableName(t) === tableName,\n ) as Table | undefined\n if (!table) {\n throw new CrudOperationError(404, ErrorCode.NOT_FOUND, 'Not found')\n }\n const tableAccess = tableEntryForName(access, tableName)\n if (!tableAccess || !tableAccess.enabled) {\n throw new CrudOperationError(404, ErrorCode.NOT_FOUND, 'Not found')\n }\n const idCol = getTableColumns(table)['id']\n if (!idCol) {\n throw new CrudOperationError(\n 400,\n ErrorCode.BAD_REQUEST,\n `Table ${tableName} has no id column`,\n )\n }\n return { table, tableAccess, idCol }\n }\n\n return {\n async list(\n tableName: string,\n params: ListParamsInput | undefined,\n ctx: CrudExecutionContext,\n ): Promise<ListResult<Record<string, unknown>>> {\n const { table, tableAccess, idCol } = resolveTable(tableName)\n\n const denied = await checkAccess(\n tableAccess.list,\n ctx,\n tableAccess.ownerColumn,\n )\n if (!denied.allowed) {\n throw new CrudOperationError(\n denied.status === 401 ? 401 : 403,\n ErrorCode.FORBIDDEN,\n 'Forbidden',\n )\n }\n\n try {\n const resolved = resolveListParams(params ?? {}, tableAccess)\n const scope = scopeFor(tableAccess.readScope, ctx)\n const scopeWhere = scope ? buildScopeWhere(table, scope) : undefined\n return await executeList(\n db,\n table,\n tableAccess,\n resolved,\n idCol,\n scopeWhere,\n )\n } catch (err) {\n if (err instanceof ListQueryError) {\n throw new CrudOperationError(400, err.code, err.message, err.details)\n }\n throw err\n }\n },\n\n async get(\n tableName: string,\n rawId: string | number,\n ctx: CrudExecutionContext,\n ): Promise<Record<string, unknown>> {\n const { table, tableAccess, idCol } = resolveTable(tableName)\n const id = coerceId(rawId)\n\n const rows = await db.select().from(table).where(eq(idCol, id))\n if (!rows[0]) {\n throw new CrudOperationError(404, ErrorCode.NOT_FOUND, 'Not found')\n }\n const row = rows[0] as Record<string, unknown>\n\n const denied = await checkAccess(\n tableAccess.get,\n { ...ctx, row },\n tableAccess.ownerColumn,\n )\n if (!denied.allowed) {\n throw new CrudOperationError(\n denied.status === 401 ? 401 : 403,\n ErrorCode.FORBIDDEN,\n 'Forbidden',\n )\n }\n\n const scope = scopeFor(tableAccess.readScope, ctx)\n if (scope && !rowMatchesScope(row, scope)) {\n throw new CrudOperationError(404, ErrorCode.NOT_FOUND, 'Not found')\n }\n\n return row\n },\n\n async create(\n tableName: string,\n body: unknown,\n rawBody: string | undefined,\n idempotencyKey: string | undefined,\n ctx: CrudExecutionContext,\n ): Promise<CreateResult> {\n const { table, tableAccess } = resolveTable(tableName)\n\n const denied = await checkAccess(\n tableAccess.create,\n ctx,\n tableAccess.ownerColumn,\n )\n if (!denied.allowed) {\n throw new CrudOperationError(\n denied.status === 401 ? 401 : 403,\n ErrorCode.FORBIDDEN,\n 'Forbidden',\n )\n }\n\n if (!isRecord(body)) {\n throw new CrudOperationError(\n 400,\n ErrorCode.BAD_REQUEST,\n 'Invalid JSON body',\n )\n }\n\n const trimmedKey = idempotencyKey?.trim()\n const effectiveRawBody = rawBody ?? JSON.stringify(body)\n\n if (idempotency && trimmedKey) {\n const lookup = await lookupIdempotency(\n db,\n tableName,\n trimmedKey,\n effectiveRawBody,\n )\n if (lookup.type === 'conflict') {\n throw new CrudOperationError(\n 409,\n ErrorCode.IDEMPOTENCY_CONFLICT,\n 'Idempotency key reused with different body',\n )\n }\n if (lookup.type === 'replay') {\n return {\n type: 'replay',\n status: lookup.status,\n body: lookup.response,\n record: JSON.parse(lookup.response) as Record<string, unknown>,\n }\n }\n }\n\n const values = sanitizeWriteBody(\n body,\n tableAccess,\n 'create',\n ctx.user?.id ?? null,\n )\n\n const scope = scopeFor(tableAccess.writeScope, { ...ctx, body })\n const stamped = scope ? stampScope(values, scope) : values\n\n let rows: Record<string, unknown>[]\n try {\n rows = await db.insert(table).values(stamped).returning()\n } catch (error) {\n if (isUniqueConstraintError(error)) {\n throw new CrudOperationError(\n 409,\n ErrorCode.CONFLICT,\n 'Record already exists',\n )\n }\n throw error\n }\n const created = rows[0] as Record<string, unknown>\n void realtime?.publish(\n table as never,\n 'create',\n created as never,\n operationMetadata(ctx.request),\n )\n\n if (idempotency && trimmedKey) {\n await storeIdempotency(\n db,\n tableName,\n trimmedKey,\n effectiveRawBody,\n 201,\n created,\n idempotency,\n )\n }\n\n return {\n type: 'created',\n status: 201,\n record: created,\n }\n },\n\n async update(\n tableName: string,\n rawId: string | number,\n body: unknown,\n ctx: CrudExecutionContext,\n ): Promise<Record<string, unknown>> {\n const { table, tableAccess, idCol } = resolveTable(tableName)\n const id = coerceId(rawId)\n\n const existing = await db.select().from(table).where(eq(idCol, id))\n if (!existing[0]) {\n throw new CrudOperationError(404, ErrorCode.NOT_FOUND, 'Not found')\n }\n const existingRow = existing[0] as Record<string, unknown>\n\n const readScope = scopeFor(tableAccess.readScope, ctx)\n if (readScope && !rowMatchesScope(existingRow, readScope)) {\n throw new CrudOperationError(404, ErrorCode.NOT_FOUND, 'Not found')\n }\n\n const denied = await checkAccess(\n tableAccess.update,\n { ...ctx, row: existingRow },\n tableAccess.ownerColumn,\n )\n if (!denied.allowed) {\n throw new CrudOperationError(\n denied.status === 401 ? 401 : 403,\n ErrorCode.FORBIDDEN,\n 'Forbidden',\n )\n }\n\n if (!isRecord(body)) {\n throw new CrudOperationError(\n 400,\n ErrorCode.BAD_REQUEST,\n 'Invalid JSON body',\n )\n }\n\n const values = sanitizeWriteBody(\n body,\n tableAccess,\n 'update',\n ctx.user?.id ?? null,\n )\n\n if (Object.keys(values).length === 0) {\n throw new CrudOperationError(\n 400,\n ErrorCode.BAD_REQUEST,\n 'No writable fields to update',\n )\n }\n\n const writeScope = scopeFor(tableAccess.writeScope, { ...ctx, body })\n const stamped = writeScope ? stampScope(values, writeScope) : values\n\n const rows = await db\n .update(table)\n .set(stamped)\n .where(eq(idCol, id))\n .returning()\n\n if (!rows[0]) {\n throw new CrudOperationError(404, ErrorCode.NOT_FOUND, 'Not found')\n }\n const updated = rows[0] as Record<string, unknown>\n void realtime?.publish(\n table as never,\n 'update',\n updated as never,\n operationMetadata(ctx.request),\n )\n return updated\n },\n\n async delete(\n tableName: string,\n rawId: string | number,\n ctx: CrudExecutionContext,\n ): Promise<void> {\n const { table, tableAccess, idCol } = resolveTable(tableName)\n const id = coerceId(rawId)\n\n const existing = await db.select().from(table).where(eq(idCol, id))\n if (!existing[0]) {\n throw new CrudOperationError(404, ErrorCode.NOT_FOUND, 'Not found')\n }\n const existingRow = existing[0] as Record<string, unknown>\n\n const readScope = scopeFor(tableAccess.readScope, ctx)\n if (readScope && !rowMatchesScope(existingRow, readScope)) {\n throw new CrudOperationError(404, ErrorCode.NOT_FOUND, 'Not found')\n }\n\n const denied = await checkAccess(\n tableAccess.delete,\n { ...ctx, row: existingRow },\n tableAccess.ownerColumn,\n )\n if (!denied.allowed) {\n throw new CrudOperationError(\n denied.status === 401 ? 401 : 403,\n ErrorCode.FORBIDDEN,\n 'Forbidden',\n )\n }\n\n await db.delete(table).where(eq(idCol, id))\n void realtime?.publish(\n table as never,\n 'delete',\n existingRow as never,\n operationMetadata(ctx.request),\n )\n },\n }\n}\n\nexport type CrudOperations = ReturnType<typeof createCrudOperations>\n"]}
package/dist/index.d.ts CHANGED
@@ -62,7 +62,7 @@ export type AppRunWorkerOptions = AppStartWorkerOptions & {
62
62
  export type BucketNamesOf<TStorage> = TStorage extends {
63
63
  buckets: infer B extends Record<string, unknown>;
64
64
  } ? keyof B & string : string;
65
- export type BunderstackApp<TSchema extends Record<string, unknown>, TAccess extends Record<string, TableAccessInput> | undefined = undefined, TBuckets extends string = string, TEnv extends EnvConfigInput | undefined = undefined, TJobsDefs extends JobsDefs | undefined = undefined, TCustomApiRouter extends AnyORPCRouter | undefined = undefined> = {
65
+ export type BunderstackApp<TSchema extends Record<string, unknown>, TAccess extends Record<string, TableAccessInput> | undefined = undefined, TBuckets extends string = string, TEnv extends EnvConfigInput | undefined = undefined, TJobsDefs extends JobsDefs | undefined = undefined, TCustomApiRouter extends AnyORPCRouter | undefined = undefined, TRealtime = undefined> = {
66
66
  handler: (req: Request) => Promise<Response>;
67
67
  db: DbFor<TSchema>;
68
68
  auth: AuthInstance;
@@ -93,12 +93,17 @@ export type BunderstackApp<TSchema extends Record<string, unknown>, TAccess exte
93
93
  schema: TSchema;
94
94
  access: TAccess;
95
95
  buckets: TBuckets;
96
- api: MergeApiRouterTypes<UnifiedApiRouter<CrudApiRouterFor<TSchema, TAccess>, TCustomApiRouter>, RealtimeApiRouter>;
96
+ api: MergeApiRouterTypes<UnifiedApiRouter<CrudApiRouterFor<TSchema, TAccess, [
97
+ TRealtime
98
+ ] extends [false | undefined] ? false : true>, TCustomApiRouter>, [
99
+ TRealtime
100
+ ] extends [false | undefined] ? {} : RealtimeApiRouter>;
97
101
  };
98
102
  };
99
- export declare function createBunderstack<TSchema extends Record<string, unknown>, const TAccess extends Record<string, TableAccessInput> | undefined = undefined, const TStorage extends StorageConfigInput | undefined = undefined, const TEnv extends EnvConfigInput | undefined = undefined, const TJobsDefs extends JobsDefs | undefined = undefined, TCustomApiRouter extends AnyORPCRouter | undefined = undefined>(options: BunderstackConfig<TSchema, TAccess, TStorage, TEnv, TCustomApiRouter> & {
103
+ export declare function createBunderstack<TSchema extends Record<string, unknown>, const TAccess extends Record<string, TableAccessInput> | undefined = undefined, const TStorage extends StorageConfigInput | undefined = undefined, const TEnv extends EnvConfigInput | undefined = undefined, const TJobsDefs extends JobsDefs | undefined = undefined, TCustomApiRouter extends AnyORPCRouter | undefined = undefined, const TRealtime extends BunderstackConfig<TSchema, TAccess, TStorage, TEnv, TCustomApiRouter>['realtime'] = undefined>(options: BunderstackConfig<TSchema, TAccess, TStorage, TEnv, TCustomApiRouter> & {
104
+ realtime?: TRealtime;
100
105
  jobs?: TJobsDefs | ((j: BunderstackJobsBuilder<TSchema, ValidatedEnv<TEnv>>) => TJobsDefs);
101
- }): Promise<BunderstackApp<TSchema, TAccess, BucketNamesOf<TStorage>, TEnv, TJobsDefs, TCustomApiRouter>>;
106
+ }): Promise<BunderstackApp<TSchema, TAccess, BucketNamesOf<TStorage>, TEnv, TJobsDefs, TCustomApiRouter, TRealtime>>;
102
107
  export { listSpec } from './api/list-spec.js';
103
108
  export type { ListSpecOptions } from './api/list-spec.js';
104
109
  export type { BunderstackDb, BunderstackTx } from './db.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}