bunderstack 0.24.0 → 0.24.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 +11 -0
- package/README.md +1 -0
- package/dist/auth.d.ts +20 -9
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +3 -8
- package/dist/auth.js.map +1 -1
- package/dist/backend.d.ts +4 -4
- package/dist/backend.d.ts.map +1 -1
- package/dist/backend.js.map +1 -1
- package/dist/config.d.ts +10 -6
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- 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-runtime.d.ts +7 -0
- package/dist/provision-runtime.d.ts.map +1 -0
- package/dist/provision-runtime.js +50 -0
- package/dist/provision-runtime.js.map +1 -0
- package/dist/provision-schema.d.ts +16 -0
- package/dist/provision-schema.d.ts.map +1 -0
- package/dist/provision-schema.js +63 -0
- package/dist/provision-schema.js.map +1 -0
- package/dist/provision.d.ts +4 -21
- package/dist/provision.d.ts.map +1 -1
- package/dist/provision.js +10 -111
- package/dist/provision.js.map +1 -1
- package/dist/runtime.d.ts +9 -7
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +1 -2
- package/dist/runtime.js.map +1 -1
- package/dist/testing/fixture.d.ts +1 -1
- package/dist/testing/fixture.d.ts.map +1 -1
- package/dist/testing/fixture.js +1 -1
- package/dist/testing/fixture.js.map +1 -1
- package/llms-full.txt +416 -226
- package/llms.txt +4 -3
- package/package.json +5 -1
- package/skills/creating-bunderstack-apps/references/verification.md +7 -6
- package/skills/migrating-to-bunderstack/SKILL.md +22 -20
- package/skills/migrating-to-bunderstack/references/runtime-replacements.md +4 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `bunderstack` will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.24.1] — 2026-09-14
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Preserve the exact Better Auth configuration through `defineAuth()`,
|
|
10
|
+
`bunderstack()`, and `BunderstackApp`, so plugin APIs and session fields
|
|
11
|
+
remain available on `app.auth`.
|
|
12
|
+
- Keep `drizzle-kit` out of the production `bunderstack/provision` bundle.
|
|
13
|
+
Production provisioning now requires committed migrations; development
|
|
14
|
+
schema push lives in `bunderstack/provision-schema`.
|
|
15
|
+
|
|
5
16
|
## [0.24.0] - 2026-09-05
|
|
6
17
|
|
|
7
18
|
### Changed
|
package/README.md
CHANGED
|
@@ -51,6 +51,7 @@ replay. Deployment metadata is generated with `bunx bunderstack blueprint`.
|
|
|
51
51
|
- `bunderstack/testing` — Isolated lexical fixtures and reusable test factories
|
|
52
52
|
(`backend.test()` / `backend.test.configure()`)
|
|
53
53
|
- `bunderstack/provision` — Explicit production schema provisioning
|
|
54
|
+
- `bunderstack/provision-schema` — Development-only schema push via Drizzle Kit
|
|
54
55
|
- `bunderstack/client` — Framework-neutral RPC & LiveView client (`createClient`, `createLiveView`)
|
|
55
56
|
- `bunderstack/client-rest` — Type-safe REST client
|
|
56
57
|
- `bunderstack/client-react`, `bunderstack/client-solid`, `bunderstack/client-vue`, `bunderstack/client-svelte` — LiveView UI bindings
|
package/dist/auth.d.ts
CHANGED
|
@@ -1,17 +1,27 @@
|
|
|
1
|
-
import { type Auth } from 'better-auth';
|
|
1
|
+
import { type Auth, type BetterAuthPlugin } from 'better-auth';
|
|
2
|
+
import { openAPI } from 'better-auth/plugins';
|
|
2
3
|
import type { AuthSessionResolver } from './access.js';
|
|
3
4
|
import type { BetterAuthConfig } from './config.js';
|
|
4
5
|
import type { AnyDb, Dialect } from './dialect.js';
|
|
5
6
|
import type { EmailFacade } from './email.js';
|
|
7
|
+
type ConfiguredAuthPlugins<TConfig extends BetterAuthConfig> = TConfig extends {
|
|
8
|
+
plugins: infer TPlugins extends readonly BetterAuthPlugin[];
|
|
9
|
+
} ? TPlugins : [];
|
|
10
|
+
type WithBunderstackAuthDefaults<TConfig extends BetterAuthConfig> = Omit<BetterAuthConfig, 'plugins'> & Omit<TConfig, 'plugins'> & {
|
|
11
|
+
plugins: [...ConfiguredAuthPlugins<TConfig>, ReturnType<typeof openAPI>];
|
|
12
|
+
};
|
|
6
13
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* better-auth's own `BetterAuthOptions` constraint. Plugin-specific endpoints
|
|
11
|
-
* are reached through runtime checks (see the OpenAPI schema lookup in
|
|
12
|
-
* `index.ts`), so nothing depends on the wider type.
|
|
14
|
+
* The public Better Auth instance retains every endpoint and model field from
|
|
15
|
+
* the declared config. Bunderstack always installs OpenAPI at runtime, so its
|
|
16
|
+
* endpoints are part of the public type even when the app omitted the plugin.
|
|
13
17
|
*/
|
|
14
|
-
export
|
|
18
|
+
export type BunderstackAuth<TConfig extends BetterAuthConfig = BetterAuthConfig> = Auth<WithBunderstackAuthDefaults<TConfig>> & Auth;
|
|
19
|
+
/**
|
|
20
|
+
* Build Better Auth while exposing its named plugin-aware public type. The
|
|
21
|
+
* implementation accepts the resolved runtime config, while `TConfig` carries
|
|
22
|
+
* the declaration that produced it; their relationship is asserted once here.
|
|
23
|
+
*/
|
|
24
|
+
export declare function createAuth<TConfig extends BetterAuthConfig = BetterAuthConfig>(db: AnyDb, cfg: BetterAuthConfig, dialect: Dialect, userSchema?: Record<string, unknown>): BunderstackAuth<TConfig>;
|
|
15
25
|
/**
|
|
16
26
|
* better-auth resolves its models out of the app's own schema, so an app that
|
|
17
27
|
* declares none has no auth at all. Session resolution must then short-circuit
|
|
@@ -28,7 +38,7 @@ export declare function missingAuthModels(schema: Record<string, unknown>, cfg:
|
|
|
28
38
|
* Keeping this adapter here means internal modules never depend on better-auth's
|
|
29
39
|
* evolving types.
|
|
30
40
|
*/
|
|
31
|
-
export declare function toAuthSessionResolver(auth:
|
|
41
|
+
export declare function toAuthSessionResolver(auth: Auth): AuthSessionResolver;
|
|
32
42
|
/**
|
|
33
43
|
* Fill better-auth's email hooks from the bunderstack email facade. Only fills
|
|
34
44
|
* gaps: user-supplied handlers always win, and nothing is injected when email
|
|
@@ -36,4 +46,5 @@ export declare function toAuthSessionResolver(auth: ReturnType<typeof createAuth
|
|
|
36
46
|
* (injecting it unasked would enable the feature).
|
|
37
47
|
*/
|
|
38
48
|
export declare function withEmailAuthDefaults(cfg: BetterAuthConfig, email: EmailFacade, emailConfigured: boolean): BetterAuthConfig;
|
|
49
|
+
export {};
|
|
39
50
|
//# sourceMappingURL=auth.d.ts.map
|
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;
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AACA,OAAO,EAAc,KAAK,IAAI,EAAE,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAE1E,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAE7C,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,KAAK,qBAAqB,CAAC,OAAO,SAAS,gBAAgB,IAAI,OAAO,SAAS;IAC7E,OAAO,EAAE,MAAM,QAAQ,SAAS,SAAS,gBAAgB,EAAE,CAAA;CAC5D,GACG,QAAQ,GACR,EAAE,CAAA;AAEN,KAAK,2BAA2B,CAAC,OAAO,SAAS,gBAAgB,IAAI,IAAI,CACvE,gBAAgB,EAChB,SAAS,CACV,GACC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,GAAG;IACzB,OAAO,EAAE,CAAC,GAAG,qBAAqB,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,OAAO,CAAC,CAAC,CAAA;CACzE,CAAA;AAEH;;;;GAIG;AACH,MAAM,MAAM,eAAe,CACzB,OAAO,SAAS,gBAAgB,GAAG,gBAAgB,IACjD,IAAI,CAAC,2BAA2B,CAAC,OAAO,CAAC,CAAC,GAAG,IAAI,CAAA;AAErD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,OAAO,SAAS,gBAAgB,GAAG,gBAAgB,EAC5E,EAAE,EAAE,KAAK,EACT,GAAG,EAAE,gBAAgB,EACrB,OAAO,EAAE,OAAO,EAChB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,eAAe,CAAC,OAAO,CAAC,CAY1B;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,CAAC,IAAI,EAAE,IAAI,GAAG,mBAAmB,CA+BrE;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
|
@@ -3,18 +3,13 @@ import { betterAuth } from 'better-auth';
|
|
|
3
3
|
import { drizzleAdapter } from 'better-auth/adapters/drizzle';
|
|
4
4
|
import { openAPI } from 'better-auth/plugins';
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* better-auth's own `BetterAuthOptions` constraint. Plugin-specific endpoints
|
|
10
|
-
* are reached through runtime checks (see the OpenAPI schema lookup in
|
|
11
|
-
* `index.ts`), so nothing depends on the wider type.
|
|
6
|
+
* Build Better Auth while exposing its named plugin-aware public type. The
|
|
7
|
+
* implementation accepts the resolved runtime config, while `TConfig` carries
|
|
8
|
+
* the declaration that produced it; their relationship is asserted once here.
|
|
12
9
|
*/
|
|
13
10
|
export function createAuth(db, cfg, dialect, userSchema) {
|
|
14
11
|
const hasOpenApi = cfg.plugins?.some((p) => p.id === 'open-api');
|
|
15
12
|
const plugins = hasOpenApi ? cfg.plugins : [...(cfg.plugins || []), openAPI()];
|
|
16
|
-
// Type-only narrowing: the value is unchanged, but the published signature
|
|
17
|
-
// stays a type better-auth itself can name.
|
|
18
13
|
return betterAuth({
|
|
19
14
|
...cfg,
|
|
20
15
|
plugins,
|
package/dist/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,cAAc;AACd,OAAO,EAAE,UAAU,
|
|
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, type BetterAuthPlugin } 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\ntype ConfiguredAuthPlugins<TConfig extends BetterAuthConfig> = TConfig extends {\n plugins: infer TPlugins extends readonly BetterAuthPlugin[]\n}\n ? TPlugins\n : []\n\ntype WithBunderstackAuthDefaults<TConfig extends BetterAuthConfig> = Omit<\n BetterAuthConfig,\n 'plugins'\n> &\n Omit<TConfig, 'plugins'> & {\n plugins: [...ConfiguredAuthPlugins<TConfig>, ReturnType<typeof openAPI>]\n }\n\n/**\n * The public Better Auth instance retains every endpoint and model field from\n * the declared config. Bunderstack always installs OpenAPI at runtime, so its\n * endpoints are part of the public type even when the app omitted the plugin.\n */\nexport type BunderstackAuth<\n TConfig extends BetterAuthConfig = BetterAuthConfig,\n> = Auth<WithBunderstackAuthDefaults<TConfig>> & Auth\n\n/**\n * Build Better Auth while exposing its named plugin-aware public type. The\n * implementation accepts the resolved runtime config, while `TConfig` carries\n * the declaration that produced it; their relationship is asserted once here.\n */\nexport function createAuth<TConfig extends BetterAuthConfig = BetterAuthConfig>(\n db: AnyDb,\n cfg: BetterAuthConfig,\n dialect: Dialect,\n userSchema?: Record<string, unknown>,\n): BunderstackAuth<TConfig> {\n const hasOpenApi = cfg.plugins?.some((p: any) => p.id === 'open-api')\n const plugins = hasOpenApi ? cfg.plugins : [...(cfg.plugins || []), openAPI()]\n\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 BunderstackAuth<TConfig>\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(auth: Auth): 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"]}
|
package/dist/backend.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AnyRouter as AnyORPCRouter } from '@orpc/server';
|
|
2
2
|
import type { TableAccessInput } from './access.js';
|
|
3
|
-
import type { BunderstackConfig, RealtimeConfigInput } from './config.js';
|
|
3
|
+
import type { BetterAuthConfig, BunderstackConfig, RealtimeConfigInput } from './config.js';
|
|
4
4
|
import type { EnvConfigInput, ValidatedEnv } from './env.js';
|
|
5
5
|
import type { BunderstackJobsBuilder, JobsDefs } from './jobs/index.js';
|
|
6
6
|
import type { BunderstackManifest } from './manifest.js';
|
|
@@ -18,7 +18,7 @@ export type BunderstackBackend<TApp> = {
|
|
|
18
18
|
test: TestMethod<TApp>;
|
|
19
19
|
readonly [BACKEND_INTERNALS]: BackendInternals<TApp>;
|
|
20
20
|
};
|
|
21
|
-
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, TMessaging extends MessagingConfig | undefined = undefined> = Omit<BunderstackConfig<TSchema, TAccess, TStorage, TEnv, TCustomApiRouter>, 'realtime' | 'messaging' | 'api'> & {
|
|
21
|
+
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, TMessaging extends MessagingConfig | undefined = undefined, TAuthConfig extends BetterAuthConfig = BetterAuthConfig> = Omit<BunderstackConfig<TSchema, TAccess, TStorage, TEnv, TCustomApiRouter, TAuthConfig>, 'realtime' | 'messaging' | 'api'> & {
|
|
22
22
|
/**
|
|
23
23
|
* An inline `api` or `jobs` builder receives the open `MessagingConfig`, not
|
|
24
24
|
* `TMessaging`. Naming `TMessaging` in a callback parameter makes TypeScript
|
|
@@ -48,7 +48,7 @@ export type DatabaseSlot = BunderstackConfig<Record<string, unknown>, undefined,
|
|
|
48
48
|
* plain data; the slots that hold credentials also accept a function of the
|
|
49
49
|
* validated environment.
|
|
50
50
|
*/
|
|
51
|
-
export type BunderstackDeclaration<TSchema extends Record<string, unknown>, TEnv extends EnvConfigInput | undefined = undefined, TAccess extends Record<string, TableAccessInput> | undefined = undefined, TStorage extends StorageConfigInput | undefined = undefined, TJobsDefs extends JobsDefs | undefined = undefined, TCustomApiRouter extends AnyORPCRouter | undefined = undefined, TRealtime = undefined, TMessaging extends MessagingConfig | undefined = undefined> = Omit<BunderstackDefinitionConfig<TSchema, TAccess, TStorage, TEnv, TJobsDefs, TCustomApiRouter, TRealtime, TMessaging>, 'database' | 'storage' | 'messaging' | 'realtime'> & {
|
|
51
|
+
export type BunderstackDeclaration<TSchema extends Record<string, unknown>, TEnv extends EnvConfigInput | undefined = undefined, TAccess extends Record<string, TableAccessInput> | undefined = undefined, TStorage extends StorageConfigInput | undefined = undefined, TJobsDefs extends JobsDefs | undefined = undefined, TCustomApiRouter extends AnyORPCRouter | undefined = undefined, TRealtime = undefined, TMessaging extends MessagingConfig | undefined = undefined, TAuthConfig extends BetterAuthConfig = BetterAuthConfig> = Omit<BunderstackDefinitionConfig<TSchema, TAccess, TStorage, TEnv, TJobsDefs, TCustomApiRouter, TRealtime, TMessaging, TAuthConfig>, 'database' | 'storage' | 'messaging' | 'realtime'> & {
|
|
52
52
|
/** Declared environment. Its names reach the blueprint; its values never do. */
|
|
53
53
|
env?: TEnv;
|
|
54
54
|
database: EnvAware<TEnv, DatabaseSlot>;
|
|
@@ -56,5 +56,5 @@ export type BunderstackDeclaration<TSchema extends Record<string, unknown>, TEnv
|
|
|
56
56
|
messaging?: EnvAware<TEnv, TMessaging>;
|
|
57
57
|
realtime?: EnvAware<TEnv, TRealtime>;
|
|
58
58
|
};
|
|
59
|
-
export declare function bunderstack<TSchema extends Record<string, unknown>, const TEnv extends EnvConfigInput | undefined = undefined, const TAccess extends Record<string, TableAccessInput> | undefined = undefined, const TStorage extends StorageConfigInput | undefined = undefined, const TJobsDefs extends JobsDefs | undefined = undefined, TCustomApiRouter extends AnyORPCRouter | undefined = undefined, const TRealtime extends RealtimeConfigInput | undefined = undefined, const TMessaging extends MessagingConfig | undefined = undefined>(declaration: BunderstackDeclaration<TSchema, TEnv, TAccess, TStorage, TJobsDefs, TCustomApiRouter, TRealtime, TMessaging>): BunderstackBackend<BunderstackApp<TSchema, TAccess, BucketNamesOf<TStorage>, TEnv, TJobsDefs, TCustomApiRouter, TRealtime, TMessaging>>;
|
|
59
|
+
export declare function bunderstack<TSchema extends Record<string, unknown>, const TEnv extends EnvConfigInput | undefined = undefined, const TAccess extends Record<string, TableAccessInput> | undefined = undefined, const TStorage extends StorageConfigInput | undefined = undefined, const TJobsDefs extends JobsDefs | undefined = undefined, TCustomApiRouter extends AnyORPCRouter | undefined = undefined, const TRealtime extends RealtimeConfigInput | undefined = undefined, const TMessaging extends MessagingConfig | undefined = undefined, const TAuthConfig extends BetterAuthConfig = BetterAuthConfig>(declaration: BunderstackDeclaration<TSchema, TEnv, TAccess, TStorage, TJobsDefs, TCustomApiRouter, TRealtime, TMessaging, TAuthConfig>): BunderstackBackend<BunderstackApp<TSchema, TAccess, BucketNamesOf<TStorage>, TEnv, TJobsDefs, TCustomApiRouter, TRealtime, TMessaging, TAuthConfig>>;
|
|
60
60
|
//# sourceMappingURL=backend.d.ts.map
|
package/dist/backend.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,cAAc,CAAA;AAE9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAChD,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"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"}
|
package/dist/backend.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backend.js","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AnyRouter as AnyORPCRouter } from '@orpc/server'\n\nimport type { TableAccessInput } from './access'\nimport type { BunderstackConfig, RealtimeConfigInput } from './config'\nimport type { EnvConfigInput, ValidatedEnv } from './env'\nimport type { BunderstackJobsBuilder, JobsDefs } from './jobs'\nimport type { BunderstackManifest } from './manifest'\nimport type { MessagingConfig } from './messaging'\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 { validateEnv } from './env'\nimport { assertHostedBlueprintFile } from './hosted-contract'\nimport { inspectConfig, type InspectedDefinition } from './inspect'\nimport { materializeBunderstack } from './runtime'\n\nexport type StartOptions = {\n env?: Record<string, string | undefined>\n}\n\nexport type BunderstackBackend<TApp> = {\n inspect(options?: StartOptions): 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 TMessaging extends MessagingConfig | undefined = undefined,\n> = Omit<\n BunderstackConfig<TSchema, TAccess, TStorage, TEnv, TCustomApiRouter>,\n 'realtime' | 'messaging' | 'api'\n> & {\n /**\n * An inline `api` or `jobs` builder receives the open `MessagingConfig`, not\n * `TMessaging`. Naming `TMessaging` in a callback parameter makes TypeScript\n * fix it before it reads the sibling `messaging` property, and the whole\n * declaration then loses its inferred channels. Declare the builder in its\n * own module with an annotated parameter to type `ctx.messaging` exactly —\n * `defineApi({ schema, env, messaging })` and `BunderstackJobsBuilder` both\n * take the channel record.\n */\n realtime?: TRealtime\n messaging?: TMessaging\n api?:\n | TCustomApiRouter\n | ((\n builder: import('./api/builder').BunderstackApiBuilder<\n TSchema,\n ValidatedEnv<TEnv>,\n MessagingConfig\n >,\n ) => TCustomApiRouter)\n jobs?:\n | TJobsDefs\n | ((\n builder: BunderstackJobsBuilder<\n TSchema,\n ValidatedEnv<TEnv>,\n MessagingConfig\n >,\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\n/**\n * A configuration slot that may read validated environment values. The shape a\n * slot produces reaches the manifest, so a callback belongs here to supply a\n * key, a URL, or a sender — never to change which channels, buckets, or tables\n * exist. Blueprint generation resolves the declaration against two accepted\n * environments and rejects a shape that differs between them.\n */\nexport type EnvAware<TEnv extends EnvConfigInput | undefined, T> =\n | T\n | ((env: ValidatedEnv<NoInfer<TEnv>>) => T)\n\nexport type DatabaseSlot = BunderstackConfig<\n Record<string, unknown>,\n undefined,\n undefined,\n undefined,\n undefined\n>['database']\n\n/**\n * The whole application in one object. `schema`, `access`, and the routers are\n * plain data; the slots that hold credentials also accept a function of the\n * validated environment.\n */\nexport type BunderstackDeclaration<\n TSchema extends Record<string, unknown>,\n TEnv extends EnvConfigInput | undefined = undefined,\n TAccess extends Record<string, TableAccessInput> | undefined = undefined,\n TStorage extends StorageConfigInput | undefined = undefined,\n TJobsDefs extends JobsDefs | undefined = undefined,\n TCustomApiRouter extends AnyORPCRouter | undefined = undefined,\n TRealtime = undefined,\n TMessaging extends MessagingConfig | undefined = undefined,\n> = Omit<\n BunderstackDefinitionConfig<\n TSchema,\n TAccess,\n TStorage,\n TEnv,\n TJobsDefs,\n TCustomApiRouter,\n TRealtime,\n TMessaging\n >,\n 'database' | 'storage' | 'messaging' | 'realtime'\n> & {\n /** Declared environment. Its names reach the blueprint; its values never do. */\n env?: TEnv\n database: EnvAware<TEnv, DatabaseSlot>\n storage?: EnvAware<TEnv, TStorage>\n messaging?: EnvAware<TEnv, TMessaging>\n realtime?: EnvAware<TEnv, TRealtime>\n}\n\nexport function bunderstack<\n TSchema extends Record<string, unknown>,\n const TEnv extends EnvConfigInput | undefined = undefined,\n const TAccess extends Record<string, TableAccessInput> | undefined =\n undefined,\n const TStorage extends StorageConfigInput | undefined = undefined,\n const TJobsDefs extends JobsDefs | undefined = undefined,\n TCustomApiRouter extends AnyORPCRouter | undefined = undefined,\n const TRealtime extends RealtimeConfigInput | undefined = undefined,\n const TMessaging extends MessagingConfig | undefined = undefined,\n>(\n declaration: BunderstackDeclaration<\n TSchema,\n TEnv,\n TAccess,\n TStorage,\n TJobsDefs,\n TCustomApiRouter,\n TRealtime,\n TMessaging\n >,\n): BunderstackBackend<\n BunderstackApp<\n TSchema,\n TAccess,\n BucketNamesOf<TStorage>,\n TEnv,\n TJobsDefs,\n TCustomApiRouter,\n TRealtime,\n TMessaging\n >\n>\nexport function bunderstack(\n declaration: BunderstackDeclaration<Record<string, unknown>, any>,\n): BunderstackBackend<any> {\n const { env: envSchema, ...slots } = declaration as Record<\n string,\n unknown\n > & {\n env?: EnvConfigInput\n }\n const inspect = (source: Record<string, string | undefined>) => {\n const env = validateEnv(envSchema, { source })\n const resolve = (value: unknown) =>\n typeof value === 'function'\n ? (value as (given: typeof env) => unknown)(env)\n : value\n const config = {\n ...slots,\n database: resolve(slots.database),\n storage: resolve(slots.storage),\n messaging: resolve(slots.messaging),\n realtime: resolve(slots.realtime),\n }\n return inspectConfig(config as never, envSchema, env)\n }\n\n type App = BunderstackApp<any, any, any, any, any, any, any, any>\n\n const start = async (\n source: Record<string, string | undefined>,\n overrides: RuntimeOverrides = {},\n inspected: InspectedDefinition = inspect(source),\n ): Promise<App> => {\n if (source.BUNDERSTACK_BLUEPRINT_PATH) {\n await assertHostedBlueprintFile(\n inspected.manifest,\n source.BUNDERSTACK_BLUEPRINT_PATH,\n )\n }\n return materializeBunderstack(\n {\n ...inspected.config,\n jobs: inspected.jobsDefs,\n api: inspected.customApiRouter,\n } as never,\n source,\n overrides,\n inspected.env,\n ) as Promise<App>\n }\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 inspect: ({ env } = {}) =>\n inspect(env ?? (process.env as Record<string, string | undefined>))\n .manifest,\n start: async ({ env } = {}) =>\n await start(env ?? (process.env as Record<string, string | undefined>)),\n test,\n [BACKEND_INTERNALS]: {\n envSchema,\n inspect,\n start,\n },\n }\n return backend\n}\n"]}
|
|
1
|
+
{"version":3,"file":"backend.js","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AnyRouter as AnyORPCRouter } from '@orpc/server'\n\nimport type { TableAccessInput } from './access'\nimport type {\n BetterAuthConfig,\n BunderstackConfig,\n RealtimeConfigInput,\n} from './config'\nimport type { EnvConfigInput, ValidatedEnv } from './env'\nimport type { BunderstackJobsBuilder, JobsDefs } from './jobs'\nimport type { BunderstackManifest } from './manifest'\nimport type { MessagingConfig } from './messaging'\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 { validateEnv } from './env'\nimport { assertHostedBlueprintFile } from './hosted-contract'\nimport { inspectConfig, type InspectedDefinition } from './inspect'\nimport { materializeBunderstack } from './runtime'\n\nexport type StartOptions = {\n env?: Record<string, string | undefined>\n}\n\nexport type BunderstackBackend<TApp> = {\n inspect(options?: StartOptions): 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 TMessaging extends MessagingConfig | undefined = undefined,\n TAuthConfig extends BetterAuthConfig = BetterAuthConfig,\n> = Omit<\n BunderstackConfig<\n TSchema,\n TAccess,\n TStorage,\n TEnv,\n TCustomApiRouter,\n TAuthConfig\n >,\n 'realtime' | 'messaging' | 'api'\n> & {\n /**\n * An inline `api` or `jobs` builder receives the open `MessagingConfig`, not\n * `TMessaging`. Naming `TMessaging` in a callback parameter makes TypeScript\n * fix it before it reads the sibling `messaging` property, and the whole\n * declaration then loses its inferred channels. Declare the builder in its\n * own module with an annotated parameter to type `ctx.messaging` exactly —\n * `defineApi({ schema, env, messaging })` and `BunderstackJobsBuilder` both\n * take the channel record.\n */\n realtime?: TRealtime\n messaging?: TMessaging\n api?:\n | TCustomApiRouter\n | ((\n builder: import('./api/builder').BunderstackApiBuilder<\n TSchema,\n ValidatedEnv<TEnv>,\n MessagingConfig\n >,\n ) => TCustomApiRouter)\n jobs?:\n | TJobsDefs\n | ((\n builder: BunderstackJobsBuilder<\n TSchema,\n ValidatedEnv<TEnv>,\n MessagingConfig\n >,\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\n/**\n * A configuration slot that may read validated environment values. The shape a\n * slot produces reaches the manifest, so a callback belongs here to supply a\n * key, a URL, or a sender — never to change which channels, buckets, or tables\n * exist. Blueprint generation resolves the declaration against two accepted\n * environments and rejects a shape that differs between them.\n */\nexport type EnvAware<TEnv extends EnvConfigInput | undefined, T> =\n | T\n | ((env: ValidatedEnv<NoInfer<TEnv>>) => T)\n\nexport type DatabaseSlot = BunderstackConfig<\n Record<string, unknown>,\n undefined,\n undefined,\n undefined,\n undefined\n>['database']\n\n/**\n * The whole application in one object. `schema`, `access`, and the routers are\n * plain data; the slots that hold credentials also accept a function of the\n * validated environment.\n */\nexport type BunderstackDeclaration<\n TSchema extends Record<string, unknown>,\n TEnv extends EnvConfigInput | undefined = undefined,\n TAccess extends Record<string, TableAccessInput> | undefined = undefined,\n TStorage extends StorageConfigInput | undefined = undefined,\n TJobsDefs extends JobsDefs | undefined = undefined,\n TCustomApiRouter extends AnyORPCRouter | undefined = undefined,\n TRealtime = undefined,\n TMessaging extends MessagingConfig | undefined = undefined,\n TAuthConfig extends BetterAuthConfig = BetterAuthConfig,\n> = Omit<\n BunderstackDefinitionConfig<\n TSchema,\n TAccess,\n TStorage,\n TEnv,\n TJobsDefs,\n TCustomApiRouter,\n TRealtime,\n TMessaging,\n TAuthConfig\n >,\n 'database' | 'storage' | 'messaging' | 'realtime'\n> & {\n /** Declared environment. Its names reach the blueprint; its values never do. */\n env?: TEnv\n database: EnvAware<TEnv, DatabaseSlot>\n storage?: EnvAware<TEnv, TStorage>\n messaging?: EnvAware<TEnv, TMessaging>\n realtime?: EnvAware<TEnv, TRealtime>\n}\n\nexport function bunderstack<\n TSchema extends Record<string, unknown>,\n const TEnv extends EnvConfigInput | undefined = undefined,\n const TAccess extends Record<string, TableAccessInput> | undefined =\n undefined,\n const TStorage extends StorageConfigInput | undefined = undefined,\n const TJobsDefs extends JobsDefs | undefined = undefined,\n TCustomApiRouter extends AnyORPCRouter | undefined = undefined,\n const TRealtime extends RealtimeConfigInput | undefined = undefined,\n const TMessaging extends MessagingConfig | undefined = undefined,\n const TAuthConfig extends BetterAuthConfig = BetterAuthConfig,\n>(\n declaration: BunderstackDeclaration<\n TSchema,\n TEnv,\n TAccess,\n TStorage,\n TJobsDefs,\n TCustomApiRouter,\n TRealtime,\n TMessaging,\n TAuthConfig\n >,\n): BunderstackBackend<\n BunderstackApp<\n TSchema,\n TAccess,\n BucketNamesOf<TStorage>,\n TEnv,\n TJobsDefs,\n TCustomApiRouter,\n TRealtime,\n TMessaging,\n TAuthConfig\n >\n>\nexport function bunderstack(\n declaration: BunderstackDeclaration<Record<string, unknown>, any>,\n): BunderstackBackend<any> {\n const { env: envSchema, ...slots } = declaration as Record<\n string,\n unknown\n > & {\n env?: EnvConfigInput\n }\n const inspect = (source: Record<string, string | undefined>) => {\n const env = validateEnv(envSchema, { source })\n const resolve = (value: unknown) =>\n typeof value === 'function'\n ? (value as (given: typeof env) => unknown)(env)\n : value\n const config = {\n ...slots,\n database: resolve(slots.database),\n storage: resolve(slots.storage),\n messaging: resolve(slots.messaging),\n realtime: resolve(slots.realtime),\n }\n return inspectConfig(config as never, envSchema, env)\n }\n\n type App = BunderstackApp<any, any, any, any, any, any, any, any, any>\n\n const start = async (\n source: Record<string, string | undefined>,\n overrides: RuntimeOverrides = {},\n inspected: InspectedDefinition = inspect(source),\n ): Promise<App> => {\n if (source.BUNDERSTACK_BLUEPRINT_PATH) {\n await assertHostedBlueprintFile(\n inspected.manifest,\n source.BUNDERSTACK_BLUEPRINT_PATH,\n )\n }\n return materializeBunderstack(\n {\n ...inspected.config,\n jobs: inspected.jobsDefs,\n api: inspected.customApiRouter,\n } as never,\n source,\n overrides,\n inspected.env,\n ) as Promise<App>\n }\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 inspect: ({ env } = {}) =>\n inspect(env ?? (process.env as Record<string, string | undefined>))\n .manifest,\n start: async ({ env } = {}) =>\n await start(env ?? (process.env as Record<string, string | undefined>)),\n test,\n [BACKEND_INTERNALS]: {\n envSchema,\n inspect,\n start,\n },\n }\n return backend\n}\n"]}
|
package/dist/config.d.ts
CHANGED
|
@@ -21,7 +21,7 @@ export type AuthConfigContext<TSchema extends Record<string, unknown>, TEnv exte
|
|
|
21
21
|
db: DbFor<TSchema>;
|
|
22
22
|
env: ValidatedEnv<TEnv>;
|
|
23
23
|
};
|
|
24
|
-
export type AuthConfigInput<TSchema extends Record<string, unknown>, TEnv extends EnvConfigInput | undefined = undefined
|
|
24
|
+
export type AuthConfigInput<TSchema extends Record<string, unknown>, TEnv extends EnvConfigInput | undefined = undefined, TConfig extends BetterAuthConfig = BetterAuthConfig> = TConfig | ((ctx: AuthConfigContext<TSchema, TEnv>) => TConfig);
|
|
25
25
|
/**
|
|
26
26
|
* Identity helper for defining an auth config in a separate file with full
|
|
27
27
|
* type inference — no explicit generic annotations required.
|
|
@@ -43,8 +43,12 @@ export type AuthConfigInput<TSchema extends Record<string, unknown>, TEnv extend
|
|
|
43
43
|
* }))
|
|
44
44
|
* ```
|
|
45
45
|
*/
|
|
46
|
-
export declare function defineAuth(config:
|
|
47
|
-
export declare function defineAuth<TSchema extends Record<string, unknown>, TEnv extends EnvConfigInput | undefined
|
|
46
|
+
export declare function defineAuth<const TConfig extends BetterAuthConfig>(config: TConfig): TConfig;
|
|
47
|
+
export declare function defineAuth<TSchema extends Record<string, unknown>, TEnv extends EnvConfigInput | undefined, const TConfig extends BetterAuthConfig>(context: {
|
|
48
|
+
schema: TSchema;
|
|
49
|
+
env: TEnv;
|
|
50
|
+
}, builder: (ctx: AuthConfigContext<TSchema, TEnv>) => TConfig): (ctx: AuthConfigContext<TSchema, TEnv>) => TConfig;
|
|
51
|
+
export declare function defineAuth<TSchema extends Record<string, unknown>, const TConfig extends BetterAuthConfig, TEnv extends EnvConfigInput | undefined = undefined>(schema: TSchema, builder: (ctx: AuthConfigContext<TSchema, TEnv>) => TConfig): (ctx: AuthConfigContext<TSchema, TEnv>) => TConfig;
|
|
48
52
|
/**
|
|
49
53
|
* The builder as {@link ResolvedConfig} carries it: schema-agnostic, because
|
|
50
54
|
* ResolvedConfig is not generic. {@link resolveAuthConfig} is the only caller.
|
|
@@ -62,7 +66,7 @@ export type RealtimeConfigInput = boolean | {
|
|
|
62
66
|
token?: string;
|
|
63
67
|
};
|
|
64
68
|
};
|
|
65
|
-
export type BunderstackConfig<TSchema extends Record<string, unknown>, TAccess extends Record<string, TableAccessInput> | undefined = Record<string, TableAccessInput> | undefined, TStorage extends StorageConfigInput | undefined = StorageConfigInput | undefined, TEnv extends EnvConfigInput | undefined = EnvConfigInput | undefined, TCustomApiRouter extends AnyRouter | undefined = AnyRouter | undefined> = {
|
|
69
|
+
export type BunderstackConfig<TSchema extends Record<string, unknown>, TAccess extends Record<string, TableAccessInput> | undefined = Record<string, TableAccessInput> | undefined, TStorage extends StorageConfigInput | undefined = StorageConfigInput | undefined, TEnv extends EnvConfigInput | undefined = EnvConfigInput | undefined, TCustomApiRouter extends AnyRouter | undefined = AnyRouter | undefined, TAuthConfig extends BetterAuthConfig = BetterAuthConfig> = {
|
|
66
70
|
schema: TSchema;
|
|
67
71
|
access?: TAccess;
|
|
68
72
|
database: {
|
|
@@ -77,7 +81,7 @@ export type BunderstackConfig<TSchema extends Record<string, unknown>, TAccess e
|
|
|
77
81
|
* connection, so the application never opens a second one just to satisfy a
|
|
78
82
|
* config that is built before the app exists.
|
|
79
83
|
*/
|
|
80
|
-
auth?: AuthConfigInput<NoInfer<TSchema>, NoInfer<TEnv
|
|
84
|
+
auth?: AuthConfigInput<NoInfer<TSchema>, NoInfer<TEnv>, TAuthConfig>;
|
|
81
85
|
/**
|
|
82
86
|
* Reuse an application-owned session reader for the unified API while
|
|
83
87
|
* keeping Bunderstack's auth handler available.
|
|
@@ -121,7 +125,7 @@ export type ResolvedConfig = {
|
|
|
121
125
|
storage: ResolvedStorageBuckets;
|
|
122
126
|
realtime?: RealtimeConfigInput;
|
|
123
127
|
};
|
|
124
|
-
export declare function resolveConfig<TSchema extends Record<string, unknown>, TAccess extends Record<string, TableAccessInput> | undefined = undefined, TStorage extends StorageConfigInput | undefined = undefined, TEnv extends EnvConfigInput | undefined = undefined, TCustomApiRouter extends AnyRouter | undefined = undefined>(options: BunderstackConfig<TSchema, TAccess, TStorage, TEnv, TCustomApiRouter>, env?: BaseEnv, platformSource?: Record<string, string | undefined>): ResolvedConfig;
|
|
128
|
+
export declare function resolveConfig<TSchema extends Record<string, unknown>, TAccess extends Record<string, TableAccessInput> | undefined = undefined, TStorage extends StorageConfigInput | undefined = undefined, TEnv extends EnvConfigInput | undefined = undefined, TCustomApiRouter extends AnyRouter | undefined = undefined, TAuthConfig extends BetterAuthConfig = BetterAuthConfig>(options: BunderstackConfig<TSchema, TAccess, TStorage, TEnv, TCustomApiRouter, TAuthConfig>, env?: BaseEnv, platformSource?: Record<string, string | undefined>): ResolvedConfig;
|
|
125
129
|
/** Collapse the object/builder union once the db is up. */
|
|
126
130
|
export declare function resolveAuthConfig(auth: ResolvedConfig['auth'], ctx: {
|
|
127
131
|
db: AnyDb;
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAG5D,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAGxC,OAAO,KAAK,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AACrE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,MAAM,CAAA;AACjC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,WAAW,CAAA;AACtC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AACtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAEnD,OAAO,EAEL,KAAK,OAAO,EACZ,KAAK,cAAc,EACnB,KAAK,YAAY,EAClB,MAAM,OAAO,CAAA;AACd,OAAO,EAEL,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACxB,MAAM,mBAAmB,CAAA;AAE1B,MAAM,MAAM,gBAAgB,GAAG,IAAI,CACjC,WAAW,CAAC,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,EAC7C,UAAU,CACX,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,CAC3B,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACvC,IAAI,SAAS,cAAc,GAAG,SAAS,GAAG,SAAS,IACjD;IACF,EAAE,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;IAClB,GAAG,EAAE,YAAY,CAAC,IAAI,CAAC,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,eAAe,CACzB,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACvC,IAAI,SAAS,cAAc,GAAG,SAAS,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AnyMiddleware, AnyRouter } from '@orpc/server'\n\n// src/config.ts\nimport { betterAuth } from 'better-auth'\nimport * as v from 'valibot'\n\nimport type { AuthSessionResolver, TableAccessInput } from './access'\nimport type { BunderstackApiBuilder } from './api/builder'\nimport type { DatabaseAdapter } from './database/adapter'\nimport type { DbFor } from './db'\nimport type { AnyDb } from './dialect'\nimport type { IdempotencyConfig } from './idempotency'\nimport type { MessagingConfig } from './messaging'\nimport type { RateLimitConfig } from './rate-limit'\n\nimport {\n validateEnv,\n type BaseEnv,\n type EnvConfigInput,\n type ValidatedEnv,\n} from './env'\nimport {\n resolveBuckets,\n type ResolvedStorageBuckets,\n type StorageConfigInput,\n} from './storage/buckets'\n\nexport type BetterAuthConfig = Omit<\n NonNullable<Parameters<typeof betterAuth>[0]>,\n 'database'\n>\n\n/**\n * What an `auth` builder is handed. `db` is the app's own connection, typed\n * from `schema` alone — that is what keeps the builder cycle-free: better-auth\n * hooks living in another file get a db without importing the app whose type\n * they help produce.\n */\nexport type AuthConfigContext<\n TSchema extends Record<string, unknown>,\n TEnv extends EnvConfigInput | undefined = undefined,\n> = {\n db: DbFor<TSchema>\n env: ValidatedEnv<TEnv>\n}\n\nexport type AuthConfigInput<\n TSchema extends Record<string, unknown>,\n TEnv extends EnvConfigInput | undefined = undefined,\n> =\n | BetterAuthConfig\n | ((ctx: AuthConfigContext<TSchema, TEnv>) => BetterAuthConfig)\n\n/**\n * Identity helper for defining an auth config in a separate file with full\n * type inference — no explicit generic annotations required.\n *\n * Follows the `defineConfig` / `defineComponent` ecosystem convention:\n * the function does nothing at runtime but gives TypeScript an inference\n * anchor through the `schema` parameter.\n *\n * @example\n * ```ts\n * // Static config (no db/env access needed)\n * export const authConfig = defineAuth({ ... })\n *\n * // Builder with schema-typed db\n * export const authConfig = defineAuth(schema, ({ db }) => ({\n * databaseHooks: {\n * user: { create: { after: async (user) => { await db.insert(...) } } }\n * }\n * }))\n * ```\n */\nexport function defineAuth(config: BetterAuthConfig): BetterAuthConfig\nexport function defineAuth<\n TSchema extends Record<string, unknown>,\n TEnv extends EnvConfigInput | undefined = undefined,\n>(\n schema: TSchema,\n builder: (ctx: AuthConfigContext<TSchema, TEnv>) => BetterAuthConfig,\n): (ctx: AuthConfigContext<TSchema, TEnv>) => BetterAuthConfig\nexport function defineAuth(\n schemaOrConfig: Record<string, unknown>,\n builder?: (ctx: any) => BetterAuthConfig,\n) {\n return builder ?? schemaOrConfig\n}\n\n/**\n * The builder as {@link ResolvedConfig} carries it: schema-agnostic, because\n * ResolvedConfig is not generic. {@link resolveAuthConfig} is the only caller.\n */\nexport type AuthConfigFactory = (ctx: {\n db: AnyDb\n env: BaseEnv\n}) => BetterAuthConfig\n\n// Only the union-shaped options need runtime validation: they are the ones a\n// JavaScript caller can plausibly get wrong in a way that fails confusingly\n// downstream. Everything else is either typed-only or read raw from `options`.\nconst RuntimeOptionsSchema = v.object({\n rateLimit: v.optional(\n v.union([\n v.boolean(),\n v.object({\n windowMs: v.optional(v.number()),\n max: v.optional(v.number()),\n }),\n ]),\n ),\n idempotency: v.optional(\n v.union([v.boolean(), v.object({ ttlMs: v.optional(v.number()) })]),\n ),\n realtime: v.optional(\n v.union([\n v.boolean(),\n v.object({\n bufferSize: v.optional(v.number()),\n resumeSeconds: v.optional(v.number()),\n redis: v.optional(\n v.union([\n v.string(),\n v.object({ url: v.string(), token: v.optional(v.string()) }),\n ]),\n ),\n }),\n ]),\n ),\n openapi: v.optional(v.boolean()),\n})\n\n/** Realtime declaration. Independent of schema, storage, and env. */\nexport type RealtimeConfigInput =\n | boolean\n | {\n bufferSize?: number\n resumeSeconds?: number\n redis?: string | { url: string; token?: string }\n }\n\nexport type BunderstackConfig<\n TSchema extends Record<string, unknown>,\n TAccess extends Record<string, TableAccessInput> | undefined =\n | Record<string, TableAccessInput>\n | undefined,\n TStorage extends StorageConfigInput | undefined =\n | StorageConfigInput\n | undefined,\n TEnv extends EnvConfigInput | undefined = EnvConfigInput | undefined,\n TCustomApiRouter extends AnyRouter | undefined = AnyRouter | undefined,\n> = {\n schema: TSchema\n access?: TAccess\n database: {\n adapter: DatabaseAdapter\n url?: string\n authToken?: string\n migrations?: string\n }\n /**\n * better-auth options, or a builder receiving `{ db, env }`. Use the builder\n * form when database hooks need to write: it hands out the app's own\n * connection, so the application never opens a second one just to satisfy a\n * config that is built before the app exists.\n */\n auth?: AuthConfigInput<NoInfer<TSchema>, NoInfer<TEnv>>\n /**\n * Reuse an application-owned session reader for the unified API while\n * keeping Bunderstack's auth handler available.\n */\n authResolver?: AuthSessionResolver\n storage?: TStorage\n background?: { autoStart?: boolean }\n messaging?: MessagingConfig\n /**\n * The application's oRPC router. Pass the finished router object, or a\n * callback when the router needs the framework builder at configuration\n * time. Declare the router at module scope with `defineApi` and the object\n * form keeps router modules free of factory wrappers.\n */\n api?:\n | TCustomApiRouter\n | ((\n builder: BunderstackApiBuilder<TSchema, ValidatedEnv<TEnv>>,\n ) => TCustomApiRouter)\n /**\n * Middleware applied to every procedure in the graph: generated CRUD,\n * storage, realtime, health, and the application's own procedures. Declare\n * each one with `o.middleware(...)` from `defineApi`.\n *\n * It runs before authentication, so `context.user` is not available inside\n * it. Read an already-resolved caller with `context.peekSession()`.\n */\n middleware?: AnyMiddleware[]\n rateLimit?: boolean | RateLimitConfig\n idempotency?: boolean | IdempotencyConfig\n /** Generate and serve `/api/openapi.json`. Disabled by default. */\n openapi?: boolean\n realtime?: RealtimeConfigInput\n}\n\nexport type ResolvedConfig = {\n database: {\n adapter: DatabaseAdapter\n url: string\n authToken?: string\n migrations: string\n }\n auth: BetterAuthConfig | AuthConfigFactory\n storage: ResolvedStorageBuckets\n realtime?: RealtimeConfigInput\n}\n\nexport function resolveConfig<\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 TCustomApiRouter extends AnyRouter | undefined = undefined,\n>(\n options: BunderstackConfig<\n TSchema,\n TAccess,\n TStorage,\n TEnv,\n TCustomApiRouter\n >,\n env?: BaseEnv,\n // Platform-injected overrides (Bunderhost & co.) beat code-level config so\n // apps with hardcoded local urls deploy unchanged.\n platformSource: Record<string, string | undefined> = process.env as Record<\n string,\n string | undefined\n >,\n): ResolvedConfig {\n const parsed = v.parse(RuntimeOptionsSchema, options)\n // Self-validate when the caller didn't pass a pre-validated env, so\n // resolveConfig stays usable standalone.\n const resolvedEnv = env ?? validateEnv(undefined)\n\n const adapter = options.database?.adapter\n if (!adapter) {\n throw new Error('[bunderstack] database.adapter is required')\n }\n\n const defaultUrl =\n adapter.dialect === 'sqlite' ? 'file:./data.db' : 'file:./data.pglite'\n\n return {\n database: {\n adapter,\n url:\n platformSource['BUNDERSTACK_DATABASE_URL'] ??\n options.database?.url ??\n resolvedEnv.DATABASE_URL ??\n defaultUrl,\n authToken:\n platformSource['BUNDERSTACK_DATABASE_AUTH_TOKEN'] ??\n options.database?.authToken ??\n resolvedEnv.DATABASE_AUTH_TOKEN,\n migrations: options.database?.migrations ?? './migrations',\n },\n auth: (() => {\n // The secret default has to survive the builder form too, and the builder\n // can only run once the db exists — so wrap it and default afterwards.\n const withSecret = (cfg: BetterAuthConfig): BetterAuthConfig => ({\n ...cfg,\n secret: cfg.secret ?? resolvedEnv.AUTH_SECRET,\n })\n const authInput = options.auth\n return typeof authInput === 'function'\n ? (((ctx) =>\n withSecret(authInput(ctx as never))) satisfies AuthConfigFactory)\n : withSecret(authInput ?? {})\n })(),\n storage: resolveBuckets(options.storage, platformSource),\n realtime: parsed.realtime,\n }\n}\n\n/** Collapse the object/builder union once the db is up. */\nexport function resolveAuthConfig(\n auth: ResolvedConfig['auth'],\n ctx: { db: AnyDb; env: BaseEnv },\n): BetterAuthConfig {\n return typeof auth === 'function' ? auth(ctx) : auth\n}\n\nexport function resolveRealtimeRedisUrl(\n realtime: ResolvedConfig['realtime'],\n env?: BaseEnv,\n platformSource: Record<string, string | undefined> = process.env as Record<\n string,\n string | undefined\n >,\n): string | undefined {\n const platformRedis = platformSource['REDIS_URL']\n if (platformRedis) return platformRedis\n\n const envRedis = env?.REDIS_URL\n if (envRedis) return envRedis\n\n const fromConfig =\n typeof realtime === 'object' && realtime.redis\n ? typeof realtime.redis === 'string'\n ? realtime.redis\n : realtime.redis.url\n : undefined\n\n return fromConfig ?? undefined\n}\n"]}
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,gBAAgB;AAChB,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AAW5B,OAAO,EACL,WAAW,GAIZ,MAAM,OAAO,CAAA;AACd,OAAO,EACL,cAAc,GAGf,MAAM,mBAAmB,CAAA;AAmE1B,MAAM,UAAU,UAAU,CACxB,cAAuC,EACvC,OAAwC;IAExC,OAAO,OAAO,IAAI,cAAc,CAAA;AAClC,CAAC;AAWD,6EAA6E;AAC7E,4EAA4E;AAC5E,+EAA+E;AAC/E,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,SAAS,EAAE,CAAC,CAAC,QAAQ,CACnB,CAAC,CAAC,KAAK,CAAC;QACN,CAAC,CAAC,OAAO,EAAE;QACX,CAAC,CAAC,MAAM,CAAC;YACP,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;YAChC,GAAG,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;SAC5B,CAAC;KACH,CAAC,CACH;IACD,WAAW,EAAE,CAAC,CAAC,QAAQ,CACrB,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CACpE;IACD,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAClB,CAAC,CAAC,KAAK,CAAC;QACN,CAAC,CAAC,OAAO,EAAE;QACX,CAAC,CAAC,MAAM,CAAC;YACP,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;YAClC,aAAa,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;YACrC,KAAK,EAAE,CAAC,CAAC,QAAQ,CACf,CAAC,CAAC,KAAK,CAAC;gBACN,CAAC,CAAC,MAAM,EAAE;gBACV,CAAC,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;aAC7D,CAAC,CACH;SACF,CAAC;KACH,CAAC,CACH;IACD,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;CACjC,CAAC,CAAA;AAqFF,MAAM,UAAU,aAAa,CAQ3B,OAOC,EACD,GAAa;AACb,2EAA2E;AAC3E,mDAAmD;AACnD,iBAAqD,OAAO,CAAC,GAG5D;IAED,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,oBAAoB,EAAE,OAAO,CAAC,CAAA;IACrD,oEAAoE;IACpE,yCAAyC;IACzC,MAAM,WAAW,GAAG,GAAG,IAAI,WAAW,CAAC,SAAS,CAAC,CAAA;IAEjD,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAA;IACzC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAA;IAC/D,CAAC;IAED,MAAM,UAAU,GACd,OAAO,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,oBAAoB,CAAA;IAExE,OAAO;QACL,QAAQ,EAAE;YACR,OAAO;YACP,GAAG,EACD,cAAc,CAAC,0BAA0B,CAAC;gBAC1C,OAAO,CAAC,QAAQ,EAAE,GAAG;gBACrB,WAAW,CAAC,YAAY;gBACxB,UAAU;YACZ,SAAS,EACP,cAAc,CAAC,iCAAiC,CAAC;gBACjD,OAAO,CAAC,QAAQ,EAAE,SAAS;gBAC3B,WAAW,CAAC,mBAAmB;YACjC,UAAU,EAAE,OAAO,CAAC,QAAQ,EAAE,UAAU,IAAI,cAAc;SAC3D;QACD,IAAI,EAAE,CAAC,GAAG,EAAE;YACV,0EAA0E;YAC1E,uEAAuE;YACvE,MAAM,UAAU,GAAG,CAAC,GAAqB,EAAoB,EAAE,CAAC,CAAC;gBAC/D,GAAG,GAAG;gBACN,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,WAAW,CAAC,WAAW;aAC9C,CAAC,CAAA;YACF,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAA;YAC9B,OAAO,OAAO,SAAS,KAAK,UAAU;gBACpC,CAAC,CAAE,CAAC,CAAC,GAAG,EAAE,EAAE,CACR,UAAU,CAAC,SAAS,CAAC,GAAY,CAAC,CAAC,CAA8B;gBACrE,CAAC,CAAC,UAAU,CAAC,SAAS,IAAI,EAAE,CAAC,CAAA;QACjC,CAAC,CAAC,EAAE;QACJ,OAAO,EAAE,cAAc,CAAC,OAAO,CAAC,OAAO,EAAE,cAAc,CAAC;QACxD,QAAQ,EAAE,MAAM,CAAC,QAAQ;KAC1B,CAAA;AACH,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,iBAAiB,CAC/B,IAA4B,EAC5B,GAAgC;IAEhC,OAAO,OAAO,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;AACtD,CAAC;AAED,MAAM,UAAU,uBAAuB,CACrC,QAAoC,EACpC,GAAa,EACb,iBAAqD,OAAO,CAAC,GAG5D;IAED,MAAM,aAAa,GAAG,cAAc,CAAC,WAAW,CAAC,CAAA;IACjD,IAAI,aAAa;QAAE,OAAO,aAAa,CAAA;IAEvC,MAAM,QAAQ,GAAG,GAAG,EAAE,SAAS,CAAA;IAC/B,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAA;IAE7B,MAAM,UAAU,GACd,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,KAAK;QAC5C,CAAC,CAAC,OAAO,QAAQ,CAAC,KAAK,KAAK,QAAQ;YAClC,CAAC,CAAC,QAAQ,CAAC,KAAK;YAChB,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG;QACtB,CAAC,CAAC,SAAS,CAAA;IAEf,OAAO,UAAU,IAAI,SAAS,CAAA;AAChC,CAAC","sourcesContent":["import type { AnyMiddleware, AnyRouter } from '@orpc/server'\n\n// src/config.ts\nimport { betterAuth } from 'better-auth'\nimport * as v from 'valibot'\n\nimport type { AuthSessionResolver, TableAccessInput } from './access'\nimport type { BunderstackApiBuilder } from './api/builder'\nimport type { DatabaseAdapter } from './database/adapter'\nimport type { DbFor } from './db'\nimport type { AnyDb } from './dialect'\nimport type { IdempotencyConfig } from './idempotency'\nimport type { MessagingConfig } from './messaging'\nimport type { RateLimitConfig } from './rate-limit'\n\nimport {\n validateEnv,\n type BaseEnv,\n type EnvConfigInput,\n type ValidatedEnv,\n} from './env'\nimport {\n resolveBuckets,\n type ResolvedStorageBuckets,\n type StorageConfigInput,\n} from './storage/buckets'\n\nexport type BetterAuthConfig = Omit<\n NonNullable<Parameters<typeof betterAuth>[0]>,\n 'database'\n>\n\n/**\n * What an `auth` builder is handed. `db` is the app's own connection, typed\n * from `schema` alone — that is what keeps the builder cycle-free: better-auth\n * hooks living in another file get a db without importing the app whose type\n * they help produce.\n */\nexport type AuthConfigContext<\n TSchema extends Record<string, unknown>,\n TEnv extends EnvConfigInput | undefined = undefined,\n> = {\n db: DbFor<TSchema>\n env: ValidatedEnv<TEnv>\n}\n\nexport type AuthConfigInput<\n TSchema extends Record<string, unknown>,\n TEnv extends EnvConfigInput | undefined = undefined,\n TConfig extends BetterAuthConfig = BetterAuthConfig,\n> = TConfig | ((ctx: AuthConfigContext<TSchema, TEnv>) => TConfig)\n\n/**\n * Identity helper for defining an auth config in a separate file with full\n * type inference — no explicit generic annotations required.\n *\n * Follows the `defineConfig` / `defineComponent` ecosystem convention:\n * the function does nothing at runtime but gives TypeScript an inference\n * anchor through the `schema` parameter.\n *\n * @example\n * ```ts\n * // Static config (no db/env access needed)\n * export const authConfig = defineAuth({ ... })\n *\n * // Builder with schema-typed db\n * export const authConfig = defineAuth(schema, ({ db }) => ({\n * databaseHooks: {\n * user: { create: { after: async (user) => { await db.insert(...) } } }\n * }\n * }))\n * ```\n */\nexport function defineAuth<const TConfig extends BetterAuthConfig>(\n config: TConfig,\n): TConfig\nexport function defineAuth<\n TSchema extends Record<string, unknown>,\n TEnv extends EnvConfigInput | undefined,\n const TConfig extends BetterAuthConfig,\n>(\n context: { schema: TSchema; env: TEnv },\n builder: (ctx: AuthConfigContext<TSchema, TEnv>) => TConfig,\n): (ctx: AuthConfigContext<TSchema, TEnv>) => TConfig\nexport function defineAuth<\n TSchema extends Record<string, unknown>,\n const TConfig extends BetterAuthConfig,\n TEnv extends EnvConfigInput | undefined = undefined,\n>(\n schema: TSchema,\n builder: (ctx: AuthConfigContext<TSchema, TEnv>) => TConfig,\n): (ctx: AuthConfigContext<TSchema, TEnv>) => TConfig\nexport function defineAuth(\n schemaOrConfig: Record<string, unknown>,\n builder?: (ctx: any) => BetterAuthConfig,\n) {\n return builder ?? schemaOrConfig\n}\n\n/**\n * The builder as {@link ResolvedConfig} carries it: schema-agnostic, because\n * ResolvedConfig is not generic. {@link resolveAuthConfig} is the only caller.\n */\nexport type AuthConfigFactory = (ctx: {\n db: AnyDb\n env: BaseEnv\n}) => BetterAuthConfig\n\n// Only the union-shaped options need runtime validation: they are the ones a\n// JavaScript caller can plausibly get wrong in a way that fails confusingly\n// downstream. Everything else is either typed-only or read raw from `options`.\nconst RuntimeOptionsSchema = v.object({\n rateLimit: v.optional(\n v.union([\n v.boolean(),\n v.object({\n windowMs: v.optional(v.number()),\n max: v.optional(v.number()),\n }),\n ]),\n ),\n idempotency: v.optional(\n v.union([v.boolean(), v.object({ ttlMs: v.optional(v.number()) })]),\n ),\n realtime: v.optional(\n v.union([\n v.boolean(),\n v.object({\n bufferSize: v.optional(v.number()),\n resumeSeconds: v.optional(v.number()),\n redis: v.optional(\n v.union([\n v.string(),\n v.object({ url: v.string(), token: v.optional(v.string()) }),\n ]),\n ),\n }),\n ]),\n ),\n openapi: v.optional(v.boolean()),\n})\n\n/** Realtime declaration. Independent of schema, storage, and env. */\nexport type RealtimeConfigInput =\n | boolean\n | {\n bufferSize?: number\n resumeSeconds?: number\n redis?: string | { url: string; token?: string }\n }\n\nexport type BunderstackConfig<\n TSchema extends Record<string, unknown>,\n TAccess extends Record<string, TableAccessInput> | undefined =\n | Record<string, TableAccessInput>\n | undefined,\n TStorage extends StorageConfigInput | undefined =\n | StorageConfigInput\n | undefined,\n TEnv extends EnvConfigInput | undefined = EnvConfigInput | undefined,\n TCustomApiRouter extends AnyRouter | undefined = AnyRouter | undefined,\n TAuthConfig extends BetterAuthConfig = BetterAuthConfig,\n> = {\n schema: TSchema\n access?: TAccess\n database: {\n adapter: DatabaseAdapter\n url?: string\n authToken?: string\n migrations?: string\n }\n /**\n * better-auth options, or a builder receiving `{ db, env }`. Use the builder\n * form when database hooks need to write: it hands out the app's own\n * connection, so the application never opens a second one just to satisfy a\n * config that is built before the app exists.\n */\n auth?: AuthConfigInput<NoInfer<TSchema>, NoInfer<TEnv>, TAuthConfig>\n /**\n * Reuse an application-owned session reader for the unified API while\n * keeping Bunderstack's auth handler available.\n */\n authResolver?: AuthSessionResolver\n storage?: TStorage\n background?: { autoStart?: boolean }\n messaging?: MessagingConfig\n /**\n * The application's oRPC router. Pass the finished router object, or a\n * callback when the router needs the framework builder at configuration\n * time. Declare the router at module scope with `defineApi` and the object\n * form keeps router modules free of factory wrappers.\n */\n api?:\n | TCustomApiRouter\n | ((\n builder: BunderstackApiBuilder<TSchema, ValidatedEnv<TEnv>>,\n ) => TCustomApiRouter)\n /**\n * Middleware applied to every procedure in the graph: generated CRUD,\n * storage, realtime, health, and the application's own procedures. Declare\n * each one with `o.middleware(...)` from `defineApi`.\n *\n * It runs before authentication, so `context.user` is not available inside\n * it. Read an already-resolved caller with `context.peekSession()`.\n */\n middleware?: AnyMiddleware[]\n rateLimit?: boolean | RateLimitConfig\n idempotency?: boolean | IdempotencyConfig\n /** Generate and serve `/api/openapi.json`. Disabled by default. */\n openapi?: boolean\n realtime?: RealtimeConfigInput\n}\n\nexport type ResolvedConfig = {\n database: {\n adapter: DatabaseAdapter\n url: string\n authToken?: string\n migrations: string\n }\n auth: BetterAuthConfig | AuthConfigFactory\n storage: ResolvedStorageBuckets\n realtime?: RealtimeConfigInput\n}\n\nexport function resolveConfig<\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 TCustomApiRouter extends AnyRouter | undefined = undefined,\n TAuthConfig extends BetterAuthConfig = BetterAuthConfig,\n>(\n options: BunderstackConfig<\n TSchema,\n TAccess,\n TStorage,\n TEnv,\n TCustomApiRouter,\n TAuthConfig\n >,\n env?: BaseEnv,\n // Platform-injected overrides (Bunderhost & co.) beat code-level config so\n // apps with hardcoded local urls deploy unchanged.\n platformSource: Record<string, string | undefined> = process.env as Record<\n string,\n string | undefined\n >,\n): ResolvedConfig {\n const parsed = v.parse(RuntimeOptionsSchema, options)\n // Self-validate when the caller didn't pass a pre-validated env, so\n // resolveConfig stays usable standalone.\n const resolvedEnv = env ?? validateEnv(undefined)\n\n const adapter = options.database?.adapter\n if (!adapter) {\n throw new Error('[bunderstack] database.adapter is required')\n }\n\n const defaultUrl =\n adapter.dialect === 'sqlite' ? 'file:./data.db' : 'file:./data.pglite'\n\n return {\n database: {\n adapter,\n url:\n platformSource['BUNDERSTACK_DATABASE_URL'] ??\n options.database?.url ??\n resolvedEnv.DATABASE_URL ??\n defaultUrl,\n authToken:\n platformSource['BUNDERSTACK_DATABASE_AUTH_TOKEN'] ??\n options.database?.authToken ??\n resolvedEnv.DATABASE_AUTH_TOKEN,\n migrations: options.database?.migrations ?? './migrations',\n },\n auth: (() => {\n // The secret default has to survive the builder form too, and the builder\n // can only run once the db exists — so wrap it and default afterwards.\n const withSecret = (cfg: BetterAuthConfig): BetterAuthConfig => ({\n ...cfg,\n secret: cfg.secret ?? resolvedEnv.AUTH_SECRET,\n })\n const authInput = options.auth\n return typeof authInput === 'function'\n ? (((ctx) =>\n withSecret(authInput(ctx as never))) satisfies AuthConfigFactory)\n : withSecret(authInput ?? {})\n })(),\n storage: resolveBuckets(options.storage, platformSource),\n realtime: parsed.realtime,\n }\n}\n\n/** Collapse the object/builder union once the db is up. */\nexport function resolveAuthConfig(\n auth: ResolvedConfig['auth'],\n ctx: { db: AnyDb; env: BaseEnv },\n): BetterAuthConfig {\n return typeof auth === 'function' ? auth(ctx) : auth\n}\n\nexport function resolveRealtimeRedisUrl(\n realtime: ResolvedConfig['realtime'],\n env?: BaseEnv,\n platformSource: Record<string, string | undefined> = process.env as Record<\n string,\n string | undefined\n >,\n): string | undefined {\n const platformRedis = platformSource['REDIS_URL']\n if (platformRedis) return platformRedis\n\n const envRedis = env?.REDIS_URL\n if (envRedis) return envRedis\n\n const fromConfig =\n typeof realtime === 'object' && realtime.redis\n ? typeof realtime.redis === 'string'\n ? realtime.redis\n : realtime.redis.url\n : undefined\n\n return fromConfig ?? undefined\n}\n"]}
|
|
@@ -3,7 +3,7 @@ import type { AnyDb, Dialect } from './dialect.js';
|
|
|
3
3
|
/**
|
|
4
4
|
* Hidden handle connecting `bunderstack()` to the optional
|
|
5
5
|
* `bunderstack/provision` entry. Lives in its own module so the main entry
|
|
6
|
-
* never imports
|
|
6
|
+
* never imports provisioning code.
|
|
7
7
|
*/
|
|
8
8
|
export declare const PROVISION_INTERNALS: unique symbol;
|
|
9
9
|
export interface ProvisionInternals {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Hidden handle connecting `bunderstack()` to the optional
|
|
3
3
|
* `bunderstack/provision` entry. Lives in its own module so the main entry
|
|
4
|
-
* never imports
|
|
4
|
+
* never imports provisioning code.
|
|
5
5
|
*/
|
|
6
6
|
export const PROVISION_INTERNALS = Symbol.for('bunderstack.provision-internals');
|
|
7
7
|
//# sourceMappingURL=provision-internals.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provision-internals.js","sourceRoot":"","sources":["../src/provision-internals.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAkB,MAAM,CAAC,GAAG,CAC1D,iCAAiC,CAClC,CAAA","sourcesContent":["import type { Driver } from './db'\n// src/provision-internals.ts\nimport type { AnyDb, Dialect } from './dialect'\n\n/**\n * Hidden handle connecting `bunderstack()` to the optional\n * `bunderstack/provision` entry. Lives in its own module so the main entry\n * never imports
|
|
1
|
+
{"version":3,"file":"provision-internals.js","sourceRoot":"","sources":["../src/provision-internals.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAkB,MAAM,CAAC,GAAG,CAC1D,iCAAiC,CAClC,CAAA","sourcesContent":["import type { Driver } from './db'\n// src/provision-internals.ts\nimport type { AnyDb, Dialect } from './dialect'\n\n/**\n * Hidden handle connecting `bunderstack()` to the optional\n * `bunderstack/provision` entry. Lives in its own module so the main entry\n * never imports provisioning code.\n */\nexport const PROVISION_INTERNALS: unique symbol = Symbol.for(\n 'bunderstack.provision-internals',\n)\n\nexport interface ProvisionInternals {\n /** Runtime db typed over the MERGED schema (user + internal tables). */\n db: AnyDb\n /** Merged schema used for push. */\n schema: Record<string, unknown>\n databaseUrl: string\n /** Resolved migrations folder (config `database.migrations`). */\n migrationsFolder: string\n dialect: Dialect\n driver: Driver\n adapter: import('./database/adapter').DatabaseAdapter\n}\n\nexport interface WithProvisionInternals {\n [PROVISION_INTERNALS]?: ProvisionInternals\n}\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Dialect } from './dialect.js';
|
|
2
|
+
/** Create the local backing directory for file-based urls, per dialect. */
|
|
3
|
+
export declare function ensureLocalDataDir(url: string, dialect: Dialect): Promise<void>;
|
|
4
|
+
export declare function getProvisionInternals(app: object): import("./provision-internals.js").ProvisionInternals;
|
|
5
|
+
/** Apply committed migrations, returning false when no journal exists. */
|
|
6
|
+
export declare function applyCommittedMigrations(app: object): Promise<boolean>;
|
|
7
|
+
//# sourceMappingURL=provision-runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provision-runtime.d.ts","sourceRoot":"","sources":["../src/provision-runtime.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAOxC,2EAA2E;AAC3E,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,IAAI,CAAC,CAaf;AAWD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,sDAQhD;AAED,0EAA0E;AAC1E,wBAAsB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAS5E"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { access, mkdir } from 'node:fs/promises';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
|
+
import { PROVISION_INTERNALS, } from './provision-internals.js';
|
|
4
|
+
/** Create the local backing directory for file-based urls, per dialect. */
|
|
5
|
+
export async function ensureLocalDataDir(url, dialect) {
|
|
6
|
+
if (dialect === 'pg') {
|
|
7
|
+
if (/^postgres(ql)?:\/\//.test(url))
|
|
8
|
+
return;
|
|
9
|
+
const raw = url.startsWith('file:') ? url.slice('file:'.length) : url;
|
|
10
|
+
if (raw === ':memory:' || raw.startsWith('memory://'))
|
|
11
|
+
return;
|
|
12
|
+
await mkdir(raw, { recursive: true });
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const match = /^file:(.+)$/.exec(url);
|
|
16
|
+
if (!match)
|
|
17
|
+
return;
|
|
18
|
+
const filePath = match[1];
|
|
19
|
+
if (filePath === ':memory:')
|
|
20
|
+
return;
|
|
21
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
22
|
+
}
|
|
23
|
+
async function exists(path) {
|
|
24
|
+
try {
|
|
25
|
+
await access(path);
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export function getProvisionInternals(app) {
|
|
33
|
+
const internals = app[PROVISION_INTERNALS];
|
|
34
|
+
if (!internals) {
|
|
35
|
+
throw new Error('[bunderstack] provision() expects the app returned by bunderstack().');
|
|
36
|
+
}
|
|
37
|
+
return internals;
|
|
38
|
+
}
|
|
39
|
+
/** Apply committed migrations, returning false when no journal exists. */
|
|
40
|
+
export async function applyCommittedMigrations(app) {
|
|
41
|
+
const internals = getProvisionInternals(app);
|
|
42
|
+
const { db, databaseUrl, migrationsFolder, dialect, adapter } = internals;
|
|
43
|
+
const journal = join(migrationsFolder, 'meta', '_journal.json');
|
|
44
|
+
if (!(await exists(journal)))
|
|
45
|
+
return false;
|
|
46
|
+
await ensureLocalDataDir(databaseUrl, dialect);
|
|
47
|
+
await adapter.migrate(db, migrationsFolder);
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=provision-runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provision-runtime.js","sourceRoot":"","sources":["../src/provision-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAIzC,OAAO,EACL,mBAAmB,GAEpB,MAAM,uBAAuB,CAAA;AAE9B,2EAA2E;AAC3E,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,GAAW,EACX,OAAgB;IAEhB,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,IAAI,qBAAqB,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,OAAM;QAC3C,MAAM,GAAG,GAAG,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA;QACrE,IAAI,GAAG,KAAK,UAAU,IAAI,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC;YAAE,OAAM;QAC7D,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QACrC,OAAM;IACR,CAAC;IACD,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACrC,IAAI,CAAC,KAAK;QAAE,OAAM;IAClB,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAE,CAAA;IAC1B,IAAI,QAAQ,KAAK,UAAU;QAAE,OAAM;IACnC,MAAM,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;AACrD,CAAC;AAED,KAAK,UAAU,MAAM,CAAC,IAAY;IAChC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,IAAI,CAAC,CAAA;QAClB,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,GAAW;IAC/C,MAAM,SAAS,GAAI,GAA8B,CAAC,mBAAmB,CAAC,CAAA;IACtE,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,sEAAsE,CACvE,CAAA;IACH,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,0EAA0E;AAC1E,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,GAAW;IACxD,MAAM,SAAS,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAA;IAC5C,MAAM,EAAE,EAAE,EAAE,WAAW,EAAE,gBAAgB,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,SAAS,CAAA;IACzE,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,EAAE,MAAM,EAAE,eAAe,CAAC,CAAA;IAC/D,IAAI,CAAC,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC;QAAE,OAAO,KAAK,CAAA;IAE1C,MAAM,kBAAkB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;IAC9C,MAAM,OAAO,CAAC,OAAO,CAAC,EAAW,EAAE,gBAAgB,CAAC,CAAA;IACpD,OAAO,IAAI,CAAA;AACb,CAAC","sourcesContent":["import { access, mkdir } from 'node:fs/promises'\nimport { dirname, join } from 'node:path'\n\nimport type { Dialect } from './dialect'\n\nimport {\n PROVISION_INTERNALS,\n type WithProvisionInternals,\n} from './provision-internals'\n\n/** Create the local backing directory for file-based urls, per dialect. */\nexport async function ensureLocalDataDir(\n url: string,\n dialect: Dialect,\n): Promise<void> {\n if (dialect === 'pg') {\n if (/^postgres(ql)?:\\/\\//.test(url)) return\n const raw = url.startsWith('file:') ? url.slice('file:'.length) : url\n if (raw === ':memory:' || raw.startsWith('memory://')) return\n await mkdir(raw, { recursive: true })\n return\n }\n const match = /^file:(.+)$/.exec(url)\n if (!match) return\n const filePath = match[1]!\n if (filePath === ':memory:') return\n await mkdir(dirname(filePath), { recursive: true })\n}\n\nasync function exists(path: string): Promise<boolean> {\n try {\n await access(path)\n return true\n } catch {\n return false\n }\n}\n\nexport function getProvisionInternals(app: object) {\n const internals = (app as WithProvisionInternals)[PROVISION_INTERNALS]\n if (!internals) {\n throw new Error(\n '[bunderstack] provision() expects the app returned by bunderstack().',\n )\n }\n return internals\n}\n\n/** Apply committed migrations, returning false when no journal exists. */\nexport async function applyCommittedMigrations(app: object): Promise<boolean> {\n const internals = getProvisionInternals(app)\n const { db, databaseUrl, migrationsFolder, dialect, adapter } = internals\n const journal = join(migrationsFolder, 'meta', '_journal.json')\n if (!(await exists(journal))) return false\n\n await ensureLocalDataDir(databaseUrl, dialect)\n await adapter.migrate(db as never, migrationsFolder)\n return true\n}\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AnyDb } from './dialect.js';
|
|
2
|
+
/** Push the merged schema to the database via drizzle-kit/api. */
|
|
3
|
+
export declare function provisionSchema<TSchema extends Record<string, unknown>>(db: AnyDb, schema: TSchema, options?: {
|
|
4
|
+
force?: boolean;
|
|
5
|
+
databaseUrl?: string;
|
|
6
|
+
}): Promise<void>;
|
|
7
|
+
/**
|
|
8
|
+
* Development provisioning: apply committed migrations when present,
|
|
9
|
+
* otherwise push the current schema through Drizzle Kit.
|
|
10
|
+
*/
|
|
11
|
+
export declare function provision(app: object, options?: {
|
|
12
|
+
force?: boolean;
|
|
13
|
+
}): Promise<void>;
|
|
14
|
+
export type TestSchemaMode = 'auto' | 'push' | 'migrations';
|
|
15
|
+
export declare function provisionForTest(app: object, mode: TestSchemaMode): Promise<void>;
|
|
16
|
+
//# sourceMappingURL=provision-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provision-schema.d.ts","sourceRoot":"","sources":["../src/provision-schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,WAAW,CAAA;AActC,kEAAkE;AAClE,wBAAsB,eAAe,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC3E,EAAE,EAAE,KAAK,EACT,MAAM,EAAE,OAAO,EACf,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAClD,OAAO,CAAC,IAAI,CAAC,CAgCf;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAC7B,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAC5B,OAAO,CAAC,IAAI,CAAC,CAOf;AAED,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,GAAG,YAAY,CAAA;AAE3D,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,IAAI,CAAC,CAkBf"}
|