bunderstack 0.17.0-beta.2 → 0.17.0-beta.4
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 +233 -0
- package/README.md +11 -1
- package/dist/access.d.ts +116 -0
- package/dist/access.d.ts.map +1 -0
- package/dist/access.js +325 -0
- package/dist/access.js.map +1 -0
- package/dist/api/builder.d.ts +145 -0
- package/dist/api/builder.d.ts.map +1 -0
- package/dist/api/builder.js +28 -0
- package/dist/api/builder.js.map +1 -0
- package/dist/api/context.d.ts +34 -0
- package/dist/api/context.d.ts.map +1 -0
- package/dist/api/context.js +32 -0
- package/dist/api/context.js.map +1 -0
- package/dist/api/crud-router.d.ts +290 -0
- package/dist/api/crud-router.d.ts.map +1 -0
- package/dist/api/crud-router.js +249 -0
- package/dist/api/crud-router.js.map +1 -0
- package/dist/api/openapi.d.ts +6 -0
- package/dist/api/openapi.d.ts.map +1 -0
- package/dist/api/openapi.js +146 -0
- package/dist/api/openapi.js.map +1 -0
- package/dist/api/realtime-router.d.ts +76 -0
- package/dist/api/realtime-router.d.ts.map +1 -0
- package/dist/api/realtime-router.js +41 -0
- package/dist/api/realtime-router.js.map +1 -0
- package/dist/api/registry.d.ts +30 -0
- package/dist/api/registry.d.ts.map +1 -0
- package/dist/api/registry.js +239 -0
- package/dist/api/registry.js.map +1 -0
- package/dist/api/router.d.ts +9 -0
- package/dist/api/router.d.ts.map +1 -0
- package/dist/api/router.js +19 -0
- package/dist/api/router.js.map +1 -0
- package/dist/api/storage-router.d.ts +279 -0
- package/dist/api/storage-router.d.ts.map +1 -0
- package/dist/api/storage-router.js +155 -0
- package/dist/api/storage-router.js.map +1 -0
- package/dist/api/types.d.ts +55 -0
- package/dist/api/types.d.ts.map +1 -0
- package/dist/api/types.js +2 -0
- package/dist/api/types.js.map +1 -0
- package/dist/auth.d.ts +31 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +102 -0
- package/dist/auth.js.map +1 -0
- package/dist/blueprint-generator.d.ts +18 -0
- package/dist/blueprint-generator.d.ts.map +1 -0
- package/dist/blueprint-generator.js +125 -0
- package/dist/blueprint-generator.js.map +1 -0
- package/dist/blueprint.d.ts +46 -0
- package/dist/blueprint.d.ts.map +1 -0
- package/dist/blueprint.js +162 -0
- package/dist/blueprint.js.map +1 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +68 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +108 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +90 -0
- package/dist/config.js.map +1 -0
- package/dist/cron.d.ts +4 -0
- package/dist/cron.d.ts.map +1 -0
- package/dist/cron.js +3 -0
- package/dist/cron.js.map +1 -0
- package/dist/crud-operations.d.ts +43 -0
- package/dist/crud-operations.d.ts.map +1 -0
- package/dist/crud-operations.js +238 -0
- package/dist/crud-operations.js.map +1 -0
- package/dist/database/adapter.d.ts +20 -0
- package/dist/database/adapter.d.ts.map +1 -0
- package/dist/database/adapter.js +2 -0
- package/dist/database/adapter.js.map +1 -0
- package/dist/database/bun-sql.d.ts +3 -0
- package/dist/database/bun-sql.d.ts.map +1 -0
- package/dist/database/bun-sql.js +21 -0
- package/dist/database/bun-sql.js.map +1 -0
- package/dist/database/libsql.d.ts +3 -0
- package/dist/database/libsql.d.ts.map +1 -0
- package/dist/database/libsql.js +22 -0
- package/dist/database/libsql.js.map +1 -0
- package/dist/database/pglite.d.ts +3 -0
- package/dist/database/pglite.d.ts.map +1 -0
- package/dist/database/pglite.js +27 -0
- package/dist/database/pglite.js.map +1 -0
- package/dist/database/postgres-js.d.ts +3 -0
- package/dist/database/postgres-js.d.ts.map +1 -0
- package/dist/database/postgres-js.js +21 -0
- package/dist/database/postgres-js.js.map +1 -0
- package/dist/db.d.ts +18 -0
- package/dist/db.d.ts.map +1 -0
- package/dist/db.js +26 -0
- package/dist/db.js.map +1 -0
- package/dist/dialect.d.ts +17 -0
- package/dist/dialect.d.ts.map +1 -0
- package/dist/dialect.js +22 -0
- package/dist/dialect.js.map +1 -0
- package/dist/email/smtp.d.ts +14 -0
- package/dist/email/smtp.d.ts.map +1 -0
- package/dist/email/smtp.js +27 -0
- package/dist/email/smtp.js.map +1 -0
- package/dist/email.d.ts +39 -0
- package/dist/email.d.ts.map +1 -0
- package/dist/email.js +97 -0
- package/dist/email.js.map +1 -0
- package/dist/env.d.ts +47 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +99 -0
- package/dist/env.js.map +1 -0
- package/dist/errors.d.ts +125 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +92 -0
- package/dist/errors.js.map +1 -0
- package/dist/handler.d.ts +9 -0
- package/dist/handler.d.ts.map +1 -0
- package/dist/handler.js +22 -0
- package/dist/handler.js.map +1 -0
- package/dist/idempotency.d.ts +17 -0
- package/dist/idempotency.d.ts.map +1 -0
- package/dist/idempotency.js +65 -0
- package/dist/idempotency.js.map +1 -0
- package/dist/index.d.ts +134 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +480 -0
- package/dist/index.js.map +1 -0
- package/dist/internal-tables-pg.d.ts +481 -0
- package/dist/internal-tables-pg.d.ts.map +1 -0
- package/{src/internal-tables-pg.ts → dist/internal-tables-pg.js} +10 -34
- package/dist/internal-tables-pg.js.map +1 -0
- package/dist/internal-tables.d.ts +2509 -0
- package/dist/internal-tables.d.ts.map +1 -0
- package/dist/internal-tables.js +108 -0
- package/dist/internal-tables.js.map +1 -0
- package/dist/jobs/cron.d.ts +15 -0
- package/dist/jobs/cron.d.ts.map +1 -0
- package/dist/jobs/cron.js +74 -0
- package/dist/jobs/cron.js.map +1 -0
- package/dist/jobs/define.d.ts +133 -0
- package/dist/jobs/define.d.ts.map +1 -0
- package/dist/jobs/define.js +74 -0
- package/dist/jobs/define.js.map +1 -0
- package/dist/jobs/index.d.ts +11 -0
- package/dist/jobs/index.d.ts.map +1 -0
- package/dist/jobs/index.js +8 -0
- package/dist/jobs/index.js.map +1 -0
- package/dist/jobs/queue.d.ts +6 -0
- package/dist/jobs/queue.d.ts.map +1 -0
- package/dist/jobs/queue.js +55 -0
- package/dist/jobs/queue.js.map +1 -0
- package/dist/jobs/runtime.d.ts +13 -0
- package/dist/jobs/runtime.d.ts.map +1 -0
- package/dist/jobs/runtime.js +46 -0
- package/dist/jobs/runtime.js.map +1 -0
- package/dist/jobs/slots.d.ts +25 -0
- package/dist/jobs/slots.d.ts.map +1 -0
- package/dist/jobs/slots.js +41 -0
- package/dist/jobs/slots.js.map +1 -0
- package/dist/jobs/worker.d.ts +12 -0
- package/dist/jobs/worker.d.ts.map +1 -0
- package/dist/jobs/worker.js +311 -0
- package/dist/jobs/worker.js.map +1 -0
- package/dist/lifecycle.d.ts +10 -0
- package/dist/lifecycle.d.ts.map +1 -0
- package/dist/lifecycle.js +37 -0
- package/dist/lifecycle.js.map +1 -0
- package/dist/list-query.d.ts +62 -0
- package/dist/list-query.d.ts.map +1 -0
- package/dist/list-query.js +194 -0
- package/dist/list-query.js.map +1 -0
- package/dist/manifest.d.ts +59 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +167 -0
- package/dist/manifest.js.map +1 -0
- package/dist/provision-internals.d.ts +24 -0
- package/dist/provision-internals.d.ts.map +1 -0
- package/dist/provision-internals.js +7 -0
- package/dist/provision-internals.js.map +1 -0
- package/dist/provision.d.ts +23 -0
- package/dist/provision.d.ts.map +1 -0
- package/dist/provision.js +96 -0
- package/dist/provision.js.map +1 -0
- package/dist/rate-limit.d.ts +7 -0
- package/dist/rate-limit.d.ts.map +1 -0
- package/dist/rate-limit.js +49 -0
- package/dist/rate-limit.js.map +1 -0
- package/dist/realtime/facade.d.ts +18 -0
- package/dist/realtime/facade.d.ts.map +1 -0
- package/dist/realtime/facade.js +36 -0
- package/dist/realtime/facade.js.map +1 -0
- package/dist/realtime/filter.d.ts +13 -0
- package/dist/realtime/filter.d.ts.map +1 -0
- package/dist/realtime/filter.js +48 -0
- package/dist/realtime/filter.js.map +1 -0
- package/dist/realtime/heartbeat.d.ts +14 -0
- package/dist/realtime/heartbeat.d.ts.map +1 -0
- package/dist/realtime/heartbeat.js +64 -0
- package/dist/realtime/heartbeat.js.map +1 -0
- package/dist/realtime/publisher.d.ts +21 -0
- package/dist/realtime/publisher.d.ts.map +1 -0
- package/dist/realtime/publisher.js +17 -0
- package/dist/realtime/publisher.js.map +1 -0
- package/dist/schema-export-pg.d.ts +2 -0
- package/dist/schema-export-pg.d.ts.map +1 -0
- package/dist/schema-export-pg.js +4 -0
- package/dist/schema-export-pg.js.map +1 -0
- package/dist/schema-export.d.ts +2 -0
- package/dist/schema-export.d.ts.map +1 -0
- package/dist/schema-export.js +2 -0
- package/dist/schema-export.js.map +1 -0
- package/dist/scope.d.ts +4 -0
- package/dist/scope.d.ts.map +1 -0
- package/dist/scope.js +13 -0
- package/dist/scope.js.map +1 -0
- package/dist/standard-schema.d.ts +13 -0
- package/dist/standard-schema.d.ts.map +1 -0
- package/dist/standard-schema.js +34 -0
- package/dist/standard-schema.js.map +1 -0
- package/dist/storage/buckets.d.ts +80 -0
- package/dist/storage/buckets.d.ts.map +1 -0
- package/dist/storage/buckets.js +178 -0
- package/dist/storage/buckets.js.map +1 -0
- package/dist/storage/delete.d.ts +11 -0
- package/dist/storage/delete.d.ts.map +1 -0
- package/dist/storage/delete.js +18 -0
- package/dist/storage/delete.js.map +1 -0
- package/dist/storage/file-meta.d.ts +37 -0
- package/dist/storage/file-meta.d.ts.map +1 -0
- package/dist/storage/file-meta.js +166 -0
- package/dist/storage/file-meta.js.map +1 -0
- package/dist/storage/index.d.ts +28 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +5 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/local.d.ts +15 -0
- package/dist/storage/local.d.ts.map +1 -0
- package/dist/storage/local.js +56 -0
- package/dist/storage/local.js.map +1 -0
- package/dist/storage/operations.d.ts +54 -0
- package/dist/storage/operations.d.ts.map +1 -0
- package/dist/storage/operations.js +250 -0
- package/dist/storage/operations.js.map +1 -0
- package/dist/storage/registry.d.ts +10 -0
- package/dist/storage/registry.d.ts.map +1 -0
- package/dist/storage/registry.js +23 -0
- package/dist/storage/registry.js.map +1 -0
- package/dist/storage/s3.d.ts +28 -0
- package/dist/storage/s3.d.ts.map +1 -0
- package/dist/storage/s3.js +71 -0
- package/dist/storage/s3.js.map +1 -0
- package/dist/storage/sweep.d.ts +9 -0
- package/dist/storage/sweep.d.ts.map +1 -0
- package/dist/storage/sweep.js +17 -0
- package/dist/storage/sweep.js.map +1 -0
- package/dist/storage/thumbnails.d.ts +11 -0
- package/dist/storage/thumbnails.d.ts.map +1 -0
- package/dist/storage/thumbnails.js +60 -0
- package/dist/storage/thumbnails.js.map +1 -0
- package/dist/testing.d.ts +27 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +11 -0
- package/dist/testing.js.map +1 -0
- package/dist/typeid-pg.d.ts +19 -0
- package/dist/typeid-pg.d.ts.map +1 -0
- package/{src/typeid-pg.ts → dist/typeid-pg.js} +10 -13
- package/dist/typeid-pg.js.map +1 -0
- package/dist/typeid.d.ts +45 -0
- package/dist/typeid.d.ts.map +1 -0
- package/dist/typeid.js +100 -0
- package/dist/typeid.js.map +1 -0
- package/package.json +77 -28
- package/src/access.ts +0 -532
- package/src/api/builder.ts +0 -52
- package/src/api/context.ts +0 -83
- package/src/api/crud-router.ts +0 -386
- package/src/api/openapi.ts +0 -184
- package/src/api/realtime-router.ts +0 -75
- package/src/api/registry.ts +0 -338
- package/src/api/router.ts +0 -34
- package/src/api/storage-router.ts +0 -224
- package/src/api/types.ts +0 -105
- package/src/auth.ts +0 -117
- package/src/blueprint-generator.ts +0 -203
- package/src/blueprint.ts +0 -264
- package/src/cli.ts +0 -90
- package/src/config.ts +0 -215
- package/src/cron.ts +0 -3
- package/src/crud-operations.ts +0 -478
- package/src/database/adapter.ts +0 -26
- package/src/database/bun-sql.ts +0 -23
- package/src/database/libsql.ts +0 -28
- package/src/database/pglite.ts +0 -33
- package/src/database/postgres-js.ts +0 -33
- package/src/db.ts +0 -61
- package/src/dialect.ts +0 -38
- package/src/email/smtp.ts +0 -45
- package/src/email.ts +0 -154
- package/src/env.ts +0 -180
- package/src/errors.ts +0 -123
- package/src/handler.ts +0 -30
- package/src/idempotency.ts +0 -97
- package/src/index.ts +0 -834
- package/src/internal-tables.ts +0 -149
- package/src/jobs/cron.ts +0 -87
- package/src/jobs/define.ts +0 -283
- package/src/jobs/index.ts +0 -37
- package/src/jobs/queue.ts +0 -67
- package/src/jobs/runtime.ts +0 -58
- package/src/jobs/slots.ts +0 -52
- package/src/jobs/worker.ts +0 -369
- package/src/lifecycle.ts +0 -49
- package/src/list-query.ts +0 -333
- package/src/manifest.ts +0 -297
- package/src/provision-internals.ts +0 -29
- package/src/provision.ts +0 -128
- package/src/rate-limit.ts +0 -71
- package/src/realtime/facade.ts +0 -74
- package/src/realtime/filter.ts +0 -81
- package/src/realtime/heartbeat.ts +0 -80
- package/src/realtime/publisher.ts +0 -46
- package/src/schema-export-pg.ts +0 -7
- package/src/schema-export.ts +0 -5
- package/src/scope.ts +0 -17
- package/src/standard-schema.ts +0 -59
- package/src/storage/buckets.ts +0 -308
- package/src/storage/delete.ts +0 -26
- package/src/storage/file-meta.ts +0 -222
- package/src/storage/index.ts +0 -39
- package/src/storage/local.ts +0 -69
- package/src/storage/operations.ts +0 -398
- package/src/storage/registry.ts +0 -40
- package/src/storage/s3.ts +0 -99
- package/src/storage/sweep.ts +0 -25
- package/src/storage/thumbnails.ts +0 -65
- package/src/testing.ts +0 -31
- package/src/typeid.ts +0 -116
package/src/list-query.ts
DELETED
|
@@ -1,333 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
and,
|
|
3
|
-
asc,
|
|
4
|
-
desc,
|
|
5
|
-
eq,
|
|
6
|
-
getTableColumns,
|
|
7
|
-
gt,
|
|
8
|
-
ilike,
|
|
9
|
-
inArray,
|
|
10
|
-
is,
|
|
11
|
-
like,
|
|
12
|
-
lt,
|
|
13
|
-
or,
|
|
14
|
-
sql,
|
|
15
|
-
type SQL,
|
|
16
|
-
} from 'drizzle-orm'
|
|
17
|
-
import { PgTable } from 'drizzle-orm/pg-core'
|
|
18
|
-
|
|
19
|
-
import type { ResolvedTableAccess, SortOrder } from './access'
|
|
20
|
-
import type { AnyDb } from './dialect'
|
|
21
|
-
|
|
22
|
-
import { ErrorCode, ListQueryError } from './errors'
|
|
23
|
-
|
|
24
|
-
/** Caps both `?limit=` and the number of values in an `IN` filter. */
|
|
25
|
-
export const MAX_LIST_LIMIT = 200
|
|
26
|
-
|
|
27
|
-
/** Default page size when a request omits `limit`. */
|
|
28
|
-
export const DEFAULT_LIST_LIMIT = 20
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* What a list procedure accepts. Shape and column types are enforced by the
|
|
32
|
-
* generated input schema, so by the time these params arrive they are already
|
|
33
|
-
* validated and coerced — this module only applies policy (defaults, the limit
|
|
34
|
-
* cap, cursor rules).
|
|
35
|
-
*/
|
|
36
|
-
export type ListParamsInput = {
|
|
37
|
-
limit?: number
|
|
38
|
-
offset?: number
|
|
39
|
-
cursor?: string
|
|
40
|
-
sort?: string
|
|
41
|
-
order?: SortOrder
|
|
42
|
-
q?: string
|
|
43
|
-
count?: boolean
|
|
44
|
-
filters?: Record<string, unknown>
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export type ParsedListParams = {
|
|
48
|
-
limit: number
|
|
49
|
-
offset?: number
|
|
50
|
-
sort: string
|
|
51
|
-
order: SortOrder
|
|
52
|
-
q: string
|
|
53
|
-
cursor?: string
|
|
54
|
-
count: boolean
|
|
55
|
-
filters: Record<string, unknown>
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export type ListResult<T> = {
|
|
59
|
-
items: T[]
|
|
60
|
-
limit: number
|
|
61
|
-
offset?: number
|
|
62
|
-
cursor?: string
|
|
63
|
-
nextCursor?: string
|
|
64
|
-
hasMore: boolean
|
|
65
|
-
total?: number
|
|
66
|
-
q?: string
|
|
67
|
-
sort: string
|
|
68
|
-
order: SortOrder
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
type CursorPayload = {
|
|
72
|
-
sort: string
|
|
73
|
-
order: SortOrder
|
|
74
|
-
v: string | number | null
|
|
75
|
-
id: string | number
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
79
|
-
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function isCursorPayload(value: unknown): value is CursorPayload {
|
|
83
|
-
if (!isRecord(value)) return false
|
|
84
|
-
return (
|
|
85
|
-
typeof value.sort === 'string' &&
|
|
86
|
-
(value.order === 'asc' || value.order === 'desc') &&
|
|
87
|
-
(value.v === null ||
|
|
88
|
-
typeof value.v === 'string' ||
|
|
89
|
-
typeof value.v === 'number') &&
|
|
90
|
-
(typeof value.id === 'string' || typeof value.id === 'number')
|
|
91
|
-
)
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Applies list policy to already-validated input: defaults, the limit cap, and
|
|
96
|
-
* the rules a schema cannot express (cursor excludes offset, and a cursor must
|
|
97
|
-
* agree with the sort it was minted for).
|
|
98
|
-
*/
|
|
99
|
-
export function resolveListParams(
|
|
100
|
-
input: ListParamsInput,
|
|
101
|
-
access: ResolvedTableAccess,
|
|
102
|
-
): ParsedListParams {
|
|
103
|
-
const cursor = input.cursor?.trim() || undefined
|
|
104
|
-
if (cursor && input.offset !== undefined) {
|
|
105
|
-
throw new ListQueryError('cursor and offset cannot be used together')
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const sort = input.sort ?? access.defaultSort.column
|
|
109
|
-
const order = input.order ?? (input.sort ? 'asc' : access.defaultSort.order)
|
|
110
|
-
|
|
111
|
-
if (cursor) {
|
|
112
|
-
const decoded = decodeCursor(cursor)
|
|
113
|
-
if (decoded.sort !== sort || decoded.order !== order) {
|
|
114
|
-
throw new ListQueryError(
|
|
115
|
-
'cursor does not match sort and order parameters',
|
|
116
|
-
ErrorCode.INVALID_CURSOR,
|
|
117
|
-
)
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
return {
|
|
122
|
-
limit: Math.min(input.limit ?? DEFAULT_LIST_LIMIT, MAX_LIST_LIMIT),
|
|
123
|
-
offset: cursor ? undefined : (input.offset ?? 0),
|
|
124
|
-
sort,
|
|
125
|
-
order,
|
|
126
|
-
q: input.q?.trim() ?? '',
|
|
127
|
-
cursor,
|
|
128
|
-
count: input.count ?? false,
|
|
129
|
-
filters: input.filters ?? {},
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
function buildSearchWhere(
|
|
134
|
-
table: Parameters<typeof getTableColumns>[0],
|
|
135
|
-
searchableColumns: string[] | undefined,
|
|
136
|
-
q: string,
|
|
137
|
-
): SQL | undefined {
|
|
138
|
-
if (!q || !searchableColumns?.length) return undefined
|
|
139
|
-
const columns = getTableColumns(table)
|
|
140
|
-
const pattern = `%${q.replace(/[%_\\]/g, (ch) => `\\${ch}`)}%`
|
|
141
|
-
// LIKE is case-insensitive in SQLite but case-sensitive in Postgres; use
|
|
142
|
-
// ilike there so search behaves identically across dialects.
|
|
143
|
-
const likeOp = is(table, PgTable) ? ilike : like
|
|
144
|
-
const conditions = searchableColumns
|
|
145
|
-
.filter((name) => name in columns)
|
|
146
|
-
.map((name) => likeOp(columns[name]!, pattern))
|
|
147
|
-
return conditions.length ? or(...conditions) : undefined
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Cursors carry their sort value as JSON, so a date column arrives as a string
|
|
152
|
-
* and has to be rebuilt. Filter values need no such repair — the generated
|
|
153
|
-
* input schema already types them.
|
|
154
|
-
*/
|
|
155
|
-
function coerceCursorValue(
|
|
156
|
-
table: Parameters<typeof getTableColumns>[0],
|
|
157
|
-
columnName: string,
|
|
158
|
-
raw: string | number | null,
|
|
159
|
-
): unknown {
|
|
160
|
-
if (raw === null) return null
|
|
161
|
-
const col = getTableColumns(table)[columnName]
|
|
162
|
-
if (col?.dataType === 'date') return new Date(raw)
|
|
163
|
-
return raw
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
function buildFilterWhere(
|
|
167
|
-
table: Parameters<typeof getTableColumns>[0],
|
|
168
|
-
filters: Record<string, unknown>,
|
|
169
|
-
): SQL | undefined {
|
|
170
|
-
const columns = getTableColumns(table)
|
|
171
|
-
const conditions: SQL[] = []
|
|
172
|
-
|
|
173
|
-
for (const [name, value] of Object.entries(filters)) {
|
|
174
|
-
const col = columns[name]
|
|
175
|
-
if (!col || value === undefined) continue
|
|
176
|
-
|
|
177
|
-
if (value === null) {
|
|
178
|
-
conditions.push(sql`${col} IS NULL`)
|
|
179
|
-
} else if (Array.isArray(value)) {
|
|
180
|
-
if (value.length) conditions.push(inArray(col, value))
|
|
181
|
-
} else {
|
|
182
|
-
conditions.push(eq(col, value))
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
return conditions.length ? and(...conditions) : undefined
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
function serializeCursorValue(value: unknown): string | number | null {
|
|
190
|
-
if (value == null) return null
|
|
191
|
-
if (value instanceof Date) return value.toISOString()
|
|
192
|
-
if (typeof value === 'number' || typeof value === 'string') return value
|
|
193
|
-
return String(value)
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
export function encodeCursor(payload: CursorPayload): string {
|
|
197
|
-
return Buffer.from(JSON.stringify(payload)).toString('base64url')
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
export function decodeCursor(cursor: string): CursorPayload {
|
|
201
|
-
try {
|
|
202
|
-
const parsed = JSON.parse(Buffer.from(cursor, 'base64url').toString('utf8'))
|
|
203
|
-
if (!isCursorPayload(parsed)) {
|
|
204
|
-
throw new Error('invalid cursor shape')
|
|
205
|
-
}
|
|
206
|
-
return parsed
|
|
207
|
-
} catch {
|
|
208
|
-
throw new ListQueryError('invalid cursor', ErrorCode.INVALID_CURSOR)
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
function buildCursorWhere(
|
|
213
|
-
table: Parameters<typeof getTableColumns>[0],
|
|
214
|
-
sortColName: string,
|
|
215
|
-
order: SortOrder,
|
|
216
|
-
cursor: CursorPayload,
|
|
217
|
-
idCol: unknown,
|
|
218
|
-
): SQL {
|
|
219
|
-
const columns = getTableColumns(table)
|
|
220
|
-
const sortCol = columns[sortColName]!
|
|
221
|
-
const sortValue = coerceCursorValue(table, sortColName, cursor.v)
|
|
222
|
-
|
|
223
|
-
if (order === 'desc') {
|
|
224
|
-
return or(
|
|
225
|
-
lt(sortCol, sortValue),
|
|
226
|
-
and(eq(sortCol, sortValue), lt(idCol as never, cursor.id)),
|
|
227
|
-
)!
|
|
228
|
-
}
|
|
229
|
-
return or(
|
|
230
|
-
gt(sortCol, sortValue),
|
|
231
|
-
and(eq(sortCol, sortValue), gt(idCol as never, cursor.id)),
|
|
232
|
-
)!
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
function buildOrderBy(
|
|
236
|
-
table: Parameters<typeof getTableColumns>[0],
|
|
237
|
-
sortColName: string,
|
|
238
|
-
order: SortOrder,
|
|
239
|
-
idCol: unknown,
|
|
240
|
-
) {
|
|
241
|
-
const columns = getTableColumns(table)
|
|
242
|
-
const sortCol = columns[sortColName]!
|
|
243
|
-
const idOrder = order === 'asc' ? asc(idCol as never) : desc(idCol as never)
|
|
244
|
-
return order === 'asc' ? [asc(sortCol), idOrder] : [desc(sortCol), idOrder]
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
export async function executeList<T extends Record<string, unknown>>(
|
|
248
|
-
db: AnyDb,
|
|
249
|
-
table: Parameters<typeof getTableColumns>[0],
|
|
250
|
-
access: ResolvedTableAccess,
|
|
251
|
-
params: ParsedListParams,
|
|
252
|
-
idCol: unknown,
|
|
253
|
-
scopeWhere?: SQL,
|
|
254
|
-
): Promise<ListResult<T>> {
|
|
255
|
-
const searchWhere = buildSearchWhere(
|
|
256
|
-
table,
|
|
257
|
-
access.searchableColumns,
|
|
258
|
-
params.q,
|
|
259
|
-
)
|
|
260
|
-
const filterWhere = buildFilterWhere(table, params.filters)
|
|
261
|
-
let where = and(
|
|
262
|
-
...(searchWhere ? [searchWhere] : []),
|
|
263
|
-
...(filterWhere ? [filterWhere] : []),
|
|
264
|
-
...(scopeWhere ? [scopeWhere] : []),
|
|
265
|
-
)
|
|
266
|
-
|
|
267
|
-
if (params.cursor) {
|
|
268
|
-
const cursorPayload = decodeCursor(params.cursor)
|
|
269
|
-
const cursorWhere = buildCursorWhere(
|
|
270
|
-
table,
|
|
271
|
-
params.sort,
|
|
272
|
-
params.order,
|
|
273
|
-
cursorPayload,
|
|
274
|
-
idCol,
|
|
275
|
-
)
|
|
276
|
-
where = where ? and(where, cursorWhere) : cursorWhere
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
const orderBy = buildOrderBy(table, params.sort, params.order, idCol)
|
|
280
|
-
|
|
281
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
282
|
-
let query = (db as any).select().from(table)
|
|
283
|
-
if (where) query = query.where(where)
|
|
284
|
-
query = query.orderBy(...orderBy)
|
|
285
|
-
|
|
286
|
-
if (params.offset !== undefined) {
|
|
287
|
-
query = query.limit(params.limit).offset(params.offset)
|
|
288
|
-
} else {
|
|
289
|
-
query = query.limit(params.limit)
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
const items = (await query) as T[]
|
|
293
|
-
|
|
294
|
-
let total: number | undefined
|
|
295
|
-
if (params.count) {
|
|
296
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
297
|
-
let countQuery = (db as any)
|
|
298
|
-
.select({ count: sql<number>`count(*)` })
|
|
299
|
-
.from(table)
|
|
300
|
-
if (where) countQuery = countQuery.where(where)
|
|
301
|
-
const [row] = await countQuery
|
|
302
|
-
total = Number(row?.count ?? 0)
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
const hasMore =
|
|
306
|
-
total !== undefined && params.offset !== undefined
|
|
307
|
-
? params.offset + items.length < total
|
|
308
|
-
: items.length === params.limit
|
|
309
|
-
|
|
310
|
-
let nextCursor: string | undefined
|
|
311
|
-
if (items.length === params.limit) {
|
|
312
|
-
const last = items[items.length - 1]!
|
|
313
|
-
nextCursor = encodeCursor({
|
|
314
|
-
sort: params.sort,
|
|
315
|
-
order: params.order,
|
|
316
|
-
v: serializeCursorValue(last[params.sort]),
|
|
317
|
-
id: last.id as string | number,
|
|
318
|
-
})
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
return {
|
|
322
|
-
items,
|
|
323
|
-
limit: params.limit,
|
|
324
|
-
...(params.offset !== undefined ? { offset: params.offset } : {}),
|
|
325
|
-
...(params.cursor ? { cursor: params.cursor } : {}),
|
|
326
|
-
...(nextCursor ? { nextCursor } : {}),
|
|
327
|
-
hasMore,
|
|
328
|
-
...(total !== undefined ? { total } : {}),
|
|
329
|
-
...(params.q ? { q: params.q } : {}),
|
|
330
|
-
sort: params.sort,
|
|
331
|
-
order: params.order,
|
|
332
|
-
}
|
|
333
|
-
}
|
package/src/manifest.ts
DELETED
|
@@ -1,297 +0,0 @@
|
|
|
1
|
-
import type { StandardSchemaV1 } from '@standard-schema/spec'
|
|
2
|
-
|
|
3
|
-
import { getTableName, isTable } from 'drizzle-orm'
|
|
4
|
-
import * as v from 'valibot'
|
|
5
|
-
|
|
6
|
-
import type { Dialect } from './dialect'
|
|
7
|
-
import type { EnvConfigInput } from './env'
|
|
8
|
-
import type { JobsDefs } from './jobs/define'
|
|
9
|
-
import type { ResolvedBucket, ResolvedStorageBuckets } from './storage/buckets'
|
|
10
|
-
|
|
11
|
-
import {
|
|
12
|
-
bunderstackFiles,
|
|
13
|
-
bunderstackIdempotency,
|
|
14
|
-
bunderstackJobs,
|
|
15
|
-
} from './internal-tables'
|
|
16
|
-
import { parseCron } from './jobs/cron'
|
|
17
|
-
import {
|
|
18
|
-
StandardSchemaValidationError,
|
|
19
|
-
validateStandardSchema,
|
|
20
|
-
} from './standard-schema'
|
|
21
|
-
|
|
22
|
-
export type ManifestEnvVar = {
|
|
23
|
-
key: string
|
|
24
|
-
required: boolean
|
|
25
|
-
scope: 'server' | 'client'
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export type BunderstackManifest = {
|
|
29
|
-
version: 3
|
|
30
|
-
database: {
|
|
31
|
-
dialect: Dialect
|
|
32
|
-
migrationsDirectory: string
|
|
33
|
-
tables: { exportName: string; physicalName: string; system: boolean }[]
|
|
34
|
-
}
|
|
35
|
-
storage: {
|
|
36
|
-
defaultBucket: string
|
|
37
|
-
buckets: { name: string; visibility: ResolvedBucket['visibility'] }[]
|
|
38
|
-
}
|
|
39
|
-
realtime: { required: boolean }
|
|
40
|
-
environment: ManifestEnvVar[]
|
|
41
|
-
background: {
|
|
42
|
-
jobs: { name: string }[]
|
|
43
|
-
cron: { name: string; schedule: string; timezone: 'UTC' }[]
|
|
44
|
-
maintenance: {
|
|
45
|
-
name: 'storage-sweep'
|
|
46
|
-
schedule: string
|
|
47
|
-
timezone: 'UTC'
|
|
48
|
-
}[]
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const nonEmpty = v.pipe(v.string(), v.minLength(1))
|
|
53
|
-
const migrationDirectory = v.pipe(
|
|
54
|
-
nonEmpty,
|
|
55
|
-
v.check(
|
|
56
|
-
(value) =>
|
|
57
|
-
value.startsWith('/') ||
|
|
58
|
-
(!value.includes('\\') &&
|
|
59
|
-
value.split('/').every((part) => part !== '..' && part !== '')),
|
|
60
|
-
'migrationsDirectory must be an absolute path or a relative path without traversal',
|
|
61
|
-
),
|
|
62
|
-
)
|
|
63
|
-
const cronSchedule = v.pipe(
|
|
64
|
-
nonEmpty,
|
|
65
|
-
v.check((value) => {
|
|
66
|
-
try {
|
|
67
|
-
parseCron(value)
|
|
68
|
-
return true
|
|
69
|
-
} catch {
|
|
70
|
-
return false
|
|
71
|
-
}
|
|
72
|
-
}, 'invalid cron schedule'),
|
|
73
|
-
)
|
|
74
|
-
|
|
75
|
-
const manifestSchema = v.strictObject({
|
|
76
|
-
version: v.literal(3),
|
|
77
|
-
database: v.strictObject({
|
|
78
|
-
dialect: v.picklist(['sqlite', 'pg']),
|
|
79
|
-
migrationsDirectory: migrationDirectory,
|
|
80
|
-
tables: v.array(
|
|
81
|
-
v.strictObject({
|
|
82
|
-
exportName: nonEmpty,
|
|
83
|
-
physicalName: nonEmpty,
|
|
84
|
-
system: v.boolean(),
|
|
85
|
-
}),
|
|
86
|
-
),
|
|
87
|
-
}),
|
|
88
|
-
storage: v.strictObject({
|
|
89
|
-
defaultBucket: nonEmpty,
|
|
90
|
-
buckets: v.array(
|
|
91
|
-
v.strictObject({
|
|
92
|
-
name: nonEmpty,
|
|
93
|
-
visibility: v.picklist(['public', 'private']),
|
|
94
|
-
}),
|
|
95
|
-
),
|
|
96
|
-
}),
|
|
97
|
-
realtime: v.strictObject({ required: v.boolean() }),
|
|
98
|
-
environment: v.array(
|
|
99
|
-
v.strictObject({
|
|
100
|
-
key: nonEmpty,
|
|
101
|
-
required: v.boolean(),
|
|
102
|
-
scope: v.picklist(['server', 'client']),
|
|
103
|
-
}),
|
|
104
|
-
),
|
|
105
|
-
background: v.strictObject({
|
|
106
|
-
jobs: v.array(v.strictObject({ name: nonEmpty })),
|
|
107
|
-
cron: v.array(
|
|
108
|
-
v.strictObject({
|
|
109
|
-
name: nonEmpty,
|
|
110
|
-
schedule: cronSchedule,
|
|
111
|
-
timezone: v.literal('UTC'),
|
|
112
|
-
}),
|
|
113
|
-
),
|
|
114
|
-
maintenance: v.array(
|
|
115
|
-
v.strictObject({
|
|
116
|
-
name: v.literal('storage-sweep'),
|
|
117
|
-
schedule: cronSchedule,
|
|
118
|
-
timezone: v.literal('UTC'),
|
|
119
|
-
}),
|
|
120
|
-
),
|
|
121
|
-
}),
|
|
122
|
-
})
|
|
123
|
-
|
|
124
|
-
function sortBy<T>(entries: readonly T[], key: (entry: T) => string): T[] {
|
|
125
|
-
return [...entries].sort((left, right) => key(left).localeCompare(key(right)))
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
function rejectDuplicates(collection: string, values: readonly string[]): void {
|
|
129
|
-
const seen = new Set<string>()
|
|
130
|
-
for (const value of values) {
|
|
131
|
-
if (seen.has(value))
|
|
132
|
-
throw new Error(`[bunderstack] duplicate ${collection} "${value}"`)
|
|
133
|
-
seen.add(value)
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
function describeTables(schema: Record<string, unknown>) {
|
|
138
|
-
const systemNames = new Set<string>(
|
|
139
|
-
systemTables().map((table) => table.physicalName),
|
|
140
|
-
)
|
|
141
|
-
return sortBy(
|
|
142
|
-
Object.entries(schema).flatMap(([exportName, value]) =>
|
|
143
|
-
isTable(value) && !systemNames.has(getTableName(value))
|
|
144
|
-
? [{ exportName, physicalName: getTableName(value), system: false }]
|
|
145
|
-
: [],
|
|
146
|
-
),
|
|
147
|
-
(entry) => entry.physicalName,
|
|
148
|
-
)
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
function describeSection(
|
|
152
|
-
section: Record<string, StandardSchemaV1> | undefined,
|
|
153
|
-
scope: ManifestEnvVar['scope'],
|
|
154
|
-
): ManifestEnvVar[] {
|
|
155
|
-
return Object.entries(section ?? {}).map(([key, schema]) => {
|
|
156
|
-
let required = false
|
|
157
|
-
try {
|
|
158
|
-
validateStandardSchema(schema, undefined, 'env')
|
|
159
|
-
} catch (error) {
|
|
160
|
-
if (!(error instanceof StandardSchemaValidationError)) throw error
|
|
161
|
-
required = true
|
|
162
|
-
}
|
|
163
|
-
return { key, required, scope }
|
|
164
|
-
})
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
function systemTables() {
|
|
168
|
-
return [
|
|
169
|
-
{
|
|
170
|
-
exportName: '_system.files',
|
|
171
|
-
physicalName: getTableName(bunderstackFiles),
|
|
172
|
-
system: true,
|
|
173
|
-
},
|
|
174
|
-
{
|
|
175
|
-
exportName: '_system.idempotency',
|
|
176
|
-
physicalName: getTableName(bunderstackIdempotency),
|
|
177
|
-
system: true,
|
|
178
|
-
},
|
|
179
|
-
{
|
|
180
|
-
exportName: '_system.jobs',
|
|
181
|
-
physicalName: getTableName(bunderstackJobs),
|
|
182
|
-
system: true,
|
|
183
|
-
},
|
|
184
|
-
]
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
export function parseManifest(value: unknown): BunderstackManifest {
|
|
188
|
-
const manifest = validateStandardSchema(
|
|
189
|
-
manifestSchema,
|
|
190
|
-
value,
|
|
191
|
-
'manifest',
|
|
192
|
-
) as BunderstackManifest
|
|
193
|
-
rejectDuplicates(
|
|
194
|
-
'database physical table',
|
|
195
|
-
manifest.database.tables.map((entry) => entry.physicalName),
|
|
196
|
-
)
|
|
197
|
-
rejectDuplicates(
|
|
198
|
-
'database export table',
|
|
199
|
-
manifest.database.tables.map((entry) => entry.exportName),
|
|
200
|
-
)
|
|
201
|
-
rejectDuplicates(
|
|
202
|
-
'storage bucket',
|
|
203
|
-
manifest.storage.buckets.map((entry) => entry.name),
|
|
204
|
-
)
|
|
205
|
-
rejectDuplicates(
|
|
206
|
-
'environment key',
|
|
207
|
-
manifest.environment.map((entry) => entry.key),
|
|
208
|
-
)
|
|
209
|
-
rejectDuplicates(
|
|
210
|
-
'background job',
|
|
211
|
-
manifest.background.jobs.map((entry) => entry.name),
|
|
212
|
-
)
|
|
213
|
-
rejectDuplicates(
|
|
214
|
-
'background cron',
|
|
215
|
-
manifest.background.cron.map((entry) => entry.name),
|
|
216
|
-
)
|
|
217
|
-
rejectDuplicates(
|
|
218
|
-
'background maintenance',
|
|
219
|
-
manifest.background.maintenance.map((entry) => entry.name),
|
|
220
|
-
)
|
|
221
|
-
return manifest
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
export function buildManifest(args: {
|
|
225
|
-
schema: Record<string, unknown>
|
|
226
|
-
dialect: Dialect
|
|
227
|
-
migrationsDirectory: string
|
|
228
|
-
storage: ResolvedStorageBuckets
|
|
229
|
-
envConfig: EnvConfigInput | undefined
|
|
230
|
-
emailProvider: string | undefined
|
|
231
|
-
realtime: boolean
|
|
232
|
-
jobs: JobsDefs | undefined
|
|
233
|
-
}): BunderstackManifest {
|
|
234
|
-
const environment = [
|
|
235
|
-
...describeSection(args.envConfig?.server, 'server'),
|
|
236
|
-
...describeSection(args.envConfig?.client, 'client'),
|
|
237
|
-
...(args.emailProvider === 'resend'
|
|
238
|
-
? [{ key: 'RESEND_API_KEY', required: true, scope: 'server' as const }]
|
|
239
|
-
: []),
|
|
240
|
-
...(args.emailProvider === 'smtp'
|
|
241
|
-
? [{ key: 'SMTP_URL', required: true, scope: 'server' as const }]
|
|
242
|
-
: []),
|
|
243
|
-
]
|
|
244
|
-
rejectDuplicates(
|
|
245
|
-
'environment key',
|
|
246
|
-
environment.map((entry) => entry.key),
|
|
247
|
-
)
|
|
248
|
-
|
|
249
|
-
return parseManifest({
|
|
250
|
-
version: 3,
|
|
251
|
-
database: {
|
|
252
|
-
dialect: args.dialect,
|
|
253
|
-
migrationsDirectory: args.migrationsDirectory,
|
|
254
|
-
tables: sortBy(
|
|
255
|
-
[...systemTables(), ...describeTables(args.schema)],
|
|
256
|
-
(entry) => entry.physicalName,
|
|
257
|
-
),
|
|
258
|
-
},
|
|
259
|
-
storage: {
|
|
260
|
-
defaultBucket: args.storage.defaultBucket,
|
|
261
|
-
buckets: sortBy(
|
|
262
|
-
[...args.storage.buckets.values()].map((bucket) => ({
|
|
263
|
-
name: bucket.name,
|
|
264
|
-
visibility: bucket.visibility,
|
|
265
|
-
})),
|
|
266
|
-
(bucket) => bucket.name,
|
|
267
|
-
),
|
|
268
|
-
},
|
|
269
|
-
realtime: { required: args.realtime },
|
|
270
|
-
environment: sortBy(environment, (entry) => entry.key),
|
|
271
|
-
background: {
|
|
272
|
-
jobs: sortBy(
|
|
273
|
-
Object.entries(args.jobs ?? {})
|
|
274
|
-
.filter(([, def]) => def.kind === 'job')
|
|
275
|
-
.map(([name]) => ({ name })),
|
|
276
|
-
(entry) => entry.name,
|
|
277
|
-
),
|
|
278
|
-
cron: sortBy(
|
|
279
|
-
Object.entries(args.jobs ?? {})
|
|
280
|
-
.filter(([, def]) => def.kind === 'cron')
|
|
281
|
-
.map(([name, def]) => ({
|
|
282
|
-
name,
|
|
283
|
-
schedule: def.kind === 'cron' ? def.schedule : '',
|
|
284
|
-
timezone: 'UTC' as const,
|
|
285
|
-
})),
|
|
286
|
-
(entry) => entry.name,
|
|
287
|
-
),
|
|
288
|
-
maintenance: [
|
|
289
|
-
{
|
|
290
|
-
name: 'storage-sweep',
|
|
291
|
-
schedule: '0 4 * * *',
|
|
292
|
-
timezone: 'UTC' as const,
|
|
293
|
-
},
|
|
294
|
-
],
|
|
295
|
-
},
|
|
296
|
-
})
|
|
297
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import type { Driver } from './db'
|
|
2
|
-
// src/provision-internals.ts
|
|
3
|
-
import type { AnyDb, Dialect } from './dialect'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Hidden handle connecting `createBunderstack()` to the optional
|
|
7
|
-
* `bunderstack/provision` entry. Lives in its own module so the main entry
|
|
8
|
-
* never imports provision code (and its drizzle-kit reference).
|
|
9
|
-
*/
|
|
10
|
-
export const PROVISION_INTERNALS: unique symbol = Symbol.for(
|
|
11
|
-
'bunderstack.provision-internals',
|
|
12
|
-
)
|
|
13
|
-
|
|
14
|
-
export interface ProvisionInternals {
|
|
15
|
-
/** Runtime db typed over the MERGED schema (user + internal tables). */
|
|
16
|
-
db: AnyDb
|
|
17
|
-
/** Merged schema used for push. */
|
|
18
|
-
schema: Record<string, unknown>
|
|
19
|
-
databaseUrl: string
|
|
20
|
-
/** Resolved migrations folder (config `database.migrations`). */
|
|
21
|
-
migrationsFolder: string
|
|
22
|
-
dialect: Dialect
|
|
23
|
-
driver: Driver
|
|
24
|
-
adapter: import('./database/adapter').DatabaseAdapter
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export interface WithProvisionInternals {
|
|
28
|
-
[PROVISION_INTERNALS]?: ProvisionInternals
|
|
29
|
-
}
|