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/auth.ts
DELETED
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
// src/auth.ts
|
|
2
|
-
import { betterAuth } from 'better-auth'
|
|
3
|
-
import { drizzleAdapter } from 'better-auth/adapters/drizzle'
|
|
4
|
-
import { openAPI } from 'better-auth/plugins'
|
|
5
|
-
|
|
6
|
-
import type { AuthSessionResolver } from './access'
|
|
7
|
-
import type { BetterAuthConfig } from './config'
|
|
8
|
-
import type { AnyDb, Dialect } from './dialect'
|
|
9
|
-
import type { EmailFacade } from './email'
|
|
10
|
-
|
|
11
|
-
export function createAuth(
|
|
12
|
-
db: AnyDb,
|
|
13
|
-
cfg: BetterAuthConfig,
|
|
14
|
-
dialect: Dialect,
|
|
15
|
-
userSchema?: Record<string, unknown>,
|
|
16
|
-
) {
|
|
17
|
-
const hasOpenApi = cfg.plugins?.some((p: any) => p.id === 'open-api')
|
|
18
|
-
const plugins = hasOpenApi ? cfg.plugins : [...(cfg.plugins || []), openAPI()]
|
|
19
|
-
|
|
20
|
-
return betterAuth({
|
|
21
|
-
...cfg,
|
|
22
|
-
plugins,
|
|
23
|
-
database: drizzleAdapter(db as Parameters<typeof drizzleAdapter>[0], {
|
|
24
|
-
provider: dialect === 'pg' ? 'pg' : 'sqlite',
|
|
25
|
-
...(userSchema ? { schema: userSchema } : {}),
|
|
26
|
-
}),
|
|
27
|
-
})
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Adapt the raw better-auth instance to our internal {@link AuthSessionResolver}
|
|
32
|
-
* contract. better-auth's `getSession` has a union return (a bare session, or a
|
|
33
|
-
* `{ headers, response }` wrapper when `returnHeaders` is set); we only ever
|
|
34
|
-
* call the bare form, so we narrow on `'user' in result` and map to our shape.
|
|
35
|
-
* Keeping this adapter here means internal modules never depend on better-auth's
|
|
36
|
-
* evolving types.
|
|
37
|
-
*/
|
|
38
|
-
export function toAuthSessionResolver(
|
|
39
|
-
auth: ReturnType<typeof createAuth>,
|
|
40
|
-
): AuthSessionResolver {
|
|
41
|
-
return {
|
|
42
|
-
api: {
|
|
43
|
-
async getSession({ headers }) {
|
|
44
|
-
const result = await auth.api.getSession({ headers })
|
|
45
|
-
if (result && 'user' in result && result.user) {
|
|
46
|
-
const session = 'session' in result ? result.session : null
|
|
47
|
-
const activeOrganizationId =
|
|
48
|
-
session &&
|
|
49
|
-
'activeOrganizationId' in session &&
|
|
50
|
-
typeof session.activeOrganizationId === 'string'
|
|
51
|
-
? session.activeOrganizationId
|
|
52
|
-
: null
|
|
53
|
-
const role =
|
|
54
|
-
'role' in result.user && typeof result.user.role === 'string'
|
|
55
|
-
? result.user.role
|
|
56
|
-
: undefined
|
|
57
|
-
return {
|
|
58
|
-
user: {
|
|
59
|
-
id: result.user.id,
|
|
60
|
-
email: result.user.email,
|
|
61
|
-
name: result.user.name,
|
|
62
|
-
...(role ? { role } : {}),
|
|
63
|
-
},
|
|
64
|
-
session: session ? { activeOrganizationId } : null,
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
return null
|
|
68
|
-
},
|
|
69
|
-
},
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Fill better-auth's email hooks from the bunderstack email facade. Only fills
|
|
75
|
-
* gaps: user-supplied handlers always win, and nothing is injected when email
|
|
76
|
-
* isn't configured. emailAndPassword is only touched when the user enabled it
|
|
77
|
-
* (injecting it unasked would enable the feature).
|
|
78
|
-
*/
|
|
79
|
-
export function withEmailAuthDefaults(
|
|
80
|
-
cfg: BetterAuthConfig,
|
|
81
|
-
email: EmailFacade,
|
|
82
|
-
emailConfigured: boolean,
|
|
83
|
-
): BetterAuthConfig {
|
|
84
|
-
if (!emailConfigured) return cfg
|
|
85
|
-
const out: BetterAuthConfig = { ...cfg }
|
|
86
|
-
|
|
87
|
-
if (
|
|
88
|
-
cfg.emailAndPassword?.enabled &&
|
|
89
|
-
!cfg.emailAndPassword.sendResetPassword
|
|
90
|
-
) {
|
|
91
|
-
out.emailAndPassword = {
|
|
92
|
-
...cfg.emailAndPassword,
|
|
93
|
-
sendResetPassword: async ({ user, url }) => {
|
|
94
|
-
await email.send({
|
|
95
|
-
to: user.email,
|
|
96
|
-
subject: 'Reset your password',
|
|
97
|
-
text: `Click the link to reset your password:\n\n${url}\n\nIf you didn't request this, you can ignore this email.`,
|
|
98
|
-
})
|
|
99
|
-
},
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
if (!cfg.emailVerification?.sendVerificationEmail) {
|
|
104
|
-
out.emailVerification = {
|
|
105
|
-
...cfg.emailVerification,
|
|
106
|
-
sendVerificationEmail: async ({ user, url }) => {
|
|
107
|
-
await email.send({
|
|
108
|
-
to: user.email,
|
|
109
|
-
subject: 'Verify your email',
|
|
110
|
-
text: `Click the link to verify your email address:\n\n${url}`,
|
|
111
|
-
})
|
|
112
|
-
},
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
return out
|
|
117
|
-
}
|
|
@@ -1,203 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
mkdir,
|
|
3
|
-
readFile,
|
|
4
|
-
realpath,
|
|
5
|
-
rename,
|
|
6
|
-
rm,
|
|
7
|
-
writeFile,
|
|
8
|
-
} from 'node:fs/promises'
|
|
9
|
-
import { dirname, isAbsolute, join, relative, resolve } from 'node:path'
|
|
10
|
-
import { pathToFileURL } from 'node:url'
|
|
11
|
-
|
|
12
|
-
import {
|
|
13
|
-
blueprintFromManifest,
|
|
14
|
-
serializeBlueprint,
|
|
15
|
-
type BunderstackBlueprint,
|
|
16
|
-
} from './blueprint'
|
|
17
|
-
import { parseManifest } from './manifest'
|
|
18
|
-
|
|
19
|
-
export type GenerateBlueprintOptions = {
|
|
20
|
-
directory: string
|
|
21
|
-
entry?: string
|
|
22
|
-
output?: string
|
|
23
|
-
check?: boolean
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export type GenerateBlueprintResult = {
|
|
27
|
-
path: string
|
|
28
|
-
blueprint: BunderstackBlueprint
|
|
29
|
-
source: string
|
|
30
|
-
changed: boolean
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export class BlueprintCheckError extends Error {
|
|
34
|
-
constructor() {
|
|
35
|
-
super(
|
|
36
|
-
'bunderstack.blueprint.yaml is missing or stale; run `bunderstack blueprint`',
|
|
37
|
-
)
|
|
38
|
-
this.name = 'BlueprintCheckError'
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
type AppPackage = {
|
|
43
|
-
scripts?: Record<string, unknown>
|
|
44
|
-
dependencies?: Record<string, unknown>
|
|
45
|
-
devDependencies?: Record<string, unknown>
|
|
46
|
-
bunderstack?: { entry?: unknown }
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function requireRelativePath(value: string, label: string): string {
|
|
50
|
-
const normalized = value.replaceAll('\\', '/')
|
|
51
|
-
if (
|
|
52
|
-
!normalized ||
|
|
53
|
-
isAbsolute(normalized) ||
|
|
54
|
-
normalized.split('/').some((part) => !part || part === '..')
|
|
55
|
-
) {
|
|
56
|
-
throw new Error(
|
|
57
|
-
`[bunderstack] ${label} must be a relative path without traversal`,
|
|
58
|
-
)
|
|
59
|
-
}
|
|
60
|
-
return normalized
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function resolveWithin(root: string, value: string, label: string): string {
|
|
64
|
-
const path = resolve(root, requireRelativePath(value, label))
|
|
65
|
-
const pathFromRoot = relative(root, path)
|
|
66
|
-
if (
|
|
67
|
-
pathFromRoot === '..' ||
|
|
68
|
-
pathFromRoot.startsWith('../') ||
|
|
69
|
-
isAbsolute(pathFromRoot)
|
|
70
|
-
) {
|
|
71
|
-
throw new Error(
|
|
72
|
-
`[bunderstack] ${label} must stay within the application directory`,
|
|
73
|
-
)
|
|
74
|
-
}
|
|
75
|
-
return path
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function normalizeProjectPath(
|
|
79
|
-
root: string,
|
|
80
|
-
value: string,
|
|
81
|
-
label: string,
|
|
82
|
-
): string {
|
|
83
|
-
if (!isAbsolute(value)) return requireRelativePath(value, label)
|
|
84
|
-
const pathFromRoot = relative(root, resolve(value)) || '.'
|
|
85
|
-
return requireRelativePath(pathFromRoot, label)
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function requireScript(
|
|
89
|
-
pkg: AppPackage,
|
|
90
|
-
name: 'build' | 'start' | 'worker',
|
|
91
|
-
required: boolean,
|
|
92
|
-
): boolean {
|
|
93
|
-
const value = pkg.scripts?.[name]
|
|
94
|
-
if (typeof value === 'string' && value.trim()) return true
|
|
95
|
-
if (required)
|
|
96
|
-
throw new Error(
|
|
97
|
-
`[bunderstack] package.json requires a non-empty "${name}" script`,
|
|
98
|
-
)
|
|
99
|
-
return false
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
async function packageVersion(): Promise<string> {
|
|
103
|
-
const pkg = (await Bun.file(
|
|
104
|
-
new URL('../package.json', import.meta.url),
|
|
105
|
-
).json()) as { version: string }
|
|
106
|
-
return pkg.version
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export async function generateBlueprint(
|
|
110
|
-
options: GenerateBlueprintOptions,
|
|
111
|
-
): Promise<GenerateBlueprintResult> {
|
|
112
|
-
const directory = await realpath(resolve(options.directory))
|
|
113
|
-
const packagePath = join(directory, 'package.json')
|
|
114
|
-
const pkg = JSON.parse(await readFile(packagePath, 'utf8')) as AppPackage
|
|
115
|
-
const allDependencies = { ...pkg.dependencies, ...pkg.devDependencies }
|
|
116
|
-
if (typeof allDependencies['@tanstack/react-start'] !== 'string') {
|
|
117
|
-
throw new Error(
|
|
118
|
-
'[bunderstack] package.json must depend on @tanstack/react-start',
|
|
119
|
-
)
|
|
120
|
-
}
|
|
121
|
-
requireScript(pkg, 'build', true)
|
|
122
|
-
requireScript(pkg, 'start', true)
|
|
123
|
-
|
|
124
|
-
const configuredEntry = pkg.bunderstack?.entry
|
|
125
|
-
const entry = requireRelativePath(
|
|
126
|
-
options.entry ??
|
|
127
|
-
(typeof configuredEntry === 'string'
|
|
128
|
-
? configuredEntry
|
|
129
|
-
: 'src/bunderstack.ts'),
|
|
130
|
-
'entry',
|
|
131
|
-
)
|
|
132
|
-
const entryPath = resolveWithin(directory, entry, 'entry')
|
|
133
|
-
if (!(await Bun.file(entryPath).exists())) {
|
|
134
|
-
throw new Error(`[bunderstack] entry does not exist: ${entry}`)
|
|
135
|
-
}
|
|
136
|
-
const output = requireRelativePath(
|
|
137
|
-
options.output ?? 'bunderstack.blueprint.yaml',
|
|
138
|
-
'output',
|
|
139
|
-
)
|
|
140
|
-
const outputPath = resolveWithin(directory, output, 'output')
|
|
141
|
-
|
|
142
|
-
const previousIntrospection = process.env.BUNDERSTACK_INTROSPECT
|
|
143
|
-
process.env.BUNDERSTACK_INTROSPECT = '1'
|
|
144
|
-
let app: { manifest?: unknown; close?: () => Promise<void> } | undefined
|
|
145
|
-
try {
|
|
146
|
-
const module = (await import(
|
|
147
|
-
`${pathToFileURL(entryPath).href}?blueprint=${Date.now()}`
|
|
148
|
-
)) as {
|
|
149
|
-
app?: typeof app
|
|
150
|
-
}
|
|
151
|
-
app = module.app
|
|
152
|
-
if (!app) throw new Error(`[bunderstack] ${entry} must export app`)
|
|
153
|
-
const manifest = parseManifest(app.manifest)
|
|
154
|
-
const workerRequired = manifest.background.jobs.length > 0
|
|
155
|
-
requireScript(pkg, 'worker', workerRequired)
|
|
156
|
-
const migrationsDirectory = normalizeProjectPath(
|
|
157
|
-
directory,
|
|
158
|
-
manifest.database.migrationsDirectory,
|
|
159
|
-
'migrationsDirectory',
|
|
160
|
-
)
|
|
161
|
-
const migrationJournal = join(
|
|
162
|
-
resolveWithin(directory, migrationsDirectory, 'migrationsDirectory'),
|
|
163
|
-
'meta',
|
|
164
|
-
'_journal.json',
|
|
165
|
-
)
|
|
166
|
-
const migrationMode = (await Bun.file(migrationJournal).exists())
|
|
167
|
-
? 'migrations'
|
|
168
|
-
: 'push'
|
|
169
|
-
const blueprint = blueprintFromManifest({
|
|
170
|
-
manifest: {
|
|
171
|
-
...manifest,
|
|
172
|
-
database: { ...manifest.database, migrationsDirectory },
|
|
173
|
-
},
|
|
174
|
-
generatorVersion: await packageVersion(),
|
|
175
|
-
entry,
|
|
176
|
-
migrationMode,
|
|
177
|
-
})
|
|
178
|
-
const source = serializeBlueprint(blueprint)
|
|
179
|
-
const existing = (await Bun.file(outputPath).exists())
|
|
180
|
-
? await Bun.file(outputPath).text()
|
|
181
|
-
: undefined
|
|
182
|
-
if (options.check) {
|
|
183
|
-
if (existing !== source) throw new BlueprintCheckError()
|
|
184
|
-
return { path: outputPath, blueprint, source, changed: false }
|
|
185
|
-
}
|
|
186
|
-
if (existing === source)
|
|
187
|
-
return { path: outputPath, blueprint, source, changed: false }
|
|
188
|
-
await mkdir(dirname(outputPath), { recursive: true })
|
|
189
|
-
const temporary = `${outputPath}.${process.pid}.${Date.now()}.tmp`
|
|
190
|
-
try {
|
|
191
|
-
await writeFile(temporary, source, { mode: 0o600 })
|
|
192
|
-
await rename(temporary, outputPath)
|
|
193
|
-
} finally {
|
|
194
|
-
await rm(temporary, { force: true })
|
|
195
|
-
}
|
|
196
|
-
return { path: outputPath, blueprint, source, changed: true }
|
|
197
|
-
} finally {
|
|
198
|
-
await app?.close?.()
|
|
199
|
-
if (previousIntrospection === undefined)
|
|
200
|
-
delete process.env.BUNDERSTACK_INTROSPECT
|
|
201
|
-
else process.env.BUNDERSTACK_INTROSPECT = previousIntrospection
|
|
202
|
-
}
|
|
203
|
-
}
|
package/src/blueprint.ts
DELETED
|
@@ -1,264 +0,0 @@
|
|
|
1
|
-
import * as v from 'valibot'
|
|
2
|
-
import { parse, stringify } from 'yaml'
|
|
3
|
-
|
|
4
|
-
import type { BunderstackManifest } from './manifest'
|
|
5
|
-
|
|
6
|
-
import { parseCron } from './jobs/cron'
|
|
7
|
-
import { validateStandardSchema } from './standard-schema'
|
|
8
|
-
|
|
9
|
-
export type MigrationMode = 'migrations' | 'push'
|
|
10
|
-
|
|
11
|
-
export type BunderstackBlueprint = {
|
|
12
|
-
version: 1
|
|
13
|
-
generator: { name: 'bunderstack'; version: string }
|
|
14
|
-
application: {
|
|
15
|
-
framework: 'tanstack-start'
|
|
16
|
-
scripts: { build: 'build'; start: 'start'; worker?: 'worker' }
|
|
17
|
-
}
|
|
18
|
-
bunderstack: { entry: string; manifestVersion: 3 }
|
|
19
|
-
resources: {
|
|
20
|
-
database: BunderstackManifest['database'] & { migrationMode: MigrationMode }
|
|
21
|
-
storage: BunderstackManifest['storage']
|
|
22
|
-
realtime?: { required: true }
|
|
23
|
-
}
|
|
24
|
-
environment: BunderstackManifest['environment']
|
|
25
|
-
background: BunderstackManifest['background'] & {
|
|
26
|
-
worker: { required: boolean }
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const nonEmpty = v.pipe(v.string(), v.minLength(1))
|
|
31
|
-
const relativePath = v.pipe(
|
|
32
|
-
nonEmpty,
|
|
33
|
-
v.check(
|
|
34
|
-
(value) =>
|
|
35
|
-
!value.startsWith('/') &&
|
|
36
|
-
!value.includes('\\') &&
|
|
37
|
-
value.split('/').every((part) => part !== '' && part !== '..'),
|
|
38
|
-
'entry must be a relative path without traversal',
|
|
39
|
-
),
|
|
40
|
-
)
|
|
41
|
-
const cronSchedule = v.pipe(
|
|
42
|
-
nonEmpty,
|
|
43
|
-
v.check((value) => {
|
|
44
|
-
try {
|
|
45
|
-
parseCron(value)
|
|
46
|
-
return true
|
|
47
|
-
} catch {
|
|
48
|
-
return false
|
|
49
|
-
}
|
|
50
|
-
}, 'invalid cron schedule'),
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
const blueprintSchema = v.strictObject({
|
|
54
|
-
version: v.literal(1),
|
|
55
|
-
generator: v.strictObject({
|
|
56
|
-
name: v.literal('bunderstack'),
|
|
57
|
-
version: nonEmpty,
|
|
58
|
-
}),
|
|
59
|
-
application: v.strictObject({
|
|
60
|
-
framework: v.literal('tanstack-start'),
|
|
61
|
-
scripts: v.strictObject({
|
|
62
|
-
build: v.literal('build'),
|
|
63
|
-
start: v.literal('start'),
|
|
64
|
-
worker: v.optional(v.literal('worker')),
|
|
65
|
-
}),
|
|
66
|
-
}),
|
|
67
|
-
bunderstack: v.strictObject({
|
|
68
|
-
entry: relativePath,
|
|
69
|
-
manifestVersion: v.literal(3),
|
|
70
|
-
}),
|
|
71
|
-
resources: v.strictObject({
|
|
72
|
-
database: v.strictObject({
|
|
73
|
-
dialect: v.picklist(['sqlite', 'pg']),
|
|
74
|
-
migrationsDirectory: relativePath,
|
|
75
|
-
migrationMode: v.picklist(['migrations', 'push']),
|
|
76
|
-
tables: v.array(
|
|
77
|
-
v.strictObject({
|
|
78
|
-
exportName: nonEmpty,
|
|
79
|
-
physicalName: nonEmpty,
|
|
80
|
-
system: v.boolean(),
|
|
81
|
-
}),
|
|
82
|
-
),
|
|
83
|
-
}),
|
|
84
|
-
storage: v.strictObject({
|
|
85
|
-
defaultBucket: nonEmpty,
|
|
86
|
-
buckets: v.array(
|
|
87
|
-
v.strictObject({
|
|
88
|
-
name: nonEmpty,
|
|
89
|
-
visibility: v.picklist(['public', 'private']),
|
|
90
|
-
}),
|
|
91
|
-
),
|
|
92
|
-
}),
|
|
93
|
-
realtime: v.optional(v.strictObject({ required: v.literal(true) })),
|
|
94
|
-
}),
|
|
95
|
-
environment: v.array(
|
|
96
|
-
v.strictObject({
|
|
97
|
-
key: nonEmpty,
|
|
98
|
-
required: v.boolean(),
|
|
99
|
-
scope: v.picklist(['server', 'client']),
|
|
100
|
-
}),
|
|
101
|
-
),
|
|
102
|
-
background: v.strictObject({
|
|
103
|
-
worker: v.strictObject({ required: v.boolean() }),
|
|
104
|
-
jobs: v.array(v.strictObject({ name: nonEmpty })),
|
|
105
|
-
cron: v.array(
|
|
106
|
-
v.strictObject({
|
|
107
|
-
name: nonEmpty,
|
|
108
|
-
schedule: cronSchedule,
|
|
109
|
-
timezone: v.literal('UTC'),
|
|
110
|
-
}),
|
|
111
|
-
),
|
|
112
|
-
maintenance: v.array(
|
|
113
|
-
v.strictObject({
|
|
114
|
-
name: v.literal('storage-sweep'),
|
|
115
|
-
schedule: cronSchedule,
|
|
116
|
-
timezone: v.literal('UTC'),
|
|
117
|
-
}),
|
|
118
|
-
),
|
|
119
|
-
}),
|
|
120
|
-
})
|
|
121
|
-
|
|
122
|
-
function sortBy<T>(entries: readonly T[], key: (entry: T) => string): T[] {
|
|
123
|
-
return [...entries].sort((left, right) => key(left).localeCompare(key(right)))
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
function rejectDuplicates(collection: string, values: readonly string[]): void {
|
|
127
|
-
const seen = new Set<string>()
|
|
128
|
-
for (const value of values) {
|
|
129
|
-
if (seen.has(value))
|
|
130
|
-
throw new Error(`[bunderstack] duplicate ${collection} "${value}"`)
|
|
131
|
-
seen.add(value)
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
export function parseBlueprint(value: unknown): BunderstackBlueprint {
|
|
136
|
-
const blueprint = validateStandardSchema(
|
|
137
|
-
blueprintSchema,
|
|
138
|
-
value,
|
|
139
|
-
'blueprint',
|
|
140
|
-
) as BunderstackBlueprint
|
|
141
|
-
rejectDuplicates(
|
|
142
|
-
'database physical table',
|
|
143
|
-
blueprint.resources.database.tables.map((entry) => entry.physicalName),
|
|
144
|
-
)
|
|
145
|
-
rejectDuplicates(
|
|
146
|
-
'database export table',
|
|
147
|
-
blueprint.resources.database.tables.map((entry) => entry.exportName),
|
|
148
|
-
)
|
|
149
|
-
rejectDuplicates(
|
|
150
|
-
'storage bucket',
|
|
151
|
-
blueprint.resources.storage.buckets.map((entry) => entry.name),
|
|
152
|
-
)
|
|
153
|
-
rejectDuplicates(
|
|
154
|
-
'environment key',
|
|
155
|
-
blueprint.environment.map((entry) => entry.key),
|
|
156
|
-
)
|
|
157
|
-
rejectDuplicates(
|
|
158
|
-
'background job',
|
|
159
|
-
blueprint.background.jobs.map((entry) => entry.name),
|
|
160
|
-
)
|
|
161
|
-
rejectDuplicates(
|
|
162
|
-
'background cron',
|
|
163
|
-
blueprint.background.cron.map((entry) => entry.name),
|
|
164
|
-
)
|
|
165
|
-
rejectDuplicates(
|
|
166
|
-
'background maintenance',
|
|
167
|
-
blueprint.background.maintenance.map((entry) => entry.name),
|
|
168
|
-
)
|
|
169
|
-
if (
|
|
170
|
-
!blueprint.resources.storage.buckets.some(
|
|
171
|
-
(bucket) => bucket.name === blueprint.resources.storage.defaultBucket,
|
|
172
|
-
)
|
|
173
|
-
) {
|
|
174
|
-
throw new Error(
|
|
175
|
-
'[bunderstack] storage defaultBucket must be declared in storage buckets',
|
|
176
|
-
)
|
|
177
|
-
}
|
|
178
|
-
const workerRequired = blueprint.background.jobs.length > 0
|
|
179
|
-
if (blueprint.background.worker.required !== workerRequired) {
|
|
180
|
-
throw new Error(
|
|
181
|
-
'[bunderstack] background worker.required must match declared queue jobs',
|
|
182
|
-
)
|
|
183
|
-
}
|
|
184
|
-
if (Boolean(blueprint.application.scripts.worker) !== workerRequired) {
|
|
185
|
-
throw new Error(
|
|
186
|
-
'[bunderstack] application worker script must match declared queue jobs',
|
|
187
|
-
)
|
|
188
|
-
}
|
|
189
|
-
return blueprint
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
export function blueprintFromManifest(args: {
|
|
193
|
-
manifest: BunderstackManifest
|
|
194
|
-
generatorVersion: string
|
|
195
|
-
entry: string
|
|
196
|
-
migrationMode: MigrationMode
|
|
197
|
-
}): BunderstackBlueprint {
|
|
198
|
-
const workerRequired = args.manifest.background.jobs.length > 0
|
|
199
|
-
return parseBlueprint({
|
|
200
|
-
version: 1,
|
|
201
|
-
generator: { name: 'bunderstack', version: args.generatorVersion },
|
|
202
|
-
application: {
|
|
203
|
-
framework: 'tanstack-start',
|
|
204
|
-
scripts: {
|
|
205
|
-
build: 'build',
|
|
206
|
-
start: 'start',
|
|
207
|
-
...(workerRequired ? { worker: 'worker' } : {}),
|
|
208
|
-
},
|
|
209
|
-
},
|
|
210
|
-
bunderstack: { entry: args.entry, manifestVersion: 3 },
|
|
211
|
-
resources: {
|
|
212
|
-
database: {
|
|
213
|
-
...args.manifest.database,
|
|
214
|
-
migrationMode: args.migrationMode,
|
|
215
|
-
tables: sortBy(
|
|
216
|
-
args.manifest.database.tables,
|
|
217
|
-
(entry) => entry.physicalName,
|
|
218
|
-
),
|
|
219
|
-
},
|
|
220
|
-
storage: {
|
|
221
|
-
...args.manifest.storage,
|
|
222
|
-
buckets: sortBy(args.manifest.storage.buckets, (entry) => entry.name),
|
|
223
|
-
},
|
|
224
|
-
...(args.manifest.realtime.required
|
|
225
|
-
? { realtime: { required: true } }
|
|
226
|
-
: {}),
|
|
227
|
-
},
|
|
228
|
-
environment: sortBy(args.manifest.environment, (entry) => entry.key),
|
|
229
|
-
background: {
|
|
230
|
-
worker: { required: workerRequired },
|
|
231
|
-
jobs: sortBy(args.manifest.background.jobs, (entry) => entry.name),
|
|
232
|
-
cron: sortBy(args.manifest.background.cron, (entry) => entry.name),
|
|
233
|
-
maintenance: sortBy(
|
|
234
|
-
args.manifest.background.maintenance,
|
|
235
|
-
(entry) => entry.name,
|
|
236
|
-
),
|
|
237
|
-
},
|
|
238
|
-
})
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
export function parseBlueprintYaml(source: string): BunderstackBlueprint {
|
|
242
|
-
return parseBlueprint(parse(source) as unknown)
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
export function serializeBlueprint(value: BunderstackBlueprint): string {
|
|
246
|
-
const blueprint = parseBlueprint(value)
|
|
247
|
-
const options = {
|
|
248
|
-
aliasDuplicateObjects: false,
|
|
249
|
-
defaultKeyType: 'PLAIN',
|
|
250
|
-
defaultStringType: 'PLAIN',
|
|
251
|
-
lineWidth: 0,
|
|
252
|
-
} as const
|
|
253
|
-
const source = stringify(
|
|
254
|
-
parseBlueprintYaml(stringify(blueprint, options)),
|
|
255
|
-
options,
|
|
256
|
-
)
|
|
257
|
-
return source.replace(
|
|
258
|
-
/^(\s*schedule: )(.+)$/gm,
|
|
259
|
-
(_match, prefix: string, value: string) => {
|
|
260
|
-
const schedule = value.startsWith('"') ? JSON.parse(value) : value
|
|
261
|
-
return `${prefix}${JSON.stringify(schedule)}`
|
|
262
|
-
},
|
|
263
|
-
)
|
|
264
|
-
}
|
package/src/cli.ts
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bun
|
|
2
|
-
import {
|
|
3
|
-
BlueprintCheckError,
|
|
4
|
-
generateBlueprint,
|
|
5
|
-
type GenerateBlueprintOptions,
|
|
6
|
-
} from './blueprint-generator'
|
|
7
|
-
|
|
8
|
-
export type CliIo = {
|
|
9
|
-
stdout(message: string): void
|
|
10
|
-
stderr(message: string): void
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const help = `Usage: bunderstack blueprint [directory] [--entry <path>] [--output <path>] [--check]
|
|
14
|
-
|
|
15
|
-
Generate a committed deployment declaration for a TanStack Start application.
|
|
16
|
-
Entry precedence: --entry, package.json#bunderstack.entry, src/bunderstack.ts.`
|
|
17
|
-
|
|
18
|
-
export async function runCli(
|
|
19
|
-
args: string[],
|
|
20
|
-
io: CliIo,
|
|
21
|
-
generate: typeof generateBlueprint = generateBlueprint,
|
|
22
|
-
): Promise<number> {
|
|
23
|
-
if (args[0] === '--help' || args[0] === '-h') {
|
|
24
|
-
io.stdout(help)
|
|
25
|
-
return 0
|
|
26
|
-
}
|
|
27
|
-
if (args[0] === '--version') {
|
|
28
|
-
io.stdout(
|
|
29
|
-
(
|
|
30
|
-
(await Bun.file(
|
|
31
|
-
new URL('../package.json', import.meta.url),
|
|
32
|
-
).json()) as { version: string }
|
|
33
|
-
).version,
|
|
34
|
-
)
|
|
35
|
-
return 0
|
|
36
|
-
}
|
|
37
|
-
if (args[0] !== 'blueprint') {
|
|
38
|
-
io.stderr(
|
|
39
|
-
'Usage: bunderstack blueprint [directory] [--entry <path>] [--output <path>] [--check]',
|
|
40
|
-
)
|
|
41
|
-
return 2
|
|
42
|
-
}
|
|
43
|
-
const options: GenerateBlueprintOptions = { directory: process.cwd() }
|
|
44
|
-
for (let index = 1; index < args.length; index++) {
|
|
45
|
-
const argument = args[index]!
|
|
46
|
-
if (argument === '--check') {
|
|
47
|
-
options.check = true
|
|
48
|
-
continue
|
|
49
|
-
}
|
|
50
|
-
if (argument === '--entry' || argument === '--output') {
|
|
51
|
-
const value = args[++index]
|
|
52
|
-
if (!value || value.startsWith('--')) {
|
|
53
|
-
io.stderr(`[bunderstack] missing value for ${argument}`)
|
|
54
|
-
return 2
|
|
55
|
-
}
|
|
56
|
-
if (argument === '--entry') options.entry = value
|
|
57
|
-
else options.output = value
|
|
58
|
-
continue
|
|
59
|
-
}
|
|
60
|
-
if (argument.startsWith('-')) {
|
|
61
|
-
io.stderr(`[bunderstack] unknown option: ${argument}`)
|
|
62
|
-
return 2
|
|
63
|
-
}
|
|
64
|
-
if (options.directory !== process.cwd()) {
|
|
65
|
-
io.stderr('[bunderstack] only one application directory is allowed')
|
|
66
|
-
return 2
|
|
67
|
-
}
|
|
68
|
-
options.directory = argument
|
|
69
|
-
}
|
|
70
|
-
try {
|
|
71
|
-
const result = await generate(options)
|
|
72
|
-
io.stdout(
|
|
73
|
-
options.check || !result.changed
|
|
74
|
-
? 'bunderstack.blueprint.yaml is current'
|
|
75
|
-
: 'Generated bunderstack.blueprint.yaml',
|
|
76
|
-
)
|
|
77
|
-
return 0
|
|
78
|
-
} catch (error) {
|
|
79
|
-
io.stderr(error instanceof Error ? error.message : String(error))
|
|
80
|
-
return error instanceof BlueprintCheckError ? 1 : 1
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (import.meta.main) {
|
|
85
|
-
const exitCode = await runCli(process.argv.slice(2), {
|
|
86
|
-
stdout: (message) => console.log(message),
|
|
87
|
-
stderr: (message) => console.error(message),
|
|
88
|
-
})
|
|
89
|
-
process.exit(exitCode)
|
|
90
|
-
}
|