bunderstack 0.7.0 → 0.8.0
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/README.md +23 -12
- package/package.json +23 -10
- package/src/config.ts +36 -6
- package/src/database/adapter.ts +26 -0
- package/src/database/bun-sql.ts +23 -0
- package/src/database/libsql.ts +28 -0
- package/src/database/pglite.ts +33 -0
- package/src/database/postgres-js.ts +33 -0
- package/src/db.ts +32 -74
- package/src/email/smtp.ts +45 -0
- package/src/email.ts +13 -59
- package/src/index.ts +359 -297
- package/src/lifecycle.ts +7 -2
- package/src/provision-internals.ts +2 -1
- package/src/provision.ts +7 -18
- package/src/typeid.ts +2 -2
package/src/lifecycle.ts
CHANGED
|
@@ -30,13 +30,18 @@ export class Lifecycle {
|
|
|
30
30
|
this.#closePromise = (async () => {
|
|
31
31
|
const cleanups = [...this.#cleanups].reverse()
|
|
32
32
|
this.#cleanups.clear()
|
|
33
|
-
const results = await Promise.allSettled(
|
|
33
|
+
const results = await Promise.allSettled(
|
|
34
|
+
cleanups.map(async (cleanup) => cleanup()),
|
|
35
|
+
)
|
|
34
36
|
this.#status = 'closed'
|
|
35
37
|
const errors = results.flatMap((result) =>
|
|
36
38
|
result.status === 'rejected' ? [result.reason] : [],
|
|
37
39
|
)
|
|
38
40
|
if (errors.length > 0) {
|
|
39
|
-
throw new AggregateError(
|
|
41
|
+
throw new AggregateError(
|
|
42
|
+
errors,
|
|
43
|
+
'[bunderstack] lifecycle cleanup failed',
|
|
44
|
+
)
|
|
40
45
|
}
|
|
41
46
|
})()
|
|
42
47
|
return this.#closePromise
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import type { Driver } from './db'
|
|
1
2
|
// src/provision-internals.ts
|
|
2
3
|
import type { AnyDb, Dialect } from './dialect'
|
|
3
|
-
import type { Driver } from './db'
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Hidden handle connecting `createBunderstack()` to the optional
|
|
@@ -21,6 +21,7 @@ export interface ProvisionInternals {
|
|
|
21
21
|
migrationsFolder: string
|
|
22
22
|
dialect: Dialect
|
|
23
23
|
driver: Driver
|
|
24
|
+
adapter: import('./database/adapter').DatabaseAdapter
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
export interface WithProvisionInternals {
|
package/src/provision.ts
CHANGED
|
@@ -11,7 +11,10 @@ import {
|
|
|
11
11
|
} from './provision-internals'
|
|
12
12
|
|
|
13
13
|
/** Create the local backing directory for file-based urls, per dialect. */
|
|
14
|
-
async function ensureLocalDataDir(
|
|
14
|
+
async function ensureLocalDataDir(
|
|
15
|
+
url: string,
|
|
16
|
+
dialect: Dialect,
|
|
17
|
+
): Promise<void> {
|
|
15
18
|
if (dialect === 'pg') {
|
|
16
19
|
// PGlite data dir: `file:<dir>` or a bare path; server/memory urls need nothing.
|
|
17
20
|
if (/^postgres(ql)?:\/\//.test(url)) return
|
|
@@ -54,11 +57,7 @@ export async function provisionSchema<TSchema extends Record<string, unknown>>(
|
|
|
54
57
|
|
|
55
58
|
let kit: typeof import('drizzle-kit/api')
|
|
56
59
|
try {
|
|
57
|
-
|
|
58
|
-
// drizzle-kit at build time — this branch only runs in development.
|
|
59
|
-
kit = await import(
|
|
60
|
-
/* @vite-ignore */ /* webpackIgnore: true */ 'drizzle-kit/api'
|
|
61
|
-
)
|
|
60
|
+
kit = await import('drizzle-kit/api')
|
|
62
61
|
} catch (cause) {
|
|
63
62
|
throw new Error(DRIZZLE_KIT_HINT, { cause })
|
|
64
63
|
}
|
|
@@ -89,13 +88,6 @@ export async function provisionSchema<TSchema extends Record<string, unknown>>(
|
|
|
89
88
|
)
|
|
90
89
|
}
|
|
91
90
|
|
|
92
|
-
const MIGRATOR_MODULES = {
|
|
93
|
-
libsql: 'drizzle-orm/libsql/migrator',
|
|
94
|
-
pglite: 'drizzle-orm/pglite/migrator',
|
|
95
|
-
'bun-sql': 'drizzle-orm/bun-sql/migrator',
|
|
96
|
-
'postgres-js': 'drizzle-orm/postgres-js/migrator',
|
|
97
|
-
} as const
|
|
98
|
-
|
|
99
91
|
/**
|
|
100
92
|
* Provision the database for a Bunderstack app.
|
|
101
93
|
*
|
|
@@ -120,16 +112,13 @@ export async function provision(
|
|
|
120
112
|
)
|
|
121
113
|
}
|
|
122
114
|
|
|
123
|
-
const { db, schema, databaseUrl, migrationsFolder, dialect,
|
|
115
|
+
const { db, schema, databaseUrl, migrationsFolder, dialect, adapter } =
|
|
124
116
|
internals
|
|
125
117
|
const journal = join(migrationsFolder, 'meta', '_journal.json')
|
|
126
118
|
|
|
127
119
|
if (await exists(journal)) {
|
|
128
120
|
await ensureLocalDataDir(databaseUrl, dialect)
|
|
129
|
-
|
|
130
|
-
/* @vite-ignore */ /* webpackIgnore: true */ MIGRATOR_MODULES[driver]
|
|
131
|
-
)) as { migrate: (db: never, cfg: { migrationsFolder: string }) => Promise<void> }
|
|
132
|
-
await migrate(db as never, { migrationsFolder })
|
|
121
|
+
await adapter.migrate(db as never, migrationsFolder)
|
|
133
122
|
return
|
|
134
123
|
}
|
|
135
124
|
|
package/src/typeid.ts
CHANGED
|
@@ -16,10 +16,10 @@ const PREFIX_RE = /^[a-z]([a-z_]{0,61}[a-z])?$/
|
|
|
16
16
|
// 26 base32 chars from the alphabet above.
|
|
17
17
|
const SUFFIX_RE = /^[0-9a-hjkmnp-tv-z]{26}$/
|
|
18
18
|
|
|
19
|
-
declare const
|
|
19
|
+
declare const typeIdBrand: unique symbol
|
|
20
20
|
|
|
21
21
|
/** A branded TypeID string. `TypeId<'post'>` is incompatible with `TypeId<'user'>`. */
|
|
22
|
-
export type TypeId<P extends string> = string & { readonly [
|
|
22
|
+
export type TypeId<P extends string> = string & { readonly [typeIdBrand]?: P }
|
|
23
23
|
|
|
24
24
|
/** Encode a 16-byte UUID into the 26-character base32 suffix. */
|
|
25
25
|
export function encode(bytes: Uint8Array): string {
|