bunderstack 1.0.0-beta.1 → 1.0.0-beta.2
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 +7 -0
- package/dist/blueprint-generator.d.ts.map +1 -1
- package/dist/blueprint-generator.js +5 -2
- package/dist/blueprint-generator.js.map +1 -1
- package/dist/blueprint.d.ts +4 -1
- package/dist/blueprint.d.ts.map +1 -1
- package/dist/blueprint.js +25 -8
- package/dist/blueprint.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +5 -3
- package/dist/cli.js.map +1 -1
- package/dist/dev/index.d.ts.map +1 -1
- package/dist/dev/index.js +4 -1
- package/dist/dev/index.js.map +1 -1
- package/dist/dev/push.js +6 -1
- package/dist/dev/push.js.map +1 -1
- package/dist/workers/wrangler.d.ts.map +1 -1
- package/dist/workers/wrangler.js +4 -1
- package/dist/workers/wrangler.js.map +1 -1
- package/package.json +1 -1
- package/skills/creating-bunderstack-apps/references/verification.md +4 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `bunderstack` will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [1.0.0-beta.2] — 2026-09-29
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- `bunderstack blueprint` supports Worker applications (`application.runtime: "worker"`), requiring only the `build` script in `package.json`.
|
|
10
|
+
- `bunderstack dev` updates both `wrangler.json` and `bunderstack.blueprint.yaml`, and `bunderstack build` checks both committed files for drift.
|
|
11
|
+
|
|
5
12
|
## [1.0.0-beta.1] — 2026-09-28
|
|
6
13
|
|
|
7
14
|
### Added
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blueprint-generator.d.ts","sourceRoot":"","sources":["../src/blueprint-generator.ts"],"names":[],"mappings":"AAaA,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,aAAa,CAAA;AAOpB,MAAM,MAAM,wBAAwB,GAAG;IACrC,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG;IACpC,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,oBAAoB,CAAA;IAC/B,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,qBAAa,mBAAoB,SAAQ,KAAK;;CAO7C;AAqED,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,uBAAuB,CAAC,
|
|
1
|
+
{"version":3,"file":"blueprint-generator.d.ts","sourceRoot":"","sources":["../src/blueprint-generator.ts"],"names":[],"mappings":"AAaA,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,aAAa,CAAA;AAOpB,MAAM,MAAM,wBAAwB,GAAG;IACrC,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG;IACpC,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,oBAAoB,CAAA;IAC/B,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,qBAAa,mBAAoB,SAAQ,KAAK;;CAO7C;AAqED,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,uBAAuB,CAAC,CA0HlC"}
|
|
@@ -66,7 +66,7 @@ export async function generateBlueprint(options) {
|
|
|
66
66
|
framework = 'solid';
|
|
67
67
|
}
|
|
68
68
|
requireScript(pkg, 'build', true);
|
|
69
|
-
requireScript(pkg, 'start',
|
|
69
|
+
const hasStartScript = requireScript(pkg, 'start', false);
|
|
70
70
|
const configuredEntry = pkg.bunderstack?.entry;
|
|
71
71
|
const entry = requireRelativePath(options.entry ??
|
|
72
72
|
(typeof configuredEntry === 'string'
|
|
@@ -108,7 +108,9 @@ export async function generateBlueprint(options) {
|
|
|
108
108
|
}
|
|
109
109
|
const manifest = firstManifest;
|
|
110
110
|
const workerRequired = manifest.background.jobs.length > 0;
|
|
111
|
-
|
|
111
|
+
if (hasStartScript) {
|
|
112
|
+
requireScript(pkg, 'worker', workerRequired);
|
|
113
|
+
}
|
|
112
114
|
const migrationsDirectory = normalizeProjectPath(directory, manifest.database.migrationsDirectory, 'migrationsDirectory');
|
|
113
115
|
const migrationJournal = join(resolveWithin(directory, migrationsDirectory, 'migrationsDirectory'), 'meta', '_journal.json');
|
|
114
116
|
const migrationMode = (await Bun.file(migrationJournal).exists())
|
|
@@ -123,6 +125,7 @@ export async function generateBlueprint(options) {
|
|
|
123
125
|
entry,
|
|
124
126
|
migrationMode,
|
|
125
127
|
framework,
|
|
128
|
+
...(hasStartScript ? {} : { runtime: 'worker' }),
|
|
126
129
|
});
|
|
127
130
|
const source = serializeBlueprint(blueprint);
|
|
128
131
|
const existing = (await Bun.file(outputPath).exists())
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blueprint-generator.js","sourceRoot":"","sources":["../src/blueprint-generator.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n mkdir,\n readFile,\n realpath,\n rename,\n rm,\n writeFile,\n} from 'node:fs/promises'\nimport { dirname, isAbsolute, join, relative, resolve } from 'node:path'\nimport { pathToFileURL } from 'node:url'\n\nimport { isBunderstackBackend } from './backend'\nimport { BACKEND_INTERNALS } from './backend-internals'\nimport {\n blueprintFromManifest,\n serializeBlueprint,\n type BunderstackBlueprint,\n} from './blueprint'\nimport { parseBlueprintYaml } from './blueprint'\nimport { createEnvProbeSources } from './env-probe'\nimport { assertManifestMatchesBlueprint } from './hosted-contract'\nimport { parseManifest } from './manifest'\nimport { diffManifests } from './manifest-diff'\n\nexport type GenerateBlueprintOptions = {\n directory: string\n entry?: string\n output?: string\n check?: boolean\n hostedCheck?: boolean\n}\n\nexport type GenerateBlueprintResult = {\n path: string\n blueprint: BunderstackBlueprint\n source: string\n changed: boolean\n}\n\nexport class BlueprintCheckError extends Error {\n constructor() {\n super(\n 'bunderstack.blueprint.yaml is missing or stale; run `bunderstack blueprint`',\n )\n this.name = 'BlueprintCheckError'\n }\n}\n\ntype AppPackage = {\n scripts?: Record<string, unknown>\n dependencies?: Record<string, unknown>\n devDependencies?: Record<string, unknown>\n bunderstack?: { entry?: unknown }\n}\n\nfunction requireRelativePath(value: string, label: string): string {\n const normalized = value.replaceAll('\\\\', '/')\n if (\n !normalized ||\n isAbsolute(normalized) ||\n normalized.split('/').some((part) => !part || part === '..')\n ) {\n throw new Error(\n `[bunderstack] ${label} must be a relative path without traversal`,\n )\n }\n return normalized\n}\n\nfunction resolveWithin(root: string, value: string, label: string): string {\n const path = resolve(root, requireRelativePath(value, label))\n const pathFromRoot = relative(root, path)\n if (\n pathFromRoot === '..' ||\n pathFromRoot.startsWith('../') ||\n isAbsolute(pathFromRoot)\n ) {\n throw new Error(\n `[bunderstack] ${label} must stay within the application directory`,\n )\n }\n return path\n}\n\nfunction normalizeProjectPath(\n root: string,\n value: string,\n label: string,\n): string {\n if (!isAbsolute(value)) return requireRelativePath(value, label)\n const pathFromRoot = relative(root, resolve(value)) || '.'\n return requireRelativePath(pathFromRoot, label)\n}\n\nfunction requireScript(\n pkg: AppPackage,\n name: 'build' | 'start' | 'worker',\n required: boolean,\n): boolean {\n const value = pkg.scripts?.[name]\n if (typeof value === 'string' && value.trim()) return true\n if (required)\n throw new Error(\n `[bunderstack] package.json requires a non-empty \"${name}\" script`,\n )\n return false\n}\n\nasync function packageVersion(): Promise<string> {\n const pkg = (await Bun.file(\n new URL('../package.json', import.meta.url),\n ).json()) as { version: string }\n return pkg.version\n}\n\nexport async function generateBlueprint(\n options: GenerateBlueprintOptions,\n): Promise<GenerateBlueprintResult> {\n const directory = await realpath(resolve(options.directory))\n const packagePath = join(directory, 'package.json')\n const pkg = JSON.parse(await readFile(packagePath, 'utf8')) as AppPackage\n const allDependencies = { ...pkg.dependencies, ...pkg.devDependencies }\n let framework: 'tanstack-start' | 'solid' | 'bun-ssr' = 'bun-ssr'\n if (typeof allDependencies['@tanstack/react-start'] === 'string') {\n framework = 'tanstack-start'\n } else if (\n typeof allDependencies['solid-js'] === 'string' ||\n typeof allDependencies['@solidjs/web'] === 'string'\n ) {\n framework = 'solid'\n }\n requireScript(pkg, 'build', true)\n requireScript(pkg, 'start', true)\n\n const configuredEntry = pkg.bunderstack?.entry\n const entry = requireRelativePath(\n options.entry ??\n (typeof configuredEntry === 'string'\n ? configuredEntry\n : 'src/bunderstack.ts'),\n 'entry',\n )\n const entryPath = resolveWithin(directory, entry, 'entry')\n if (!(await Bun.file(entryPath).exists())) {\n throw new Error(`[bunderstack] entry does not exist: ${entry}`)\n }\n const output = requireRelativePath(\n options.output ?? 'bunderstack.blueprint.yaml',\n 'output',\n )\n const outputPath = resolveWithin(directory, output, 'output')\n\n const module = (await import(\n `${pathToFileURL(entryPath).href}?blueprint=${Date.now()}`\n )) as { backend?: unknown }\n const backend = module.backend\n if (!isBunderstackBackend(backend)) {\n throw new Error(`[bunderstack] ${entry} must export backend`)\n }\n if (options.hostedCheck) {\n const file = Bun.file(outputPath)\n if (!(await file.exists())) {\n throw new Error(\n `[bunderstack] hosted blueprint does not exist: ${output}`,\n )\n }\n const source = await file.text()\n const manifest = parseManifest(backend.inspect({ env: process.env }))\n assertManifestMatchesBlueprint(manifest, source)\n return {\n path: outputPath,\n blueprint: parseBlueprintYaml(source),\n source,\n changed: false,\n }\n }\n const probeSources = createEnvProbeSources(\n backend[BACKEND_INTERNALS].envSchema,\n process.env as Record<string, string | undefined>,\n )\n const firstManifest = parseManifest(backend.inspect({ env: probeSources[0] }))\n const secondManifest = parseManifest(\n backend.inspect({ env: probeSources[1] }),\n )\n const differences = diffManifests(firstManifest, secondManifest)\n if (differences.length > 0) {\n throw new Error(\n '[bunderstack] environment-dependent blueprint shape:\\n' +\n differences.map(({ kind, path }) => ` - ${kind}: ${path}`).join('\\n'),\n )\n }\n const manifest = firstManifest\n const workerRequired = manifest.background.jobs.length > 0\n requireScript(pkg, 'worker', workerRequired)\n const migrationsDirectory = normalizeProjectPath(\n directory,\n manifest.database.migrationsDirectory,\n 'migrationsDirectory',\n )\n const migrationJournal = join(\n resolveWithin(directory, migrationsDirectory, 'migrationsDirectory'),\n 'meta',\n '_journal.json',\n )\n const migrationMode = (await Bun.file(migrationJournal).exists())\n ? 'migrations'\n : 'push'\n const blueprint = blueprintFromManifest({\n manifest: {\n ...manifest,\n database: { ...manifest.database, migrationsDirectory },\n },\n generatorVersion: await packageVersion(),\n entry,\n migrationMode,\n framework,\n })\n const source = serializeBlueprint(blueprint)\n const existing = (await Bun.file(outputPath).exists())\n ? await Bun.file(outputPath).text()\n : undefined\n if (options.check) {\n if (existing !== source) throw new BlueprintCheckError()\n return { path: outputPath, blueprint, source, changed: false }\n }\n if (existing === source)\n return { path: outputPath, blueprint, source, changed: false }\n await mkdir(dirname(outputPath), { recursive: true })\n const temporary = `${outputPath}.${process.pid}.${Date.now()}.tmp`\n try {\n await writeFile(temporary, source, { mode: 0o600 })\n await rename(temporary, outputPath)\n } finally {\n await rm(temporary, { force: true })\n }\n return { path: outputPath, blueprint, source, changed: true }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"blueprint-generator.js","sourceRoot":"","sources":["../src/blueprint-generator.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n mkdir,\n readFile,\n realpath,\n rename,\n rm,\n writeFile,\n} from 'node:fs/promises'\nimport { dirname, isAbsolute, join, relative, resolve } from 'node:path'\nimport { pathToFileURL } from 'node:url'\n\nimport { isBunderstackBackend } from './backend'\nimport { BACKEND_INTERNALS } from './backend-internals'\nimport {\n blueprintFromManifest,\n serializeBlueprint,\n type BunderstackBlueprint,\n} from './blueprint'\nimport { parseBlueprintYaml } from './blueprint'\nimport { createEnvProbeSources } from './env-probe'\nimport { assertManifestMatchesBlueprint } from './hosted-contract'\nimport { parseManifest } from './manifest'\nimport { diffManifests } from './manifest-diff'\n\nexport type GenerateBlueprintOptions = {\n directory: string\n entry?: string\n output?: string\n check?: boolean\n hostedCheck?: boolean\n}\n\nexport type GenerateBlueprintResult = {\n path: string\n blueprint: BunderstackBlueprint\n source: string\n changed: boolean\n}\n\nexport class BlueprintCheckError extends Error {\n constructor() {\n super(\n 'bunderstack.blueprint.yaml is missing or stale; run `bunderstack blueprint`',\n )\n this.name = 'BlueprintCheckError'\n }\n}\n\ntype AppPackage = {\n scripts?: Record<string, unknown>\n dependencies?: Record<string, unknown>\n devDependencies?: Record<string, unknown>\n bunderstack?: { entry?: unknown }\n}\n\nfunction requireRelativePath(value: string, label: string): string {\n const normalized = value.replaceAll('\\\\', '/')\n if (\n !normalized ||\n isAbsolute(normalized) ||\n normalized.split('/').some((part) => !part || part === '..')\n ) {\n throw new Error(\n `[bunderstack] ${label} must be a relative path without traversal`,\n )\n }\n return normalized\n}\n\nfunction resolveWithin(root: string, value: string, label: string): string {\n const path = resolve(root, requireRelativePath(value, label))\n const pathFromRoot = relative(root, path)\n if (\n pathFromRoot === '..' ||\n pathFromRoot.startsWith('../') ||\n isAbsolute(pathFromRoot)\n ) {\n throw new Error(\n `[bunderstack] ${label} must stay within the application directory`,\n )\n }\n return path\n}\n\nfunction normalizeProjectPath(\n root: string,\n value: string,\n label: string,\n): string {\n if (!isAbsolute(value)) return requireRelativePath(value, label)\n const pathFromRoot = relative(root, resolve(value)) || '.'\n return requireRelativePath(pathFromRoot, label)\n}\n\nfunction requireScript(\n pkg: AppPackage,\n name: 'build' | 'start' | 'worker',\n required: boolean,\n): boolean {\n const value = pkg.scripts?.[name]\n if (typeof value === 'string' && value.trim()) return true\n if (required)\n throw new Error(\n `[bunderstack] package.json requires a non-empty \"${name}\" script`,\n )\n return false\n}\n\nasync function packageVersion(): Promise<string> {\n const pkg = (await Bun.file(\n new URL('../package.json', import.meta.url),\n ).json()) as { version: string }\n return pkg.version\n}\n\nexport async function generateBlueprint(\n options: GenerateBlueprintOptions,\n): Promise<GenerateBlueprintResult> {\n const directory = await realpath(resolve(options.directory))\n const packagePath = join(directory, 'package.json')\n const pkg = JSON.parse(await readFile(packagePath, 'utf8')) as AppPackage\n const allDependencies = { ...pkg.dependencies, ...pkg.devDependencies }\n let framework: 'tanstack-start' | 'solid' | 'bun-ssr' = 'bun-ssr'\n if (typeof allDependencies['@tanstack/react-start'] === 'string') {\n framework = 'tanstack-start'\n } else if (\n typeof allDependencies['solid-js'] === 'string' ||\n typeof allDependencies['@solidjs/web'] === 'string'\n ) {\n framework = 'solid'\n }\n requireScript(pkg, 'build', true)\n const hasStartScript = requireScript(pkg, 'start', false)\n\n const configuredEntry = pkg.bunderstack?.entry\n const entry = requireRelativePath(\n options.entry ??\n (typeof configuredEntry === 'string'\n ? configuredEntry\n : 'src/bunderstack.ts'),\n 'entry',\n )\n const entryPath = resolveWithin(directory, entry, 'entry')\n if (!(await Bun.file(entryPath).exists())) {\n throw new Error(`[bunderstack] entry does not exist: ${entry}`)\n }\n const output = requireRelativePath(\n options.output ?? 'bunderstack.blueprint.yaml',\n 'output',\n )\n const outputPath = resolveWithin(directory, output, 'output')\n\n const module = (await import(\n `${pathToFileURL(entryPath).href}?blueprint=${Date.now()}`\n )) as { backend?: unknown }\n const backend = module.backend\n if (!isBunderstackBackend(backend)) {\n throw new Error(`[bunderstack] ${entry} must export backend`)\n }\n if (options.hostedCheck) {\n const file = Bun.file(outputPath)\n if (!(await file.exists())) {\n throw new Error(\n `[bunderstack] hosted blueprint does not exist: ${output}`,\n )\n }\n const source = await file.text()\n const manifest = parseManifest(backend.inspect({ env: process.env }))\n assertManifestMatchesBlueprint(manifest, source)\n return {\n path: outputPath,\n blueprint: parseBlueprintYaml(source),\n source,\n changed: false,\n }\n }\n const probeSources = createEnvProbeSources(\n backend[BACKEND_INTERNALS].envSchema,\n process.env as Record<string, string | undefined>,\n )\n const firstManifest = parseManifest(backend.inspect({ env: probeSources[0] }))\n const secondManifest = parseManifest(\n backend.inspect({ env: probeSources[1] }),\n )\n const differences = diffManifests(firstManifest, secondManifest)\n if (differences.length > 0) {\n throw new Error(\n '[bunderstack] environment-dependent blueprint shape:\\n' +\n differences.map(({ kind, path }) => ` - ${kind}: ${path}`).join('\\n'),\n )\n }\n const manifest = firstManifest\n const workerRequired = manifest.background.jobs.length > 0\n if (hasStartScript) {\n requireScript(pkg, 'worker', workerRequired)\n }\n const migrationsDirectory = normalizeProjectPath(\n directory,\n manifest.database.migrationsDirectory,\n 'migrationsDirectory',\n )\n const migrationJournal = join(\n resolveWithin(directory, migrationsDirectory, 'migrationsDirectory'),\n 'meta',\n '_journal.json',\n )\n const migrationMode = (await Bun.file(migrationJournal).exists())\n ? 'migrations'\n : 'push'\n const blueprint = blueprintFromManifest({\n manifest: {\n ...manifest,\n database: { ...manifest.database, migrationsDirectory },\n },\n generatorVersion: await packageVersion(),\n entry,\n migrationMode,\n framework,\n ...(hasStartScript ? {} : { runtime: 'worker' }),\n })\n const source = serializeBlueprint(blueprint)\n const existing = (await Bun.file(outputPath).exists())\n ? await Bun.file(outputPath).text()\n : undefined\n if (options.check) {\n if (existing !== source) throw new BlueprintCheckError()\n return { path: outputPath, blueprint, source, changed: false }\n }\n if (existing === source)\n return { path: outputPath, blueprint, source, changed: false }\n await mkdir(dirname(outputPath), { recursive: true })\n const temporary = `${outputPath}.${process.pid}.${Date.now()}.tmp`\n try {\n await writeFile(temporary, source, { mode: 0o600 })\n await rename(temporary, outputPath)\n } finally {\n await rm(temporary, { force: true })\n }\n return { path: outputPath, blueprint, source, changed: true }\n}\n"]}
|
package/dist/blueprint.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { BunderstackManifest } from './manifest.js';
|
|
2
2
|
export type MigrationMode = 'migrations' | 'push';
|
|
3
|
+
export type ApplicationRuntime = 'server' | 'worker';
|
|
3
4
|
export type ApplicationFramework = 'tanstack-start' | 'solid' | 'bun-ssr' | 'custom';
|
|
4
5
|
/**
|
|
5
6
|
* Blueprint form of an environment key. `sensitive` and `description` are
|
|
@@ -19,10 +20,11 @@ export type BunderstackBlueprint = {
|
|
|
19
20
|
version: string;
|
|
20
21
|
};
|
|
21
22
|
application: {
|
|
23
|
+
runtime?: ApplicationRuntime;
|
|
22
24
|
framework: ApplicationFramework;
|
|
23
25
|
scripts: {
|
|
24
26
|
build: 'build';
|
|
25
|
-
start
|
|
27
|
+
start?: 'start';
|
|
26
28
|
worker?: 'worker';
|
|
27
29
|
};
|
|
28
30
|
};
|
|
@@ -63,6 +65,7 @@ export declare function blueprintFromManifest(args: {
|
|
|
63
65
|
entry: string;
|
|
64
66
|
migrationMode: MigrationMode;
|
|
65
67
|
framework?: ApplicationFramework;
|
|
68
|
+
runtime?: ApplicationRuntime;
|
|
66
69
|
}): BunderstackBlueprint;
|
|
67
70
|
export declare function parseBlueprintYaml(source: string): BunderstackBlueprint;
|
|
68
71
|
export declare function serializeBlueprint(value: BunderstackBlueprint): string;
|
package/dist/blueprint.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blueprint.d.ts","sourceRoot":"","sources":["../src/blueprint.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAKrD,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG,MAAM,CAAA;AACjD,MAAM,MAAM,oBAAoB,GAC5B,gBAAgB,GAChB,OAAO,GACP,SAAS,GACT,QAAQ,CAAA;AAEZ;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,EAAE,OAAO,CAAA;IACjB,KAAK,EAAE,QAAQ,GAAG,QAAQ,CAAA;IAC1B,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,EAAE,CAAC,CAAA;IACV,SAAS,EAAE;QAAE,IAAI,EAAE,aAAa,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;IACnD,WAAW,EAAE;QACX,SAAS,EAAE,oBAAoB,CAAA;QAC/B,OAAO,EAAE;YAAE,KAAK,EAAE,OAAO,CAAC;YAAC,KAAK,EAAE,OAAO,CAAC;YAAC,MAAM,CAAC,EAAE,QAAQ,CAAA;SAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"blueprint.d.ts","sourceRoot":"","sources":["../src/blueprint.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAKrD,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG,MAAM,CAAA;AACjD,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,QAAQ,CAAA;AACpD,MAAM,MAAM,oBAAoB,GAC5B,gBAAgB,GAChB,OAAO,GACP,SAAS,GACT,QAAQ,CAAA;AAEZ;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,EAAE,OAAO,CAAA;IACjB,KAAK,EAAE,QAAQ,GAAG,QAAQ,CAAA;IAC1B,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,EAAE,CAAC,CAAA;IACV,SAAS,EAAE;QAAE,IAAI,EAAE,aAAa,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;IACnD,WAAW,EAAE;QACX,OAAO,CAAC,EAAE,kBAAkB,CAAA;QAC5B,SAAS,EAAE,oBAAoB,CAAA;QAC/B,OAAO,EAAE;YAAE,KAAK,EAAE,OAAO,CAAC;YAAC,KAAK,CAAC,EAAE,OAAO,CAAC;YAAC,MAAM,CAAC,EAAE,QAAQ,CAAA;SAAE,CAAA;KAChE,CAAA;IACD,WAAW,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,CAAC,CAAA;KAAE,CAAA;IAClD,SAAS,EAAE;QACT,QAAQ,EAAE,mBAAmB,CAAC,UAAU,CAAC,GAAG;YAAE,aAAa,EAAE,aAAa,CAAA;SAAE,CAAA;QAC5E,OAAO,EAAE,mBAAmB,CAAC,SAAS,CAAC,CAAA;QACvC,QAAQ,CAAC,EAAE;YAAE,QAAQ,EAAE,IAAI,CAAA;SAAE,CAAA;QAC7B,SAAS,EAAE,mBAAmB,CAAC,WAAW,CAAC,CAAA;KAC5C,CAAA;IACD,WAAW,EAAE,eAAe,EAAE,CAAA;IAC9B,mFAAmF;IACnF,GAAG,CAAC,EAAE;QAAE,UAAU,EAAE,mBAAmB,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAA;KAAE,CAAA;IAC9D,UAAU,EAAE,mBAAmB,CAAC,YAAY,CAAC,GAAG;QAC9C,MAAM,EAAE;YAAE,QAAQ,EAAE,OAAO,CAAA;SAAE,CAAA;KAC9B,CAAA;CACF,CAAA;AAwID,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,oBAAoB,CAiFnE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAEjE;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAC1C,QAAQ,EAAE,mBAAmB,CAAA;IAC7B,gBAAgB,EAAE,MAAM,CAAA;IACxB,KAAK,EAAE,MAAM,CAAA;IACb,aAAa,EAAE,aAAa,CAAA;IAC5B,SAAS,CAAC,EAAE,oBAAoB,CAAA;IAChC,OAAO,CAAC,EAAE,kBAAkB,CAAA;CAC7B,GAAG,oBAAoB,CAsDvB;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,oBAAoB,CAEvE;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,CAmBtE"}
|
package/dist/blueprint.js
CHANGED
|
@@ -28,10 +28,11 @@ const blueprintSchema = open({
|
|
|
28
28
|
version: nonEmpty,
|
|
29
29
|
}),
|
|
30
30
|
application: open({
|
|
31
|
+
runtime: v.optional(v.picklist(['server', 'worker'])),
|
|
31
32
|
framework: v.picklist(['tanstack-start', 'solid', 'bun-ssr', 'custom']),
|
|
32
33
|
scripts: open({
|
|
33
34
|
build: v.literal('build'),
|
|
34
|
-
start: v.literal('start'),
|
|
35
|
+
start: v.optional(v.literal('start')),
|
|
35
36
|
worker: v.optional(v.literal('worker')),
|
|
36
37
|
}),
|
|
37
38
|
}),
|
|
@@ -120,12 +121,24 @@ export function parseBlueprint(value) {
|
|
|
120
121
|
if (!blueprint.resources.storage.buckets.some((bucket) => bucket.name === blueprint.resources.storage.defaultBucket)) {
|
|
121
122
|
throw new Error('[bunderstack] storage defaultBucket must be declared in storage buckets');
|
|
122
123
|
}
|
|
124
|
+
const runtime = blueprint.application.runtime ?? 'server';
|
|
123
125
|
const workerRequired = blueprint.background.jobs.length > 0;
|
|
124
126
|
if (blueprint.background.worker.required !== workerRequired) {
|
|
125
127
|
throw new Error('[bunderstack] background worker.required must match declared queue jobs');
|
|
126
128
|
}
|
|
127
|
-
if (
|
|
128
|
-
|
|
129
|
+
if (runtime === 'worker') {
|
|
130
|
+
if (blueprint.application.scripts.start !== undefined ||
|
|
131
|
+
blueprint.application.scripts.worker !== undefined) {
|
|
132
|
+
throw new Error('[bunderstack] worker runtime blueprint must only declare the build script');
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
if (blueprint.application.scripts.start !== 'start') {
|
|
137
|
+
throw new Error('[bunderstack] server runtime blueprint must declare the start script');
|
|
138
|
+
}
|
|
139
|
+
if (Boolean(blueprint.application.scripts.worker) !== workerRequired) {
|
|
140
|
+
throw new Error('[bunderstack] application worker script must match declared queue jobs');
|
|
141
|
+
}
|
|
129
142
|
}
|
|
130
143
|
return blueprint;
|
|
131
144
|
}
|
|
@@ -137,17 +150,21 @@ export function isSensitiveEnvVar(entry) {
|
|
|
137
150
|
return entry.sensitive ?? entry.scope === 'server';
|
|
138
151
|
}
|
|
139
152
|
export function blueprintFromManifest(args) {
|
|
153
|
+
const runtime = args.runtime ?? 'server';
|
|
140
154
|
const workerRequired = args.manifest.background.jobs.length > 0;
|
|
141
155
|
return parseBlueprint({
|
|
142
156
|
version: 1,
|
|
143
157
|
generator: { name: 'bunderstack', version: args.generatorVersion },
|
|
144
158
|
application: {
|
|
159
|
+
...(args.runtime ? { runtime: args.runtime } : {}),
|
|
145
160
|
framework: args.framework ?? 'tanstack-start',
|
|
146
|
-
scripts:
|
|
147
|
-
build: 'build'
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
161
|
+
scripts: runtime === 'worker'
|
|
162
|
+
? { build: 'build' }
|
|
163
|
+
: {
|
|
164
|
+
build: 'build',
|
|
165
|
+
start: 'start',
|
|
166
|
+
...(workerRequired ? { worker: 'worker' } : {}),
|
|
167
|
+
},
|
|
151
168
|
},
|
|
152
169
|
bunderstack: { entry: args.entry, manifestVersion: 4 },
|
|
153
170
|
resources: {
|
package/dist/blueprint.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blueprint.js","sourceRoot":"","sources":["../src/blueprint.ts"],"names":[],"mappings":"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","sourcesContent":["import * as v from 'valibot'\nimport { parse, stringify } from 'yaml'\n\nimport type { BunderstackManifest } from './manifest'\n\nimport { parseCron } from './jobs/cron'\nimport { validateStandardSchema } from './standard-schema'\n\nexport type MigrationMode = 'migrations' | 'push'\nexport type ApplicationFramework =\n | 'tanstack-start'\n | 'solid'\n | 'bun-ssr'\n | 'custom'\n\n/**\n * Blueprint form of an environment key. `sensitive` and `description` are\n * optional because blueprints committed before 0.23.0 do not carry them.\n */\nexport type BlueprintEnvVar = {\n key: string\n required: boolean\n scope: 'server' | 'client'\n sensitive?: boolean\n description?: string\n}\n\nexport type BunderstackBlueprint = {\n version: 1\n generator: { name: 'bunderstack'; version: string }\n application: {\n framework: ApplicationFramework\n scripts: { build: 'build'; start: 'start'; worker?: 'worker' }\n }\n bunderstack: { entry: string; manifestVersion: 4 }\n resources: {\n database: BunderstackManifest['database'] & { migrationMode: MigrationMode }\n storage: BunderstackManifest['storage']\n realtime?: { required: true }\n messaging: BunderstackManifest['messaging']\n }\n environment: BlueprintEnvVar[]\n /** Application-declared procedures. Absent in blueprints written before 0.23.0. */\n api?: { operations: BunderstackManifest['api']['operations'] }\n background: BunderstackManifest['background'] & {\n worker: { required: boolean }\n }\n}\n\nconst nonEmpty = v.pipe(v.string(), v.minLength(1))\nconst relativePath = v.pipe(\n nonEmpty,\n v.check(\n (value) =>\n !value.startsWith('/') &&\n !value.includes('\\\\') &&\n value.split('/').every((part) => part !== '' && part !== '..'),\n 'entry must be a relative path without traversal',\n ),\n)\nconst cronSchedule = v.pipe(\n nonEmpty,\n v.check((value) => {\n try {\n parseCron(value)\n return true\n } catch {\n return false\n }\n }, 'invalid cron schedule'),\n)\n\n// Hosts parse blueprints committed by applications that upgrade bunderstack on\n// their own schedule, so a section written by a newer generator has to survive\n// an older parser instead of failing the whole file.\nfunction open<TEntries extends v.ObjectEntries>(entries: TEntries) {\n return v.objectWithRest(entries, v.unknown())\n}\n\nconst blueprintSchema = open({\n version: v.literal(1),\n generator: open({\n name: v.literal('bunderstack'),\n version: nonEmpty,\n }),\n application: open({\n framework: v.picklist(['tanstack-start', 'solid', 'bun-ssr', 'custom']),\n scripts: open({\n build: v.literal('build'),\n start: v.literal('start'),\n worker: v.optional(v.literal('worker')),\n }),\n }),\n bunderstack: open({\n entry: relativePath,\n manifestVersion: v.literal(4),\n }),\n resources: open({\n database: open({\n dialect: v.picklist(['sqlite', 'pg']),\n migrationsDirectory: relativePath,\n migrationMode: v.picklist(['migrations', 'push']),\n tables: v.array(\n open({\n exportName: nonEmpty,\n physicalName: nonEmpty,\n system: v.boolean(),\n }),\n ),\n }),\n storage: open({\n defaultBucket: nonEmpty,\n buckets: v.array(\n open({\n name: nonEmpty,\n visibility: v.picklist(['public', 'private']),\n }),\n ),\n }),\n realtime: v.optional(open({ required: v.literal(true) })),\n messaging: open({\n channels: v.array(\n open({ name: nonEmpty, kind: nonEmpty, provider: nonEmpty }),\n ),\n }),\n }),\n environment: v.array(\n open({\n key: nonEmpty,\n required: v.boolean(),\n scope: v.picklist(['server', 'client']),\n sensitive: v.optional(v.boolean()),\n description: v.optional(v.pipe(nonEmpty, v.maxLength(200))),\n }),\n ),\n api: v.optional(\n open({\n operations: v.array(\n open({\n handle: nonEmpty,\n operationId: nonEmpty,\n effect: v.picklist(['read', 'mutation', 'unknown']),\n method: v.optional(nonEmpty),\n path: v.optional(nonEmpty),\n summary: v.optional(v.pipe(nonEmpty, v.maxLength(200))),\n }),\n ),\n }),\n ),\n background: open({\n worker: open({ required: v.boolean() }),\n jobs: v.array(open({ name: nonEmpty })),\n cron: v.array(\n open({\n name: nonEmpty,\n schedule: cronSchedule,\n timezone: v.literal('UTC'),\n }),\n ),\n maintenance: v.array(\n open({\n name: v.literal('storage-sweep'),\n schedule: cronSchedule,\n timezone: v.literal('UTC'),\n }),\n ),\n }),\n})\n\nfunction sortBy<T>(entries: readonly T[], key: (entry: T) => string): T[] {\n return [...entries].sort((left, right) => key(left).localeCompare(key(right)))\n}\n\nfunction rejectDuplicates(collection: string, values: readonly string[]): void {\n const seen = new Set<string>()\n for (const value of values) {\n if (seen.has(value))\n throw new Error(`[bunderstack] duplicate ${collection} \"${value}\"`)\n seen.add(value)\n }\n}\n\nexport function parseBlueprint(value: unknown): BunderstackBlueprint {\n const blueprint = validateStandardSchema(\n blueprintSchema,\n value,\n 'blueprint',\n ) as BunderstackBlueprint\n rejectDuplicates(\n 'database physical table',\n blueprint.resources.database.tables.map((entry) => entry.physicalName),\n )\n rejectDuplicates(\n 'database export table',\n blueprint.resources.database.tables.map((entry) => entry.exportName),\n )\n rejectDuplicates(\n 'storage bucket',\n blueprint.resources.storage.buckets.map((entry) => entry.name),\n )\n rejectDuplicates(\n 'environment key',\n blueprint.environment.map((entry) => entry.key),\n )\n rejectDuplicates(\n 'messaging channel',\n blueprint.resources.messaging.channels.map((entry) => entry.name),\n )\n if (blueprint.api)\n rejectDuplicates(\n 'api operation',\n blueprint.api.operations.map((entry) => entry.handle),\n )\n rejectDuplicates(\n 'background job',\n blueprint.background.jobs.map((entry) => entry.name),\n )\n rejectDuplicates(\n 'background cron',\n blueprint.background.cron.map((entry) => entry.name),\n )\n rejectDuplicates(\n 'background maintenance',\n blueprint.background.maintenance.map((entry) => entry.name),\n )\n if (\n !blueprint.resources.storage.buckets.some(\n (bucket) => bucket.name === blueprint.resources.storage.defaultBucket,\n )\n ) {\n throw new Error(\n '[bunderstack] storage defaultBucket must be declared in storage buckets',\n )\n }\n const workerRequired = blueprint.background.jobs.length > 0\n if (blueprint.background.worker.required !== workerRequired) {\n throw new Error(\n '[bunderstack] background worker.required must match declared queue jobs',\n )\n }\n if (Boolean(blueprint.application.scripts.worker) !== workerRequired) {\n throw new Error(\n '[bunderstack] application worker script must match declared queue jobs',\n )\n }\n return blueprint\n}\n\n/**\n * Whether a host must treat this key as a secret. A blueprint generated before\n * 0.23.0 has no flag, and server keys are secret by default.\n */\nexport function isSensitiveEnvVar(entry: BlueprintEnvVar): boolean {\n return entry.sensitive ?? entry.scope === 'server'\n}\n\nexport function blueprintFromManifest(args: {\n manifest: BunderstackManifest\n generatorVersion: string\n entry: string\n migrationMode: MigrationMode\n framework?: ApplicationFramework\n}): BunderstackBlueprint {\n const workerRequired = args.manifest.background.jobs.length > 0\n return parseBlueprint({\n version: 1,\n generator: { name: 'bunderstack', version: args.generatorVersion },\n application: {\n framework: args.framework ?? 'tanstack-start',\n scripts: {\n build: 'build',\n start: 'start',\n ...(workerRequired ? { worker: 'worker' } : {}),\n },\n },\n bunderstack: { entry: args.entry, manifestVersion: 4 },\n resources: {\n database: {\n ...args.manifest.database,\n migrationMode: args.migrationMode,\n tables: sortBy(\n args.manifest.database.tables,\n (entry) => entry.physicalName,\n ),\n },\n storage: {\n ...args.manifest.storage,\n buckets: sortBy(args.manifest.storage.buckets, (entry) => entry.name),\n },\n ...(args.manifest.realtime.required\n ? { realtime: { required: true } }\n : {}),\n messaging: {\n channels: sortBy(\n args.manifest.messaging.channels,\n (entry) => entry.name,\n ),\n },\n },\n environment: sortBy(args.manifest.environment, (entry) => entry.key),\n api: { operations: args.manifest.api.operations },\n background: {\n worker: { required: workerRequired },\n jobs: sortBy(args.manifest.background.jobs, (entry) => entry.name),\n cron: sortBy(args.manifest.background.cron, (entry) => entry.name),\n maintenance: sortBy(\n args.manifest.background.maintenance,\n (entry) => entry.name,\n ),\n },\n })\n}\n\nexport function parseBlueprintYaml(source: string): BunderstackBlueprint {\n return parseBlueprint(parse(source) as unknown)\n}\n\nexport function serializeBlueprint(value: BunderstackBlueprint): string {\n const blueprint = parseBlueprint(value)\n const options = {\n aliasDuplicateObjects: false,\n defaultKeyType: 'PLAIN',\n defaultStringType: 'PLAIN',\n lineWidth: 0,\n } as const\n const source = stringify(\n parseBlueprintYaml(stringify(blueprint, options)),\n options,\n )\n return source.replace(\n /^(\\s*schedule: )(.+)$/gm,\n (_match, prefix: string, value: string) => {\n const schedule = value.startsWith('\"') ? JSON.parse(value) : value\n return `${prefix}${JSON.stringify(schedule)}`\n },\n )\n}\n"]}
|
|
1
|
+
{"version":3,"file":"blueprint.js","sourceRoot":"","sources":["../src/blueprint.ts"],"names":[],"mappings":"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","sourcesContent":["import * as v from 'valibot'\nimport { parse, stringify } from 'yaml'\n\nimport type { BunderstackManifest } from './manifest'\n\nimport { parseCron } from './jobs/cron'\nimport { validateStandardSchema } from './standard-schema'\n\nexport type MigrationMode = 'migrations' | 'push'\nexport type ApplicationRuntime = 'server' | 'worker'\nexport type ApplicationFramework =\n | 'tanstack-start'\n | 'solid'\n | 'bun-ssr'\n | 'custom'\n\n/**\n * Blueprint form of an environment key. `sensitive` and `description` are\n * optional because blueprints committed before 0.23.0 do not carry them.\n */\nexport type BlueprintEnvVar = {\n key: string\n required: boolean\n scope: 'server' | 'client'\n sensitive?: boolean\n description?: string\n}\n\nexport type BunderstackBlueprint = {\n version: 1\n generator: { name: 'bunderstack'; version: string }\n application: {\n runtime?: ApplicationRuntime\n framework: ApplicationFramework\n scripts: { build: 'build'; start?: 'start'; worker?: 'worker' }\n }\n bunderstack: { entry: string; manifestVersion: 4 }\n resources: {\n database: BunderstackManifest['database'] & { migrationMode: MigrationMode }\n storage: BunderstackManifest['storage']\n realtime?: { required: true }\n messaging: BunderstackManifest['messaging']\n }\n environment: BlueprintEnvVar[]\n /** Application-declared procedures. Absent in blueprints written before 0.23.0. */\n api?: { operations: BunderstackManifest['api']['operations'] }\n background: BunderstackManifest['background'] & {\n worker: { required: boolean }\n }\n}\n\nconst nonEmpty = v.pipe(v.string(), v.minLength(1))\nconst relativePath = v.pipe(\n nonEmpty,\n v.check(\n (value) =>\n !value.startsWith('/') &&\n !value.includes('\\\\') &&\n value.split('/').every((part) => part !== '' && part !== '..'),\n 'entry must be a relative path without traversal',\n ),\n)\nconst cronSchedule = v.pipe(\n nonEmpty,\n v.check((value) => {\n try {\n parseCron(value)\n return true\n } catch {\n return false\n }\n }, 'invalid cron schedule'),\n)\n\n// Hosts parse blueprints committed by applications that upgrade bunderstack on\n// their own schedule, so a section written by a newer generator has to survive\n// an older parser instead of failing the whole file.\nfunction open<TEntries extends v.ObjectEntries>(entries: TEntries) {\n return v.objectWithRest(entries, v.unknown())\n}\n\nconst blueprintSchema = open({\n version: v.literal(1),\n generator: open({\n name: v.literal('bunderstack'),\n version: nonEmpty,\n }),\n application: open({\n runtime: v.optional(v.picklist(['server', 'worker'])),\n framework: v.picklist(['tanstack-start', 'solid', 'bun-ssr', 'custom']),\n scripts: open({\n build: v.literal('build'),\n start: v.optional(v.literal('start')),\n worker: v.optional(v.literal('worker')),\n }),\n }),\n bunderstack: open({\n entry: relativePath,\n manifestVersion: v.literal(4),\n }),\n resources: open({\n database: open({\n dialect: v.picklist(['sqlite', 'pg']),\n migrationsDirectory: relativePath,\n migrationMode: v.picklist(['migrations', 'push']),\n tables: v.array(\n open({\n exportName: nonEmpty,\n physicalName: nonEmpty,\n system: v.boolean(),\n }),\n ),\n }),\n storage: open({\n defaultBucket: nonEmpty,\n buckets: v.array(\n open({\n name: nonEmpty,\n visibility: v.picklist(['public', 'private']),\n }),\n ),\n }),\n realtime: v.optional(open({ required: v.literal(true) })),\n messaging: open({\n channels: v.array(\n open({ name: nonEmpty, kind: nonEmpty, provider: nonEmpty }),\n ),\n }),\n }),\n environment: v.array(\n open({\n key: nonEmpty,\n required: v.boolean(),\n scope: v.picklist(['server', 'client']),\n sensitive: v.optional(v.boolean()),\n description: v.optional(v.pipe(nonEmpty, v.maxLength(200))),\n }),\n ),\n api: v.optional(\n open({\n operations: v.array(\n open({\n handle: nonEmpty,\n operationId: nonEmpty,\n effect: v.picklist(['read', 'mutation', 'unknown']),\n method: v.optional(nonEmpty),\n path: v.optional(nonEmpty),\n summary: v.optional(v.pipe(nonEmpty, v.maxLength(200))),\n }),\n ),\n }),\n ),\n background: open({\n worker: open({ required: v.boolean() }),\n jobs: v.array(open({ name: nonEmpty })),\n cron: v.array(\n open({\n name: nonEmpty,\n schedule: cronSchedule,\n timezone: v.literal('UTC'),\n }),\n ),\n maintenance: v.array(\n open({\n name: v.literal('storage-sweep'),\n schedule: cronSchedule,\n timezone: v.literal('UTC'),\n }),\n ),\n }),\n})\n\nfunction sortBy<T>(entries: readonly T[], key: (entry: T) => string): T[] {\n return [...entries].sort((left, right) => key(left).localeCompare(key(right)))\n}\n\nfunction rejectDuplicates(collection: string, values: readonly string[]): void {\n const seen = new Set<string>()\n for (const value of values) {\n if (seen.has(value))\n throw new Error(`[bunderstack] duplicate ${collection} \"${value}\"`)\n seen.add(value)\n }\n}\n\nexport function parseBlueprint(value: unknown): BunderstackBlueprint {\n const blueprint = validateStandardSchema(\n blueprintSchema,\n value,\n 'blueprint',\n ) as BunderstackBlueprint\n rejectDuplicates(\n 'database physical table',\n blueprint.resources.database.tables.map((entry) => entry.physicalName),\n )\n rejectDuplicates(\n 'database export table',\n blueprint.resources.database.tables.map((entry) => entry.exportName),\n )\n rejectDuplicates(\n 'storage bucket',\n blueprint.resources.storage.buckets.map((entry) => entry.name),\n )\n rejectDuplicates(\n 'environment key',\n blueprint.environment.map((entry) => entry.key),\n )\n rejectDuplicates(\n 'messaging channel',\n blueprint.resources.messaging.channels.map((entry) => entry.name),\n )\n if (blueprint.api)\n rejectDuplicates(\n 'api operation',\n blueprint.api.operations.map((entry) => entry.handle),\n )\n rejectDuplicates(\n 'background job',\n blueprint.background.jobs.map((entry) => entry.name),\n )\n rejectDuplicates(\n 'background cron',\n blueprint.background.cron.map((entry) => entry.name),\n )\n rejectDuplicates(\n 'background maintenance',\n blueprint.background.maintenance.map((entry) => entry.name),\n )\n if (\n !blueprint.resources.storage.buckets.some(\n (bucket) => bucket.name === blueprint.resources.storage.defaultBucket,\n )\n ) {\n throw new Error(\n '[bunderstack] storage defaultBucket must be declared in storage buckets',\n )\n }\n const runtime = blueprint.application.runtime ?? 'server'\n const workerRequired = blueprint.background.jobs.length > 0\n if (blueprint.background.worker.required !== workerRequired) {\n throw new Error(\n '[bunderstack] background worker.required must match declared queue jobs',\n )\n }\n if (runtime === 'worker') {\n if (\n blueprint.application.scripts.start !== undefined ||\n blueprint.application.scripts.worker !== undefined\n ) {\n throw new Error(\n '[bunderstack] worker runtime blueprint must only declare the build script',\n )\n }\n } else {\n if (blueprint.application.scripts.start !== 'start') {\n throw new Error(\n '[bunderstack] server runtime blueprint must declare the start script',\n )\n }\n if (Boolean(blueprint.application.scripts.worker) !== workerRequired) {\n throw new Error(\n '[bunderstack] application worker script must match declared queue jobs',\n )\n }\n }\n return blueprint\n}\n\n/**\n * Whether a host must treat this key as a secret. A blueprint generated before\n * 0.23.0 has no flag, and server keys are secret by default.\n */\nexport function isSensitiveEnvVar(entry: BlueprintEnvVar): boolean {\n return entry.sensitive ?? entry.scope === 'server'\n}\n\nexport function blueprintFromManifest(args: {\n manifest: BunderstackManifest\n generatorVersion: string\n entry: string\n migrationMode: MigrationMode\n framework?: ApplicationFramework\n runtime?: ApplicationRuntime\n}): BunderstackBlueprint {\n const runtime = args.runtime ?? 'server'\n const workerRequired = args.manifest.background.jobs.length > 0\n return parseBlueprint({\n version: 1,\n generator: { name: 'bunderstack', version: args.generatorVersion },\n application: {\n ...(args.runtime ? { runtime: args.runtime } : {}),\n framework: args.framework ?? 'tanstack-start',\n scripts:\n runtime === 'worker'\n ? { build: 'build' }\n : {\n build: 'build',\n start: 'start',\n ...(workerRequired ? { worker: 'worker' } : {}),\n },\n },\n bunderstack: { entry: args.entry, manifestVersion: 4 },\n resources: {\n database: {\n ...args.manifest.database,\n migrationMode: args.migrationMode,\n tables: sortBy(\n args.manifest.database.tables,\n (entry) => entry.physicalName,\n ),\n },\n storage: {\n ...args.manifest.storage,\n buckets: sortBy(args.manifest.storage.buckets, (entry) => entry.name),\n },\n ...(args.manifest.realtime.required\n ? { realtime: { required: true } }\n : {}),\n messaging: {\n channels: sortBy(\n args.manifest.messaging.channels,\n (entry) => entry.name,\n ),\n },\n },\n environment: sortBy(args.manifest.environment, (entry) => entry.key),\n api: { operations: args.manifest.api.operations },\n background: {\n worker: { required: workerRequired },\n jobs: sortBy(args.manifest.background.jobs, (entry) => entry.name),\n cron: sortBy(args.manifest.background.cron, (entry) => entry.name),\n maintenance: sortBy(\n args.manifest.background.maintenance,\n (entry) => entry.name,\n ),\n },\n })\n}\n\nexport function parseBlueprintYaml(source: string): BunderstackBlueprint {\n return parseBlueprint(parse(source) as unknown)\n}\n\nexport function serializeBlueprint(value: BunderstackBlueprint): string {\n const blueprint = parseBlueprint(value)\n const options = {\n aliasDuplicateObjects: false,\n defaultKeyType: 'PLAIN',\n defaultStringType: 'PLAIN',\n lineWidth: 0,\n } as const\n const source = stringify(\n parseBlueprintYaml(stringify(blueprint, options)),\n options,\n )\n return source.replace(\n /^(\\s*schedule: )(.+)$/gm,\n (_match, prefix: string, value: string) => {\n const schedule = value.startsWith('\"') ? JSON.parse(value) : value\n return `${prefix}${JSON.stringify(schedule)}`\n },\n )\n}\n"]}
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAEL,iBAAiB,EAElB,MAAM,uBAAuB,CAAA;AAG9B,MAAM,MAAM,KAAK,GAAG;IAClB,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B,CAAA;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAEL,iBAAiB,EAElB,MAAM,uBAAuB,CAAA;AAG9B,MAAM,MAAM,KAAK,GAAG;IAClB,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B,CAAA;AA+BD,KAAK,WAAW,GAAG;IACjB,GAAG,CAAC,OAAO,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACnE,KAAK,CAAC,OAAO,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;CACvD,CAAA;AAOD,wBAAsB,MAAM,CAC1B,IAAI,EAAE,MAAM,EAAE,EACd,EAAE,EAAE,KAAK,EACT,QAAQ,GAAE,OAAO,iBAAqC,EACtD,QAAQ,GAAE,WAAyB,GAClC,OAAO,CAAC,MAAM,CAAC,CAyLjB"}
|
package/dist/cli.js
CHANGED
|
@@ -21,12 +21,14 @@ wrangler Generate wrangler.json for Cloudflare and celld from the backend:
|
|
|
21
21
|
--check reports drift without writing.
|
|
22
22
|
|
|
23
23
|
dev Start the app locally: sqld, celld with the Worker, and Vite with
|
|
24
|
-
the API proxy. Pushes the schema and regenerates wrangler.json
|
|
25
|
-
each change under src/. Ctrl+C stops
|
|
24
|
+
the API proxy. Pushes the schema and regenerates wrangler.json and
|
|
25
|
+
bunderstack.blueprint.yaml on each change under src/. Ctrl+C stops
|
|
26
|
+
everything.
|
|
26
27
|
BUNDERSTACK_CELLD_BIN and BUNDERSTACK_SQLD_BIN select system
|
|
27
28
|
binaries instead of the pinned downloads.
|
|
28
29
|
|
|
29
|
-
build Build the SPA into dist/client with Vite and check wrangler.json
|
|
30
|
+
build Build the SPA into dist/client with Vite and check wrangler.json and
|
|
31
|
+
bunderstack.blueprint.yaml.`;
|
|
30
32
|
const appCommands = {
|
|
31
33
|
dev: async (options) => (await import('./dev/index.js')).runDev(options),
|
|
32
34
|
build: async (options) => (await import('./dev/index.js')).runBuild(options),
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env bun\nimport {\n BlueprintCheckError,\n generateBlueprint,\n type GenerateBlueprintOptions,\n} from './blueprint-generator'\nimport { installSkills } from './cli-skills'\n\nexport type CliIo = {\n stdout(message: string): void\n stderr(message: string): void\n}\n\nconst help = `Usage:\n bunderstack blueprint [directory] [--entry <path>] [--output <path>] [--check|--hosted-check]\n bunderstack skills [--dir <path>] [--check]\n bunderstack wrangler [directory] [--entry <path>] [--name <name>] [--assets <dir>] [--output <path>] [--check]\n bunderstack dev [directory] [--port <port>]\n bunderstack build [directory]\n\nblueprint Generate a committed deployment declaration for a TanStack Start\n application. Entry precedence: --entry,\n package.json#bunderstack.entry, src/bunderstack.ts.\n\nskills Install the Bunderstack agent skills that match this version into\n .agents/skills, and point AGENTS.md at them so an agent loads them\n before touching the API. --check reports drift without writing.\n\nwrangler Generate wrangler.json for Cloudflare and celld from the backend:\n Durable Objects, R2 buckets, static assets, and Cron Triggers.\n --check reports drift without writing.\n\ndev Start the app locally: sqld, celld with the Worker, and Vite with\n the API proxy. Pushes the schema and regenerates wrangler.json on\n each change under src/. Ctrl+C stops everything.\n BUNDERSTACK_CELLD_BIN and BUNDERSTACK_SQLD_BIN select system\n binaries instead of the pinned downloads.\n\nbuild Build the SPA into dist/client with Vite and check wrangler.json.`\n\ntype AppCommands = {\n dev(options: { directory: string; port?: number }): Promise<number>\n build(options: { directory: string }): Promise<number>\n}\n\nconst appCommands: AppCommands = {\n dev: async (options) => (await import('./dev/index')).runDev(options),\n build: async (options) => (await import('./dev/index')).runBuild(options),\n}\n\nexport async function runCli(\n args: string[],\n io: CliIo,\n generate: typeof generateBlueprint = generateBlueprint,\n commands: AppCommands = appCommands,\n): Promise<number> {\n if (args[0] === '--help' || args[0] === '-h') {\n io.stdout(help)\n return 0\n }\n if (args[0] === '--version') {\n io.stdout(\n (\n (await Bun.file(\n new URL('../package.json', import.meta.url),\n ).json()) as { version: string }\n ).version,\n )\n return 0\n }\n if (args[0] === 'skills') {\n const options: { cwd: string; directory?: string; check?: boolean } = {\n cwd: process.cwd(),\n }\n for (let index = 1; index < args.length; index++) {\n const argument = args[index]!\n if (argument === '--check') {\n options.check = true\n continue\n }\n if (argument === '--dir') {\n const value = args[++index]\n if (!value || value.startsWith('--')) {\n io.stderr('[bunderstack] missing value for --dir')\n return 2\n }\n options.directory = value\n continue\n }\n io.stderr(`[bunderstack] unknown option: ${argument}`)\n return 2\n }\n return installSkills(options, io)\n }\n\n if (args[0] === 'dev' || args[0] === 'build') {\n const command = args[0]\n let directory: string | undefined\n let port: number | undefined\n for (let index = 1; index < args.length; index++) {\n const argument = args[index]!\n if (command === 'dev' && argument === '--port') {\n const value = Number(args[++index])\n if (!Number.isInteger(value) || value <= 0) {\n io.stderr('[bunderstack] --port needs a port number')\n return 2\n }\n port = value\n continue\n }\n if (argument.startsWith('-')) {\n io.stderr(`[bunderstack] unknown option: ${argument}`)\n return 2\n }\n if (directory !== undefined) {\n io.stderr('[bunderstack] only one application directory is allowed')\n return 2\n }\n directory = argument\n }\n directory ??= process.cwd()\n return command === 'dev'\n ? commands.dev({ directory, ...(port ? { port } : {}) })\n : commands.build({ directory })\n }\n\n if (args[0] === 'wrangler') {\n const options: {\n directory: string\n entry?: string\n name?: string\n assets?: string\n output?: string\n check?: boolean\n } = { directory: process.cwd() }\n const valued = {\n '--entry': 'entry',\n '--name': 'name',\n '--assets': 'assets',\n '--output': 'output',\n } as const\n let directorySet = false\n for (let index = 1; index < args.length; index++) {\n const argument = args[index]!\n if (argument === '--check') {\n options.check = true\n continue\n }\n if (argument in valued) {\n const value = args[++index]\n if (!value || value.startsWith('--')) {\n io.stderr(`[bunderstack] missing value for ${argument}`)\n return 2\n }\n options[valued[argument as keyof typeof valued]] = value\n continue\n }\n if (argument.startsWith('-')) {\n io.stderr(`[bunderstack] unknown option: ${argument}`)\n return 2\n }\n if (directorySet) {\n io.stderr('[bunderstack] only one application directory is allowed')\n return 2\n }\n options.directory = argument\n directorySet = true\n }\n try {\n const { runWranglerCommand } = await import('./workers/wrangler')\n const result = await runWranglerCommand(options)\n io.stdout(\n result.changed ? 'Generated wrangler.json' : 'wrangler.json is current',\n )\n return 0\n } catch (error) {\n io.stderr(error instanceof Error ? error.message : String(error))\n return 1\n }\n }\n\n if (args[0] !== 'blueprint') {\n io.stderr(help)\n return 2\n }\n const options: GenerateBlueprintOptions = { directory: process.cwd() }\n for (let index = 1; index < args.length; index++) {\n const argument = args[index]!\n if (argument === '--check') {\n if (options.hostedCheck) {\n io.stderr(\n '[bunderstack] --check and --hosted-check are mutually exclusive',\n )\n return 2\n }\n options.check = true\n continue\n }\n if (argument === '--hosted-check') {\n if (options.check) {\n io.stderr(\n '[bunderstack] --check and --hosted-check are mutually exclusive',\n )\n return 2\n }\n options.hostedCheck = true\n continue\n }\n if (argument === '--entry' || argument === '--output') {\n const value = args[++index]\n if (!value || value.startsWith('--')) {\n io.stderr(`[bunderstack] missing value for ${argument}`)\n return 2\n }\n if (argument === '--entry') options.entry = value\n else options.output = value\n continue\n }\n if (argument.startsWith('-')) {\n io.stderr(`[bunderstack] unknown option: ${argument}`)\n return 2\n }\n if (options.directory !== process.cwd()) {\n io.stderr('[bunderstack] only one application directory is allowed')\n return 2\n }\n options.directory = argument\n }\n try {\n const result = await generate(options)\n io.stdout(\n options.check || options.hostedCheck || !result.changed\n ? 'bunderstack.blueprint.yaml is current'\n : 'Generated bunderstack.blueprint.yaml',\n )\n return 0\n } catch (error) {\n io.stderr(error instanceof Error ? error.message : String(error))\n return error instanceof BlueprintCheckError ? 1 : 1\n }\n}\n\nif (import.meta.main) {\n const exitCode = await runCli(process.argv.slice(2), {\n stdout: (message) => console.log(message),\n stderr: (message) => console.error(message),\n })\n process.exit(exitCode)\n}\n"]}
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env bun\nimport {\n BlueprintCheckError,\n generateBlueprint,\n type GenerateBlueprintOptions,\n} from './blueprint-generator'\nimport { installSkills } from './cli-skills'\n\nexport type CliIo = {\n stdout(message: string): void\n stderr(message: string): void\n}\n\nconst help = `Usage:\n bunderstack blueprint [directory] [--entry <path>] [--output <path>] [--check|--hosted-check]\n bunderstack skills [--dir <path>] [--check]\n bunderstack wrangler [directory] [--entry <path>] [--name <name>] [--assets <dir>] [--output <path>] [--check]\n bunderstack dev [directory] [--port <port>]\n bunderstack build [directory]\n\nblueprint Generate a committed deployment declaration for a TanStack Start\n application. Entry precedence: --entry,\n package.json#bunderstack.entry, src/bunderstack.ts.\n\nskills Install the Bunderstack agent skills that match this version into\n .agents/skills, and point AGENTS.md at them so an agent loads them\n before touching the API. --check reports drift without writing.\n\nwrangler Generate wrangler.json for Cloudflare and celld from the backend:\n Durable Objects, R2 buckets, static assets, and Cron Triggers.\n --check reports drift without writing.\n\ndev Start the app locally: sqld, celld with the Worker, and Vite with\n the API proxy. Pushes the schema and regenerates wrangler.json and\n bunderstack.blueprint.yaml on each change under src/. Ctrl+C stops\n everything.\n BUNDERSTACK_CELLD_BIN and BUNDERSTACK_SQLD_BIN select system\n binaries instead of the pinned downloads.\n\nbuild Build the SPA into dist/client with Vite and check wrangler.json and\n bunderstack.blueprint.yaml.`\n\ntype AppCommands = {\n dev(options: { directory: string; port?: number }): Promise<number>\n build(options: { directory: string }): Promise<number>\n}\n\nconst appCommands: AppCommands = {\n dev: async (options) => (await import('./dev/index')).runDev(options),\n build: async (options) => (await import('./dev/index')).runBuild(options),\n}\n\nexport async function runCli(\n args: string[],\n io: CliIo,\n generate: typeof generateBlueprint = generateBlueprint,\n commands: AppCommands = appCommands,\n): Promise<number> {\n if (args[0] === '--help' || args[0] === '-h') {\n io.stdout(help)\n return 0\n }\n if (args[0] === '--version') {\n io.stdout(\n (\n (await Bun.file(\n new URL('../package.json', import.meta.url),\n ).json()) as { version: string }\n ).version,\n )\n return 0\n }\n if (args[0] === 'skills') {\n const options: { cwd: string; directory?: string; check?: boolean } = {\n cwd: process.cwd(),\n }\n for (let index = 1; index < args.length; index++) {\n const argument = args[index]!\n if (argument === '--check') {\n options.check = true\n continue\n }\n if (argument === '--dir') {\n const value = args[++index]\n if (!value || value.startsWith('--')) {\n io.stderr('[bunderstack] missing value for --dir')\n return 2\n }\n options.directory = value\n continue\n }\n io.stderr(`[bunderstack] unknown option: ${argument}`)\n return 2\n }\n return installSkills(options, io)\n }\n\n if (args[0] === 'dev' || args[0] === 'build') {\n const command = args[0]\n let directory: string | undefined\n let port: number | undefined\n for (let index = 1; index < args.length; index++) {\n const argument = args[index]!\n if (command === 'dev' && argument === '--port') {\n const value = Number(args[++index])\n if (!Number.isInteger(value) || value <= 0) {\n io.stderr('[bunderstack] --port needs a port number')\n return 2\n }\n port = value\n continue\n }\n if (argument.startsWith('-')) {\n io.stderr(`[bunderstack] unknown option: ${argument}`)\n return 2\n }\n if (directory !== undefined) {\n io.stderr('[bunderstack] only one application directory is allowed')\n return 2\n }\n directory = argument\n }\n directory ??= process.cwd()\n return command === 'dev'\n ? commands.dev({ directory, ...(port ? { port } : {}) })\n : commands.build({ directory })\n }\n\n if (args[0] === 'wrangler') {\n const options: {\n directory: string\n entry?: string\n name?: string\n assets?: string\n output?: string\n check?: boolean\n } = { directory: process.cwd() }\n const valued = {\n '--entry': 'entry',\n '--name': 'name',\n '--assets': 'assets',\n '--output': 'output',\n } as const\n let directorySet = false\n for (let index = 1; index < args.length; index++) {\n const argument = args[index]!\n if (argument === '--check') {\n options.check = true\n continue\n }\n if (argument in valued) {\n const value = args[++index]\n if (!value || value.startsWith('--')) {\n io.stderr(`[bunderstack] missing value for ${argument}`)\n return 2\n }\n options[valued[argument as keyof typeof valued]] = value\n continue\n }\n if (argument.startsWith('-')) {\n io.stderr(`[bunderstack] unknown option: ${argument}`)\n return 2\n }\n if (directorySet) {\n io.stderr('[bunderstack] only one application directory is allowed')\n return 2\n }\n options.directory = argument\n directorySet = true\n }\n try {\n const { runWranglerCommand } = await import('./workers/wrangler')\n const result = await runWranglerCommand(options)\n io.stdout(\n result.changed ? 'Generated wrangler.json' : 'wrangler.json is current',\n )\n return 0\n } catch (error) {\n io.stderr(error instanceof Error ? error.message : String(error))\n return 1\n }\n }\n\n if (args[0] !== 'blueprint') {\n io.stderr(help)\n return 2\n }\n const options: GenerateBlueprintOptions = { directory: process.cwd() }\n for (let index = 1; index < args.length; index++) {\n const argument = args[index]!\n if (argument === '--check') {\n if (options.hostedCheck) {\n io.stderr(\n '[bunderstack] --check and --hosted-check are mutually exclusive',\n )\n return 2\n }\n options.check = true\n continue\n }\n if (argument === '--hosted-check') {\n if (options.check) {\n io.stderr(\n '[bunderstack] --check and --hosted-check are mutually exclusive',\n )\n return 2\n }\n options.hostedCheck = true\n continue\n }\n if (argument === '--entry' || argument === '--output') {\n const value = args[++index]\n if (!value || value.startsWith('--')) {\n io.stderr(`[bunderstack] missing value for ${argument}`)\n return 2\n }\n if (argument === '--entry') options.entry = value\n else options.output = value\n continue\n }\n if (argument.startsWith('-')) {\n io.stderr(`[bunderstack] unknown option: ${argument}`)\n return 2\n }\n if (options.directory !== process.cwd()) {\n io.stderr('[bunderstack] only one application directory is allowed')\n return 2\n }\n options.directory = argument\n }\n try {\n const result = await generate(options)\n io.stdout(\n options.check || options.hostedCheck || !result.changed\n ? 'bunderstack.blueprint.yaml is current'\n : 'Generated bunderstack.blueprint.yaml',\n )\n return 0\n } catch (error) {\n io.stderr(error instanceof Error ? error.message : String(error))\n return error instanceof BlueprintCheckError ? 1 : 1\n }\n}\n\nif (import.meta.main) {\n const exitCode = await runCli(process.argv.slice(2), {\n stdout: (message) => console.log(message),\n stderr: (message) => console.error(message),\n })\n process.exit(exitCode)\n}\n"]}
|
package/dist/dev/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dev/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dev/index.ts"],"names":[],"mappings":"AAaA,OAAO,EAAgB,KAAK,WAAW,EAAE,MAAM,aAAa,CAAA;AAE5D,MAAM,MAAM,OAAO,GAAG;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,CAAC,EAAE,WAAW,CAAA;IAClB,MAAM,EAAE,WAAW,CAAA;IACnB,IAAI,CAAC,EAAE,WAAW,CAAA;CACnB,CAAA;AAID;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAc1D;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAA;IAC/C,QAAQ,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;CAC3D,GAAG,OAAO,CA4DV;AA+BD;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAKlE;AAgCD,wBAAsB,MAAM,CAAC,OAAO,EAAE;IACpC,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,GAAG,OAAO,CAAC,MAAM,CAAC,CAwHlB;AAED,wBAAsB,QAAQ,CAAC,OAAO,EAAE;IACtC,SAAS,EAAE,MAAM,CAAA;CAClB,GAAG,OAAO,CAAC,MAAM,CAAC,CAoBlB"}
|
package/dist/dev/index.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
// `bunderstack dev` and `bunderstack build`. dev starts sqld, celld, and Vite
|
|
2
2
|
// with one command; build writes the SPA to dist/client and checks
|
|
3
|
-
// wrangler.json.
|
|
3
|
+
// wrangler.json and bunderstack.blueprint.yaml.
|
|
4
4
|
import { watch } from 'node:fs';
|
|
5
5
|
import { mkdir, readdir, writeFile } from 'node:fs/promises';
|
|
6
6
|
import { createServer } from 'node:net';
|
|
7
7
|
import { dirname, join, resolve } from 'node:path';
|
|
8
8
|
import { fileURLToPath } from 'node:url';
|
|
9
|
+
import { generateBlueprint } from '../blueprint-generator.js';
|
|
9
10
|
import { runWranglerCommand } from '../workers/wrangler.js';
|
|
10
11
|
import { resolveBinary } from './binaries.js';
|
|
11
12
|
import { devSecret, devVars, readUserEnv } from './env.js';
|
|
@@ -277,6 +278,8 @@ export async function runBuild(options) {
|
|
|
277
278
|
try {
|
|
278
279
|
await runWranglerCommand({ directory, check: true });
|
|
279
280
|
console.log('wrangler.json is current');
|
|
281
|
+
await generateBlueprint({ directory, check: true });
|
|
282
|
+
console.log('bunderstack.blueprint.yaml is current');
|
|
280
283
|
return 0;
|
|
281
284
|
}
|
|
282
285
|
catch (error) {
|
package/dist/dev/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/dev/index.ts"],"names":[],"mappings":"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","sourcesContent":["// `bunderstack dev` and `bunderstack build`. dev starts sqld, celld, and Vite\n// with one command; build writes the SPA to dist/client and checks\n// wrangler.json.\nimport { watch } from 'node:fs'\nimport { mkdir, readdir, writeFile } from 'node:fs/promises'\nimport { createServer } from 'node:net'\nimport { dirname, join, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nimport { runWranglerCommand } from '../workers/wrangler'\nimport { resolveBinary } from './binaries'\nimport { devSecret, devVars, readUserEnv } from './env'\nimport { ProcessGroup, type ProcessSpec } from './processes'\n\nexport type DevPlan = {\n appUrl: string\n apiUrl: string\n databaseUrl: string\n sqld?: ProcessSpec\n worker: ProcessSpec\n vite?: ProcessSpec\n}\n\nconst LOG_LINE = /^\\S+Z\\s+(TRACE|DEBUG|INFO|WARN|ERROR)\\s+([\\w:]+): (.*)$/\n\n/**\n * celld --logs mixes the Worker's console output with its own INFO lines.\n * Keep the Worker output (without the timestamp), warnings, errors, and the\n * start summary.\n */\nexport function celldLine(line: string): string | undefined {\n if (line.startsWith('<jemalloc>')) return undefined\n const match = LOG_LINE.exec(line)\n if (!match) return line\n const [, level, target, message] = match as unknown as [\n string,\n string,\n string,\n string,\n ]\n if (target === 'cell_console') return message\n if (target === 'celld::memory') return undefined // allocator notice on macOS\n if (level === 'WARN' || level === 'ERROR') return `${level} ${message}`\n return undefined\n}\n\nexport function planDev(input: {\n directory: string\n stateDir: string\n userEnv: Record<string, string>\n hasVite: boolean\n ports: { app: number; api: number; db: number }\n binaries: { celld: string; sqld: string; esbuild: string }\n}): DevPlan {\n const { directory, ports, binaries } = input\n const apiUrl = `http://127.0.0.1:${ports.api}`\n const appUrl = input.hasVite ? `http://localhost:${ports.app}` : apiUrl\n const external = input.userEnv.BUNDERSTACK_DATABASE_URL\n const databaseUrl = external || `http://127.0.0.1:${ports.db}`\n return {\n appUrl,\n apiUrl,\n databaseUrl,\n sqld: external\n ? undefined\n : {\n name: 'sqld',\n cmd: [\n binaries.sqld,\n '--http-listen-addr',\n `127.0.0.1:${ports.db}`,\n '-d',\n join(input.stateDir, 'db'),\n ],\n cwd: directory,\n },\n worker: {\n name: 'celld',\n cmd: [\n binaries.celld,\n 'dev',\n directory,\n '--port',\n String(ports.api),\n // Shows the Worker's console output.\n '--logs',\n // sqld writes here; a rebuild per write would restart the Worker.\n '--watch-ignore',\n '.bunderstack/**',\n '--watch-ignore',\n 'dist/**',\n ],\n cwd: directory,\n env: { CELLD_ESBUILD: binaries.esbuild },\n filter: celldLine,\n },\n vite: input.hasVite\n ? {\n name: 'vite',\n cmd: [\n process.execPath,\n 'x',\n '--bun',\n 'vite',\n '--port',\n String(ports.app),\n '--strictPort',\n ],\n cwd: directory,\n env: { BUNDERSTACK_DEV_API_URL: apiUrl },\n }\n : undefined,\n }\n}\n\nasync function hasViteConfig(directory: string) {\n const files = await readdir(directory)\n return files.some((file) => /^vite\\.config\\.[cm]?[jt]s$/.test(file))\n}\n\nasync function freePort(): Promise<number> {\n return new Promise((resolvePort, reject) => {\n const server = createServer()\n server.listen(0, '127.0.0.1', () => {\n const address = server.address()\n server.close(() =>\n typeof address === 'object' && address\n ? resolvePort(address.port)\n : reject(new Error('no free port')),\n )\n })\n })\n}\n\nfunction canListen(port: number, hostname: string): boolean {\n try {\n Bun.listen({ hostname, port, socket: { data() {} } }).stop(true)\n return true\n } catch (error) {\n // No IPv6 on this machine: nothing can take the port there either.\n return (error as { code?: string }).code === 'EADDRNOTAVAIL'\n }\n}\n\n/**\n * The first port from `start` that is free on 127.0.0.1 and on ::1. The\n * browser opens `localhost`, which can resolve to either; Vite on ::1 next to\n * another server on 127.0.0.1 would answer only some requests.\n */\nexport async function firstFreePort(start: number): Promise<number> {\n for (let port = start; port < start + 100; port++) {\n if (canListen(port, '127.0.0.1') && canListen(port, '::1')) return port\n }\n throw new Error(`[bunderstack] no free port from ${start}`)\n}\n\nasync function waitForHealth(\n url: string,\n timeoutMs: number,\n cancelled: () => boolean,\n) {\n const deadline = Date.now() + timeoutMs\n for (;;) {\n if (cancelled()) return\n const ok = await fetch(url).then(\n (res) => res.ok,\n () => false,\n )\n if (ok) return\n if (Date.now() > deadline) throw new Error(`timed out waiting for ${url}`)\n await Bun.sleep(200)\n }\n}\n\nfunction esbuildBinary() {\n const pkg = Bun.resolveSync('esbuild/package.json', import.meta.dir)\n return join(dirname(pkg), 'bin', 'esbuild')\n}\n\nconst pushScript = fileURLToPath(\n new URL(\n import.meta.url.endsWith('.ts') ? './push.ts' : './push.js',\n import.meta.url,\n ),\n)\n\nexport async function runDev(options: {\n directory: string\n port?: number\n}): Promise<number> {\n const directory = resolve(options.directory)\n const stateDir = join(directory, '.bunderstack', 'dev')\n const group = new ProcessGroup()\n const say = (line: string) => group.log('dev', line)\n\n const userEnv = await readUserEnv(directory)\n const external = Boolean(userEnv.BUNDERSTACK_DATABASE_URL)\n const [celld, sqld] = await Promise.all([\n resolveBinary('celld', { log: say }),\n external ? '' : resolveBinary('sqld', { log: say }),\n ])\n const plan = planDev({\n directory,\n stateDir,\n userEnv,\n hasVite: await hasViteConfig(directory),\n ports: {\n // An explicit port is kept, and Vite fails when it is taken.\n app:\n options.port ??\n (process.env.PORT\n ? Number(process.env.PORT)\n : await firstFreePort(5173)),\n api: await freePort(),\n db: await freePort(),\n },\n binaries: { celld, sqld, esbuild: esbuildBinary() },\n })\n\n // Children run in their own process groups, so the terminal's Ctrl+C does\n // not reach them; group.stop() passes it on.\n let interrupted = false\n const interrupt = new Promise<void>((resolveInterrupt) => {\n for (const signal of ['SIGINT', 'SIGTERM', 'SIGHUP'] as const) {\n process.once(signal, () => {\n interrupted = true\n resolveInterrupt()\n })\n }\n })\n const cancelled = () => interrupted\n let watcher: ReturnType<typeof watch> | undefined\n\n try {\n await mkdir(stateDir, { recursive: true })\n if (plan.sqld) {\n group.start(plan.sqld)\n await waitForHealth(`${plan.databaseUrl}/health`, 20_000, cancelled)\n }\n const authSecret = await devSecret(stateDir)\n await writeFile(\n join(directory, '.dev.vars'),\n devVars({\n userEnv,\n databaseUrl: plan.databaseUrl,\n appUrl: plan.appUrl,\n authSecret,\n }),\n )\n const pushEnv = {\n ...userEnv,\n BUNDERSTACK_DATABASE_URL: plan.databaseUrl,\n AUTH_SECRET: userEnv.AUTH_SECRET || authSecret,\n APP_URL: plan.appUrl,\n }\n const push = async () => {\n const child = Bun.spawn([process.execPath, pushScript, directory], {\n cwd: directory,\n env: { ...process.env, ...pushEnv },\n stdout: 'pipe',\n stderr: 'pipe',\n })\n const [out, err, code] = await Promise.all([\n new Response(child.stdout).text(),\n new Response(child.stderr).text(),\n child.exited,\n ])\n // drizzle-kit draws a spinner with escape codes; keep the text only.\n // oxlint-disable-next-line no-control-regex\n const text = `${out}${err}`.replace(/\\x1b\\[[0-9;]*[A-Za-z]/g, '')\n for (const line of text.trim().split('\\n')) {\n if (line.trim()) group.log('push', line.trim())\n }\n if (code !== 0) group.log('push', 'failed; fix the code and save again')\n return code === 0\n }\n // The first push also writes wrangler.json, which celld reads at start.\n await push()\n\n let timer: ReturnType<typeof setTimeout> | undefined\n let running = Promise.resolve(true)\n watcher = watch(join(directory, 'src'), { recursive: true }, (_, file) => {\n if (file && String(file).endsWith('routeTree.gen.ts')) return\n clearTimeout(timer)\n timer = setTimeout(() => {\n running = running.then(push)\n }, 300)\n })\n\n group.start(plan.worker)\n await waitForHealth(`${plan.apiUrl}/api/health`, 60_000, cancelled).catch(\n () => say('the Worker did not answer /api/health yet; see the celld log'),\n )\n if (plan.vite && !interrupted) group.start(plan.vite)\n if (!interrupted) say(`App: ${plan.appUrl}`)\n\n const outcome = await Promise.race([group.exited, interrupt])\n if (outcome && !interrupted) {\n say(`${outcome.name} exited with code ${outcome.code}; stopping`)\n return 1\n }\n return 0\n } catch (error) {\n say(error instanceof Error ? error.message : String(error))\n return 1\n } finally {\n watcher?.close()\n await group.stop()\n }\n}\n\nexport async function runBuild(options: {\n directory: string\n}): Promise<number> {\n const directory = resolve(options.directory)\n if (await hasViteConfig(directory)) {\n const vite = Bun.spawn([process.execPath, 'x', '--bun', 'vite', 'build'], {\n cwd: directory,\n stdout: 'inherit',\n stderr: 'inherit',\n })\n if ((await vite.exited) !== 0) return 1\n }\n try {\n await runWranglerCommand({ directory, check: true })\n console.log('wrangler.json is current')\n return 0\n } catch (error) {\n console.error(error instanceof Error ? error.message : String(error))\n return 1\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/dev/index.ts"],"names":[],"mappings":"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","sourcesContent":["// `bunderstack dev` and `bunderstack build`. dev starts sqld, celld, and Vite\n// with one command; build writes the SPA to dist/client and checks\n// wrangler.json and bunderstack.blueprint.yaml.\nimport { watch } from 'node:fs'\nimport { mkdir, readdir, writeFile } from 'node:fs/promises'\nimport { createServer } from 'node:net'\nimport { dirname, join, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nimport { generateBlueprint } from '../blueprint-generator'\nimport { runWranglerCommand } from '../workers/wrangler'\nimport { resolveBinary } from './binaries'\nimport { devSecret, devVars, readUserEnv } from './env'\nimport { ProcessGroup, type ProcessSpec } from './processes'\n\nexport type DevPlan = {\n appUrl: string\n apiUrl: string\n databaseUrl: string\n sqld?: ProcessSpec\n worker: ProcessSpec\n vite?: ProcessSpec\n}\n\nconst LOG_LINE = /^\\S+Z\\s+(TRACE|DEBUG|INFO|WARN|ERROR)\\s+([\\w:]+): (.*)$/\n\n/**\n * celld --logs mixes the Worker's console output with its own INFO lines.\n * Keep the Worker output (without the timestamp), warnings, errors, and the\n * start summary.\n */\nexport function celldLine(line: string): string | undefined {\n if (line.startsWith('<jemalloc>')) return undefined\n const match = LOG_LINE.exec(line)\n if (!match) return line\n const [, level, target, message] = match as unknown as [\n string,\n string,\n string,\n string,\n ]\n if (target === 'cell_console') return message\n if (target === 'celld::memory') return undefined // allocator notice on macOS\n if (level === 'WARN' || level === 'ERROR') return `${level} ${message}`\n return undefined\n}\n\nexport function planDev(input: {\n directory: string\n stateDir: string\n userEnv: Record<string, string>\n hasVite: boolean\n ports: { app: number; api: number; db: number }\n binaries: { celld: string; sqld: string; esbuild: string }\n}): DevPlan {\n const { directory, ports, binaries } = input\n const apiUrl = `http://127.0.0.1:${ports.api}`\n const appUrl = input.hasVite ? `http://localhost:${ports.app}` : apiUrl\n const external = input.userEnv.BUNDERSTACK_DATABASE_URL\n const databaseUrl = external || `http://127.0.0.1:${ports.db}`\n return {\n appUrl,\n apiUrl,\n databaseUrl,\n sqld: external\n ? undefined\n : {\n name: 'sqld',\n cmd: [\n binaries.sqld,\n '--http-listen-addr',\n `127.0.0.1:${ports.db}`,\n '-d',\n join(input.stateDir, 'db'),\n ],\n cwd: directory,\n },\n worker: {\n name: 'celld',\n cmd: [\n binaries.celld,\n 'dev',\n directory,\n '--port',\n String(ports.api),\n // Shows the Worker's console output.\n '--logs',\n // sqld writes here; a rebuild per write would restart the Worker.\n '--watch-ignore',\n '.bunderstack/**',\n '--watch-ignore',\n 'dist/**',\n ],\n cwd: directory,\n env: { CELLD_ESBUILD: binaries.esbuild },\n filter: celldLine,\n },\n vite: input.hasVite\n ? {\n name: 'vite',\n cmd: [\n process.execPath,\n 'x',\n '--bun',\n 'vite',\n '--port',\n String(ports.app),\n '--strictPort',\n ],\n cwd: directory,\n env: { BUNDERSTACK_DEV_API_URL: apiUrl },\n }\n : undefined,\n }\n}\n\nasync function hasViteConfig(directory: string) {\n const files = await readdir(directory)\n return files.some((file) => /^vite\\.config\\.[cm]?[jt]s$/.test(file))\n}\n\nasync function freePort(): Promise<number> {\n return new Promise((resolvePort, reject) => {\n const server = createServer()\n server.listen(0, '127.0.0.1', () => {\n const address = server.address()\n server.close(() =>\n typeof address === 'object' && address\n ? resolvePort(address.port)\n : reject(new Error('no free port')),\n )\n })\n })\n}\n\nfunction canListen(port: number, hostname: string): boolean {\n try {\n Bun.listen({ hostname, port, socket: { data() {} } }).stop(true)\n return true\n } catch (error) {\n // No IPv6 on this machine: nothing can take the port there either.\n return (error as { code?: string }).code === 'EADDRNOTAVAIL'\n }\n}\n\n/**\n * The first port from `start` that is free on 127.0.0.1 and on ::1. The\n * browser opens `localhost`, which can resolve to either; Vite on ::1 next to\n * another server on 127.0.0.1 would answer only some requests.\n */\nexport async function firstFreePort(start: number): Promise<number> {\n for (let port = start; port < start + 100; port++) {\n if (canListen(port, '127.0.0.1') && canListen(port, '::1')) return port\n }\n throw new Error(`[bunderstack] no free port from ${start}`)\n}\n\nasync function waitForHealth(\n url: string,\n timeoutMs: number,\n cancelled: () => boolean,\n) {\n const deadline = Date.now() + timeoutMs\n for (;;) {\n if (cancelled()) return\n const ok = await fetch(url).then(\n (res) => res.ok,\n () => false,\n )\n if (ok) return\n if (Date.now() > deadline) throw new Error(`timed out waiting for ${url}`)\n await Bun.sleep(200)\n }\n}\n\nfunction esbuildBinary() {\n const pkg = Bun.resolveSync('esbuild/package.json', import.meta.dir)\n return join(dirname(pkg), 'bin', 'esbuild')\n}\n\nconst pushScript = fileURLToPath(\n new URL(\n import.meta.url.endsWith('.ts') ? './push.ts' : './push.js',\n import.meta.url,\n ),\n)\n\nexport async function runDev(options: {\n directory: string\n port?: number\n}): Promise<number> {\n const directory = resolve(options.directory)\n const stateDir = join(directory, '.bunderstack', 'dev')\n const group = new ProcessGroup()\n const say = (line: string) => group.log('dev', line)\n\n const userEnv = await readUserEnv(directory)\n const external = Boolean(userEnv.BUNDERSTACK_DATABASE_URL)\n const [celld, sqld] = await Promise.all([\n resolveBinary('celld', { log: say }),\n external ? '' : resolveBinary('sqld', { log: say }),\n ])\n const plan = planDev({\n directory,\n stateDir,\n userEnv,\n hasVite: await hasViteConfig(directory),\n ports: {\n // An explicit port is kept, and Vite fails when it is taken.\n app:\n options.port ??\n (process.env.PORT\n ? Number(process.env.PORT)\n : await firstFreePort(5173)),\n api: await freePort(),\n db: await freePort(),\n },\n binaries: { celld, sqld, esbuild: esbuildBinary() },\n })\n\n // Children run in their own process groups, so the terminal's Ctrl+C does\n // not reach them; group.stop() passes it on.\n let interrupted = false\n const interrupt = new Promise<void>((resolveInterrupt) => {\n for (const signal of ['SIGINT', 'SIGTERM', 'SIGHUP'] as const) {\n process.once(signal, () => {\n interrupted = true\n resolveInterrupt()\n })\n }\n })\n const cancelled = () => interrupted\n let watcher: ReturnType<typeof watch> | undefined\n\n try {\n await mkdir(stateDir, { recursive: true })\n if (plan.sqld) {\n group.start(plan.sqld)\n await waitForHealth(`${plan.databaseUrl}/health`, 20_000, cancelled)\n }\n const authSecret = await devSecret(stateDir)\n await writeFile(\n join(directory, '.dev.vars'),\n devVars({\n userEnv,\n databaseUrl: plan.databaseUrl,\n appUrl: plan.appUrl,\n authSecret,\n }),\n )\n const pushEnv = {\n ...userEnv,\n BUNDERSTACK_DATABASE_URL: plan.databaseUrl,\n AUTH_SECRET: userEnv.AUTH_SECRET || authSecret,\n APP_URL: plan.appUrl,\n }\n const push = async () => {\n const child = Bun.spawn([process.execPath, pushScript, directory], {\n cwd: directory,\n env: { ...process.env, ...pushEnv },\n stdout: 'pipe',\n stderr: 'pipe',\n })\n const [out, err, code] = await Promise.all([\n new Response(child.stdout).text(),\n new Response(child.stderr).text(),\n child.exited,\n ])\n // drizzle-kit draws a spinner with escape codes; keep the text only.\n // oxlint-disable-next-line no-control-regex\n const text = `${out}${err}`.replace(/\\x1b\\[[0-9;]*[A-Za-z]/g, '')\n for (const line of text.trim().split('\\n')) {\n if (line.trim()) group.log('push', line.trim())\n }\n if (code !== 0) group.log('push', 'failed; fix the code and save again')\n return code === 0\n }\n // The first push also writes wrangler.json, which celld reads at start.\n await push()\n\n let timer: ReturnType<typeof setTimeout> | undefined\n let running = Promise.resolve(true)\n watcher = watch(join(directory, 'src'), { recursive: true }, (_, file) => {\n if (file && String(file).endsWith('routeTree.gen.ts')) return\n clearTimeout(timer)\n timer = setTimeout(() => {\n running = running.then(push)\n }, 300)\n })\n\n group.start(plan.worker)\n await waitForHealth(`${plan.apiUrl}/api/health`, 60_000, cancelled).catch(\n () => say('the Worker did not answer /api/health yet; see the celld log'),\n )\n if (plan.vite && !interrupted) group.start(plan.vite)\n if (!interrupted) say(`App: ${plan.appUrl}`)\n\n const outcome = await Promise.race([group.exited, interrupt])\n if (outcome && !interrupted) {\n say(`${outcome.name} exited with code ${outcome.code}; stopping`)\n return 1\n }\n return 0\n } catch (error) {\n say(error instanceof Error ? error.message : String(error))\n return 1\n } finally {\n watcher?.close()\n await group.stop()\n }\n}\n\nexport async function runBuild(options: {\n directory: string\n}): Promise<number> {\n const directory = resolve(options.directory)\n if (await hasViteConfig(directory)) {\n const vite = Bun.spawn([process.execPath, 'x', '--bun', 'vite', 'build'], {\n cwd: directory,\n stdout: 'inherit',\n stderr: 'inherit',\n })\n if ((await vite.exited) !== 0) return 1\n }\n try {\n await runWranglerCommand({ directory, check: true })\n console.log('wrangler.json is current')\n await generateBlueprint({ directory, check: true })\n console.log('bunderstack.blueprint.yaml is current')\n return 0\n } catch (error) {\n console.error(error instanceof Error ? error.message : String(error))\n return 1\n }\n}\n"]}
|
package/dist/dev/push.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// Subprocess of `bunderstack dev`: `bun push.ts <app directory>`. A fresh
|
|
2
2
|
// process sees the current app code on each run. It regenerates wrangler.json
|
|
3
|
-
// and pushes the schema (or applies committed
|
|
3
|
+
// and bunderstack.blueprint.yaml, and pushes the schema (or applies committed
|
|
4
|
+
// migrations) to the dev database.
|
|
5
|
+
import { generateBlueprint } from '../blueprint-generator.js';
|
|
4
6
|
import { loadBackend, runWranglerCommand } from '../workers/wrangler.js';
|
|
5
7
|
const directory = process.argv[2];
|
|
6
8
|
if (!directory)
|
|
@@ -8,6 +10,9 @@ if (!directory)
|
|
|
8
10
|
const wrangler = await runWranglerCommand({ directory });
|
|
9
11
|
if (wrangler.changed)
|
|
10
12
|
console.log('wrangler.json updated');
|
|
13
|
+
const blueprint = await generateBlueprint({ directory });
|
|
14
|
+
if (blueprint.changed)
|
|
15
|
+
console.log('bunderstack.blueprint.yaml updated');
|
|
11
16
|
const { backend } = await loadBackend(directory);
|
|
12
17
|
// Resolve from the app, so provision sees the same bunderstack instance as
|
|
13
18
|
// the backend it provisions.
|
package/dist/dev/push.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push.js","sourceRoot":"","sources":["../../src/dev/push.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,8EAA8E;AAC9E
|
|
1
|
+
{"version":3,"file":"push.js","sourceRoot":"","sources":["../../src/dev/push.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,8EAA8E;AAC9E,8EAA8E;AAC9E,mCAAmC;AACnC,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC1D,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAErE,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjC,IAAI,CAAC,SAAS;IAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAA;AAEjE,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CAAC,EAAE,SAAS,EAAE,CAAC,CAAA;AACxD,IAAI,QAAQ,CAAC,OAAO;IAAE,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAA;AAE1D,MAAM,SAAS,GAAG,MAAM,iBAAiB,CAAC,EAAE,SAAS,EAAE,CAAC,CAAA;AACxD,IAAI,SAAS,CAAC,OAAO;IAAE,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAA;AAExE,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,WAAW,CAAC,SAAS,CAAC,CAAA;AAChD,2EAA2E;AAC3E,6BAA6B;AAC7B,MAAM,EAAE,SAAS,EAAE,GAAG,CAAC,MAAM,MAAM,CACjC,GAAG,CAAC,WAAW,CAAC,8BAA8B,EAAE,SAAS,CAAC,CAC3D,CAAyC,CAAA;AAC1C,MAAM,GAAG,GAAG,CAAC,MAAM,OAAO,CAAC,KAAK,CAAC;IAC/B,GAAG,EAAE,OAAO,CAAC,GAAyC;CACvD,CAAC,CAA+B,CAAA;AACjC,IAAI,CAAC;IACH,MAAM,SAAS,CAAC,GAAG,CAAC,CAAA;IACpB,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAA;AAClC,CAAC;QAAS,CAAC;IACT,MAAM,GAAG,CAAC,KAAK,EAAE,CAAA;AACnB,CAAC","sourcesContent":["// Subprocess of `bunderstack dev`: `bun push.ts <app directory>`. A fresh\n// process sees the current app code on each run. It regenerates wrangler.json\n// and bunderstack.blueprint.yaml, and pushes the schema (or applies committed\n// migrations) to the dev database.\nimport { generateBlueprint } from '../blueprint-generator'\nimport { loadBackend, runWranglerCommand } from '../workers/wrangler'\n\nconst directory = process.argv[2]\nif (!directory) throw new Error('usage: push.ts <app directory>')\n\nconst wrangler = await runWranglerCommand({ directory })\nif (wrangler.changed) console.log('wrangler.json updated')\n\nconst blueprint = await generateBlueprint({ directory })\nif (blueprint.changed) console.log('bunderstack.blueprint.yaml updated')\n\nconst { backend } = await loadBackend(directory)\n// Resolve from the app, so provision sees the same bunderstack instance as\n// the backend it provisions.\nconst { provision } = (await import(\n Bun.resolveSync('bunderstack/provision-schema', directory)\n)) as typeof import('../provision-schema')\nconst app = (await backend.start({\n env: process.env as Record<string, string | undefined>,\n})) as { close(): Promise<void> }\ntry {\n await provision(app)\n console.log('schema is current')\n} finally {\n await app.close()\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrangler.d.ts","sourceRoot":"","sources":["../../src/workers/wrangler.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"wrangler.d.ts","sourceRoot":"","sources":["../../src/workers/wrangler.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAUtD,MAAM,MAAM,cAAc,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAEnE,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,mBAAmB,EAC7B,OAAO,EAAE;IACP,IAAI,EAAE,MAAM,CAAA;IACZ,iBAAiB,EAAE,MAAM,CAAA;IACzB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwDF;AAED,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,IAAI,EAAE,MAAM;CAIzB;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM;;eAGnD,MAAM;sBAAgB;YAAE,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE;;;GASvD;AAED,wBAAsB,kBAAkB,CAAC,OAAO,EAAE;IAChD,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAmC9C"}
|
package/dist/workers/wrangler.js
CHANGED
|
@@ -4,6 +4,8 @@ import { readFile, writeFile } from 'node:fs/promises';
|
|
|
4
4
|
import { join, resolve } from 'node:path';
|
|
5
5
|
import { pathToFileURL } from 'node:url';
|
|
6
6
|
import { isBunderstackBackend } from '../backend.js';
|
|
7
|
+
import { BACKEND_INTERNALS } from '../backend-internals.js';
|
|
8
|
+
import { createEnvProbeSources } from '../env-probe.js';
|
|
7
9
|
import { bucketBindingName } from './r2.js';
|
|
8
10
|
/** Cloudflare's per-Worker Cron Trigger limit on the free plan. */
|
|
9
11
|
const MAX_CRONS = 5;
|
|
@@ -94,7 +96,8 @@ export async function runWranglerCommand(options) {
|
|
|
94
96
|
.replace(/^@[^/]+\//, '')
|
|
95
97
|
.toLowerCase()
|
|
96
98
|
.replace(/[^a-z0-9-]/g, '-');
|
|
97
|
-
const
|
|
99
|
+
const [probeEnv] = createEnvProbeSources(backend[BACKEND_INTERNALS].envSchema, process.env);
|
|
100
|
+
const config = buildWranglerConfig(backend.inspect({ env: probeEnv }), {
|
|
98
101
|
name,
|
|
99
102
|
// Keep the date once chosen, so --check stays stable across days.
|
|
100
103
|
compatibilityDate: previous?.compatibility_date ?? new Date().toISOString().slice(0, 10),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrangler.js","sourceRoot":"","sources":["../../src/workers/wrangler.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"wrangler.js","sourceRoot":"","sources":["../../src/workers/wrangler.ts"],"names":[],"mappings":"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","sourcesContent":["// src/workers/wrangler.ts — wrangler.json from the backend manifest. The same\n// file deploys with `wrangler deploy` (Cloudflare) and `celld deploy`.\nimport { readFile, writeFile } from 'node:fs/promises'\nimport { join, resolve } from 'node:path'\nimport { pathToFileURL } from 'node:url'\n\nimport type { BunderstackManifest } from '../manifest'\n\nimport { isBunderstackBackend } from '../backend'\nimport { BACKEND_INTERNALS } from '../backend-internals'\nimport { createEnvProbeSources } from '../env-probe'\nimport { bucketBindingName } from './r2'\n\n/** Cloudflare's per-Worker Cron Trigger limit on the free plan. */\nconst MAX_CRONS = 5\n\nexport type WranglerConfig = ReturnType<typeof buildWranglerConfig>\n\nexport function buildWranglerConfig(\n manifest: BunderstackManifest,\n options: {\n name: string\n compatibilityDate: string\n main?: string\n assetsDirectory?: string\n },\n) {\n const hasStorage = manifest.storage.buckets.length > 0\n const crons = [\n ...new Set([\n ...manifest.background.cron.map((cron) => cron.schedule),\n ...(hasStorage\n ? manifest.background.maintenance.map((task) => task.schedule)\n : []),\n ]),\n ].sort()\n // Operations without their own path are served through /api/rpc.\n const prefixes = [\n ...new Set([\n '/api/*',\n ...manifest.api.operations\n .filter((op) => op.path)\n .map((op) => `/${op.path!.split('/')[1]}/*`),\n ]),\n ]\n return {\n name: options.name,\n main: options.main ?? 'src/worker.ts',\n compatibility_date: options.compatibilityDate,\n compatibility_flags: ['nodejs_compat'],\n durable_objects: {\n bindings: [\n { name: 'SCHEDULER', class_name: 'Scheduler' },\n { name: 'REALTIME', class_name: 'RealtimeHub' },\n { name: 'RATE_LIMITER', class_name: 'RateLimiter' },\n ],\n },\n migrations: [\n {\n tag: 'v1',\n new_sqlite_classes: ['Scheduler', 'RealtimeHub', 'RateLimiter'],\n },\n ],\n r2_buckets: manifest.storage.buckets.map((bucket) => ({\n binding: bucketBindingName(bucket.name),\n bucket_name: `${options.name}-${bucket.name}`,\n })),\n assets: {\n directory: options.assetsDirectory ?? 'dist/client',\n binding: 'ASSETS',\n not_found_handling: 'single-page-application',\n run_worker_first: prefixes,\n },\n ...(crons.length > 0\n ? {\n triggers: {\n crons: crons.length > MAX_CRONS ? ['* * * * *'] : crons,\n },\n }\n : {}),\n }\n}\n\nexport class WranglerCheckError extends Error {\n constructor(path: string) {\n super(`[bunderstack] ${path} is out of date; run \\`bunderstack wrangler\\``)\n this.name = 'WranglerCheckError'\n }\n}\n\n/**\n * Imports the app's backend. Entry precedence: the argument,\n * package.json#bunderstack.entry, src/bunderstack.ts.\n */\nexport async function loadBackend(directory: string, entry?: string) {\n const pkg = JSON.parse(\n await readFile(join(directory, 'package.json'), 'utf8'),\n ) as { name?: string; bunderstack?: { entry?: string } }\n const path = entry ?? pkg.bunderstack?.entry ?? 'src/bunderstack.ts'\n const module = (await import(pathToFileURL(join(directory, path)).href)) as {\n backend?: unknown\n }\n if (!isBunderstackBackend(module.backend)) {\n throw new Error(`[bunderstack] ${path} must export backend`)\n }\n return { pkg, backend: module.backend }\n}\n\nexport async function runWranglerCommand(options: {\n directory: string\n entry?: string\n name?: string\n assets?: string\n output?: string\n check?: boolean\n}): Promise<{ path: string; changed: boolean }> {\n const directory = resolve(options.directory)\n const { pkg, backend } = await loadBackend(directory, options.entry)\n const path = join(directory, options.output ?? 'wrangler.json')\n const existing = await readFile(path, 'utf8').catch(() => undefined)\n const previous = existing\n ? (JSON.parse(existing) as {\n compatibility_date?: string\n assets?: { directory?: string }\n })\n : undefined\n const name = (options.name ?? pkg.name ?? 'app')\n .replace(/^@[^/]+\\//, '')\n .toLowerCase()\n .replace(/[^a-z0-9-]/g, '-')\n const [probeEnv] = createEnvProbeSources(\n backend[BACKEND_INTERNALS].envSchema,\n process.env as Record<string, string | undefined>,\n )\n const config = buildWranglerConfig(backend.inspect({ env: probeEnv }), {\n name,\n // Keep the date once chosen, so --check stays stable across days.\n compatibilityDate:\n previous?.compatibility_date ?? new Date().toISOString().slice(0, 10),\n // Keep a directory set once with --assets; `bunderstack dev` passes none.\n assetsDirectory: options.assets ?? previous?.assets?.directory,\n })\n const text = `${JSON.stringify(config, null, 2)}\\n`\n if (options.check) {\n if (existing !== text) throw new WranglerCheckError(path)\n return { path, changed: false }\n }\n if (existing === text) return { path, changed: false }\n await writeFile(path, text)\n return { path, changed: true }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bunderstack",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.2",
|
|
4
4
|
"description": "Batteries-included backend framework for Bun: type-safe oRPC APIs, auth, storage, realtime, jobs, messaging, and validated env from one declaration.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"backend",
|
|
@@ -15,7 +15,10 @@ bun run blueprint:check
|
|
|
15
15
|
`bun run blueprint` generates the committed `bunderstack.blueprint.yaml` from
|
|
16
16
|
the configured Bunderstack entry. Set `package.json#bunderstack.entry` when the
|
|
17
17
|
entry is not `src/bunderstack.ts`. `bun run blueprint:check` must pass in CI so
|
|
18
|
-
the committed declaration matches the application.
|
|
18
|
+
the committed declaration matches the application. Worker applications commit
|
|
19
|
+
both `wrangler.json` and `bunderstack.blueprint.yaml`; `bunderstack dev`
|
|
20
|
+
updates both files on startup and rebuild, and `bunderstack build` verifies
|
|
21
|
+
both are current.
|
|
19
22
|
|
|
20
23
|
Before production, generate and commit the Drizzle `migrations/` folder.
|
|
21
24
|
`provision(app)` from `bunderstack/provision` only applies committed
|