bunderstack 0.25.2 → 1.0.0-beta.2

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 (172) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/dist/auth-password.d.ts +27 -0
  3. package/dist/auth-password.d.ts.map +1 -0
  4. package/dist/auth-password.js +60 -0
  5. package/dist/auth-password.js.map +1 -0
  6. package/dist/auth.d.ts +1 -1
  7. package/dist/auth.d.ts.map +1 -1
  8. package/dist/auth.js +1 -0
  9. package/dist/auth.js.map +1 -1
  10. package/dist/backend.d.ts +3 -0
  11. package/dist/backend.d.ts.map +1 -1
  12. package/dist/backend.js +3 -1
  13. package/dist/backend.js.map +1 -1
  14. package/dist/blueprint-generator.d.ts.map +1 -1
  15. package/dist/blueprint-generator.js +5 -2
  16. package/dist/blueprint-generator.js.map +1 -1
  17. package/dist/blueprint.d.ts +4 -1
  18. package/dist/blueprint.d.ts.map +1 -1
  19. package/dist/blueprint.js +25 -8
  20. package/dist/blueprint.js.map +1 -1
  21. package/dist/cli.d.ts +11 -1
  22. package/dist/cli.d.ts.map +1 -1
  23. package/dist/cli.js +99 -2
  24. package/dist/cli.js.map +1 -1
  25. package/dist/config.d.ts +0 -8
  26. package/dist/config.d.ts.map +1 -1
  27. package/dist/config.js +0 -18
  28. package/dist/config.js.map +1 -1
  29. package/dist/crud-operations.d.ts.map +1 -1
  30. package/dist/crud-operations.js +19 -3
  31. package/dist/crud-operations.js.map +1 -1
  32. package/dist/dev/binaries.d.ts +22 -0
  33. package/dist/dev/binaries.d.ts.map +1 -0
  34. package/dist/dev/binaries.js +119 -0
  35. package/dist/dev/binaries.js.map +1 -0
  36. package/dist/dev/env.d.ts +11 -0
  37. package/dist/dev/env.d.ts.map +1 -0
  38. package/dist/dev/env.js +71 -0
  39. package/dist/dev/env.js.map +1 -0
  40. package/dist/dev/index.d.ts +45 -0
  41. package/dist/dev/index.d.ts.map +1 -0
  42. package/dist/dev/index.js +290 -0
  43. package/dist/dev/index.js.map +1 -0
  44. package/dist/dev/processes.d.ts +37 -0
  45. package/dist/dev/processes.d.ts.map +1 -0
  46. package/dist/dev/processes.js +104 -0
  47. package/dist/dev/processes.js.map +1 -0
  48. package/dist/dev/push.d.ts +2 -0
  49. package/dist/dev/push.d.ts.map +1 -0
  50. package/dist/dev/push.js +30 -0
  51. package/dist/dev/push.js.map +1 -0
  52. package/dist/env-probe.d.ts.map +1 -1
  53. package/dist/env-probe.js +0 -1
  54. package/dist/env-probe.js.map +1 -1
  55. package/dist/env.d.ts +0 -3
  56. package/dist/env.d.ts.map +1 -1
  57. package/dist/env.js +0 -7
  58. package/dist/env.js.map +1 -1
  59. package/dist/handler.d.ts +2 -0
  60. package/dist/handler.d.ts.map +1 -1
  61. package/dist/handler.js +1 -2
  62. package/dist/handler.js.map +1 -1
  63. package/dist/hosted-contract.d.ts.map +1 -1
  64. package/dist/hosted-contract.js +7 -3
  65. package/dist/hosted-contract.js.map +1 -1
  66. package/dist/index.d.ts +4 -2
  67. package/dist/index.d.ts.map +1 -1
  68. package/dist/index.js +1 -0
  69. package/dist/index.js.map +1 -1
  70. package/dist/jobs/define.d.ts +5 -0
  71. package/dist/jobs/define.d.ts.map +1 -1
  72. package/dist/jobs/define.js.map +1 -1
  73. package/dist/jobs/index.d.ts +2 -4
  74. package/dist/jobs/index.d.ts.map +1 -1
  75. package/dist/jobs/index.js +2 -3
  76. package/dist/jobs/index.js.map +1 -1
  77. package/dist/jobs/queue.d.ts +1 -0
  78. package/dist/jobs/queue.d.ts.map +1 -1
  79. package/dist/jobs/queue.js +6 -3
  80. package/dist/jobs/queue.js.map +1 -1
  81. package/dist/jobs/slots.d.ts +5 -0
  82. package/dist/jobs/slots.d.ts.map +1 -1
  83. package/dist/jobs/slots.js +12 -0
  84. package/dist/jobs/slots.js.map +1 -1
  85. package/dist/jobs/worker.d.ts +6 -0
  86. package/dist/jobs/worker.d.ts.map +1 -1
  87. package/dist/jobs/worker.js +32 -1
  88. package/dist/jobs/worker.js.map +1 -1
  89. package/dist/platform.d.ts +25 -0
  90. package/dist/platform.d.ts.map +1 -0
  91. package/dist/platform.js +24 -0
  92. package/dist/platform.js.map +1 -0
  93. package/dist/rate-limit.d.ts +2 -1
  94. package/dist/rate-limit.d.ts.map +1 -1
  95. package/dist/rate-limit.js +19 -22
  96. package/dist/rate-limit.js.map +1 -1
  97. package/dist/realtime/facade.d.ts +1 -1
  98. package/dist/realtime/facade.d.ts.map +1 -1
  99. package/dist/realtime/facade.js.map +1 -1
  100. package/dist/realtime/publisher.d.ts +0 -4
  101. package/dist/realtime/publisher.d.ts.map +1 -1
  102. package/dist/realtime/publisher.js +0 -9
  103. package/dist/realtime/publisher.js.map +1 -1
  104. package/dist/runtime.d.ts +5 -19
  105. package/dist/runtime.d.ts.map +1 -1
  106. package/dist/runtime.js +28 -102
  107. package/dist/runtime.js.map +1 -1
  108. package/dist/storage/registry.d.ts +2 -1
  109. package/dist/storage/registry.d.ts.map +1 -1
  110. package/dist/storage/registry.js +2 -2
  111. package/dist/storage/registry.js.map +1 -1
  112. package/dist/storage/s3.d.ts +11 -4
  113. package/dist/storage/s3.d.ts.map +1 -1
  114. package/dist/storage/s3.js +88 -34
  115. package/dist/storage/s3.js.map +1 -1
  116. package/dist/storage/sigv4.d.ts +24 -0
  117. package/dist/storage/sigv4.d.ts.map +1 -0
  118. package/dist/storage/sigv4.js +107 -0
  119. package/dist/storage/sigv4.js.map +1 -0
  120. package/dist/testing/fixture.d.ts.map +1 -1
  121. package/dist/testing/fixture.js +0 -3
  122. package/dist/testing/fixture.js.map +1 -1
  123. package/dist/testing/workers-fakes.d.ts +17 -0
  124. package/dist/testing/workers-fakes.d.ts.map +1 -0
  125. package/dist/testing/workers-fakes.js +98 -0
  126. package/dist/testing/workers-fakes.js.map +1 -0
  127. package/dist/typeid.d.ts +1 -0
  128. package/dist/typeid.d.ts.map +1 -1
  129. package/dist/typeid.js +34 -4
  130. package/dist/typeid.js.map +1 -1
  131. package/dist/vite.d.ts +30 -0
  132. package/dist/vite.d.ts.map +1 -0
  133. package/dist/vite.js +37 -0
  134. package/dist/vite.js.map +1 -0
  135. package/dist/workers/app.d.ts +19 -0
  136. package/dist/workers/app.d.ts.map +1 -0
  137. package/dist/workers/app.js +56 -0
  138. package/dist/workers/app.js.map +1 -0
  139. package/dist/workers/index.d.ts +21 -0
  140. package/dist/workers/index.d.ts.map +1 -0
  141. package/dist/workers/index.js +33 -0
  142. package/dist/workers/index.js.map +1 -0
  143. package/dist/workers/r2.d.ts +23 -0
  144. package/dist/workers/r2.d.ts.map +1 -0
  145. package/dist/workers/r2.js +77 -0
  146. package/dist/workers/r2.js.map +1 -0
  147. package/dist/workers/rate-limiter.d.ts +9 -0
  148. package/dist/workers/rate-limiter.d.ts.map +1 -0
  149. package/dist/workers/rate-limiter.js +22 -0
  150. package/dist/workers/rate-limiter.js.map +1 -0
  151. package/dist/workers/realtime-hub.d.ts +20 -0
  152. package/dist/workers/realtime-hub.d.ts.map +1 -0
  153. package/dist/workers/realtime-hub.js +117 -0
  154. package/dist/workers/realtime-hub.js.map +1 -0
  155. package/dist/workers/scheduler.d.ts +13 -0
  156. package/dist/workers/scheduler.d.ts.map +1 -0
  157. package/dist/workers/scheduler.js +71 -0
  158. package/dist/workers/scheduler.js.map +1 -0
  159. package/dist/workers/types.d.ts +55 -0
  160. package/dist/workers/types.d.ts.map +1 -0
  161. package/dist/workers/types.js +4 -0
  162. package/dist/workers/types.js.map +1 -0
  163. package/dist/workers/wrangler.d.ts +64 -0
  164. package/dist/workers/wrangler.d.ts.map +1 -0
  165. package/dist/workers/wrangler.js +118 -0
  166. package/dist/workers/wrangler.js.map +1 -0
  167. package/package.json +11 -3
  168. package/skills/creating-bunderstack-apps/references/verification.md +4 -1
  169. package/dist/jobs/runtime.d.ts +0 -17
  170. package/dist/jobs/runtime.d.ts.map +0 -1
  171. package/dist/jobs/runtime.js +0 -56
  172. package/dist/jobs/runtime.js.map +0 -1
@@ -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 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"]}
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 { consoleLogger } from './logging'\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 await broadcast(realtime, table, 'create', created, ctx.request)\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 await broadcast(realtime, table, 'update', updated, ctx.request)\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 await broadcast(realtime, table, 'delete', existingRow, ctx.request)\n },\n }\n}\n\n/**\n * Broadcast-on-write, best effort: the write has committed, so a failed\n * publish only logs. Awaited, because a Worker cancels I/O that is still\n * pending after the response, and the event would never reach the hub.\n */\nasync function broadcast(\n realtime: RealtimeFacade<any> | undefined,\n table: unknown,\n action: 'create' | 'update' | 'delete',\n record: Record<string, unknown>,\n request: Request,\n): Promise<void> {\n if (!realtime) return\n try {\n await realtime.publish(\n table as never,\n action,\n record as never,\n operationMetadata(request),\n )\n } catch (error) {\n consoleLogger.error('[bunderstack] realtime publish failed:', error)\n }\n}\n\nexport type CrudOperations = ReturnType<typeof createCrudOperations>\n"]}
@@ -0,0 +1,22 @@
1
+ export type BinaryName = 'celld' | 'sqld';
2
+ export type Pin = {
3
+ version: string;
4
+ format: 'gz' | 'tar.xz';
5
+ url: (target: string) => string;
6
+ /** sha256 of the downloaded asset, per release target. */
7
+ sha256: Partial<Record<string, string>>;
8
+ };
9
+ export type Pins = Partial<Record<BinaryName, Pin>>;
10
+ export type ResolveOptions = {
11
+ env?: Record<string, string | undefined>;
12
+ cacheDir?: string;
13
+ platform?: string;
14
+ arch?: string;
15
+ fetch?: (url: string) => Promise<Response>;
16
+ log?: (message: string) => void;
17
+ /** Replaces the pinned table; for tests. */
18
+ pins?: Pins;
19
+ };
20
+ export declare function binaryTarget(platform: string, arch: string): string | undefined;
21
+ export declare function resolveBinary(name: BinaryName, options?: ResolveOptions): Promise<string>;
22
+ //# sourceMappingURL=binaries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binaries.d.ts","sourceRoot":"","sources":["../../src/dev/binaries.ts"],"names":[],"mappings":"AAiBA,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,MAAM,CAAA;AAEzC,MAAM,MAAM,GAAG,GAAG;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,IAAI,GAAG,QAAQ,CAAA;IACvB,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAA;IAC/B,0DAA0D;IAC1D,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CACxC,CAAA;AAED,MAAM,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAA;AAmCnD,MAAM,MAAM,cAAc,GAAG;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC1C,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IAC/B,4CAA4C;IAC5C,IAAI,CAAC,EAAE,IAAI,CAAA;CACZ,CAAA;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,sBAM1D;AAyBD,wBAAsB,aAAa,CACjC,IAAI,EAAE,UAAU,EAChB,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,MAAM,CAAC,CAmEjB"}
@@ -0,0 +1,119 @@
1
+ // Pinned celld and sqld binaries for `bunderstack dev`. The first run
2
+ // downloads them to ~/.cache/bunderstack and checks their sha256; an env var
3
+ // selects a system binary instead.
4
+ import { access, chmod, constants, mkdir, mkdtemp, readdir, rename, rm, stat, } from 'node:fs/promises';
5
+ import { homedir } from 'node:os';
6
+ import { join } from 'node:path';
7
+ const PINS = {
8
+ celld: {
9
+ version: 'v0.6.0',
10
+ format: 'gz',
11
+ url: (target) => `https://github.com/denoland/celld/releases/download/v0.6.0/celld-${target}.gz`,
12
+ sha256: {
13
+ 'aarch64-apple-darwin': 'bf6f0c06c4f815eecddf61ae40340935a0dbf76be3d643bf75fdd92bfac425cd',
14
+ 'aarch64-unknown-linux-gnu': '3d4945df3abcc6832b6e7fa978b9ee3c26e46a0b7791924843d42c0ed14eff96',
15
+ 'x86_64-unknown-linux-gnu': '8f1e18072c234ab75459d4da104c13cebc9b29a3e4a4772086bf985829bea8aa',
16
+ },
17
+ },
18
+ sqld: {
19
+ version: 'v0.24.32',
20
+ format: 'tar.xz',
21
+ url: (target) => `https://github.com/tursodatabase/libsql/releases/download/libsql-server-v0.24.32/libsql-server-${target}.tar.xz`,
22
+ sha256: {
23
+ 'aarch64-apple-darwin': 'ced2a9d65a5d4b6bd72c67e98ad6c63139e2a139d91769f07fdd15be935381dd',
24
+ 'x86_64-apple-darwin': '461480ea5a17781bab7dd5974aa804007434611baced37b6349c8060d0648e34',
25
+ 'aarch64-unknown-linux-gnu': '37f9eee45b388a30192907ecf4565b93df945c079331657073b5b3caf8bb1cd0',
26
+ 'x86_64-unknown-linux-gnu': '71720fc8648c19efef416efebd47145ef59b62e198770533530a858e1336879f',
27
+ },
28
+ },
29
+ };
30
+ export function binaryTarget(platform, arch) {
31
+ const cpu = arch === 'arm64' ? 'aarch64' : arch === 'x64' ? 'x86_64' : '';
32
+ if (!cpu)
33
+ return undefined;
34
+ if (platform === 'darwin')
35
+ return `${cpu}-apple-darwin`;
36
+ if (platform === 'linux')
37
+ return `${cpu}-unknown-linux-gnu`;
38
+ return undefined;
39
+ }
40
+ async function isExecutable(path) {
41
+ return access(path, constants.X_OK).then(() => true, () => false);
42
+ }
43
+ async function findFile(dir, name) {
44
+ for (const entry of await readdir(dir, { withFileTypes: true })) {
45
+ const path = join(dir, entry.name);
46
+ if (entry.isDirectory()) {
47
+ const found = await findFile(path, name);
48
+ if (found)
49
+ return found;
50
+ }
51
+ else if (entry.name === name) {
52
+ return path;
53
+ }
54
+ }
55
+ return undefined;
56
+ }
57
+ export async function resolveBinary(name, options = {}) {
58
+ const env = options.env ?? process.env;
59
+ const envName = `BUNDERSTACK_${name.toUpperCase()}_BIN`;
60
+ const override = env[envName];
61
+ if (override)
62
+ return override;
63
+ const pin = (options.pins ?? PINS)[name];
64
+ const target = binaryTarget(options.platform ?? process.platform, options.arch ?? process.arch);
65
+ const checksum = target ? pin?.sha256[target] : undefined;
66
+ if (!pin || !target || !checksum) {
67
+ throw new Error(`[bunderstack] no ${name} build for ${options.platform ?? process.platform} ${options.arch ?? process.arch}; install ${name} and set ${envName} to its path`);
68
+ }
69
+ const cacheDir = options.cacheDir ??
70
+ env.BUNDERSTACK_CACHE_DIR ??
71
+ join(homedir(), '.cache', 'bunderstack');
72
+ const home = join(cacheDir, `${name}-${pin.version}-${target}`);
73
+ const cached = await findFile(home, name).catch(() => undefined);
74
+ if (cached && (await isExecutable(cached)))
75
+ return cached;
76
+ const url = pin.url(target);
77
+ options.log?.(`downloading ${name} ${pin.version} from ${url}`);
78
+ const response = await (options.fetch ?? fetch)(url);
79
+ if (!response.ok) {
80
+ throw new Error(`[bunderstack] ${url} returned ${response.status}`);
81
+ }
82
+ const bytes = new Uint8Array(await response.arrayBuffer());
83
+ const actual = new Bun.CryptoHasher('sha256').update(bytes).digest('hex');
84
+ if (actual !== checksum) {
85
+ throw new Error(`[bunderstack] ${name} checksum mismatch: expected ${checksum}, got ${actual}`);
86
+ }
87
+ await mkdir(cacheDir, { recursive: true });
88
+ const staging = await mkdtemp(join(cacheDir, `.${name}-`));
89
+ try {
90
+ if (pin.format === 'gz') {
91
+ await Bun.write(join(staging, name), Bun.gunzipSync(bytes));
92
+ }
93
+ else {
94
+ const archive = join(staging, 'asset.tar.xz');
95
+ await Bun.write(archive, bytes);
96
+ const tar = Bun.spawnSync(['tar', '-xJf', archive], { cwd: staging });
97
+ if (tar.exitCode !== 0) {
98
+ throw new Error(`[bunderstack] tar failed: ${tar.stderr.toString()}`);
99
+ }
100
+ await rm(archive);
101
+ }
102
+ const binary = await findFile(staging, name);
103
+ if (!binary)
104
+ throw new Error(`[bunderstack] ${url} has no ${name} file`);
105
+ await chmod(binary, 0o755);
106
+ // Another run may have finished first; keep its copy.
107
+ if (!(await stat(home).catch(() => undefined))) {
108
+ await rename(staging, home);
109
+ }
110
+ }
111
+ finally {
112
+ await rm(staging, { recursive: true, force: true });
113
+ }
114
+ const path = await findFile(home, name);
115
+ if (!path)
116
+ throw new Error(`[bunderstack] ${name} is missing from ${home}`);
117
+ return path;
118
+ }
119
+ //# sourceMappingURL=binaries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binaries.js","sourceRoot":"","sources":["../../src/dev/binaries.ts"],"names":[],"mappings":"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","sourcesContent":["// Pinned celld and sqld binaries for `bunderstack dev`. The first run\n// downloads them to ~/.cache/bunderstack and checks their sha256; an env var\n// selects a system binary instead.\nimport {\n access,\n chmod,\n constants,\n mkdir,\n mkdtemp,\n readdir,\n rename,\n rm,\n stat,\n} from 'node:fs/promises'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nexport type BinaryName = 'celld' | 'sqld'\n\nexport type Pin = {\n version: string\n format: 'gz' | 'tar.xz'\n url: (target: string) => string\n /** sha256 of the downloaded asset, per release target. */\n sha256: Partial<Record<string, string>>\n}\n\nexport type Pins = Partial<Record<BinaryName, Pin>>\n\nconst PINS: Record<BinaryName, Pin> = {\n celld: {\n version: 'v0.6.0',\n format: 'gz',\n url: (target) =>\n `https://github.com/denoland/celld/releases/download/v0.6.0/celld-${target}.gz`,\n sha256: {\n 'aarch64-apple-darwin':\n 'bf6f0c06c4f815eecddf61ae40340935a0dbf76be3d643bf75fdd92bfac425cd',\n 'aarch64-unknown-linux-gnu':\n '3d4945df3abcc6832b6e7fa978b9ee3c26e46a0b7791924843d42c0ed14eff96',\n 'x86_64-unknown-linux-gnu':\n '8f1e18072c234ab75459d4da104c13cebc9b29a3e4a4772086bf985829bea8aa',\n },\n },\n sqld: {\n version: 'v0.24.32',\n format: 'tar.xz',\n url: (target) =>\n `https://github.com/tursodatabase/libsql/releases/download/libsql-server-v0.24.32/libsql-server-${target}.tar.xz`,\n sha256: {\n 'aarch64-apple-darwin':\n 'ced2a9d65a5d4b6bd72c67e98ad6c63139e2a139d91769f07fdd15be935381dd',\n 'x86_64-apple-darwin':\n '461480ea5a17781bab7dd5974aa804007434611baced37b6349c8060d0648e34',\n 'aarch64-unknown-linux-gnu':\n '37f9eee45b388a30192907ecf4565b93df945c079331657073b5b3caf8bb1cd0',\n 'x86_64-unknown-linux-gnu':\n '71720fc8648c19efef416efebd47145ef59b62e198770533530a858e1336879f',\n },\n },\n}\n\nexport type ResolveOptions = {\n env?: Record<string, string | undefined>\n cacheDir?: string\n platform?: string\n arch?: string\n fetch?: (url: string) => Promise<Response>\n log?: (message: string) => void\n /** Replaces the pinned table; for tests. */\n pins?: Pins\n}\n\nexport function binaryTarget(platform: string, arch: string) {\n const cpu = arch === 'arm64' ? 'aarch64' : arch === 'x64' ? 'x86_64' : ''\n if (!cpu) return undefined\n if (platform === 'darwin') return `${cpu}-apple-darwin`\n if (platform === 'linux') return `${cpu}-unknown-linux-gnu`\n return undefined\n}\n\nasync function isExecutable(path: string) {\n return access(path, constants.X_OK).then(\n () => true,\n () => false,\n )\n}\n\nasync function findFile(\n dir: string,\n name: string,\n): Promise<string | undefined> {\n for (const entry of await readdir(dir, { withFileTypes: true })) {\n const path = join(dir, entry.name)\n if (entry.isDirectory()) {\n const found = await findFile(path, name)\n if (found) return found\n } else if (entry.name === name) {\n return path\n }\n }\n return undefined\n}\n\nexport async function resolveBinary(\n name: BinaryName,\n options: ResolveOptions = {},\n): Promise<string> {\n const env = options.env ?? process.env\n const envName = `BUNDERSTACK_${name.toUpperCase()}_BIN`\n const override = env[envName]\n if (override) return override\n\n const pin = (options.pins ?? PINS)[name]\n const target = binaryTarget(\n options.platform ?? process.platform,\n options.arch ?? process.arch,\n )\n const checksum = target ? pin?.sha256[target] : undefined\n if (!pin || !target || !checksum) {\n throw new Error(\n `[bunderstack] no ${name} build for ${options.platform ?? process.platform} ${options.arch ?? process.arch}; install ${name} and set ${envName} to its path`,\n )\n }\n\n const cacheDir =\n options.cacheDir ??\n env.BUNDERSTACK_CACHE_DIR ??\n join(homedir(), '.cache', 'bunderstack')\n const home = join(cacheDir, `${name}-${pin.version}-${target}`)\n const cached = await findFile(home, name).catch(() => undefined)\n if (cached && (await isExecutable(cached))) return cached\n\n const url = pin.url(target)\n options.log?.(`downloading ${name} ${pin.version} from ${url}`)\n const response = await (options.fetch ?? fetch)(url)\n if (!response.ok) {\n throw new Error(`[bunderstack] ${url} returned ${response.status}`)\n }\n const bytes = new Uint8Array(await response.arrayBuffer())\n const actual = new Bun.CryptoHasher('sha256').update(bytes).digest('hex')\n if (actual !== checksum) {\n throw new Error(\n `[bunderstack] ${name} checksum mismatch: expected ${checksum}, got ${actual}`,\n )\n }\n\n await mkdir(cacheDir, { recursive: true })\n const staging = await mkdtemp(join(cacheDir, `.${name}-`))\n try {\n if (pin.format === 'gz') {\n await Bun.write(join(staging, name), Bun.gunzipSync(bytes))\n } else {\n const archive = join(staging, 'asset.tar.xz')\n await Bun.write(archive, bytes)\n const tar = Bun.spawnSync(['tar', '-xJf', archive], { cwd: staging })\n if (tar.exitCode !== 0) {\n throw new Error(`[bunderstack] tar failed: ${tar.stderr.toString()}`)\n }\n await rm(archive)\n }\n const binary = await findFile(staging, name)\n if (!binary) throw new Error(`[bunderstack] ${url} has no ${name} file`)\n await chmod(binary, 0o755)\n // Another run may have finished first; keep its copy.\n if (!(await stat(home).catch(() => undefined))) {\n await rename(staging, home)\n }\n } finally {\n await rm(staging, { recursive: true, force: true })\n }\n const path = await findFile(home, name)\n if (!path) throw new Error(`[bunderstack] ${name} is missing from ${home}`)\n return path\n}\n"]}
@@ -0,0 +1,11 @@
1
+ export declare function parseDotenv(text: string): Record<string, string>;
2
+ export declare function readUserEnv(directory: string): Promise<Record<string, string>>;
3
+ /** A random AUTH_SECRET kept in the dev state dir, so sessions survive restarts. */
4
+ export declare function devSecret(stateDir: string): Promise<string>;
5
+ export declare function devVars(input: {
6
+ userEnv: Record<string, string>;
7
+ databaseUrl: string;
8
+ appUrl: string;
9
+ authSecret: string;
10
+ }): string;
11
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/dev/env.ts"],"names":[],"mappings":"AAKA,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAyBhE;AAED,wBAAsB,WAAW,CAC/B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CASjC;AAED,oFAAoF;AACpF,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAWjE;AAOD,wBAAgB,OAAO,CAAC,KAAK,EAAE;IAC7B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,CAAA;CACnB,GAAG,MAAM,CAaT"}
@@ -0,0 +1,71 @@
1
+ // The Worker env for `bunderstack dev`: the app's .env files plus the values
2
+ // the dev command owns, written as .dev.vars for celld.
3
+ import { mkdir, readFile, writeFile } from 'node:fs/promises';
4
+ import { join } from 'node:path';
5
+ export function parseDotenv(text) {
6
+ const vars = {};
7
+ for (const raw of text.split(/\r?\n/)) {
8
+ const line = raw.trim();
9
+ if (!line || line.startsWith('#'))
10
+ continue;
11
+ const match = /^(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/.exec(line);
12
+ if (!match)
13
+ continue;
14
+ const [, key, rest] = match;
15
+ let value;
16
+ if (rest.startsWith('"')) {
17
+ const end = rest.lastIndexOf('"');
18
+ value = rest
19
+ .slice(1, end > 0 ? end : undefined)
20
+ .replace(/\\(["\\n])/g, (_, c) => (c === 'n' ? '\n' : c));
21
+ }
22
+ else if (rest.startsWith("'")) {
23
+ const end = rest.lastIndexOf("'");
24
+ value = rest.slice(1, end > 0 ? end : undefined);
25
+ }
26
+ else {
27
+ value = rest.replace(/\s+#.*$/, '').trim();
28
+ }
29
+ vars[key] = value;
30
+ }
31
+ return vars;
32
+ }
33
+ export async function readUserEnv(directory) {
34
+ const vars = {};
35
+ for (const name of ['.env', '.env.local']) {
36
+ const text = await readFile(join(directory, name), 'utf8').catch(() => undefined);
37
+ if (text !== undefined)
38
+ Object.assign(vars, parseDotenv(text));
39
+ }
40
+ return vars;
41
+ }
42
+ /** A random AUTH_SECRET kept in the dev state dir, so sessions survive restarts. */
43
+ export async function devSecret(stateDir) {
44
+ const path = join(stateDir, 'auth-secret');
45
+ const existing = (await readFile(path, 'utf8').catch(() => '')).trim();
46
+ if (existing)
47
+ return existing;
48
+ await mkdir(stateDir, { recursive: true });
49
+ const bytes = crypto.getRandomValues(new Uint8Array(32));
50
+ const secret = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');
51
+ await writeFile(path, `${secret}\n`, { mode: 0o600 });
52
+ return secret;
53
+ }
54
+ function quote(value) {
55
+ if (/^[A-Za-z0-9_./:@+-]*$/.test(value))
56
+ return value;
57
+ return `"${value.replace(/["\\]/g, '\\$&').replace(/\n/g, '\\n')}"`;
58
+ }
59
+ export function devVars(input) {
60
+ const vars = {
61
+ ...input.userEnv,
62
+ AUTH_SECRET: input.userEnv.AUTH_SECRET || input.authSecret,
63
+ // The dev command picks these; a value from .env would point elsewhere.
64
+ APP_URL: input.appUrl,
65
+ BUNDERSTACK_DATABASE_URL: input.databaseUrl,
66
+ };
67
+ return (Object.entries(vars)
68
+ .map(([key, value]) => `${key}=${quote(value)}`)
69
+ .join('\n') + '\n');
70
+ }
71
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/dev/env.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,wDAAwD;AACxD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAC7D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEhC,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,MAAM,IAAI,GAA2B,EAAE,CAAA;IACvC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAA;QACvB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAQ;QAC3C,MAAM,KAAK,GAAG,qDAAqD,CAAC,IAAI,CACtE,IAAI,CACL,CAAA;QACD,IAAI,CAAC,KAAK;YAAE,SAAQ;QACpB,MAAM,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,KAA4C,CAAA;QAClE,IAAI,KAAa,CAAA;QACjB,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACzB,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;YACjC,KAAK,GAAG,IAAI;iBACT,KAAK,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;iBACnC,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC,EAAE,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QACrE,CAAC;aAAM,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAChC,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;YACjC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;QAClD,CAAC;aAAM,CAAC;YACN,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;QAC5C,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;IACnB,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,SAAiB;IAEjB,MAAM,IAAI,GAA2B,EAAE,CAAA;IACvC,KAAK,MAAM,IAAI,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC,KAAK,CAC9D,GAAG,EAAE,CAAC,SAAS,CAChB,CAAA;QACD,IAAI,IAAI,KAAK,SAAS;YAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC,CAAA;IAChE,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED,oFAAoF;AACpF,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,QAAgB;IAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAA;IAC1C,MAAM,QAAQ,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;IACtE,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAA;IAC7B,MAAM,KAAK,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC1C,MAAM,KAAK,GAAG,MAAM,CAAC,eAAe,CAAC,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC,CAAA;IACxD,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAC3E,EAAE,CACH,CAAA;IACD,MAAM,SAAS,CAAC,IAAI,EAAE,GAAG,MAAM,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;IACrD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,SAAS,KAAK,CAAC,KAAa;IAC1B,IAAI,uBAAuB,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAA;IACrD,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAA;AACrE,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,KAKvB;IACC,MAAM,IAAI,GAA2B;QACnC,GAAG,KAAK,CAAC,OAAO;QAChB,WAAW,EAAE,KAAK,CAAC,OAAO,CAAC,WAAW,IAAI,KAAK,CAAC,UAAU;QAC1D,wEAAwE;QACxE,OAAO,EAAE,KAAK,CAAC,MAAM;QACrB,wBAAwB,EAAE,KAAK,CAAC,WAAW;KAC5C,CAAA;IACD,OAAO,CACL,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;SACjB,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;SAC/C,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CACrB,CAAA;AACH,CAAC","sourcesContent":["// The Worker env for `bunderstack dev`: the app's .env files plus the values\n// the dev command owns, written as .dev.vars for celld.\nimport { mkdir, readFile, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\n\nexport function parseDotenv(text: string): Record<string, string> {\n const vars: Record<string, string> = {}\n for (const raw of text.split(/\\r?\\n/)) {\n const line = raw.trim()\n if (!line || line.startsWith('#')) continue\n const match = /^(?:export\\s+)?([A-Za-z_][A-Za-z0-9_]*)\\s*=\\s*(.*)$/.exec(\n line,\n )\n if (!match) continue\n const [, key, rest] = match as unknown as [string, string, string]\n let value: string\n if (rest.startsWith('\"')) {\n const end = rest.lastIndexOf('\"')\n value = rest\n .slice(1, end > 0 ? end : undefined)\n .replace(/\\\\([\"\\\\n])/g, (_, c: string) => (c === 'n' ? '\\n' : c))\n } else if (rest.startsWith(\"'\")) {\n const end = rest.lastIndexOf(\"'\")\n value = rest.slice(1, end > 0 ? end : undefined)\n } else {\n value = rest.replace(/\\s+#.*$/, '').trim()\n }\n vars[key] = value\n }\n return vars\n}\n\nexport async function readUserEnv(\n directory: string,\n): Promise<Record<string, string>> {\n const vars: Record<string, string> = {}\n for (const name of ['.env', '.env.local']) {\n const text = await readFile(join(directory, name), 'utf8').catch(\n () => undefined,\n )\n if (text !== undefined) Object.assign(vars, parseDotenv(text))\n }\n return vars\n}\n\n/** A random AUTH_SECRET kept in the dev state dir, so sessions survive restarts. */\nexport async function devSecret(stateDir: string): Promise<string> {\n const path = join(stateDir, 'auth-secret')\n const existing = (await readFile(path, 'utf8').catch(() => '')).trim()\n if (existing) return existing\n await mkdir(stateDir, { recursive: true })\n const bytes = crypto.getRandomValues(new Uint8Array(32))\n const secret = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join(\n '',\n )\n await writeFile(path, `${secret}\\n`, { mode: 0o600 })\n return secret\n}\n\nfunction quote(value: string) {\n if (/^[A-Za-z0-9_./:@+-]*$/.test(value)) return value\n return `\"${value.replace(/[\"\\\\]/g, '\\\\$&').replace(/\\n/g, '\\\\n')}\"`\n}\n\nexport function devVars(input: {\n userEnv: Record<string, string>\n databaseUrl: string\n appUrl: string\n authSecret: string\n}): string {\n const vars: Record<string, string> = {\n ...input.userEnv,\n AUTH_SECRET: input.userEnv.AUTH_SECRET || input.authSecret,\n // The dev command picks these; a value from .env would point elsewhere.\n APP_URL: input.appUrl,\n BUNDERSTACK_DATABASE_URL: input.databaseUrl,\n }\n return (\n Object.entries(vars)\n .map(([key, value]) => `${key}=${quote(value)}`)\n .join('\\n') + '\\n'\n )\n}\n"]}
@@ -0,0 +1,45 @@
1
+ import { type ProcessSpec } from './processes.js';
2
+ export type DevPlan = {
3
+ appUrl: string;
4
+ apiUrl: string;
5
+ databaseUrl: string;
6
+ sqld?: ProcessSpec;
7
+ worker: ProcessSpec;
8
+ vite?: ProcessSpec;
9
+ };
10
+ /**
11
+ * celld --logs mixes the Worker's console output with its own INFO lines.
12
+ * Keep the Worker output (without the timestamp), warnings, errors, and the
13
+ * start summary.
14
+ */
15
+ export declare function celldLine(line: string): string | undefined;
16
+ export declare function planDev(input: {
17
+ directory: string;
18
+ stateDir: string;
19
+ userEnv: Record<string, string>;
20
+ hasVite: boolean;
21
+ ports: {
22
+ app: number;
23
+ api: number;
24
+ db: number;
25
+ };
26
+ binaries: {
27
+ celld: string;
28
+ sqld: string;
29
+ esbuild: string;
30
+ };
31
+ }): DevPlan;
32
+ /**
33
+ * The first port from `start` that is free on 127.0.0.1 and on ::1. The
34
+ * browser opens `localhost`, which can resolve to either; Vite on ::1 next to
35
+ * another server on 127.0.0.1 would answer only some requests.
36
+ */
37
+ export declare function firstFreePort(start: number): Promise<number>;
38
+ export declare function runDev(options: {
39
+ directory: string;
40
+ port?: number;
41
+ }): Promise<number>;
42
+ export declare function runBuild(options: {
43
+ directory: string;
44
+ }): Promise<number>;
45
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dev/index.ts"],"names":[],"mappings":"AAaA,OAAO,EAAgB,KAAK,WAAW,EAAE,MAAM,aAAa,CAAA;AAE5D,MAAM,MAAM,OAAO,GAAG;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,CAAC,EAAE,WAAW,CAAA;IAClB,MAAM,EAAE,WAAW,CAAA;IACnB,IAAI,CAAC,EAAE,WAAW,CAAA;CACnB,CAAA;AAID;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAc1D;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAA;IAC/C,QAAQ,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;CAC3D,GAAG,OAAO,CA4DV;AA+BD;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAKlE;AAgCD,wBAAsB,MAAM,CAAC,OAAO,EAAE;IACpC,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,GAAG,OAAO,CAAC,MAAM,CAAC,CAwHlB;AAED,wBAAsB,QAAQ,CAAC,OAAO,EAAE;IACtC,SAAS,EAAE,MAAM,CAAA;CAClB,GAAG,OAAO,CAAC,MAAM,CAAC,CAoBlB"}