bunderstack 0.21.1 → 0.22.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +55 -0
- package/README.md +15 -10
- package/dist/api/builder.d.ts +2 -2
- package/dist/api/builder.js +1 -1
- package/dist/api/builder.js.map +1 -1
- package/dist/api/context.d.ts +4 -1
- package/dist/api/context.d.ts.map +1 -1
- package/dist/api/context.js +2 -0
- package/dist/api/context.js.map +1 -1
- package/dist/auth.d.ts +8 -0
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +14 -0
- package/dist/auth.js.map +1 -1
- package/dist/backend-internals.d.ts +43 -0
- package/dist/backend-internals.d.ts.map +1 -0
- package/dist/backend-internals.js +2 -0
- package/dist/backend-internals.js.map +1 -0
- package/dist/backend.d.ts +26 -0
- package/dist/backend.d.ts.map +1 -0
- package/dist/backend.js +58 -0
- package/dist/backend.js.map +1 -0
- package/dist/blueprint-generator.d.ts.map +1 -1
- package/dist/blueprint-generator.js +41 -51
- package/dist/blueprint-generator.js.map +1 -1
- package/dist/config.d.ts +0 -6
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/database/adapter.d.ts +10 -3
- package/dist/database/adapter.d.ts.map +1 -1
- package/dist/database/adapter.js.map +1 -1
- package/dist/database/bun-sql.d.ts.map +1 -1
- package/dist/database/bun-sql.js +1 -3
- package/dist/database/bun-sql.js.map +1 -1
- package/dist/database/bun-sqlite.d.ts +8 -0
- package/dist/database/bun-sqlite.d.ts.map +1 -0
- package/dist/database/bun-sqlite.js +56 -0
- package/dist/database/bun-sqlite.js.map +1 -0
- package/dist/database/libsql.d.ts.map +1 -1
- package/dist/database/libsql.js +25 -3
- package/dist/database/libsql.js.map +1 -1
- package/dist/database/pglite.d.ts.map +1 -1
- package/dist/database/pglite.js +25 -4
- package/dist/database/pglite.js.map +1 -1
- package/dist/database/postgres-js.d.ts.map +1 -1
- package/dist/database/postgres-js.js +1 -3
- package/dist/database/postgres-js.js.map +1 -1
- package/dist/db.d.ts +1 -2
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +5 -3
- package/dist/db.js.map +1 -1
- package/dist/email.d.ts +3 -1
- package/dist/email.d.ts.map +1 -1
- package/dist/email.js +9 -2
- package/dist/email.js.map +1 -1
- package/dist/env.d.ts +1 -1
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +1 -4
- package/dist/env.js.map +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +4 -2
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +3 -108
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -484
- package/dist/index.js.map +1 -1
- package/dist/jobs/define.d.ts +1 -1
- package/dist/jobs/define.d.ts.map +1 -1
- package/dist/jobs/define.js.map +1 -1
- package/dist/jobs/index.js +1 -1
- package/dist/jobs/index.js.map +1 -1
- package/dist/jobs/queue.d.ts +1 -1
- package/dist/jobs/queue.d.ts.map +1 -1
- package/dist/jobs/queue.js +1 -2
- package/dist/jobs/queue.js.map +1 -1
- package/dist/jobs/worker.d.ts +21 -0
- package/dist/jobs/worker.d.ts.map +1 -1
- package/dist/jobs/worker.js +64 -4
- package/dist/jobs/worker.js.map +1 -1
- package/dist/logging.d.ts +8 -0
- package/dist/logging.d.ts.map +1 -0
- package/dist/logging.js +6 -0
- package/dist/logging.js.map +1 -0
- package/dist/provision-internals.d.ts +1 -1
- package/dist/provision-internals.js +1 -1
- package/dist/provision-internals.js.map +1 -1
- package/dist/provision.d.ts +2 -0
- package/dist/provision.d.ts.map +1 -1
- package/dist/provision.js +24 -3
- package/dist/provision.js.map +1 -1
- package/dist/query/infer.d.ts +1 -1
- package/dist/query/infer.d.ts.map +1 -1
- package/dist/query/infer.js.map +1 -1
- package/dist/runtime.d.ts +153 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +537 -0
- package/dist/runtime.js.map +1 -0
- package/dist/schema-export-pg.js +1 -1
- package/dist/schema-export-pg.js.map +1 -1
- package/dist/storage/background.d.ts +3 -0
- package/dist/storage/background.d.ts.map +1 -0
- package/dist/storage/background.js +3 -0
- package/dist/storage/background.js.map +1 -0
- package/dist/testing/auth.d.ts +85 -0
- package/dist/testing/auth.d.ts.map +1 -0
- package/dist/testing/auth.js +140 -0
- package/dist/testing/auth.js.map +1 -0
- package/dist/testing/client.d.ts +6 -0
- package/dist/testing/client.d.ts.map +1 -0
- package/dist/testing/client.js +9 -0
- package/dist/testing/client.js.map +1 -0
- package/dist/testing/database.d.ts +6 -0
- package/dist/testing/database.d.ts.map +1 -0
- package/dist/testing/database.js +8 -0
- package/dist/testing/database.js.map +1 -0
- package/dist/testing/email.d.ts +15 -0
- package/dist/testing/email.d.ts.map +1 -0
- package/dist/testing/email.js +32 -0
- package/dist/testing/email.js.map +1 -0
- package/dist/testing/fixture.d.ts +51 -0
- package/dist/testing/fixture.d.ts.map +1 -0
- package/dist/testing/fixture.js +178 -0
- package/dist/testing/fixture.js.map +1 -0
- package/dist/testing/jobs.d.ts +40 -0
- package/dist/testing/jobs.d.ts.map +1 -0
- package/dist/testing/jobs.js +76 -0
- package/dist/testing/jobs.js.map +1 -0
- package/dist/testing/logs.d.ts +18 -0
- package/dist/testing/logs.d.ts.map +1 -0
- package/dist/testing/logs.js +53 -0
- package/dist/testing/logs.js.map +1 -0
- package/dist/testing/storage.d.ts +7 -0
- package/dist/testing/storage.d.ts.map +1 -0
- package/dist/testing/storage.js +29 -0
- package/dist/testing/storage.js.map +1 -0
- package/dist/testing.d.ts +10 -26
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +3 -9
- package/dist/testing.js.map +1 -1
- package/llms.txt +51 -14
- package/package.json +23 -15
- package/skills/creating-bunderstack-apps/references/application-structure.md +16 -12
- package/skills/creating-bunderstack-apps/references/runtime-integrations.md +4 -1
- package/skills/migrating-to-bunderstack/SKILL.md +7 -6
- package/skills/migrating-to-bunderstack/references/audit-checklist.md +4 -4
- package/skills/migrating-to-bunderstack/references/runtime-replacements.md +55 -49
|
@@ -1,23 +1,27 @@
|
|
|
1
1
|
# Application structure
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## Separate declaration from runtime
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
`src/bunderstack/backend.ts` synchronously constructs and exports `backend =
|
|
6
|
+
bunderstack({...})`. It is pure: it validates the declaration and exposes
|
|
7
|
+
`backend.manifest`, but it does not connect to infrastructure. The blueprint
|
|
8
|
+
imports this declaration without starting the application.
|
|
9
|
+
|
|
10
|
+
`src/bunderstack/index.ts` owns the production runtime: it imports `backend`,
|
|
11
|
+
calls `await backend.start()`, exports `app`, and calls `provision(app)` when the
|
|
12
|
+
application owns provisioning. Keep unrelated external side effects out of the
|
|
13
|
+
backend import graph.
|
|
10
14
|
|
|
11
15
|
Start a small API in `src/bunderstack.ts`. Split a meaningful configuration
|
|
12
|
-
into `src/bunderstack/` with `index.ts`, `schema/`, `access.ts`, `auth.ts`,
|
|
16
|
+
into `src/bunderstack/` with `backend.ts`, `index.ts`, `schema/`, `access.ts`, `auth.ts`,
|
|
13
17
|
`env.ts`, `jobs/`, and `api/` as needed. The entry remains the one place that
|
|
14
|
-
|
|
18
|
+
starts the declared backend; do not create parallel app,
|
|
15
19
|
database, or auth instances.
|
|
16
20
|
|
|
17
21
|
## Aggregate the schema
|
|
18
22
|
|
|
19
23
|
Export every domain, Better Auth, plugin, and Bunderstack internal table from
|
|
20
|
-
the schema object passed to `
|
|
24
|
+
the schema object passed to `bunderstack()`. Include
|
|
21
25
|
`export * from 'bunderstack/schema'` so migrations include the internal tables.
|
|
22
26
|
Define Better Auth tables required by the selected auth flows and plugins; do
|
|
23
27
|
not assume a minimal auth configuration needs every optional provider table.
|
|
@@ -61,8 +65,8 @@ export const projectsRouter = {
|
|
|
61
65
|
// src/bunderstack/api/index.ts
|
|
62
66
|
export const api = { projects: projectsRouter }
|
|
63
67
|
|
|
64
|
-
//
|
|
65
|
-
|
|
68
|
+
// backend.ts
|
|
69
|
+
bunderstack({ schema, database, api })
|
|
66
70
|
```
|
|
67
71
|
|
|
68
72
|
Do not write a router factory that receives a bag of procedures. That shape
|
|
@@ -118,7 +122,7 @@ const instrumentation = o.middleware(async ({ context, next, path }) => {
|
|
|
118
122
|
}
|
|
119
123
|
})
|
|
120
124
|
|
|
121
|
-
|
|
125
|
+
bunderstack({ schema, database, middleware: [instrumentation], api })
|
|
122
126
|
```
|
|
123
127
|
|
|
124
128
|
Three rules apply to a graph-wide middleware. It runs before authentication, so
|
|
@@ -39,8 +39,11 @@ Declare queue jobs with `jobs: (j) => j.define(...)`, then run them in a
|
|
|
39
39
|
separate production process:
|
|
40
40
|
|
|
41
41
|
```ts
|
|
42
|
-
import {
|
|
42
|
+
import { backend } from './bunderstack/backend'
|
|
43
43
|
|
|
44
|
+
const app = await backend.start({
|
|
45
|
+
env: { ...process.env, BUNDERSTACK_ROLE: 'web' },
|
|
46
|
+
})
|
|
44
47
|
await app.runWorker()
|
|
45
48
|
```
|
|
46
49
|
|
|
@@ -16,7 +16,7 @@ infrastructure, use `creating-bunderstack-apps` instead.
|
|
|
16
16
|
capability today and which call sites depend on it.
|
|
17
17
|
2. Add a migration contract test before removing legacy paths, so every
|
|
18
18
|
deletion has a gate that fails when behaviour is lost.
|
|
19
|
-
3. Establish one Bunderstack
|
|
19
|
+
3. Establish one Bunderstack backend declaration, one runtime, and one schema aggregate.
|
|
20
20
|
4. Move auth and access without creating duplicate instances.
|
|
21
21
|
5. Replace infrastructure capability by capability.
|
|
22
22
|
6. Mount one handler and separate the production worker.
|
|
@@ -31,8 +31,9 @@ database client sits outside provisioning, migration state, and request
|
|
|
31
31
|
transactions. A second env schema drifts from the validated one and passes
|
|
32
32
|
locally while failing at boot.
|
|
33
33
|
|
|
34
|
-
Pass `authConfig` into `
|
|
35
|
-
|
|
34
|
+
Pass `authConfig` into `bunderstack()`, start that declaration once in the web
|
|
35
|
+
entry, and re-export `app.auth` and `app.db` from the runtime entry. Let the
|
|
36
|
+
declared `env` schema plus the source passed to `backend.start()` be the only
|
|
36
37
|
validated source. A more specific file route also shadows the catch-all, so a
|
|
37
38
|
surviving `/api/auth/$` silently keeps serving the instance you meant to delete.
|
|
38
39
|
|
|
@@ -53,7 +54,7 @@ surviving `/api/auth/$` silently keeps serving the instance you meant to delete.
|
|
|
53
54
|
| Channel-and-payload realtime publishing | `ctx.realtime.publish(schema.tasks, 'update', row)` after the write commits |
|
|
54
55
|
| AWS or Tigris SDK wrapper | `app.storage` buckets |
|
|
55
56
|
| Resend SDK wrapper | `app.email.send(...)` |
|
|
56
|
-
| `createEnv()` beside the app | `env`
|
|
57
|
+
| `createEnv()` beside the app | `env` schema in `bunderstack()` and source in `backend.start()` |
|
|
57
58
|
| Implicit database driver | Explicit adapter, `database: { adapter: libsql(), url }` |
|
|
58
59
|
| Schema push in production | Committed Drizzle `migrations/`, applied by `provision(app)` |
|
|
59
60
|
| Undeclared deployment | `package.json#bunderstack.entry` and a checked blueprint |
|
|
@@ -73,8 +74,8 @@ shim is acceptable when call sites are numerous; the shim is deleted under this
|
|
|
73
74
|
same gate. Uninstall the replaced SDK package in the commit that removes its
|
|
74
75
|
last importer, so a stale wrapper cannot be reintroduced silently.
|
|
75
76
|
|
|
76
|
-
Tests
|
|
77
|
-
|
|
77
|
+
Tests should use lexically scoped `await using` fixtures from `backend.test()`;
|
|
78
|
+
scripts that explicitly start a runtime must close the runtime they own.
|
|
78
79
|
|
|
79
80
|
## Production gate
|
|
80
81
|
|
|
@@ -6,26 +6,26 @@ output or a file reference, not an assertion.
|
|
|
6
6
|
|
|
7
7
|
| Capability | Legacy shape to find | Authoritative replacement | Evidence that the move is done | Deletion gate |
|
|
8
8
|
| ---------------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- |
|
|
9
|
-
| Auth instance | A second `betterAuth({...})` call, a custom session resolver, a patched `getSession` | `authConfig` passed to `
|
|
9
|
+
| Auth instance | A second `betterAuth({...})` call, a custom session resolver, a patched `getSession` | `authConfig` passed to `bunderstack()`; consumers import `app.auth` | One `betterAuth` construction in the repository; a protected route rejects an unauthenticated request | No importer of the legacy auth module remains |
|
|
10
10
|
| Auth schema | Auth tables generated into a legacy schema directory | Auth tables in the one schema aggregate | Generated migration includes `user`, `session`, `account`, `verification` | Legacy schema directory has no importers |
|
|
11
11
|
| Database client | A module constructing its own libSQL/Postgres client | `app.db`, re-exported from the entry | The entry is the only place calling the adapter factory | Legacy `db` module deleted or reduced to a re-export, then deleted |
|
|
12
12
|
| API mounting | Hand-written handler maps; separate `/api/auth/$`, `/api/trpc/$` | `createApiHandlers(app)` on one `/api/$` | Auth and oRPC requests succeed with only the catch-all present | Shadowing route files deleted |
|
|
13
13
|
| Custom API routes | Route files doing CRUD the framework can generate | Generated CRUD plus `defineAccess`, or an `o.protected` procedure | Access rules cover each exposed table; a cross-owner request is denied | Route file has no client callers |
|
|
14
14
|
| Access control | Per-endpoint session checks and hand-written SQL filters | `defineAccess(schema, rules)` with `scope.read` / `scope.write` | A test asserts a second user cannot read or write the first user's rows | Manual filter helpers unused |
|
|
15
|
-
| Jobs | BullMQ or a bespoke queue module | `jobs.define({ ... })` and `app.jobs.enqueue(...)` | Job appears in `
|
|
15
|
+
| Jobs | BullMQ or a bespoke queue module | `jobs.define({ ... })` and `app.jobs.enqueue(...)` | Job appears in `backend.manifest.background.jobs` | No queue library importer; package uninstalled |
|
|
16
16
|
| Cron | `/api/cron/*` guarded by a shared secret | `jobs.cron({ schedule, handler })` | Cron task appears in the blueprint | Cron route file and its secret removed from env |
|
|
17
17
|
| Worker topology | `startWorker()` or a queue bootstrap in the web entry | `src/worker.ts` calling `app.runWorker()`, run as its own process | Web entry starts no worker; the worker command exists in deployment config | Worker process is deployed before the embedded call is removed |
|
|
18
18
|
| Realtime | Custom WebSocket server, manual pub/sub, channel-and-payload publishing | `realtime` config plus `ctx.realtime.publish(table, event, row)` after commit | A direct write reaches a subscriber with the complete row | Custom transport deleted; shared Redis configured for multi-process |
|
|
19
19
|
| Storage | AWS or Tigris SDK wrapper, custom multipart upload route | Declared buckets and `app.storage` | Upload, signed URL, and delete work through the facade | Wrapper deleted and SDK uninstalled |
|
|
20
20
|
| Email | Resend or SMTP SDK wrapper | `email` config and `app.email.send(...)` | A send succeeds through the configured provider | Wrapper deleted and SDK uninstalled |
|
|
21
|
-
| Env | `createEnv()` beside the app, `dotenv`, unchecked `process.env` reads | `env`
|
|
21
|
+
| Env | `createEnv()` beside the app, `dotenv`, unchecked `process.env` reads | `env` schema in `bunderstack()`; source in `backend.start()`; `app.env` / `ctx.env` | Boot fails with a clear message when a required variable is missing | Legacy env module unused; `.env.example` lists names only |
|
|
22
22
|
| API declaration | Router factories taking a bag of procedures; hand-written builder generics | `defineApi({ schema, env })` bases in one module, plain router objects, `api` object | A router module imports its base and exports an object; no factory remains | `BunderstackApiBuilder<...>` and `os.$context<...>()` deleted |
|
|
23
23
|
| Observability | Tracing or logging attached to an application procedure base | `middleware: [...]` in the config, which also reaches the generated CRUD | A generated CRUD request produces a span or log line | Per-base instrumentation removed |
|
|
24
24
|
| Errors | `new ORPCError(...)` at call sites, or a second error model | `errors.CODE({ message })`; `BunderstackError` outside a handler | A failing request answers the declared status, not 500 | `ORPCError` import gone from the api layer |
|
|
25
25
|
| List endpoints | Hand-rolled limit/offset/filter/count blocks repeated per table | `listSpec(table, options)` applied to your own base | The endpoint accepts cursor and `count: true` and answers `ListResult` | Duplicated paging helpers deleted |
|
|
26
26
|
| Migrations | Schema push against production | Committed Drizzle `migrations/`, applied by `provision(app)` | `migrations/` is under version control and applies cleanly to an empty database | Push command removed from deployment |
|
|
27
27
|
| Deployment declaration | No `bunderstack.entry`, no blueprint | `package.json#bunderstack.entry` and a committed blueprint | `bun run blueprint:check` passes in CI | Deployment reads the blueprint rather than ad-hoc process config |
|
|
28
|
-
| App lifetime | Tests and scripts leaking app instances | `
|
|
28
|
+
| App lifetime | Tests and scripts leaking app instances | Lexical `await using` fixture from `backend.test()` | Concurrent tests own independent fixtures and the run exits without hanging | — |
|
|
29
29
|
|
|
30
30
|
## Reading a partially migrated application
|
|
31
31
|
|
|
@@ -6,13 +6,12 @@ names; do not change the contracts.
|
|
|
6
6
|
## Modular entry
|
|
7
7
|
|
|
8
8
|
A migrated application has enough configuration to justify `src/bunderstack/`
|
|
9
|
-
with `index.ts`, `schema/`, `access.ts`, `auth.ts`, `env.ts`,
|
|
10
|
-
`api/`. The
|
|
9
|
+
with `backend.ts`, `index.ts`, `schema/`, `access.ts`, `auth.ts`, `env.ts`,
|
|
10
|
+
`jobs/`, and `api/`. The declaration is the only place that assembles them:
|
|
11
11
|
|
|
12
12
|
```ts
|
|
13
|
-
import {
|
|
14
|
-
import { libsql } from 'bunderstack/
|
|
15
|
-
import { provision } from 'bunderstack/provision'
|
|
13
|
+
import { bunderstack } from 'bunderstack'
|
|
14
|
+
import { libsql } from 'bunderstack/libsql'
|
|
16
15
|
import { access } from './access'
|
|
17
16
|
import { authConfig } from './auth'
|
|
18
17
|
import { envSchema } from './env'
|
|
@@ -20,33 +19,31 @@ import { defineJobs } from './jobs'
|
|
|
20
19
|
import { schema } from './schema'
|
|
21
20
|
import * as v from 'valibot'
|
|
22
21
|
|
|
23
|
-
export
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
access: { create: 'authenticated', get: 'owner', delete: 'owner' },
|
|
41
|
-
},
|
|
22
|
+
export const backend = bunderstack({
|
|
23
|
+
schema,
|
|
24
|
+
access,
|
|
25
|
+
env: envSchema,
|
|
26
|
+
database: {
|
|
27
|
+
adapter: libsql(),
|
|
28
|
+
url: 'file:./data.db',
|
|
29
|
+
},
|
|
30
|
+
auth: authConfig,
|
|
31
|
+
email: { from: 'App <no-reply@example.com>' },
|
|
32
|
+
storage: {
|
|
33
|
+
local: './uploads',
|
|
34
|
+
defaultBucket: 'files',
|
|
35
|
+
buckets: {
|
|
36
|
+
files: {
|
|
37
|
+
visibility: 'private',
|
|
38
|
+
access: { create: 'authenticated', get: 'owner', delete: 'owner' },
|
|
42
39
|
},
|
|
43
40
|
},
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
41
|
+
},
|
|
42
|
+
realtime: true,
|
|
43
|
+
jobs: defineJobs,
|
|
44
|
+
middleware: [instrumentation],
|
|
45
|
+
api,
|
|
46
|
+
})
|
|
50
47
|
|
|
51
48
|
// api/base.ts — the builder is a module value, so router modules import the
|
|
52
49
|
// bases they need instead of receiving them through the config callback.
|
|
@@ -59,7 +56,11 @@ export async function createApp(options: { databaseUrl?: string } = {}) {
|
|
|
59
56
|
//
|
|
60
57
|
// export const api = { projects: projectsRouter }
|
|
61
58
|
|
|
62
|
-
|
|
59
|
+
// index.ts
|
|
60
|
+
import { provision } from 'bunderstack/provision'
|
|
61
|
+
import { backend } from './backend'
|
|
62
|
+
|
|
63
|
+
export const app = await backend.start()
|
|
63
64
|
export const { db, auth, env } = app
|
|
64
65
|
export type App = typeof app
|
|
65
66
|
|
|
@@ -67,12 +68,9 @@ await provision(app)
|
|
|
67
68
|
```
|
|
68
69
|
|
|
69
70
|
The database adapter is imported explicitly; there is no implicit driver. Keep
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
command imports the entry with `BUNDERSTACK_INTROSPECT=1`, so a module that
|
|
74
|
-
connects to a queue or calls a third-party API at import time breaks
|
|
75
|
-
introspection.
|
|
71
|
+
unrelated external side effects out of the backend import graph. The blueprint
|
|
72
|
+
imports the declaration and reads `backend.manifest`; it never starts the app,
|
|
73
|
+
connects to a queue, or needs a special environment flag.
|
|
76
74
|
|
|
77
75
|
Aggregate every domain, Better Auth, plugin, and internal table in the schema
|
|
78
76
|
object, including `export * from 'bunderstack/schema'`, so migrations cover the
|
|
@@ -116,8 +114,11 @@ Production queue work is its own process:
|
|
|
116
114
|
|
|
117
115
|
```ts
|
|
118
116
|
// src/worker.ts
|
|
119
|
-
import {
|
|
117
|
+
import { backend } from './bunderstack/backend'
|
|
120
118
|
|
|
119
|
+
const app = await backend.start({
|
|
120
|
+
env: { ...process.env, BUNDERSTACK_ROLE: 'web' },
|
|
121
|
+
})
|
|
121
122
|
await app.runWorker()
|
|
122
123
|
```
|
|
123
124
|
|
|
@@ -224,7 +225,7 @@ const url = await app.storage.getUrl(key, { expiresIn: 3600 })
|
|
|
224
225
|
await app.storage.delete(fileId)
|
|
225
226
|
```
|
|
226
227
|
|
|
227
|
-
Buckets are declared in `
|
|
228
|
+
Buckets are declared in `bunderstack()` with their own visibility and
|
|
228
229
|
access rules. Delete the AWS or Tigris wrapper and uninstall the SDK. A custom
|
|
229
230
|
multipart upload route is replaced by the bucket's own upload route unless it
|
|
230
231
|
performs domain work that cannot move into a job.
|
|
@@ -241,7 +242,7 @@ Standard `fetch`, so the `resend` package is uninstalled.
|
|
|
241
242
|
|
|
242
243
|
## Env
|
|
243
244
|
|
|
244
|
-
Pass `envSchema` to `
|
|
245
|
+
Pass `envSchema` to `bunderstack({ env: envSchema })` and read `app.env`
|
|
245
246
|
or `ctx.env`. Remove `@t3-oss/env-core` `createEnv()` calls and `dotenv`; Bun
|
|
246
247
|
loads `.env` itself. Server variables must not use the `PUBLIC_` prefix, and
|
|
247
248
|
browser-safe variables must. Declared env appears in the deployment blueprint,
|
|
@@ -256,7 +257,7 @@ commit migrations before production:
|
|
|
256
257
|
|
|
257
258
|
```json
|
|
258
259
|
{
|
|
259
|
-
"bunderstack": { "entry": "src/bunderstack/
|
|
260
|
+
"bunderstack": { "entry": "src/bunderstack/backend.ts" },
|
|
260
261
|
"scripts": {
|
|
261
262
|
"worker": "bun src/worker.ts",
|
|
262
263
|
"db:generate": "drizzle-kit generate",
|
|
@@ -273,14 +274,19 @@ or build output.
|
|
|
273
274
|
|
|
274
275
|
## Test and script ownership
|
|
275
276
|
|
|
276
|
-
A test or script
|
|
277
|
+
A test or script owns its fixture lexically:
|
|
277
278
|
|
|
278
279
|
```ts
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
280
|
+
await using t = await backend.test({ database: { schema: 'push' } })
|
|
281
|
+
const identity = t.auth.mockSession({
|
|
282
|
+
id: 'user-1',
|
|
283
|
+
email: 'dev@example.com',
|
|
284
|
+
name: 'Developer',
|
|
285
|
+
})
|
|
286
|
+
const client = t.client(identity)
|
|
287
|
+
// ...
|
|
286
288
|
```
|
|
289
|
+
|
|
290
|
+
The fixture isolates database, email, storage, realtime, and queue state and is
|
|
291
|
+
disposed at the end of the block. Keep application-specific organization setup
|
|
292
|
+
in a typed helper layered on top of the base user/session auth helper.
|