bunderstack 0.23.4 → 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 +67 -0
- package/README.md +7 -4
- package/dist/api/builder.d.ts +13 -11
- package/dist/api/builder.d.ts.map +1 -1
- package/dist/api/builder.js.map +1 -1
- package/dist/api/context.d.ts +6 -6
- package/dist/api/context.d.ts.map +1 -1
- package/dist/api/context.js +1 -1
- package/dist/api/context.js.map +1 -1
- package/dist/api/crud-router.d.ts +6 -6
- package/dist/api/realtime-router.d.ts +1 -1
- package/dist/api/storage-router.d.ts +5 -5
- 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-internals.d.ts +5 -13
- package/dist/backend-internals.d.ts.map +1 -1
- package/dist/backend-internals.js.map +1 -1
- package/dist/backend.d.ts +39 -5
- package/dist/backend.d.ts.map +1 -1
- package/dist/backend.js +37 -46
- package/dist/backend.js.map +1 -1
- package/dist/blueprint-generator.d.ts +1 -0
- package/dist/blueprint-generator.d.ts.map +1 -1
- package/dist/blueprint-generator.js +29 -1
- package/dist/blueprint-generator.js.map +1 -1
- package/dist/blueprint.d.ts +2 -1
- package/dist/blueprint.d.ts.map +1 -1
- package/dist/blueprint.js +9 -2
- package/dist/blueprint.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +14 -2
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +23 -25
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/email/smtp.d.ts +7 -1
- package/dist/email/smtp.d.ts.map +1 -1
- package/dist/email/smtp.js +5 -1
- package/dist/email/smtp.js.map +1 -1
- package/dist/email.d.ts +3 -29
- package/dist/email.d.ts.map +1 -1
- package/dist/email.js +1 -194
- package/dist/email.js.map +1 -1
- package/dist/env-probe.d.ts +9 -0
- package/dist/env-probe.d.ts.map +1 -0
- package/dist/env-probe.js +73 -0
- package/dist/env-probe.js.map +1 -0
- package/dist/env.d.ts +2 -5
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +2 -9
- package/dist/env.js.map +1 -1
- package/dist/hosted-contract.d.ts +11 -0
- package/dist/hosted-contract.d.ts.map +1 -0
- package/dist/hosted-contract.js +46 -0
- package/dist/hosted-contract.js.map +1 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/inspect.d.ts +15 -0
- package/dist/inspect.d.ts.map +1 -0
- package/dist/inspect.js +43 -0
- package/dist/inspect.js.map +1 -0
- package/dist/internal-tables-pg.d.ts +43 -94
- package/dist/internal-tables-pg.d.ts.map +1 -1
- package/dist/internal-tables-pg.js +14 -17
- package/dist/internal-tables-pg.js.map +1 -1
- package/dist/internal-tables.d.ts +213 -488
- package/dist/internal-tables.d.ts.map +1 -1
- package/dist/internal-tables.js +33 -33
- package/dist/internal-tables.js.map +1 -1
- package/dist/jobs/define.d.ts +20 -20
- package/dist/jobs/define.d.ts.map +1 -1
- package/dist/jobs/define.js.map +1 -1
- package/dist/manifest-diff.d.ts +6 -0
- package/dist/manifest-diff.d.ts.map +1 -0
- package/dist/manifest-diff.js +42 -0
- package/dist/manifest-diff.js.map +1 -0
- package/dist/manifest.d.ts +10 -2
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +27 -29
- package/dist/manifest.js.map +1 -1
- package/dist/messaging/email.d.ts +16 -0
- package/dist/messaging/email.d.ts.map +1 -0
- package/dist/messaging/email.js +8 -0
- package/dist/messaging/email.js.map +1 -0
- package/dist/messaging/index.d.ts +8 -0
- package/dist/messaging/index.d.ts.map +1 -0
- package/dist/messaging/index.js +4 -0
- package/dist/messaging/index.js.map +1 -0
- package/dist/messaging/journal.d.ts +4 -0
- package/dist/messaging/journal.d.ts.map +1 -0
- package/dist/messaging/journal.js +19 -0
- package/dist/messaging/journal.js.map +1 -0
- package/dist/messaging/runtime.d.ts +16 -0
- package/dist/messaging/runtime.d.ts.map +1 -0
- package/dist/messaging/runtime.js +213 -0
- package/dist/messaging/runtime.js.map +1 -0
- package/dist/messaging/standalone.d.ts +27 -0
- package/dist/messaging/standalone.d.ts.map +1 -0
- package/dist/messaging/standalone.js +18 -0
- package/dist/messaging/standalone.js.map +1 -0
- package/dist/messaging/telegram.d.ts +16 -0
- package/dist/messaging/telegram.d.ts.map +1 -0
- package/dist/messaging/telegram.js +5 -0
- package/dist/messaging/telegram.js.map +1 -0
- package/dist/messaging/types.d.ts +22 -0
- package/dist/messaging/types.d.ts.map +1 -0
- package/dist/messaging/types.js +17 -0
- package/dist/messaging/types.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-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 +17 -14
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +20 -33
- package/dist/runtime.js.map +1 -1
- package/dist/schema-export-pg.d.ts +1 -1
- package/dist/schema-export-pg.d.ts.map +1 -1
- package/dist/schema-export-pg.js +1 -1
- package/dist/schema-export-pg.js.map +1 -1
- package/dist/schema-export.d.ts +1 -1
- package/dist/schema-export.d.ts.map +1 -1
- package/dist/schema-export.js +1 -1
- package/dist/schema-export.js.map +1 -1
- package/dist/testing/fixture.d.ts +3 -3
- package/dist/testing/fixture.d.ts.map +1 -1
- package/dist/testing/fixture.js +12 -10
- package/dist/testing/fixture.js.map +1 -1
- package/dist/testing/messaging.d.ts +21 -0
- package/dist/testing/messaging.d.ts.map +1 -0
- package/dist/testing/messaging.js +34 -0
- package/dist/testing/messaging.js.map +1 -0
- package/dist/testing.d.ts +1 -0
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js.map +1 -1
- package/llms-full.txt +416 -226
- package/llms.txt +4 -3
- package/package.json +10 -2
- package/skills/creating-bunderstack-apps/references/application-structure.md +16 -7
- package/skills/creating-bunderstack-apps/references/verification.md +7 -6
- package/skills/migrating-to-bunderstack/SKILL.md +75 -51
- package/skills/migrating-to-bunderstack/references/audit-checklist.md +2 -2
- package/skills/migrating-to-bunderstack/references/runtime-replacements.md +20 -15
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { createMessaging as materialize } from './runtime.js';
|
|
2
|
+
/**
|
|
3
|
+
* Builds channel facades outside a started app, for code that runs before or
|
|
4
|
+
* beside it — a Better Auth builder sending an invitation, a script, a
|
|
5
|
+
* one-off worker. Channels behave exactly as they do on `app.messaging`,
|
|
6
|
+
* capture included.
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* export const auth = defineAuth(schema, ({ db, env }) => {
|
|
10
|
+
* const messaging = createMessaging({ email: resend({ from: env.EMAIL_FROM }) }, { env, db })
|
|
11
|
+
* return { …, sendInvitation: (to) => messaging.email.send({ to, … }) }
|
|
12
|
+
* })
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export function createMessaging(channels, context) {
|
|
16
|
+
return materialize(channels, { env: context.env, db: context.db });
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=standalone.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"standalone.js","sourceRoot":"","sources":["../../src/messaging/standalone.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,eAAe,IAAI,WAAW,EAAE,MAAM,WAAW,CAAA;AAY1D;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAiB,EACjB,OAAyB;IAEzB,OAAO,WAAW,CAAC,QAAQ,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAA;AACpE,CAAC","sourcesContent":["import type { AnyDb } from '../dialect'\nimport type { BaseEnv } from '../env'\nimport type { MessagingConfig, MessagingFacades } from './types'\n\nimport { createMessaging as materialize } from './runtime'\n\n/**\n * What a standalone messaging facade needs. `db` is the application's own\n * connection: pass it so captured and sent messages reach the same journal the\n * app writes, and omit it only when there is no database to write to.\n */\nexport type MessagingContext = {\n env: BaseEnv\n db?: AnyDb\n}\n\n/**\n * Builds channel facades outside a started app, for code that runs before or\n * beside it — a Better Auth builder sending an invitation, a script, a\n * one-off worker. Channels behave exactly as they do on `app.messaging`,\n * capture included.\n *\n * ```ts\n * export const auth = defineAuth(schema, ({ db, env }) => {\n * const messaging = createMessaging({ email: resend({ from: env.EMAIL_FROM }) }, { env, db })\n * return { …, sendInvitation: (to) => messaging.email.send({ to, … }) }\n * })\n * ```\n */\nexport function createMessaging<const TConfig extends MessagingConfig>(\n channels: TConfig,\n context: MessagingContext,\n): MessagingFacades<TConfig> {\n return materialize(channels, { env: context.env, db: context.db })\n}\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type MessagingDescriptor } from './types.js';
|
|
2
|
+
export type TelegramMessage = {
|
|
3
|
+
to: string | number;
|
|
4
|
+
text: string;
|
|
5
|
+
parseMode?: 'HTML' | 'MarkdownV2';
|
|
6
|
+
};
|
|
7
|
+
export type SentTelegramMessage = {
|
|
8
|
+
id?: string;
|
|
9
|
+
providerId?: string;
|
|
10
|
+
};
|
|
11
|
+
export type TelegramConfig = {
|
|
12
|
+
botToken?: string;
|
|
13
|
+
};
|
|
14
|
+
export type TelegramDescriptor = MessagingDescriptor<'telegram', 'telegram', TelegramMessage, SentTelegramMessage, TelegramConfig>;
|
|
15
|
+
export declare function telegram(config?: TelegramConfig): TelegramDescriptor;
|
|
16
|
+
//# sourceMappingURL=telegram.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telegram.d.ts","sourceRoot":"","sources":["../../src/messaging/telegram.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,mBAAmB,EAAE,MAAM,SAAS,CAAA;AAE9D,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,MAAM,GAAG,YAAY,CAAA;CAClC,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAElD,MAAM,MAAM,kBAAkB,GAAG,mBAAmB,CAClD,UAAU,EACV,UAAU,EACV,eAAe,EACf,mBAAmB,EACnB,cAAc,CACf,CAAA;AAED,wBAAgB,QAAQ,CAAC,MAAM,GAAE,cAAmB,GAAG,kBAAkB,CAExE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telegram.js","sourceRoot":"","sources":["../../src/messaging/telegram.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA4B,MAAM,SAAS,CAAA;AAuB9D,MAAM,UAAU,QAAQ,CAAC,SAAyB,EAAE;IAClD,OAAO,UAAU,CAAC,UAAU,EAAE,UAAU,EAAE,MAAM,CAAC,CAAA;AACnD,CAAC","sourcesContent":["import { descriptor, type MessagingDescriptor } from './types'\n\nexport type TelegramMessage = {\n to: string | number\n text: string\n parseMode?: 'HTML' | 'MarkdownV2'\n}\n\nexport type SentTelegramMessage = {\n id?: string\n providerId?: string\n}\n\nexport type TelegramConfig = { botToken?: string }\n\nexport type TelegramDescriptor = MessagingDescriptor<\n 'telegram',\n 'telegram',\n TelegramMessage,\n SentTelegramMessage,\n TelegramConfig\n>\n\nexport function telegram(config: TelegramConfig = {}): TelegramDescriptor {\n return descriptor('telegram', 'telegram', config)\n}\n"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare const MESSAGING_DESCRIPTOR: unique symbol;
|
|
2
|
+
export type MessagingDescriptor<TKind extends string, TProvider extends string, TInput, TResult, TConfig = unknown> = {
|
|
3
|
+
readonly kind: TKind;
|
|
4
|
+
readonly provider: TProvider;
|
|
5
|
+
readonly config: Readonly<TConfig>;
|
|
6
|
+
readonly [MESSAGING_DESCRIPTOR]: {
|
|
7
|
+
readonly input: TInput;
|
|
8
|
+
readonly result: TResult;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
export type AnyMessagingDescriptor = MessagingDescriptor<string, string, any, any, any>;
|
|
12
|
+
export type MessagingConfig = Record<string, AnyMessagingDescriptor>;
|
|
13
|
+
export type MessagingFacade<TDescriptor extends AnyMessagingDescriptor> = {
|
|
14
|
+
send(input: TDescriptor[typeof MESSAGING_DESCRIPTOR]['input']): Promise<TDescriptor[typeof MESSAGING_DESCRIPTOR]['result']>;
|
|
15
|
+
};
|
|
16
|
+
export type MessagingFacades<TConfig extends MessagingConfig> = {
|
|
17
|
+
readonly [K in keyof TConfig]: MessagingFacade<TConfig[K]>;
|
|
18
|
+
};
|
|
19
|
+
export type MessagingFacadesFor<TConfig extends MessagingConfig | undefined> = TConfig extends MessagingConfig ? MessagingFacades<TConfig> : Record<never, never>;
|
|
20
|
+
export declare function descriptor<TKind extends string, TProvider extends string, TInput, TResult, TConfig>(kind: TKind, provider: TProvider, config: TConfig): MessagingDescriptor<TKind, TProvider, TInput, TResult, TConfig>;
|
|
21
|
+
export declare function isMessagingDescriptor(value: unknown): value is AnyMessagingDescriptor;
|
|
22
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/messaging/types.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,EAAE,OAAO,MAEzC,CAAA;AAED,MAAM,MAAM,mBAAmB,CAC7B,KAAK,SAAS,MAAM,EACpB,SAAS,SAAS,MAAM,EACxB,MAAM,EACN,OAAO,EACP,OAAO,GAAG,OAAO,IACf;IACF,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAA;IACpB,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAA;IAC5B,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;IAClC,QAAQ,CAAC,CAAC,oBAAoB,CAAC,EAAE;QAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;QACtB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;KACzB,CAAA;CACF,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG,mBAAmB,CACtD,MAAM,EACN,MAAM,EACN,GAAG,EACH,GAAG,EACH,GAAG,CACJ,CAAA;AAED,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAA;AAEpE,MAAM,MAAM,eAAe,CAAC,WAAW,SAAS,sBAAsB,IAAI;IACxE,IAAI,CACF,KAAK,EAAE,WAAW,CAAC,OAAO,oBAAoB,CAAC,CAAC,OAAO,CAAC,GACvD,OAAO,CAAC,WAAW,CAAC,OAAO,oBAAoB,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAA;CAC/D,CAAA;AAED,MAAM,MAAM,gBAAgB,CAAC,OAAO,SAAS,eAAe,IAAI;IAC9D,QAAQ,EAAE,CAAC,IAAI,MAAM,OAAO,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;CAC3D,CAAA;AAED,MAAM,MAAM,mBAAmB,CAAC,OAAO,SAAS,eAAe,GAAG,SAAS,IACzE,OAAO,SAAS,eAAe,GAC3B,gBAAgB,CAAC,OAAO,CAAC,GACzB,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;AAE1B,wBAAgB,UAAU,CACxB,KAAK,SAAS,MAAM,EACpB,SAAS,SAAS,MAAM,EACxB,MAAM,EACN,OAAO,EACP,OAAO,EAEP,IAAI,EAAE,KAAK,EACX,QAAQ,EAAE,SAAS,EACnB,MAAM,EAAE,OAAO,GACd,mBAAmB,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAOjE;AAED,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,sBAAsB,CAQjC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const MESSAGING_DESCRIPTOR = Symbol.for('bunderstack.messaging-descriptor');
|
|
2
|
+
export function descriptor(kind, provider, config) {
|
|
3
|
+
return Object.freeze({
|
|
4
|
+
kind,
|
|
5
|
+
provider,
|
|
6
|
+
config: Object.freeze({ ...config }),
|
|
7
|
+
[MESSAGING_DESCRIPTOR]: undefined,
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
export function isMessagingDescriptor(value) {
|
|
11
|
+
return (typeof value === 'object' &&
|
|
12
|
+
value !== null &&
|
|
13
|
+
MESSAGING_DESCRIPTOR in value &&
|
|
14
|
+
typeof value.kind === 'string' &&
|
|
15
|
+
typeof value.provider === 'string');
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/messaging/types.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,oBAAoB,GAAkB,MAAM,CAAC,GAAG,CAC3D,kCAAkC,CACnC,CAAA;AA2CD,MAAM,UAAU,UAAU,CAOxB,IAAW,EACX,QAAmB,EACnB,MAAe;IAEf,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,IAAI;QACJ,QAAQ;QACR,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC;QACpC,CAAC,oBAAoB,CAAC,EAAE,SAAkB;KAC3C,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,KAAc;IAEd,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,oBAAoB,IAAI,KAAK;QAC7B,OAAQ,KAAgC,CAAC,IAAI,KAAK,QAAQ;QAC1D,OAAQ,KAAgC,CAAC,QAAQ,KAAK,QAAQ,CAC/D,CAAA;AACH,CAAC","sourcesContent":["export const MESSAGING_DESCRIPTOR: unique symbol = Symbol.for(\n 'bunderstack.messaging-descriptor',\n)\n\nexport type MessagingDescriptor<\n TKind extends string,\n TProvider extends string,\n TInput,\n TResult,\n TConfig = unknown,\n> = {\n readonly kind: TKind\n readonly provider: TProvider\n readonly config: Readonly<TConfig>\n readonly [MESSAGING_DESCRIPTOR]: {\n readonly input: TInput\n readonly result: TResult\n }\n}\n\nexport type AnyMessagingDescriptor = MessagingDescriptor<\n string,\n string,\n any,\n any,\n any\n>\n\nexport type MessagingConfig = Record<string, AnyMessagingDescriptor>\n\nexport type MessagingFacade<TDescriptor extends AnyMessagingDescriptor> = {\n send(\n input: TDescriptor[typeof MESSAGING_DESCRIPTOR]['input'],\n ): Promise<TDescriptor[typeof MESSAGING_DESCRIPTOR]['result']>\n}\n\nexport type MessagingFacades<TConfig extends MessagingConfig> = {\n readonly [K in keyof TConfig]: MessagingFacade<TConfig[K]>\n}\n\nexport type MessagingFacadesFor<TConfig extends MessagingConfig | undefined> =\n TConfig extends MessagingConfig\n ? MessagingFacades<TConfig>\n : Record<never, never>\n\nexport function descriptor<\n TKind extends string,\n TProvider extends string,\n TInput,\n TResult,\n TConfig,\n>(\n kind: TKind,\n provider: TProvider,\n config: TConfig,\n): MessagingDescriptor<TKind, TProvider, TInput, TResult, TConfig> {\n return Object.freeze({\n kind,\n provider,\n config: Object.freeze({ ...config }),\n [MESSAGING_DESCRIPTOR]: undefined as never,\n })\n}\n\nexport function isMessagingDescriptor(\n value: unknown,\n): value is AnyMessagingDescriptor {\n return (\n typeof value === 'object' &&\n value !== null &&\n MESSAGING_DESCRIPTOR in value &&\n typeof (value as AnyMessagingDescriptor).kind === 'string' &&\n typeof (value as AnyMessagingDescriptor).provider === 'string'\n )\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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { detectDialect } from './dialect.js';
|
|
2
|
+
import { applyCommittedMigrations, ensureLocalDataDir, getProvisionInternals, } from './provision-runtime.js';
|
|
3
|
+
const DRIZZLE_KIT_HINT = '[bunderstack] Schema push requires drizzle-kit, which is not installed.\n' +
|
|
4
|
+
' Development: run `bun add -d drizzle-kit` and import provision from `bunderstack/provision-schema`.\n' +
|
|
5
|
+
' Production: generate migrations with `bunx drizzle-kit generate`, commit them, and use `bunderstack/provision`.';
|
|
6
|
+
/** Push the merged schema to the database via drizzle-kit/api. */
|
|
7
|
+
export async function provisionSchema(db, schema, options) {
|
|
8
|
+
const dialect = detectDialect(schema);
|
|
9
|
+
if (options?.databaseUrl) {
|
|
10
|
+
await ensureLocalDataDir(options.databaseUrl, dialect);
|
|
11
|
+
}
|
|
12
|
+
let kit;
|
|
13
|
+
try {
|
|
14
|
+
kit = await import('drizzle-kit/api');
|
|
15
|
+
}
|
|
16
|
+
catch (cause) {
|
|
17
|
+
throw new Error(DRIZZLE_KIT_HINT, { cause });
|
|
18
|
+
}
|
|
19
|
+
const result = dialect === 'pg'
|
|
20
|
+
? await kit.pushSchema(schema, db)
|
|
21
|
+
: await kit.pushSQLiteSchema(schema, db);
|
|
22
|
+
if (result.hasDataLoss && !options?.force) {
|
|
23
|
+
throw new Error('[bunderstack] Schema push would cause data loss. Run `bunx drizzle-kit push` or call provision(app, { force: true }).');
|
|
24
|
+
}
|
|
25
|
+
for (const warning of result.warnings) {
|
|
26
|
+
console.warn(`[bunderstack] ${warning}`);
|
|
27
|
+
}
|
|
28
|
+
if (result.statementsToExecute.length === 0)
|
|
29
|
+
return;
|
|
30
|
+
await result.apply();
|
|
31
|
+
console.log(`[bunderstack] provisioned ${result.statementsToExecute.length} schema change(s)`);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Development provisioning: apply committed migrations when present,
|
|
35
|
+
* otherwise push the current schema through Drizzle Kit.
|
|
36
|
+
*/
|
|
37
|
+
export async function provision(app, options) {
|
|
38
|
+
if (await applyCommittedMigrations(app))
|
|
39
|
+
return;
|
|
40
|
+
const internals = getProvisionInternals(app);
|
|
41
|
+
await provisionSchema(internals.db, internals.schema, {
|
|
42
|
+
force: options?.force,
|
|
43
|
+
databaseUrl: internals.databaseUrl,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
export async function provisionForTest(app, mode) {
|
|
47
|
+
if (mode === 'auto') {
|
|
48
|
+
await provision(app, { force: true });
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const internals = getProvisionInternals(app);
|
|
52
|
+
if (mode === 'push') {
|
|
53
|
+
await provisionSchema(internals.db, internals.schema, {
|
|
54
|
+
force: true,
|
|
55
|
+
databaseUrl: internals.databaseUrl,
|
|
56
|
+
});
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (!(await applyCommittedMigrations(app))) {
|
|
60
|
+
throw new Error('[bunderstack] committed migrations journal not found');
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=provision-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provision-schema.js","sourceRoot":"","sources":["../src/provision-schema.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EACL,wBAAwB,EACxB,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,qBAAqB,CAAA;AAE5B,MAAM,gBAAgB,GACpB,2EAA2E;IAC3E,yGAAyG;IACzG,mHAAmH,CAAA;AAErH,kEAAkE;AAClE,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,EAAS,EACT,MAAe,EACf,OAAmD;IAEnD,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,CAAA;IACrC,IAAI,OAAO,EAAE,WAAW,EAAE,CAAC;QACzB,MAAM,kBAAkB,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;IACxD,CAAC;IAED,IAAI,GAAqC,CAAA;IACzC,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAA;IACvC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,gBAAgB,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;IAC9C,CAAC;IAED,MAAM,MAAM,GACV,OAAO,KAAK,IAAI;QACd,CAAC,CAAC,MAAM,GAAG,CAAC,UAAU,CAAC,MAAM,EAAE,EAAW,CAAC;QAC3C,CAAC,CAAC,MAAM,GAAG,CAAC,gBAAgB,CAAC,MAAM,EAAE,EAAW,CAAC,CAAA;IAErD,IAAI,MAAM,CAAC,WAAW,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CACb,uHAAuH,CACxH,CAAA;IACH,CAAC;IACD,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QACtC,OAAO,CAAC,IAAI,CAAC,iBAAiB,OAAO,EAAE,CAAC,CAAA;IAC1C,CAAC;IACD,IAAI,MAAM,CAAC,mBAAmB,CAAC,MAAM,KAAK,CAAC;QAAE,OAAM;IAEnD,MAAM,MAAM,CAAC,KAAK,EAAE,CAAA;IACpB,OAAO,CAAC,GAAG,CACT,6BAA6B,MAAM,CAAC,mBAAmB,CAAC,MAAM,mBAAmB,CAClF,CAAA;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,GAAW,EACX,OAA6B;IAE7B,IAAI,MAAM,wBAAwB,CAAC,GAAG,CAAC;QAAE,OAAM;IAC/C,MAAM,SAAS,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAA;IAC5C,MAAM,eAAe,CAAC,SAAS,CAAC,EAAE,EAAE,SAAS,CAAC,MAAM,EAAE;QACpD,KAAK,EAAE,OAAO,EAAE,KAAK;QACrB,WAAW,EAAE,SAAS,CAAC,WAAW;KACnC,CAAC,CAAA;AACJ,CAAC;AAID,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,GAAW,EACX,IAAoB;IAEpB,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,MAAM,SAAS,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;QACrC,OAAM;IACR,CAAC;IAED,MAAM,SAAS,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAA;IAC5C,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,MAAM,eAAe,CAAC,SAAS,CAAC,EAAE,EAAE,SAAS,CAAC,MAAM,EAAE;YACpD,KAAK,EAAE,IAAI;YACX,WAAW,EAAE,SAAS,CAAC,WAAW;SACnC,CAAC,CAAA;QACF,OAAM;IACR,CAAC;IAED,IAAI,CAAC,CAAC,MAAM,wBAAwB,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAA;IACzE,CAAC;AACH,CAAC","sourcesContent":["import type { AnyDb } from './dialect'\n\nimport { detectDialect } from './dialect'\nimport {\n applyCommittedMigrations,\n ensureLocalDataDir,\n getProvisionInternals,\n} from './provision-runtime'\n\nconst DRIZZLE_KIT_HINT =\n '[bunderstack] Schema push requires drizzle-kit, which is not installed.\\n' +\n ' Development: run `bun add -d drizzle-kit` and import provision from `bunderstack/provision-schema`.\\n' +\n ' Production: generate migrations with `bunx drizzle-kit generate`, commit them, and use `bunderstack/provision`.'\n\n/** Push the merged schema to the database via drizzle-kit/api. */\nexport async function provisionSchema<TSchema extends Record<string, unknown>>(\n db: AnyDb,\n schema: TSchema,\n options?: { force?: boolean; databaseUrl?: string },\n): Promise<void> {\n const dialect = detectDialect(schema)\n if (options?.databaseUrl) {\n await ensureLocalDataDir(options.databaseUrl, dialect)\n }\n\n let kit: typeof import('drizzle-kit/api')\n try {\n kit = await import('drizzle-kit/api')\n } catch (cause) {\n throw new Error(DRIZZLE_KIT_HINT, { cause })\n }\n\n const result =\n dialect === 'pg'\n ? await kit.pushSchema(schema, db as never)\n : await kit.pushSQLiteSchema(schema, db as never)\n\n if (result.hasDataLoss && !options?.force) {\n throw new Error(\n '[bunderstack] Schema push would cause data loss. Run `bunx drizzle-kit push` or call provision(app, { force: true }).',\n )\n }\n for (const warning of result.warnings) {\n console.warn(`[bunderstack] ${warning}`)\n }\n if (result.statementsToExecute.length === 0) return\n\n await result.apply()\n console.log(\n `[bunderstack] provisioned ${result.statementsToExecute.length} schema change(s)`,\n )\n}\n\n/**\n * Development provisioning: apply committed migrations when present,\n * otherwise push the current schema through Drizzle Kit.\n */\nexport async function provision(\n app: object,\n options?: { force?: boolean },\n): Promise<void> {\n if (await applyCommittedMigrations(app)) return\n const internals = getProvisionInternals(app)\n await provisionSchema(internals.db, internals.schema, {\n force: options?.force,\n databaseUrl: internals.databaseUrl,\n })\n}\n\nexport type TestSchemaMode = 'auto' | 'push' | 'migrations'\n\nexport async function provisionForTest(\n app: object,\n mode: TestSchemaMode,\n): Promise<void> {\n if (mode === 'auto') {\n await provision(app, { force: true })\n return\n }\n\n const internals = getProvisionInternals(app)\n if (mode === 'push') {\n await provisionSchema(internals.db, internals.schema, {\n force: true,\n databaseUrl: internals.databaseUrl,\n })\n return\n }\n\n if (!(await applyCommittedMigrations(app))) {\n throw new Error('[bunderstack] committed migrations journal not found')\n }\n}\n"]}
|
package/dist/provision.d.ts
CHANGED
|
@@ -1,25 +1,8 @@
|
|
|
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
1
|
/**
|
|
8
|
-
*
|
|
2
|
+
* Apply committed migrations for a Bunderstack app.
|
|
9
3
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* drizzle-orm's migrator. Pure runtime; drizzle-kit is never imported, so a
|
|
13
|
-
* fresh clone deploys with `bun install --production`.
|
|
14
|
-
* - No migrations → development: push the schema straight to the database via
|
|
15
|
-
* drizzle-kit (install it with `bun add -d drizzle-kit`).
|
|
16
|
-
*
|
|
17
|
-
* Once you run `bunx drizzle-kit generate` for the first time, provision stops
|
|
18
|
-
* pushing and every schema change goes through an explicit `generate`.
|
|
4
|
+
* This production entrypoint has no Drizzle Kit dependency. Development
|
|
5
|
+
* schema push is deliberately isolated in `bunderstack/provision-schema`.
|
|
19
6
|
*/
|
|
20
|
-
export declare function provision(app: object
|
|
21
|
-
force?: boolean;
|
|
22
|
-
}): Promise<void>;
|
|
23
|
-
export type TestSchemaMode = 'auto' | 'push' | 'migrations';
|
|
24
|
-
export declare function provisionForTest(app: object, mode: TestSchemaMode): Promise<void>;
|
|
7
|
+
export declare function provision(app: object): Promise<void>;
|
|
25
8
|
//# sourceMappingURL=provision.d.ts.map
|
package/dist/provision.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provision.d.ts","sourceRoot":"","sources":["../src/provision.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"provision.d.ts","sourceRoot":"","sources":["../src/provision.ts"],"names":[],"mappings":"AAOA;;;;;GAKG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAI1D"}
|
package/dist/provision.js
CHANGED
|
@@ -1,117 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import { PROVISION_INTERNALS, } from './provision-internals.js';
|
|
6
|
-
/** Create the local backing directory for file-based urls, per dialect. */
|
|
7
|
-
async function ensureLocalDataDir(url, dialect) {
|
|
8
|
-
if (dialect === 'pg') {
|
|
9
|
-
// PGlite data dir: `file:<dir>` or a bare path; server/memory urls need nothing.
|
|
10
|
-
if (/^postgres(ql)?:\/\//.test(url))
|
|
11
|
-
return;
|
|
12
|
-
const raw = url.startsWith('file:') ? url.slice('file:'.length) : url;
|
|
13
|
-
if (raw === ':memory:' || raw.startsWith('memory://'))
|
|
14
|
-
return;
|
|
15
|
-
await mkdir(raw, { recursive: true });
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
const match = /^file:(.+)$/.exec(url);
|
|
19
|
-
if (!match)
|
|
20
|
-
return;
|
|
21
|
-
const filePath = match[1];
|
|
22
|
-
if (filePath === ':memory:')
|
|
23
|
-
return;
|
|
24
|
-
await mkdir(dirname(filePath), { recursive: true });
|
|
25
|
-
}
|
|
26
|
-
async function exists(path) {
|
|
27
|
-
try {
|
|
28
|
-
await access(path);
|
|
29
|
-
return true;
|
|
30
|
-
}
|
|
31
|
-
catch {
|
|
32
|
-
return false;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
const DRIZZLE_KIT_HINT = '[bunderstack] Schema push requires drizzle-kit, which is not installed.\n' +
|
|
36
|
-
' Development: run `bun add -d drizzle-kit` — provision() will push schema changes to the database on startup.\n' +
|
|
37
|
-
' Production: generate migrations locally with `bunx drizzle-kit generate` and commit the folder — provision() applies them without drizzle-kit.';
|
|
38
|
-
/** Push the merged schema to the database via drizzle-kit/api. */
|
|
39
|
-
export async function provisionSchema(db, schema, options) {
|
|
40
|
-
const dialect = detectDialect(schema);
|
|
41
|
-
if (options?.databaseUrl) {
|
|
42
|
-
await ensureLocalDataDir(options.databaseUrl, dialect);
|
|
43
|
-
}
|
|
44
|
-
let kit;
|
|
45
|
-
try {
|
|
46
|
-
kit = await import('drizzle-kit/api');
|
|
47
|
-
}
|
|
48
|
-
catch (cause) {
|
|
49
|
-
throw new Error(DRIZZLE_KIT_HINT, { cause });
|
|
50
|
-
}
|
|
51
|
-
const result = dialect === 'pg'
|
|
52
|
-
? await kit.pushSchema(schema, db)
|
|
53
|
-
: await kit.pushSQLiteSchema(schema, db);
|
|
54
|
-
if (result.hasDataLoss && !options?.force) {
|
|
55
|
-
throw new Error('[bunderstack] Schema push would cause data loss. Run `bunx drizzle-kit push` or call provision(app, { force: true }).');
|
|
56
|
-
}
|
|
57
|
-
if (result.warnings.length > 0) {
|
|
58
|
-
for (const warning of result.warnings) {
|
|
59
|
-
console.warn(`[bunderstack] ${warning}`);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
if (result.statementsToExecute.length === 0)
|
|
63
|
-
return;
|
|
64
|
-
await result.apply();
|
|
65
|
-
console.log(`[bunderstack] provisioned ${result.statementsToExecute.length} schema change(s)`);
|
|
66
|
-
}
|
|
1
|
+
import { applyCommittedMigrations } from './provision-runtime.js';
|
|
2
|
+
const MIGRATIONS_REQUIRED = '[bunderstack] No committed migrations journal was found.\n' +
|
|
3
|
+
' Production: generate migrations with `bunx drizzle-kit generate`, commit them, and keep using `bunderstack/provision`.\n' +
|
|
4
|
+
' Development schema push: import provision from `bunderstack/provision-schema`.';
|
|
67
5
|
/**
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
* The migrations folder is the mode switch:
|
|
71
|
-
* - `<migrations>/meta/_journal.json` exists → apply committed migrations via
|
|
72
|
-
* drizzle-orm's migrator. Pure runtime; drizzle-kit is never imported, so a
|
|
73
|
-
* fresh clone deploys with `bun install --production`.
|
|
74
|
-
* - No migrations → development: push the schema straight to the database via
|
|
75
|
-
* drizzle-kit (install it with `bun add -d drizzle-kit`).
|
|
6
|
+
* Apply committed migrations for a Bunderstack app.
|
|
76
7
|
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
8
|
+
* This production entrypoint has no Drizzle Kit dependency. Development
|
|
9
|
+
* schema push is deliberately isolated in `bunderstack/provision-schema`.
|
|
79
10
|
*/
|
|
80
|
-
export async function provision(app
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
throw new Error('[bunderstack] provision() expects the app returned by bunderstack().');
|
|
84
|
-
}
|
|
85
|
-
const { db, schema, databaseUrl, migrationsFolder, dialect, adapter } = internals;
|
|
86
|
-
const journal = join(migrationsFolder, 'meta', '_journal.json');
|
|
87
|
-
if (await exists(journal)) {
|
|
88
|
-
await ensureLocalDataDir(databaseUrl, dialect);
|
|
89
|
-
await adapter.migrate(db, migrationsFolder);
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
await provisionSchema(db, schema, { force: options?.force, databaseUrl });
|
|
93
|
-
}
|
|
94
|
-
export async function provisionForTest(app, mode) {
|
|
95
|
-
if (mode === 'auto') {
|
|
96
|
-
await provision(app, { force: true });
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
const internals = app[PROVISION_INTERNALS];
|
|
100
|
-
if (!internals) {
|
|
101
|
-
throw new Error('[bunderstack] test provisioning expects a Bunderstack runtime');
|
|
102
|
-
}
|
|
103
|
-
if (mode === 'push') {
|
|
104
|
-
await provisionSchema(internals.db, internals.schema, {
|
|
105
|
-
force: true,
|
|
106
|
-
databaseUrl: internals.databaseUrl,
|
|
107
|
-
});
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
const journal = join(internals.migrationsFolder, 'meta', '_journal.json');
|
|
111
|
-
if (!(await exists(journal))) {
|
|
112
|
-
throw new Error('[bunderstack] committed migrations journal not found');
|
|
11
|
+
export async function provision(app) {
|
|
12
|
+
if (!(await applyCommittedMigrations(app))) {
|
|
13
|
+
throw new Error(MIGRATIONS_REQUIRED);
|
|
113
14
|
}
|
|
114
|
-
await ensureLocalDataDir(internals.databaseUrl, internals.dialect);
|
|
115
|
-
await internals.adapter.migrate(internals.db, internals.migrationsFolder);
|
|
116
15
|
}
|
|
117
16
|
//# sourceMappingURL=provision.js.map
|
package/dist/provision.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provision.js","sourceRoot":"","sources":["../src/provision.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"provision.js","sourceRoot":"","sources":["../src/provision.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAA;AAE9D,MAAM,mBAAmB,GACvB,4DAA4D;IAC5D,4HAA4H;IAC5H,kFAAkF,CAAA;AAEpF;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAW;IACzC,IAAI,CAAC,CAAC,MAAM,wBAAwB,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAA;IACtC,CAAC;AACH,CAAC","sourcesContent":["import { applyCommittedMigrations } from './provision-runtime'\n\nconst MIGRATIONS_REQUIRED =\n '[bunderstack] No committed migrations journal was found.\\n' +\n ' Production: generate migrations with `bunx drizzle-kit generate`, commit them, and keep using `bunderstack/provision`.\\n' +\n ' Development schema push: import provision from `bunderstack/provision-schema`.'\n\n/**\n * Apply committed migrations for a Bunderstack app.\n *\n * This production entrypoint has no Drizzle Kit dependency. Development\n * schema push is deliberately isolated in `bunderstack/provision-schema`.\n */\nexport async function provision(app: object): Promise<void> {\n if (!(await applyCommittedMigrations(app))) {\n throw new Error(MIGRATIONS_REQUIRED)\n }\n}\n"]}
|
package/dist/runtime.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AnyRouter as AnyORPCRouter } from '@orpc/server';
|
|
2
|
+
import type { Auth } from 'better-auth';
|
|
2
3
|
import type { TableAccessInput } from './access.js';
|
|
3
4
|
import type { AuthSessionResolver } from './access.js';
|
|
4
5
|
import type { RealtimeApiRouter } from './api/realtime-router.js';
|
|
@@ -7,20 +8,22 @@ import type { RuntimeTestingHandle } from './backend-internals.js';
|
|
|
7
8
|
import type { DatabaseConnection } from './database/adapter.js';
|
|
8
9
|
import type { DbFor } from './db.js';
|
|
9
10
|
import type { BunderstackJobsBuilder, JobsDefs, JobsFacade, StartWorkerOptions, WorkerHandle } from './jobs/index.js';
|
|
11
|
+
import type { MessagingConfig, MessagingFacadesFor } from './messaging/index.js';
|
|
12
|
+
import type { MessagingAdapter } from './messaging/runtime.js';
|
|
10
13
|
import type { ResolvedStorageBuckets, StorageConfigInput } from './storage/buckets.js';
|
|
11
14
|
import type { StorageAdapter } from './storage/index.js';
|
|
12
|
-
import {
|
|
13
|
-
import { type BunderstackConfig } from './config.js';
|
|
14
|
-
import { type EmailAdapter, type EmailFacade } from './email.js';
|
|
15
|
+
import { type BunderstackAuth } from './auth.js';
|
|
16
|
+
import { type BetterAuthConfig, type BunderstackConfig } from './config.js';
|
|
15
17
|
import { type EnvConfigInput, type ValidatedEnv } from './env.js';
|
|
16
18
|
import { type LifecycleStatus } from './lifecycle.js';
|
|
17
19
|
import { type BunderstackLogger } from './logging.js';
|
|
18
20
|
import { type RealtimeFacade } from './realtime/facade.js';
|
|
19
|
-
|
|
21
|
+
/** Base Better Auth contract used by framework internals and API context. */
|
|
22
|
+
export type AuthInstance = Auth;
|
|
20
23
|
export type RuntimeOverrides = {
|
|
21
24
|
database?: DatabaseConnection;
|
|
22
25
|
resolvedStorage?: ResolvedStorageBuckets;
|
|
23
|
-
|
|
26
|
+
messagingAdapters?: Record<string, MessagingAdapter>;
|
|
24
27
|
forceMemoryRealtime?: boolean;
|
|
25
28
|
backgroundAutoStart?: false;
|
|
26
29
|
authResolver?: AuthSessionResolver;
|
|
@@ -76,15 +79,15 @@ export type AppRunWorkerOptions = AppStartWorkerOptions & {
|
|
|
76
79
|
export type BucketNamesOf<TStorage> = TStorage extends {
|
|
77
80
|
buckets: infer B extends Record<string, unknown>;
|
|
78
81
|
} ? keyof B & string : string;
|
|
79
|
-
export type BunderstackApp<TSchema extends Record<string, unknown>, TAccess extends Record<string, TableAccessInput> | undefined = undefined, TBuckets extends string = string, TEnv extends EnvConfigInput | undefined = undefined, TJobsDefs extends JobsDefs | undefined = undefined, TCustomApiRouter extends AnyORPCRouter | undefined = undefined, TRealtime = undefined> = {
|
|
82
|
+
export type BunderstackApp<TSchema extends Record<string, unknown>, TAccess extends Record<string, TableAccessInput> | undefined = undefined, TBuckets extends string = string, TEnv extends EnvConfigInput | undefined = undefined, TJobsDefs extends JobsDefs | undefined = undefined, TCustomApiRouter extends AnyORPCRouter | undefined = undefined, TRealtime = undefined, TMessaging extends MessagingConfig | undefined = undefined, TAuthConfig extends BetterAuthConfig = BetterAuthConfig> = {
|
|
80
83
|
handler: (req: Request) => Promise<Response>;
|
|
81
84
|
db: DbFor<TSchema>;
|
|
82
|
-
auth:
|
|
85
|
+
auth: BunderstackAuth<TAuthConfig>;
|
|
83
86
|
storage: StorageFacade;
|
|
84
87
|
/** Validated env: bunderstack's base vars plus the config's `env` extension. */
|
|
85
88
|
env: ValidatedEnv<TEnv>;
|
|
86
|
-
/**
|
|
87
|
-
|
|
89
|
+
/** Named, provider-specific outbound messaging channels. */
|
|
90
|
+
messaging: MessagingFacadesFor<TMessaging>;
|
|
88
91
|
/** Job queue facade; always present — enqueue throws when jobs aren't configured. */
|
|
89
92
|
jobs: JobsFacade<TJobsDefs extends JobsDefs ? TJobsDefs : Record<never, never>>;
|
|
90
93
|
/** Typed custom row publication; enabled=false/no-op when realtime is off. */
|
|
@@ -112,10 +115,11 @@ export type BunderstackApp<TSchema extends Record<string, unknown>, TAccess exte
|
|
|
112
115
|
] extends [false | undefined] ? {} : RealtimeApiRouter>;
|
|
113
116
|
};
|
|
114
117
|
};
|
|
115
|
-
export declare function materializeBunderstack<TSchema extends Record<string, unknown>, const TAccess extends Record<string, TableAccessInput> | undefined = undefined, const TStorage extends StorageConfigInput | undefined = undefined, const TEnv extends EnvConfigInput | undefined = undefined, const TJobsDefs extends JobsDefs | undefined = undefined, TCustomApiRouter extends AnyORPCRouter | undefined = undefined, const TRealtime extends BunderstackConfig<TSchema, TAccess, TStorage, TEnv, TCustomApiRouter>['realtime'] = undefined>(options: BunderstackConfig<TSchema, TAccess, TStorage, TEnv, TCustomApiRouter> & {
|
|
118
|
+
export declare function materializeBunderstack<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, const TMessaging extends MessagingConfig | undefined = undefined, const TAuthConfig extends BetterAuthConfig = BetterAuthConfig>(options: BunderstackConfig<TSchema, TAccess, TStorage, TEnv, TCustomApiRouter, TAuthConfig> & {
|
|
116
119
|
realtime?: TRealtime;
|
|
117
|
-
|
|
118
|
-
|
|
120
|
+
messaging?: TMessaging;
|
|
121
|
+
jobs?: TJobsDefs | ((j: BunderstackJobsBuilder<TSchema, ValidatedEnv<TEnv>, TMessaging>) => TJobsDefs);
|
|
122
|
+
}, source: Record<string, string | undefined>, overrides?: RuntimeOverrides, env?: ValidatedEnv<TEnv>): Promise<BunderstackApp<TSchema, TAccess, BucketNamesOf<TStorage>, TEnv, TJobsDefs, TCustomApiRouter, TRealtime, TMessaging, TAuthConfig>>;
|
|
119
123
|
export { listSpec } from './api/list-spec.js';
|
|
120
124
|
export type { ListSpecOptions } from './api/list-spec.js';
|
|
121
125
|
export type { BunderstackDb, BunderstackTx } from './db.js';
|
|
@@ -128,8 +132,7 @@ export { validateEnv, createClientEnv, BunderstackEnvError } from './env.js';
|
|
|
128
132
|
export type { EnvConfigInput, BaseEnv, ValidatedEnv } from './env.js';
|
|
129
133
|
export { buildManifest, parseManifest } from './manifest.js';
|
|
130
134
|
export type { BunderstackManifest, ManifestEnvVar } from './manifest.js';
|
|
131
|
-
export {
|
|
132
|
-
export type { EmailMessage, EmailAdapter, EmailConfigInput, EmailFacade, } from './email.js';
|
|
135
|
+
export type { EmailMessage, EmailAdapter } from './email.js';
|
|
133
136
|
export { createJobsBuilder } from './jobs/index.js';
|
|
134
137
|
export type { BunderstackJobContext, BunderstackJobsBuilder, BackgroundDefinition, BackgroundDefs, CronDefinition, CronInvocation, EnqueueOptions, JobContext, JobDefinition, JobsDefs, JobsFacade, JobsRuntimeFacade, QueueJobDefinition, QueueJobKeys, RunWorkerOptions, StartWorkerOptions, WorkerHandle, } from './jobs/index.js';
|
|
135
138
|
export { defineAccess, validateAndResolveAccess, checkAccess, AUTH_TABLE_NAMES, } from './access.js';
|