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
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,61 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `bunderstack` will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.22.1] - 2026-08-28
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **Configured test factories.** `backend.test.configure({ env, database, logs, setup })`
|
|
10
|
+
creates a reusable fixture factory. Per-test options deep-merge `env` and
|
|
11
|
+
`database`, and the setup result is available as `fixture.context`.
|
|
12
|
+
- **Fixture-owned cleanup and logs.** `fixture.defer()` runs async cleanup in LIFO
|
|
13
|
+
order before runtime shutdown. Internal runtime logs are captured by default in
|
|
14
|
+
`fixture.logs`; use `logs: 'inherit'` to forward them or `logs: 'silent'` to discard
|
|
15
|
+
them.
|
|
16
|
+
- **Complete auth test lifecycle.** Added `signInEmail()`, `getSession()`, `signOut()`,
|
|
17
|
+
and `verifyEmail()`. Mock identities are header-scoped, so multiple users can safely
|
|
18
|
+
coexist in one fixture.
|
|
19
|
+
- **Queue inspection.** `fixture.jobs.inspect()`, `.pending()`, and `.failed()` expose
|
|
20
|
+
normalized queue rows and accept `name` and `dedupeKey` filters.
|
|
21
|
+
|
|
22
|
+
## [0.22.0] - 2026-08-28
|
|
23
|
+
|
|
24
|
+
### Breaking Changes
|
|
25
|
+
|
|
26
|
+
- **Flat subpath exports.** Every nested subpath is now a single segment:
|
|
27
|
+
`bunderstack/database/libsql` → `bunderstack/libsql` (same for `bun-sql`, `pglite`,
|
|
28
|
+
`postgres-js`), `bunderstack/client/react` → `bunderstack/client-react` (same for
|
|
29
|
+
`rest`, `solid`, `svelte`, `vue`), `bunderstack/query/react` → `bunderstack/query-react`,
|
|
30
|
+
`bunderstack/start/auth` → `bunderstack/start-auth`, `bunderstack/schema/pg` →
|
|
31
|
+
`bunderstack/schema-pg`, `bunderstack/typeid/pg` → `bunderstack/typeid-pg`,
|
|
32
|
+
`bunderstack/email/smtp` → `bunderstack/email-smtp`. TypeScript's auto-import
|
|
33
|
+
completion returns a replacement span covering the whole specifier for any
|
|
34
|
+
multi-segment subpath, so accepting the suggestion dropped the package name and
|
|
35
|
+
produced a broken import. Single-segment names get the correct span.
|
|
36
|
+
- **Pure declaration and explicit runtime separation.** Replaced `createBunderstack()`
|
|
37
|
+
with synchronous `bunderstack(config)`. The declaration computes static metadata
|
|
38
|
+
synchronously (`backend.manifest`) without connecting to databases, reading ambient
|
|
39
|
+
`process.env`, or starting background workers.
|
|
40
|
+
- **Explicit startup environment.** `backend.start({ env })` treats the passed `env`
|
|
41
|
+
object as the exclusive source of environment configuration and never mixes it with
|
|
42
|
+
`process.env`.
|
|
43
|
+
- **Pure Blueprint generation.** `bunderstack blueprint` now directly imports
|
|
44
|
+
`backend` declarations without booting the runtime or relying on
|
|
45
|
+
`BUNDERSTACK_INTROSPECT`.
|
|
46
|
+
|
|
47
|
+
### Added
|
|
48
|
+
|
|
49
|
+
- **First-class testing framework (`bunderstack/testing`).** Exported `createTestApp`,
|
|
50
|
+
`TestFixture`, and `backend.test()`:
|
|
51
|
+
- Lexical fixture lifecycle with `AsyncDisposable` (`await using t = await backend.test()`).
|
|
52
|
+
- Isolated in-memory/temporary databases for libSQL and PGlite.
|
|
53
|
+
- In-memory email capturing (`t.email.sent`), isolated local storage (`t.storage.read`),
|
|
54
|
+
and forced memory realtime.
|
|
55
|
+
- Real Better Auth sign-up (`t.auth.signUpEmail()`), session mocking
|
|
56
|
+
(`t.auth.mockSession()`), and typed in-process RPC clients (`t.client(identity)`).
|
|
57
|
+
- Deterministic job execution with `t.jobs.runNext()` and `t.jobs.runUntilIdle()`
|
|
58
|
+
without network or timing delays.
|
|
59
|
+
|
|
5
60
|
## [0.21.0] - 2026-08-25
|
|
6
61
|
|
|
7
62
|
### Changed
|
package/README.md
CHANGED
|
@@ -7,12 +7,12 @@ bun add bunderstack better-auth drizzle-orm valibot @libsql/client
|
|
|
7
7
|
```
|
|
8
8
|
|
|
9
9
|
```ts
|
|
10
|
-
import {
|
|
11
|
-
import { libsql } from 'bunderstack/
|
|
10
|
+
import { bunderstack, defineApi } from 'bunderstack'
|
|
11
|
+
import { libsql } from 'bunderstack/libsql'
|
|
12
12
|
import * as v from 'valibot'
|
|
13
13
|
import * as schema from './schema'
|
|
14
14
|
|
|
15
|
-
export const
|
|
15
|
+
export const backend = bunderstack({
|
|
16
16
|
schema,
|
|
17
17
|
database: { adapter: libsql(), url: 'file:./data.db' },
|
|
18
18
|
access: { posts: { crud: true } },
|
|
@@ -25,6 +25,7 @@ export const app = await createBunderstack({
|
|
|
25
25
|
},
|
|
26
26
|
})
|
|
27
27
|
|
|
28
|
+
export const app = await backend.start()
|
|
28
29
|
Bun.serve({ fetch: app.handler })
|
|
29
30
|
export type App = typeof app
|
|
30
31
|
```
|
|
@@ -46,16 +47,19 @@ replay. Deployment metadata is generated with `bunx bunderstack blueprint`.
|
|
|
46
47
|
|
|
47
48
|
## Package Subpaths (0.21+)
|
|
48
49
|
|
|
49
|
-
- `bunderstack` —
|
|
50
|
+
- `bunderstack` — Declarative backend and runtime (`bunderstack`, `defineApi`, `buildApiRegistry`)
|
|
51
|
+
- `bunderstack/testing` — Isolated lexical fixtures and reusable test factories
|
|
52
|
+
(`backend.test()` / `backend.test.configure()`)
|
|
53
|
+
- `bunderstack/provision` — Explicit production schema provisioning
|
|
50
54
|
- `bunderstack/client` — Framework-neutral RPC & LiveView client (`createClient`, `createLiveView`)
|
|
51
|
-
- `bunderstack/client
|
|
52
|
-
- `bunderstack/client
|
|
53
|
-
- `bunderstack/query` & `bunderstack/query
|
|
55
|
+
- `bunderstack/client-rest` — Type-safe REST client
|
|
56
|
+
- `bunderstack/client-react`, `bunderstack/client-solid`, `bunderstack/client-vue`, `bunderstack/client-svelte` — LiveView UI bindings
|
|
57
|
+
- `bunderstack/query` & `bunderstack/query-react` — TanStack Query client (`createClient`, `syncRealtime`)
|
|
54
58
|
- `bunderstack/sync` — TanStack DB collections (`createSyncClient`)
|
|
55
|
-
- `bunderstack/start` & `bunderstack/start
|
|
56
|
-
- `bunderstack/
|
|
59
|
+
- `bunderstack/start` & `bunderstack/start-auth` — TanStack Start full-stack integration
|
|
60
|
+
- `bunderstack/libsql`, `bunderstack/postgres-js`, `bunderstack/bun-sql`, `bunderstack/bun-sqlite`, `bunderstack/pglite` — Database adapters
|
|
57
61
|
- `bunderstack/storage/*` — Storage adapters (`s3`, `disk`)
|
|
58
|
-
- `bunderstack/email
|
|
62
|
+
- `bunderstack/email-smtp` — SMTP email adapter
|
|
59
63
|
- `bunderstack/jobs/*` — Job queue adapters (`memory`, `redis`)
|
|
60
64
|
|
|
61
65
|
See the [workspace documentation](https://github.com/kirill-dev-pro/bunderstack#readme) for webhooks, clients,
|
|
@@ -65,6 +69,7 @@ storage, collections, lifecycle, and complete examples.
|
|
|
65
69
|
|
|
66
70
|
Every change is listed with before/after code in the migration guides, which live in full at:
|
|
67
71
|
|
|
72
|
+
- [Migrating to 0.22](https://github.com/kirill-dev-pro/bunderstack/blob/main/docs/MIGRATION-0.22.md)
|
|
68
73
|
- [Migrating to 0.21](https://github.com/kirill-dev-pro/bunderstack/blob/main/docs/MIGRATION-0.21.md)
|
|
69
74
|
- [Migrating to 0.17](https://github.com/kirill-dev-pro/bunderstack/blob/main/docs/MIGRATION-0.17.md)
|
|
70
75
|
- [Migrating to 0.16](https://github.com/kirill-dev-pro/bunderstack/blob/main/docs/MIGRATION-0.16.md)
|
package/dist/api/builder.d.ts
CHANGED
|
@@ -185,7 +185,7 @@ export declare function createApiBuilder<TSchema extends Record<string, unknown>
|
|
|
185
185
|
}>;
|
|
186
186
|
/**
|
|
187
187
|
* Declares a standalone middleware over the base context. Use it for
|
|
188
|
-
* `
|
|
188
|
+
* `bunderstack({ middleware })`, which reaches every procedure in
|
|
189
189
|
* the graph, and for `.use(...)` on any base declared here.
|
|
190
190
|
*
|
|
191
191
|
* The annotation is explicit because the inferred `DecoratedMiddleware`
|
|
@@ -383,7 +383,7 @@ export declare function defineApi<TSchema extends Record<string, unknown>, TEnv
|
|
|
383
383
|
}>;
|
|
384
384
|
/**
|
|
385
385
|
* Declares a standalone middleware over the base context. Use it for
|
|
386
|
-
* `
|
|
386
|
+
* `bunderstack({ middleware })`, which reaches every procedure in
|
|
387
387
|
* the graph, and for `.use(...)` on any base declared here.
|
|
388
388
|
*
|
|
389
389
|
* The annotation is explicit because the inferred `DecoratedMiddleware`
|
package/dist/api/builder.js
CHANGED
|
@@ -25,7 +25,7 @@ export function createApiBuilder() {
|
|
|
25
25
|
webhook: base,
|
|
26
26
|
/**
|
|
27
27
|
* Declares a standalone middleware over the base context. Use it for
|
|
28
|
-
* `
|
|
28
|
+
* `bunderstack({ middleware })`, which reaches every procedure in
|
|
29
29
|
* the graph, and for `.use(...)` on any base declared here.
|
|
30
30
|
*
|
|
31
31
|
* The annotation is explicit because the inferred `DecoratedMiddleware`
|
package/dist/api/builder.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builder.js","sourceRoot":"","sources":["../../src/api/builder.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,EAAE,GAKH,MAAM,cAAc,CAAA;AAKrB,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,WAAW,CAAA;AAGlB,MAAM,UAAU,gBAAgB;IAI9B,MAAM,IAAI,GAAG,EAAE;SACZ,QAAQ,EAA6B;SACrC,MAAM,CAAC,kBAAkB,CAAC;SAC1B,GAAG,CAAC,oBAAoB,CAAC,CAAA;IAE5B,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE;QACzD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,EAAE,CAAA;QAC1C,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClB,MAAM,IAAI,gBAAgB,CAAC,cAAc,EAAE,yBAAyB,CAAC,CAAA;QACvE,CAAC;QACD,OAAO,IAAI,CAAC;YACV,OAAO,EAAE;gBACP,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,OAAO,EAAE;oBACP,oBAAoB,EAAE,OAAO,CAAC,oBAAoB;iBACnD;aACF;SACF,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,OAAO;QACL,MAAM,EAAE,IAAI;QACZ,SAAS,EAAE,aAAa;QACxB,OAAO,EAAE,IAAI;QACb;;;;;;;WAOG;QACH,UAAU,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAQnB;KACnB,CAAA;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAGvB,QAAyC;IACzC,OAAO,gBAAgB,EAA+B,CAAA;AACxD,CAAC","sourcesContent":["import {\n os,\n type AnyMiddleware,\n type AnyRouter,\n type Context,\n type Middleware,\n} from '@orpc/server'\n\nimport type { EnvConfigInput, ValidatedEnv } from '../env'\nimport type { ApiContext } from './context'\n\nimport {\n BUNDERSTACK_ERRORS,\n BunderstackError,\n mapBunderstackErrors,\n} from '../errors'\nexport type { ProtectedContextAdditions } from './types'\n\nexport function createApiBuilder<\n TSchema extends Record<string, unknown> = Record<string, unknown>,\n TEnv = Record<string, unknown>,\n>() {\n const base = os\n .$context<ApiContext<TSchema, TEnv>>()\n .errors(BUNDERSTACK_ERRORS)\n .use(mapBunderstackErrors)\n\n const protectedProc = base.use(async ({ context, next }) => {\n const session = await context.getSession()\n if (!session.user) {\n throw new BunderstackError('UNAUTHORIZED', 'Authentication required')\n }\n return next({\n context: {\n user: session.user,\n session: {\n activeOrganizationId: session.activeOrganizationId,\n },\n },\n })\n })\n\n return {\n public: base,\n protected: protectedProc,\n webhook: base,\n /**\n * Declares a standalone middleware over the base context. Use it for\n * `
|
|
1
|
+
{"version":3,"file":"builder.js","sourceRoot":"","sources":["../../src/api/builder.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,EAAE,GAKH,MAAM,cAAc,CAAA;AAKrB,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,WAAW,CAAA;AAGlB,MAAM,UAAU,gBAAgB;IAI9B,MAAM,IAAI,GAAG,EAAE;SACZ,QAAQ,EAA6B;SACrC,MAAM,CAAC,kBAAkB,CAAC;SAC1B,GAAG,CAAC,oBAAoB,CAAC,CAAA;IAE5B,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE;QACzD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,EAAE,CAAA;QAC1C,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClB,MAAM,IAAI,gBAAgB,CAAC,cAAc,EAAE,yBAAyB,CAAC,CAAA;QACvE,CAAC;QACD,OAAO,IAAI,CAAC;YACV,OAAO,EAAE;gBACP,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,OAAO,EAAE;oBACP,oBAAoB,EAAE,OAAO,CAAC,oBAAoB;iBACnD;aACF;SACF,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,OAAO;QACL,MAAM,EAAE,IAAI;QACZ,SAAS,EAAE,aAAa;QACxB,OAAO,EAAE,IAAI;QACb;;;;;;;WAOG;QACH,UAAU,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAQnB;KACnB,CAAA;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAGvB,QAAyC;IACzC,OAAO,gBAAgB,EAA+B,CAAA;AACxD,CAAC","sourcesContent":["import {\n os,\n type AnyMiddleware,\n type AnyRouter,\n type Context,\n type Middleware,\n} from '@orpc/server'\n\nimport type { EnvConfigInput, ValidatedEnv } from '../env'\nimport type { ApiContext } from './context'\n\nimport {\n BUNDERSTACK_ERRORS,\n BunderstackError,\n mapBunderstackErrors,\n} from '../errors'\nexport type { ProtectedContextAdditions } from './types'\n\nexport function createApiBuilder<\n TSchema extends Record<string, unknown> = Record<string, unknown>,\n TEnv = Record<string, unknown>,\n>() {\n const base = os\n .$context<ApiContext<TSchema, TEnv>>()\n .errors(BUNDERSTACK_ERRORS)\n .use(mapBunderstackErrors)\n\n const protectedProc = base.use(async ({ context, next }) => {\n const session = await context.getSession()\n if (!session.user) {\n throw new BunderstackError('UNAUTHORIZED', 'Authentication required')\n }\n return next({\n context: {\n user: session.user,\n session: {\n activeOrganizationId: session.activeOrganizationId,\n },\n },\n })\n })\n\n return {\n public: base,\n protected: protectedProc,\n webhook: base,\n /**\n * Declares a standalone middleware over the base context. Use it for\n * `bunderstack({ middleware })`, which reaches every procedure in\n * the graph, and for `.use(...)` on any base declared here.\n *\n * The annotation is explicit because the inferred `DecoratedMiddleware`\n * is internal to `@orpc/server` and cannot be named in the emitted types.\n */\n middleware: base.middleware.bind(base) as <TOutContext extends Context>(\n middleware: Middleware<\n ApiContext<TSchema, TEnv>,\n TOutContext,\n unknown,\n unknown,\n typeof BUNDERSTACK_ERRORS\n >,\n ) => AnyMiddleware,\n }\n}\n\n/**\n * Same builder as `createApiBuilder`, but the generics come from the values an\n * application already has. It reads nothing at runtime, so a module can call it\n * at import time and export the bases that its router modules import.\n */\nexport function defineApi<\n TSchema extends Record<string, unknown>,\n TEnv extends EnvConfigInput | undefined = undefined,\n>(_options: { schema: TSchema; env?: TEnv }) {\n return createApiBuilder<TSchema, ValidatedEnv<TEnv>>()\n}\n\nexport type BunderstackApiBuilder<\n TSchema extends Record<string, unknown>,\n TEnv = Record<string, unknown>,\n> = ReturnType<typeof createApiBuilder<TSchema, TEnv>>\n\nexport type ApiFactory<\n TSchema extends Record<string, unknown>,\n TEnv,\n TCustomApiRouter extends AnyRouter,\n> = (builder: BunderstackApiBuilder<TSchema, TEnv>) => TCustomApiRouter\n"]}
|
package/dist/api/context.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { AccessUser, AuthSessionResolver } from '../access.js';
|
|
2
2
|
import type { DbFor } from '../db.js';
|
|
3
3
|
import type { EmailFacade } from '../email.js';
|
|
4
|
-
import type { AuthInstance, StorageFacade } from '../index.js';
|
|
5
4
|
import type { JobsRuntimeFacade } from '../jobs/define.js';
|
|
5
|
+
import type { BunderstackLogger } from '../logging.js';
|
|
6
6
|
import type { RealtimeFacade } from '../realtime/facade.js';
|
|
7
|
+
import type { AuthInstance, StorageFacade } from '../runtime.js';
|
|
7
8
|
export interface ApiContextDeps<TSchema extends Record<string, unknown> = Record<string, unknown>, TEnv = Record<string, unknown>> {
|
|
8
9
|
db: DbFor<TSchema>;
|
|
9
10
|
env: TEnv;
|
|
@@ -13,6 +14,7 @@ export interface ApiContextDeps<TSchema extends Record<string, unknown> = Record
|
|
|
13
14
|
realtime: RealtimeFacade<TSchema>;
|
|
14
15
|
auth: AuthInstance;
|
|
15
16
|
authResolver?: AuthSessionResolver;
|
|
17
|
+
logger?: BunderstackLogger;
|
|
16
18
|
}
|
|
17
19
|
export interface ApiContext<TSchema extends Record<string, unknown> = Record<string, unknown>, TEnv = Record<string, unknown>> {
|
|
18
20
|
db: DbFor<TSchema>;
|
|
@@ -22,6 +24,7 @@ export interface ApiContext<TSchema extends Record<string, unknown> = Record<str
|
|
|
22
24
|
jobs: JobsRuntimeFacade;
|
|
23
25
|
realtime: RealtimeFacade<TSchema>;
|
|
24
26
|
auth: AuthInstance;
|
|
27
|
+
logger: BunderstackLogger;
|
|
25
28
|
request: Request;
|
|
26
29
|
resHeaders: Headers;
|
|
27
30
|
getRawBody: () => Promise<string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/api/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAA;AAChE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,OAAO,CAAA;AAClC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAC3C,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/api/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAA;AAChE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,OAAO,CAAA;AAClC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAC3C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AACvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAK7D,MAAM,WAAW,cAAc,CAC7B,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjE,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAE9B,EAAE,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;IAClB,GAAG,EAAE,IAAI,CAAA;IACT,OAAO,EAAE,aAAa,CAAA;IACtB,KAAK,EAAE,WAAW,CAAA;IAClB,IAAI,EAAE,iBAAiB,CAAA;IACvB,QAAQ,EAAE,cAAc,CAAC,OAAO,CAAC,CAAA;IACjC,IAAI,EAAE,YAAY,CAAA;IAClB,YAAY,CAAC,EAAE,mBAAmB,CAAA;IAClC,MAAM,CAAC,EAAE,iBAAiB,CAAA;CAC3B;AAED,MAAM,WAAW,UAAU,CACzB,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjE,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAE9B,EAAE,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;IAClB,GAAG,EAAE,IAAI,CAAA;IACT,OAAO,EAAE,aAAa,CAAA;IACtB,KAAK,EAAE,WAAW,CAAA;IAClB,IAAI,EAAE,iBAAiB,CAAA;IACvB,QAAQ,EAAE,cAAc,CAAC,OAAO,CAAC,CAAA;IACjC,IAAI,EAAE,YAAY,CAAA;IAClB,MAAM,EAAE,iBAAiB,CAAA;IACzB,OAAO,EAAE,OAAO,CAAA;IAChB,UAAU,EAAE,OAAO,CAAA;IACnB,UAAU,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;IACjC,UAAU,EAAE,MAAM,OAAO,CAAC;QACxB,IAAI,EAAE,UAAU,GAAG,IAAI,CAAA;QACvB,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAA;KACpC,CAAC,CAAA;IACF;;;;;OAKG;IACH,WAAW,EAAE,MACT;QAAE,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC;QAAC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAChE,SAAS,CAAA;CACd;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjE,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAE9B,IAAI,EAAE,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,EACnC,OAAO,EAAE,OAAO,GACf,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CA8C3B"}
|
package/dist/api/context.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { resolveSession } from '../access.js';
|
|
2
|
+
import { consoleLogger } from '../logging.js';
|
|
2
3
|
export function createApiContext(deps, request) {
|
|
3
4
|
// Reserve the body stream before a transport codec consumes `request`.
|
|
4
5
|
const rawBodyRequest = request.clone();
|
|
@@ -28,6 +29,7 @@ export function createApiContext(deps, request) {
|
|
|
28
29
|
jobs: deps.jobs,
|
|
29
30
|
realtime: deps.realtime,
|
|
30
31
|
auth: deps.auth,
|
|
32
|
+
logger: deps.logger ?? consoleLogger,
|
|
31
33
|
request,
|
|
32
34
|
resHeaders: new Headers(),
|
|
33
35
|
getRawBody,
|
package/dist/api/context.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/api/context.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/api/context.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AA+C1C,MAAM,UAAU,gBAAgB,CAI9B,IAAmC,EACnC,OAAgB;IAEhB,uEAAuE;IACvE,MAAM,cAAc,GAAG,OAAO,CAAC,KAAK,EAAE,CAAA;IACtC,IAAI,cAA2C,CAAA;IAC/C,IAAI,cAES,CAAA;IAEb,IAAI,cAES,CAAA;IAEb,MAAM,UAAU,GAAG,GAAG,EAAE;QACtB,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,cAAc,GAAG,cAAc,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CACtE,CAAC,OAAO,EAAE,EAAE;gBACV,cAAc,GAAG,OAAO,CAAA;gBACxB,OAAO,OAAO,CAAA;YAChB,CAAC,CACF,CAAA;QACH,CAAC;QACD,OAAO,cAAc,CAAA;IACvB,CAAC,CAAA;IAED,MAAM,WAAW,GAAG,GAAG,EAAE,CAAC,cAAc,CAAA;IAExC,MAAM,UAAU,GAAG,GAAG,EAAE;QACtB,IAAI,CAAC,cAAc;YAAE,cAAc,GAAG,cAAc,CAAC,IAAI,EAAE,CAAA;QAC3D,OAAO,cAAc,CAAA;IACvB,CAAC,CAAA;IAED,OAAO;QACL,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,aAAa;QACpC,OAAO;QACP,UAAU,EAAE,IAAI,OAAO,EAAE;QACzB,UAAU;QACV,UAAU;QACV,WAAW;KACZ,CAAA;AACH,CAAC","sourcesContent":["import type { AccessUser, AuthSessionResolver } from '../access'\nimport type { DbFor } from '../db'\nimport type { EmailFacade } from '../email'\nimport type { JobsRuntimeFacade } from '../jobs/define'\nimport type { BunderstackLogger } from '../logging'\nimport type { RealtimeFacade } from '../realtime/facade'\nimport type { AuthInstance, StorageFacade } from '../runtime'\n\nimport { resolveSession } from '../access'\nimport { consoleLogger } from '../logging'\n\nexport interface ApiContextDeps<\n TSchema extends Record<string, unknown> = Record<string, unknown>,\n TEnv = Record<string, unknown>,\n> {\n db: DbFor<TSchema>\n env: TEnv\n storage: StorageFacade\n email: EmailFacade\n jobs: JobsRuntimeFacade\n realtime: RealtimeFacade<TSchema>\n auth: AuthInstance\n authResolver?: AuthSessionResolver\n logger?: BunderstackLogger\n}\n\nexport interface ApiContext<\n TSchema extends Record<string, unknown> = Record<string, unknown>,\n TEnv = Record<string, unknown>,\n> {\n db: DbFor<TSchema>\n env: TEnv\n storage: StorageFacade\n email: EmailFacade\n jobs: JobsRuntimeFacade\n realtime: RealtimeFacade<TSchema>\n auth: AuthInstance\n logger: BunderstackLogger\n request: Request\n resHeaders: Headers\n getRawBody: () => Promise<string>\n getSession: () => Promise<{\n user: AccessUser | null\n activeOrganizationId: string | null\n }>\n /**\n * The session that some earlier code already resolved, or `undefined`.\n * Never starts a resolution, so a global middleware can log the caller\n * without removing the lazy session behavior that signed webhooks rely on.\n * Use it for observability only. Never use it for authorization.\n */\n peekSession: () =>\n | { user: AccessUser | null; activeOrganizationId: string | null }\n | undefined\n}\n\nexport function createApiContext<\n TSchema extends Record<string, unknown> = Record<string, unknown>,\n TEnv = Record<string, unknown>,\n>(\n deps: ApiContextDeps<TSchema, TEnv>,\n request: Request,\n): ApiContext<TSchema, TEnv> {\n // Reserve the body stream before a transport codec consumes `request`.\n const rawBodyRequest = request.clone()\n let rawBodyPromise: Promise<string> | undefined\n let sessionPromise:\n | Promise<{ user: AccessUser | null; activeOrganizationId: string | null }>\n | undefined\n\n let settledSession:\n | { user: AccessUser | null; activeOrganizationId: string | null }\n | undefined\n\n const getSession = () => {\n if (!sessionPromise) {\n sessionPromise = resolveSession(deps.authResolver, request.headers).then(\n (session) => {\n settledSession = session\n return session\n },\n )\n }\n return sessionPromise\n }\n\n const peekSession = () => settledSession\n\n const getRawBody = () => {\n if (!rawBodyPromise) rawBodyPromise = rawBodyRequest.text()\n return rawBodyPromise\n }\n\n return {\n db: deps.db,\n env: deps.env,\n storage: deps.storage,\n email: deps.email,\n jobs: deps.jobs,\n realtime: deps.realtime,\n auth: deps.auth,\n logger: deps.logger ?? consoleLogger,\n request,\n resHeaders: new Headers(),\n getRawBody,\n getSession,\n peekSession,\n }\n}\n"]}
|
package/dist/auth.d.ts
CHANGED
|
@@ -12,6 +12,14 @@ import type { EmailFacade } from './email.js';
|
|
|
12
12
|
* `index.ts`), so nothing depends on the wider type.
|
|
13
13
|
*/
|
|
14
14
|
export declare function createAuth(db: AnyDb, cfg: BetterAuthConfig, dialect: Dialect, userSchema?: Record<string, unknown>): Auth;
|
|
15
|
+
/**
|
|
16
|
+
* better-auth resolves its models out of the app's own schema, so an app that
|
|
17
|
+
* declares none has no auth at all. Session resolution must then short-circuit
|
|
18
|
+
* to null: the drizzle adapter throws on a missing model, and any session
|
|
19
|
+
* cookie for the host — a browser keeps those per host, not per port, so one
|
|
20
|
+
* minted by another local app arrives here too — would break every request.
|
|
21
|
+
*/
|
|
22
|
+
export declare function missingAuthModels(schema: Record<string, unknown>, cfg: BetterAuthConfig): string[];
|
|
15
23
|
/**
|
|
16
24
|
* Adapt the raw better-auth instance to our internal {@link AuthSessionResolver}
|
|
17
25
|
* contract. better-auth's `getSession` has a union return (a bare session, or a
|
package/dist/auth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AACA,OAAO,EAAc,KAAK,IAAI,EAAE,MAAM,aAAa,CAAA;AAInD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAChD,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAE1C;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,EAAE,EAAE,KAAK,EACT,GAAG,EAAE,gBAAgB,EACrB,OAAO,EAAE,OAAO,EAChB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,IAAI,CAcN;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,GAClC,mBAAmB,CA+BrB;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,gBAAgB,EACrB,KAAK,EAAE,WAAW,EAClB,eAAe,EAAE,OAAO,GACvB,gBAAgB,CAkClB"}
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AACA,OAAO,EAAc,KAAK,IAAI,EAAE,MAAM,aAAa,CAAA;AAInD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAChD,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAE1C;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,EAAE,EAAE,KAAK,EACT,GAAG,EAAE,gBAAgB,EACrB,OAAO,EAAE,OAAO,EAChB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,IAAI,CAcN;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,GAAG,EAAE,gBAAgB,GACpB,MAAM,EAAE,CAMV;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,GAClC,mBAAmB,CA+BrB;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,gBAAgB,EACrB,KAAK,EAAE,WAAW,EAClB,eAAe,EAAE,OAAO,GACvB,gBAAgB,CAkClB"}
|
package/dist/auth.js
CHANGED
|
@@ -24,6 +24,20 @@ export function createAuth(db, cfg, dialect, userSchema) {
|
|
|
24
24
|
}),
|
|
25
25
|
});
|
|
26
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* better-auth resolves its models out of the app's own schema, so an app that
|
|
29
|
+
* declares none has no auth at all. Session resolution must then short-circuit
|
|
30
|
+
* to null: the drizzle adapter throws on a missing model, and any session
|
|
31
|
+
* cookie for the host — a browser keeps those per host, not per port, so one
|
|
32
|
+
* minted by another local app arrives here too — would break every request.
|
|
33
|
+
*/
|
|
34
|
+
export function missingAuthModels(schema, cfg) {
|
|
35
|
+
const models = [
|
|
36
|
+
cfg.user?.modelName ?? 'user',
|
|
37
|
+
cfg.session?.modelName ?? 'session',
|
|
38
|
+
];
|
|
39
|
+
return models.filter((model) => !schema[model]);
|
|
40
|
+
}
|
|
27
41
|
/**
|
|
28
42
|
* Adapt the raw better-auth instance to our internal {@link AuthSessionResolver}
|
|
29
43
|
* contract. better-auth's `getSession` has a union return (a bare session, or a
|
package/dist/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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","sourcesContent":["// src/auth.ts\nimport { betterAuth, type Auth } from 'better-auth'\nimport { drizzleAdapter } from 'better-auth/adapters/drizzle'\nimport { openAPI } from 'better-auth/plugins'\n\nimport type { AuthSessionResolver } from './access'\nimport type { BetterAuthConfig } from './config'\nimport type { AnyDb, Dialect } from './dialect'\nimport type { EmailFacade } from './email'\n\n/**\n * Returns better-auth's plain `Auth`, not the plugin-parameterised type its\n * builder infers: declaration emit would otherwise inline that whole inferred\n * options object into the published `.d.ts`, where it no longer satisfies\n * better-auth's own `BetterAuthOptions` constraint. Plugin-specific endpoints\n * are reached through runtime checks (see the OpenAPI schema lookup in\n * `index.ts`), so nothing depends on the wider type.\n */\nexport function createAuth(\n db: AnyDb,\n cfg: BetterAuthConfig,\n dialect: Dialect,\n userSchema?: Record<string, unknown>,\n): Auth {\n const hasOpenApi = cfg.plugins?.some((p: any) => p.id === 'open-api')\n const plugins = hasOpenApi ? cfg.plugins : [...(cfg.plugins || []), openAPI()]\n\n // Type-only narrowing: the value is unchanged, but the published signature\n // stays a type better-auth itself can name.\n return betterAuth({\n ...cfg,\n plugins,\n database: drizzleAdapter(db as Parameters<typeof drizzleAdapter>[0], {\n provider: dialect === 'pg' ? 'pg' : 'sqlite',\n ...(userSchema ? { schema: userSchema } : {}),\n }),\n }) as unknown as Auth\n}\n\n/**\n * Adapt the raw better-auth instance to our internal {@link AuthSessionResolver}\n * contract. better-auth's `getSession` has a union return (a bare session, or a\n * `{ headers, response }` wrapper when `returnHeaders` is set); we only ever\n * call the bare form, so we narrow on `'user' in result` and map to our shape.\n * Keeping this adapter here means internal modules never depend on better-auth's\n * evolving types.\n */\nexport function toAuthSessionResolver(\n auth: ReturnType<typeof createAuth>,\n): AuthSessionResolver {\n return {\n api: {\n async getSession({ headers }) {\n const result = await auth.api.getSession({ headers })\n if (result && 'user' in result && result.user) {\n const session = 'session' in result ? result.session : null\n const activeOrganizationId =\n session &&\n 'activeOrganizationId' in session &&\n typeof session.activeOrganizationId === 'string'\n ? session.activeOrganizationId\n : null\n const role =\n 'role' in result.user && typeof result.user.role === 'string'\n ? result.user.role\n : undefined\n return {\n user: {\n id: result.user.id,\n email: result.user.email,\n name: result.user.name,\n ...(role ? { role } : {}),\n },\n session: session ? { activeOrganizationId } : null,\n }\n }\n return null\n },\n },\n }\n}\n\n/**\n * Fill better-auth's email hooks from the bunderstack email facade. Only fills\n * gaps: user-supplied handlers always win, and nothing is injected when email\n * isn't configured. emailAndPassword is only touched when the user enabled it\n * (injecting it unasked would enable the feature).\n */\nexport function withEmailAuthDefaults(\n cfg: BetterAuthConfig,\n email: EmailFacade,\n emailConfigured: boolean,\n): BetterAuthConfig {\n if (!emailConfigured) return cfg\n const out: BetterAuthConfig = { ...cfg }\n\n if (\n cfg.emailAndPassword?.enabled &&\n !cfg.emailAndPassword.sendResetPassword\n ) {\n out.emailAndPassword = {\n ...cfg.emailAndPassword,\n sendResetPassword: async ({ user, url }) => {\n await email.send({\n to: user.email,\n subject: 'Reset your password',\n text: `Click the link to reset your password:\\n\\n${url}\\n\\nIf you didn't request this, you can ignore this email.`,\n })\n },\n }\n }\n\n if (!cfg.emailVerification?.sendVerificationEmail) {\n out.emailVerification = {\n ...cfg.emailVerification,\n sendVerificationEmail: async ({ user, url }) => {\n await email.send({\n to: user.email,\n subject: 'Verify your email',\n text: `Click the link to verify your email address:\\n\\n${url}`,\n })\n },\n }\n }\n\n return out\n}\n"]}
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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","sourcesContent":["// src/auth.ts\nimport { betterAuth, type Auth } from 'better-auth'\nimport { drizzleAdapter } from 'better-auth/adapters/drizzle'\nimport { openAPI } from 'better-auth/plugins'\n\nimport type { AuthSessionResolver } from './access'\nimport type { BetterAuthConfig } from './config'\nimport type { AnyDb, Dialect } from './dialect'\nimport type { EmailFacade } from './email'\n\n/**\n * Returns better-auth's plain `Auth`, not the plugin-parameterised type its\n * builder infers: declaration emit would otherwise inline that whole inferred\n * options object into the published `.d.ts`, where it no longer satisfies\n * better-auth's own `BetterAuthOptions` constraint. Plugin-specific endpoints\n * are reached through runtime checks (see the OpenAPI schema lookup in\n * `index.ts`), so nothing depends on the wider type.\n */\nexport function createAuth(\n db: AnyDb,\n cfg: BetterAuthConfig,\n dialect: Dialect,\n userSchema?: Record<string, unknown>,\n): Auth {\n const hasOpenApi = cfg.plugins?.some((p: any) => p.id === 'open-api')\n const plugins = hasOpenApi ? cfg.plugins : [...(cfg.plugins || []), openAPI()]\n\n // Type-only narrowing: the value is unchanged, but the published signature\n // stays a type better-auth itself can name.\n return betterAuth({\n ...cfg,\n plugins,\n database: drizzleAdapter(db as Parameters<typeof drizzleAdapter>[0], {\n provider: dialect === 'pg' ? 'pg' : 'sqlite',\n ...(userSchema ? { schema: userSchema } : {}),\n }),\n }) as unknown as Auth\n}\n\n/**\n * better-auth resolves its models out of the app's own schema, so an app that\n * declares none has no auth at all. Session resolution must then short-circuit\n * to null: the drizzle adapter throws on a missing model, and any session\n * cookie for the host — a browser keeps those per host, not per port, so one\n * minted by another local app arrives here too — would break every request.\n */\nexport function missingAuthModels(\n schema: Record<string, unknown>,\n cfg: BetterAuthConfig,\n): string[] {\n const models = [\n cfg.user?.modelName ?? 'user',\n cfg.session?.modelName ?? 'session',\n ]\n return models.filter((model) => !schema[model])\n}\n\n/**\n * Adapt the raw better-auth instance to our internal {@link AuthSessionResolver}\n * contract. better-auth's `getSession` has a union return (a bare session, or a\n * `{ headers, response }` wrapper when `returnHeaders` is set); we only ever\n * call the bare form, so we narrow on `'user' in result` and map to our shape.\n * Keeping this adapter here means internal modules never depend on better-auth's\n * evolving types.\n */\nexport function toAuthSessionResolver(\n auth: ReturnType<typeof createAuth>,\n): AuthSessionResolver {\n return {\n api: {\n async getSession({ headers }) {\n const result = await auth.api.getSession({ headers })\n if (result && 'user' in result && result.user) {\n const session = 'session' in result ? result.session : null\n const activeOrganizationId =\n session &&\n 'activeOrganizationId' in session &&\n typeof session.activeOrganizationId === 'string'\n ? session.activeOrganizationId\n : null\n const role =\n 'role' in result.user && typeof result.user.role === 'string'\n ? result.user.role\n : undefined\n return {\n user: {\n id: result.user.id,\n email: result.user.email,\n name: result.user.name,\n ...(role ? { role } : {}),\n },\n session: session ? { activeOrganizationId } : null,\n }\n }\n return null\n },\n },\n }\n}\n\n/**\n * Fill better-auth's email hooks from the bunderstack email facade. Only fills\n * gaps: user-supplied handlers always win, and nothing is injected when email\n * isn't configured. emailAndPassword is only touched when the user enabled it\n * (injecting it unasked would enable the feature).\n */\nexport function withEmailAuthDefaults(\n cfg: BetterAuthConfig,\n email: EmailFacade,\n emailConfigured: boolean,\n): BetterAuthConfig {\n if (!emailConfigured) return cfg\n const out: BetterAuthConfig = { ...cfg }\n\n if (\n cfg.emailAndPassword?.enabled &&\n !cfg.emailAndPassword.sendResetPassword\n ) {\n out.emailAndPassword = {\n ...cfg.emailAndPassword,\n sendResetPassword: async ({ user, url }) => {\n await email.send({\n to: user.email,\n subject: 'Reset your password',\n text: `Click the link to reset your password:\\n\\n${url}\\n\\nIf you didn't request this, you can ignore this email.`,\n })\n },\n }\n }\n\n if (!cfg.emailVerification?.sendVerificationEmail) {\n out.emailVerification = {\n ...cfg.emailVerification,\n sendVerificationEmail: async ({ user, url }) => {\n await email.send({\n to: user.email,\n subject: 'Verify your email',\n text: `Click the link to verify your email address:\\n\\n${url}`,\n })\n },\n }\n }\n\n return out\n}\n"]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { DatabaseAdapter } from './database/adapter.js';
|
|
2
|
+
import type { TickResult } from './jobs/index.js';
|
|
3
|
+
import type { RuntimeOverrides } from './runtime.js';
|
|
4
|
+
import type { StorageConfigInput } from './storage/buckets.js';
|
|
5
|
+
export declare const BACKEND_INTERNALS: unique symbol;
|
|
6
|
+
export type ResolvedDeclaration = {
|
|
7
|
+
readonly config: {
|
|
8
|
+
readonly database: {
|
|
9
|
+
readonly adapter: DatabaseAdapter;
|
|
10
|
+
};
|
|
11
|
+
readonly storage?: StorageConfigInput;
|
|
12
|
+
};
|
|
13
|
+
readonly jobsDefs: unknown;
|
|
14
|
+
};
|
|
15
|
+
export type RuntimeJobFailure = {
|
|
16
|
+
id: string;
|
|
17
|
+
name: string;
|
|
18
|
+
attempts: number;
|
|
19
|
+
lastError: string | null;
|
|
20
|
+
};
|
|
21
|
+
export type RuntimeTestJob = {
|
|
22
|
+
id: string;
|
|
23
|
+
name: string;
|
|
24
|
+
kind: 'job' | 'cron';
|
|
25
|
+
status: 'pending' | 'running' | 'succeeded' | 'failed';
|
|
26
|
+
attempts: number;
|
|
27
|
+
runAt: number;
|
|
28
|
+
dedupeKey: string | null;
|
|
29
|
+
lastError: string | null;
|
|
30
|
+
};
|
|
31
|
+
export type RuntimeTestingHandle = {
|
|
32
|
+
tick(now: number): Promise<TickResult>;
|
|
33
|
+
inspect(now: number): Promise<{
|
|
34
|
+
runnable: number;
|
|
35
|
+
failed: RuntimeJobFailure[];
|
|
36
|
+
jobs: RuntimeTestJob[];
|
|
37
|
+
}>;
|
|
38
|
+
};
|
|
39
|
+
export type BackendInternals<TApp> = {
|
|
40
|
+
readonly declaration: ResolvedDeclaration;
|
|
41
|
+
start(source: Record<string, string | undefined>, overrides?: RuntimeOverrides): Promise<TApp>;
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=backend-internals.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend-internals.d.ts","sourceRoot":"","sources":["../src/backend-internals.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AACxC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AACjD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAE3D,eAAO,MAAM,iBAAiB,EAAE,OAAO,MAEtC,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,CAAC,MAAM,EAAE;QACf,QAAQ,CAAC,QAAQ,EAAE;YAAE,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAA;SAAE,CAAA;QACxD,QAAQ,CAAC,OAAO,CAAC,EAAE,kBAAkB,CAAA;KACtC,CAAA;IACD,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;CAC3B,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,KAAK,GAAG,MAAM,CAAA;IACpB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAA;IACtD,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;IACtC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAC5B,QAAQ,EAAE,MAAM,CAAA;QAChB,MAAM,EAAE,iBAAiB,EAAE,CAAA;QAC3B,IAAI,EAAE,cAAc,EAAE,CAAA;KACvB,CAAC,CAAA;CACH,CAAA;AAED,MAAM,MAAM,gBAAgB,CAAC,IAAI,IAAI;IACnC,QAAQ,CAAC,WAAW,EAAE,mBAAmB,CAAA;IACzC,KAAK,CACH,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EAC1C,SAAS,CAAC,EAAE,gBAAgB,GAC3B,OAAO,CAAC,IAAI,CAAC,CAAA;CACjB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend-internals.js","sourceRoot":"","sources":["../src/backend-internals.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,iBAAiB,GAAkB,MAAM,CAAC,GAAG,CACxD,+BAA+B,CAChC,CAAA","sourcesContent":["import type { DatabaseAdapter } from './database/adapter'\nimport type { TickResult } from './jobs'\nimport type { RuntimeOverrides } from './runtime'\nimport type { StorageConfigInput } from './storage/buckets'\n\nexport const BACKEND_INTERNALS: unique symbol = Symbol.for(\n 'bunderstack.backend-internals',\n)\n\nexport type ResolvedDeclaration = {\n readonly config: {\n readonly database: { readonly adapter: DatabaseAdapter }\n readonly storage?: StorageConfigInput\n }\n readonly jobsDefs: unknown\n}\n\nexport type RuntimeJobFailure = {\n id: string\n name: string\n attempts: number\n lastError: string | null\n}\n\nexport type RuntimeTestJob = {\n id: string\n name: string\n kind: 'job' | 'cron'\n status: 'pending' | 'running' | 'succeeded' | 'failed'\n attempts: number\n runAt: number\n dedupeKey: string | null\n lastError: string | null\n}\n\nexport type RuntimeTestingHandle = {\n tick(now: number): Promise<TickResult>\n inspect(now: number): Promise<{\n runnable: number\n failed: RuntimeJobFailure[]\n jobs: RuntimeTestJob[]\n }>\n}\n\nexport type BackendInternals<TApp> = {\n readonly declaration: ResolvedDeclaration\n start(\n source: Record<string, string | undefined>,\n overrides?: RuntimeOverrides,\n ): Promise<TApp>\n}\n"]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { AnyRouter as AnyORPCRouter } from '@orpc/server';
|
|
2
|
+
import type { TableAccessInput } from './access.js';
|
|
3
|
+
import type { BunderstackConfig } from './config.js';
|
|
4
|
+
import type { EnvConfigInput, ValidatedEnv } from './env.js';
|
|
5
|
+
import type { BunderstackJobsBuilder, JobsDefs } from './jobs/index.js';
|
|
6
|
+
import type { BunderstackManifest } from './manifest.js';
|
|
7
|
+
import type { BunderstackApp, BucketNamesOf } from './runtime.js';
|
|
8
|
+
import type { StorageConfigInput } from './storage/buckets.js';
|
|
9
|
+
import type { TestMethod } from './testing/fixture.js';
|
|
10
|
+
import { BACKEND_INTERNALS, type BackendInternals } from './backend-internals.js';
|
|
11
|
+
export type StartOptions = {
|
|
12
|
+
env?: Record<string, string | undefined>;
|
|
13
|
+
};
|
|
14
|
+
export type BunderstackBackend<TApp> = {
|
|
15
|
+
readonly manifest: BunderstackManifest;
|
|
16
|
+
start(options?: StartOptions): Promise<TApp>;
|
|
17
|
+
test: TestMethod<TApp>;
|
|
18
|
+
readonly [BACKEND_INTERNALS]: BackendInternals<TApp>;
|
|
19
|
+
};
|
|
20
|
+
export type BunderstackDefinitionConfig<TSchema extends Record<string, unknown>, TAccess extends Record<string, TableAccessInput> | undefined = undefined, TStorage extends StorageConfigInput | undefined = undefined, TEnv extends EnvConfigInput | undefined = undefined, TJobsDefs extends JobsDefs | undefined = undefined, TCustomApiRouter extends AnyORPCRouter | undefined = undefined, TRealtime = undefined> = Omit<BunderstackConfig<TSchema, TAccess, TStorage, TEnv, TCustomApiRouter>, 'realtime'> & {
|
|
21
|
+
realtime?: TRealtime;
|
|
22
|
+
jobs?: TJobsDefs | ((builder: BunderstackJobsBuilder<TSchema, ValidatedEnv<TEnv>>) => TJobsDefs);
|
|
23
|
+
};
|
|
24
|
+
export declare function isBunderstackBackend(value: unknown): value is BunderstackBackend<unknown>;
|
|
25
|
+
export declare function bunderstack<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>(config: BunderstackDefinitionConfig<TSchema, TAccess, TStorage, TEnv, TJobsDefs, TCustomApiRouter, TRealtime>): BunderstackBackend<BunderstackApp<TSchema, TAccess, BucketNamesOf<TStorage>, TEnv, TJobsDefs, TCustomApiRouter, TRealtime>>;
|
|
26
|
+
//# sourceMappingURL=backend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"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"}
|
package/dist/backend.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { BACKEND_INTERNALS } from './backend-internals.js';
|
|
2
|
+
import { detectDialect } from './dialect.js';
|
|
3
|
+
import { emailProviderTag } from './email.js';
|
|
4
|
+
import { createJobsBuilder, validateJobsDefs } from './jobs/index.js';
|
|
5
|
+
import { buildManifest } from './manifest.js';
|
|
6
|
+
import { materializeBunderstack } from './runtime.js';
|
|
7
|
+
import { STORAGE_SWEEP_JOB_NAME, STORAGE_SWEEP_SCHEDULE, } from './storage/background.js';
|
|
8
|
+
import { resolveBuckets } from './storage/buckets.js';
|
|
9
|
+
export function isBunderstackBackend(value) {
|
|
10
|
+
return (typeof value === 'object' && value !== null && BACKEND_INTERNALS in value);
|
|
11
|
+
}
|
|
12
|
+
export function bunderstack(config) {
|
|
13
|
+
const dialect = detectDialect(config.schema);
|
|
14
|
+
const jobsDefs = config.jobs
|
|
15
|
+
? typeof config.jobs === 'function'
|
|
16
|
+
? config.jobs(createJobsBuilder())
|
|
17
|
+
: config.jobs
|
|
18
|
+
: undefined;
|
|
19
|
+
if (jobsDefs)
|
|
20
|
+
validateJobsDefs(jobsDefs);
|
|
21
|
+
const manifest = buildManifest({
|
|
22
|
+
schema: config.schema,
|
|
23
|
+
dialect,
|
|
24
|
+
migrationsDirectory: config.database.migrations ?? './migrations',
|
|
25
|
+
storage: resolveBuckets(config.storage, {}),
|
|
26
|
+
envConfig: config.env,
|
|
27
|
+
emailProvider: emailProviderTag(config.email),
|
|
28
|
+
realtime: Boolean(config.realtime),
|
|
29
|
+
jobs: config.storage
|
|
30
|
+
? {
|
|
31
|
+
...jobsDefs,
|
|
32
|
+
[STORAGE_SWEEP_JOB_NAME]: {
|
|
33
|
+
kind: 'cron',
|
|
34
|
+
schedule: STORAGE_SWEEP_SCHEDULE,
|
|
35
|
+
handler: () => { },
|
|
36
|
+
},
|
|
37
|
+
}
|
|
38
|
+
: jobsDefs,
|
|
39
|
+
});
|
|
40
|
+
const start = (source, overrides = {}) => materializeBunderstack({ ...config, jobs: jobsDefs }, source, overrides);
|
|
41
|
+
let backend;
|
|
42
|
+
const test = (async (options) => {
|
|
43
|
+
const testing = await import('./testing.js');
|
|
44
|
+
return testing.createTestApp(backend, options);
|
|
45
|
+
});
|
|
46
|
+
test.configure = (options) => (async (overrides = {}) => {
|
|
47
|
+
const testing = await import('./testing.js');
|
|
48
|
+
return testing.configureTestApp(backend, options)(overrides);
|
|
49
|
+
});
|
|
50
|
+
backend = {
|
|
51
|
+
manifest,
|
|
52
|
+
start: ({ env } = {}) => start(env ?? process.env),
|
|
53
|
+
test,
|
|
54
|
+
[BACKEND_INTERNALS]: { declaration: { config, jobsDefs }, start },
|
|
55
|
+
};
|
|
56
|
+
return backend;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=backend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend.js","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,iBAAiB,EAAyB,MAAM,qBAAqB,CAAA;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAC1C,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAA;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAC1C,OAAO,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAA;AAClD,OAAO,EACL,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAiClD,MAAM,UAAU,oBAAoB,CAClC,KAAc;IAEd,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,iBAAiB,IAAI,KAAK,CAC1E,CAAA;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAgBzB,MAQC;IAYD,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IAC5C,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI;QAC1B,CAAC,CAAC,OAAO,MAAM,CAAC,IAAI,KAAK,UAAU;YACjC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,iBAAiB,EAA+B,CAAC;YAC/D,CAAC,CAAC,MAAM,CAAC,IAAI;QACf,CAAC,CAAC,SAAS,CAAA;IACb,IAAI,QAAQ;QAAE,gBAAgB,CAAC,QAAQ,CAAC,CAAA;IAExC,MAAM,QAAQ,GAAG,aAAa,CAAC;QAC7B,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,OAAO;QACP,mBAAmB,EAAE,MAAM,CAAC,QAAQ,CAAC,UAAU,IAAI,cAAc;QACjE,OAAO,EAAE,cAAc,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC;QAC3C,SAAS,EAAE,MAAM,CAAC,GAAG;QACrB,aAAa,EAAE,gBAAgB,CAAC,MAAM,CAAC,KAAK,CAAC;QAC7C,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC;QAClC,IAAI,EAAE,MAAM,CAAC,OAAO;YAClB,CAAC,CAAC;gBACE,GAAG,QAAQ;gBACX,CAAC,sBAAsB,CAAC,EAAE;oBACxB,IAAI,EAAE,MAAM;oBACZ,QAAQ,EAAE,sBAAsB;oBAChC,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC;iBAClB;aACF;YACH,CAAC,CAAC,QAAQ;KACb,CAAC,CAAA;IAYF,MAAM,KAAK,GAAG,CACZ,MAA0C,EAC1C,YAA8B,EAAE,EAClB,EAAE,CAChB,sBAAsB,CACpB,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAW,EACtC,MAAM,EACN,SAAS,CACM,CAAA;IAEnB,IAAI,OAAgC,CAAA;IACpC,MAAM,IAAI,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;QAC9B,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAA;QACzC,OAAO,OAAO,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IAChD,CAAC,CAAoB,CAAA;IACrB,IAAI,CAAC,SAAS,GAAG,CAAC,OAAO,EAAE,EAAE,CAC3B,CAAC,KAAK,EAAE,YAAyB,EAAE,EAAE,EAAE;QACrC,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAA;QACzC,OAAO,OAAO,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC,CAAA;IAC9D,CAAC,CAAU,CAAA;IACb,OAAO,GAAG;QACR,QAAQ;QACR,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,CACtB,KAAK,CAAC,GAAG,IAAK,OAAO,CAAC,GAA0C,CAAC;QACnE,IAAI;QACJ,CAAC,iBAAiB,CAAC,EAAE,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE;KAClE,CAAA;IACD,OAAO,OAAO,CAAA;AAChB,CAAC","sourcesContent":["import type { AnyRouter as AnyORPCRouter } from '@orpc/server'\n\nimport type { TableAccessInput } from './access'\nimport type { BunderstackConfig } from './config'\nimport type { EnvConfigInput, ValidatedEnv } from './env'\nimport type { BunderstackJobsBuilder, JobsDefs } from './jobs'\nimport type { BunderstackManifest } from './manifest'\nimport type { BunderstackApp, BucketNamesOf, RuntimeOverrides } from './runtime'\nimport type { StorageConfigInput } from './storage/buckets'\nimport type { TestMethod, TestOptions } from './testing/fixture'\n\nimport { BACKEND_INTERNALS, type BackendInternals } from './backend-internals'\nimport { detectDialect } from './dialect'\nimport { emailProviderTag } from './email'\nimport { createJobsBuilder, validateJobsDefs } from './jobs'\nimport { buildManifest } from './manifest'\nimport { materializeBunderstack } from './runtime'\nimport {\n STORAGE_SWEEP_JOB_NAME,\n STORAGE_SWEEP_SCHEDULE,\n} from './storage/background'\nimport { resolveBuckets } from './storage/buckets'\n\nexport type StartOptions = {\n env?: Record<string, string | undefined>\n}\n\nexport type BunderstackBackend<TApp> = {\n readonly manifest: BunderstackManifest\n start(options?: StartOptions): Promise<TApp>\n test: TestMethod<TApp>\n readonly [BACKEND_INTERNALS]: BackendInternals<TApp>\n}\n\nexport type BunderstackDefinitionConfig<\n TSchema extends Record<string, unknown>,\n TAccess extends Record<string, TableAccessInput> | undefined = undefined,\n TStorage extends StorageConfigInput | undefined = undefined,\n TEnv extends EnvConfigInput | undefined = undefined,\n TJobsDefs extends JobsDefs | undefined = undefined,\n TCustomApiRouter extends AnyORPCRouter | undefined = undefined,\n TRealtime = undefined,\n> = Omit<\n BunderstackConfig<TSchema, TAccess, TStorage, TEnv, TCustomApiRouter>,\n 'realtime'\n> & {\n realtime?: TRealtime\n jobs?:\n | TJobsDefs\n | ((\n builder: BunderstackJobsBuilder<TSchema, ValidatedEnv<TEnv>>,\n ) => TJobsDefs)\n}\n\nexport function isBunderstackBackend(\n value: unknown,\n): value is BunderstackBackend<unknown> {\n return (\n typeof value === 'object' && value !== null && BACKEND_INTERNALS in value\n )\n}\n\nexport function bunderstack<\n TSchema extends Record<string, unknown>,\n const TAccess extends Record<string, TableAccessInput> | undefined =\n undefined,\n const TStorage extends StorageConfigInput | undefined = undefined,\n const TEnv extends EnvConfigInput | undefined = undefined,\n const TJobsDefs extends JobsDefs | undefined = undefined,\n TCustomApiRouter extends AnyORPCRouter | undefined = undefined,\n const TRealtime extends BunderstackConfig<\n TSchema,\n TAccess,\n TStorage,\n TEnv,\n TCustomApiRouter\n >['realtime'] = undefined,\n>(\n config: BunderstackDefinitionConfig<\n TSchema,\n TAccess,\n TStorage,\n TEnv,\n TJobsDefs,\n TCustomApiRouter,\n TRealtime\n >,\n): BunderstackBackend<\n BunderstackApp<\n TSchema,\n TAccess,\n BucketNamesOf<TStorage>,\n TEnv,\n TJobsDefs,\n TCustomApiRouter,\n TRealtime\n >\n> {\n const dialect = detectDialect(config.schema)\n const jobsDefs = config.jobs\n ? typeof config.jobs === 'function'\n ? config.jobs(createJobsBuilder<TSchema, ValidatedEnv<TEnv>>())\n : config.jobs\n : undefined\n if (jobsDefs) validateJobsDefs(jobsDefs)\n\n const manifest = buildManifest({\n schema: config.schema,\n dialect,\n migrationsDirectory: config.database.migrations ?? './migrations',\n storage: resolveBuckets(config.storage, {}),\n envConfig: config.env,\n emailProvider: emailProviderTag(config.email),\n realtime: Boolean(config.realtime),\n jobs: config.storage\n ? {\n ...jobsDefs,\n [STORAGE_SWEEP_JOB_NAME]: {\n kind: 'cron',\n schedule: STORAGE_SWEEP_SCHEDULE,\n handler: () => {},\n },\n }\n : jobsDefs,\n })\n\n type App = BunderstackApp<\n TSchema,\n TAccess,\n BucketNamesOf<TStorage>,\n TEnv,\n TJobsDefs,\n TCustomApiRouter,\n TRealtime\n >\n\n const start = (\n source: Record<string, string | undefined>,\n overrides: RuntimeOverrides = {},\n ): Promise<App> =>\n materializeBunderstack(\n { ...config, jobs: jobsDefs } as never,\n source,\n overrides,\n ) as Promise<App>\n\n let backend: BunderstackBackend<App>\n const test = (async (options) => {\n const testing = await import('./testing')\n return testing.createTestApp(backend, options)\n }) as TestMethod<App>\n test.configure = (options) =>\n (async (overrides: TestOptions = {}) => {\n const testing = await import('./testing')\n return testing.configureTestApp(backend, options)(overrides)\n }) as never\n backend = {\n manifest,\n start: ({ env } = {}) =>\n start(env ?? (process.env as Record<string, string | undefined>)),\n test,\n [BACKEND_INTERNALS]: { declaration: { config, jobsDefs }, start },\n }\n return backend\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blueprint-generator.d.ts","sourceRoot":"","sources":["../src/blueprint-generator.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"blueprint-generator.d.ts","sourceRoot":"","sources":["../src/blueprint-generator.ts"],"names":[],"mappings":"AAYA,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,aAAa,CAAA;AAGpB,MAAM,MAAM,wBAAwB,GAAG;IACrC,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG;IACpC,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,oBAAoB,CAAA;IAC/B,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,qBAAa,mBAAoB,SAAQ,KAAK;;CAO7C;AAqED,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,uBAAuB,CAAC,CAuFlC"}
|