bunderstack 0.19.1 → 0.19.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 +10 -0
- package/dist/blueprint-generator.d.ts.map +1 -1
- package/dist/blueprint-generator.js +8 -2
- package/dist/blueprint-generator.js.map +1 -1
- package/dist/blueprint.d.ts +3 -1
- package/dist/blueprint.d.ts.map +1 -1
- package/dist/blueprint.js +2 -2
- package/dist/blueprint.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,16 @@ All notable changes to `bunderstack` will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.19.2] - 2026-08-24
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **Solid and Bun SSR application support in deployment blueprint.** The
|
|
12
|
+
`bunderstack blueprint` generator and contract schema now support
|
|
13
|
+
standalone Solid 2, Bun SSR, and custom full-stack setups without requiring
|
|
14
|
+
`@tanstack/react-start`. The generator automatically infers the framework from
|
|
15
|
+
declared dependencies.
|
|
16
|
+
|
|
7
17
|
## [0.19.1] - 2026-08-23
|
|
8
18
|
|
|
9
19
|
### Fixed
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blueprint-generator.d.ts","sourceRoot":"","sources":["../src/blueprint-generator.ts"],"names":[],"mappings":"AAWA,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,aAAa,CAAA;AAGpB,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;CAChB,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":"AAWA,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,aAAa,CAAA;AAGpB,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;CAChB,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,CAiGlC"}
|
|
@@ -51,8 +51,13 @@ export async function generateBlueprint(options) {
|
|
|
51
51
|
const packagePath = join(directory, 'package.json');
|
|
52
52
|
const pkg = JSON.parse(await readFile(packagePath, 'utf8'));
|
|
53
53
|
const allDependencies = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
let framework = 'bun-ssr';
|
|
55
|
+
if (typeof allDependencies['@tanstack/react-start'] === 'string') {
|
|
56
|
+
framework = 'tanstack-start';
|
|
57
|
+
}
|
|
58
|
+
else if (typeof allDependencies['solid-js'] === 'string' ||
|
|
59
|
+
typeof allDependencies['@solidjs/web'] === 'string') {
|
|
60
|
+
framework = 'solid';
|
|
56
61
|
}
|
|
57
62
|
requireScript(pkg, 'build', true);
|
|
58
63
|
requireScript(pkg, 'start', true);
|
|
@@ -91,6 +96,7 @@ export async function generateBlueprint(options) {
|
|
|
91
96
|
generatorVersion: await packageVersion(),
|
|
92
97
|
entry,
|
|
93
98
|
migrationMode,
|
|
99
|
+
framework,
|
|
94
100
|
});
|
|
95
101
|
const source = serializeBlueprint(blueprint);
|
|
96
102
|
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 {\n blueprintFromManifest,\n serializeBlueprint,\n type BunderstackBlueprint,\n} from './blueprint'\nimport { parseManifest } from './manifest'\n\nexport type GenerateBlueprintOptions = {\n directory: string\n entry?: string\n output?: string\n check?: 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 if (typeof allDependencies['@tanstack/react-start'] !== 'string') {\n throw new Error(\n '[bunderstack] package.json must depend on @tanstack/react-start',\n )\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 previousIntrospection = process.env.BUNDERSTACK_INTROSPECT\n process.env.BUNDERSTACK_INTROSPECT = '1'\n let app: { manifest?: unknown; close?: () => Promise<void> } | undefined\n try {\n const module = (await import(\n `${pathToFileURL(entryPath).href}?blueprint=${Date.now()}`\n )) as {\n app?: typeof app\n }\n app = module.app\n if (!app) throw new Error(`[bunderstack] ${entry} must export app`)\n const manifest = parseManifest(app.manifest)\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 })\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 } finally {\n await app?.close?.()\n if (previousIntrospection === undefined)\n delete process.env.BUNDERSTACK_INTROSPECT\n else process.env.BUNDERSTACK_INTROSPECT = previousIntrospection\n }\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 {\n blueprintFromManifest,\n serializeBlueprint,\n type BunderstackBlueprint,\n} from './blueprint'\nimport { parseManifest } from './manifest'\n\nexport type GenerateBlueprintOptions = {\n directory: string\n entry?: string\n output?: string\n check?: 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 previousIntrospection = process.env.BUNDERSTACK_INTROSPECT\n process.env.BUNDERSTACK_INTROSPECT = '1'\n let app: { manifest?: unknown; close?: () => Promise<void> } | undefined\n try {\n const module = (await import(\n `${pathToFileURL(entryPath).href}?blueprint=${Date.now()}`\n )) as {\n app?: typeof app\n }\n app = module.app\n if (!app) throw new Error(`[bunderstack] ${entry} must export app`)\n const manifest = parseManifest(app.manifest)\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 } finally {\n await app?.close?.()\n if (previousIntrospection === undefined)\n delete process.env.BUNDERSTACK_INTROSPECT\n else process.env.BUNDERSTACK_INTROSPECT = previousIntrospection\n }\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 ApplicationFramework = 'tanstack-start' | 'solid' | 'bun-ssr' | 'custom';
|
|
3
4
|
export type BunderstackBlueprint = {
|
|
4
5
|
version: 1;
|
|
5
6
|
generator: {
|
|
@@ -7,7 +8,7 @@ export type BunderstackBlueprint = {
|
|
|
7
8
|
version: string;
|
|
8
9
|
};
|
|
9
10
|
application: {
|
|
10
|
-
framework:
|
|
11
|
+
framework: ApplicationFramework;
|
|
11
12
|
scripts: {
|
|
12
13
|
build: 'build';
|
|
13
14
|
start: 'start';
|
|
@@ -40,6 +41,7 @@ export declare function blueprintFromManifest(args: {
|
|
|
40
41
|
generatorVersion: string;
|
|
41
42
|
entry: string;
|
|
42
43
|
migrationMode: MigrationMode;
|
|
44
|
+
framework?: ApplicationFramework;
|
|
43
45
|
}): BunderstackBlueprint;
|
|
44
46
|
export declare function parseBlueprintYaml(source: string): BunderstackBlueprint;
|
|
45
47
|
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;
|
|
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,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;KAC/D,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;KAC9B,CAAA;IACD,WAAW,EAAE,mBAAmB,CAAC,aAAa,CAAC,CAAA;IAC/C,UAAU,EAAE,mBAAmB,CAAC,YAAY,CAAC,GAAG;QAC9C,MAAM,EAAE;YAAE,QAAQ,EAAE,OAAO,CAAA;SAAE,CAAA;KAC9B,CAAA;CACF,CAAA;AA2GD,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,oBAAoB,CAuDnE;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;CACjC,GAAG,oBAAoB,CA0CvB;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
|
@@ -22,7 +22,7 @@ const blueprintSchema = v.strictObject({
|
|
|
22
22
|
version: nonEmpty,
|
|
23
23
|
}),
|
|
24
24
|
application: v.strictObject({
|
|
25
|
-
framework: v.
|
|
25
|
+
framework: v.picklist(['tanstack-start', 'solid', 'bun-ssr', 'custom']),
|
|
26
26
|
scripts: v.strictObject({
|
|
27
27
|
build: v.literal('build'),
|
|
28
28
|
start: v.literal('start'),
|
|
@@ -111,7 +111,7 @@ export function blueprintFromManifest(args) {
|
|
|
111
111
|
version: 1,
|
|
112
112
|
generator: { name: 'bunderstack', version: args.generatorVersion },
|
|
113
113
|
application: {
|
|
114
|
-
framework: 'tanstack-start',
|
|
114
|
+
framework: args.framework ?? 'tanstack-start',
|
|
115
115
|
scripts: {
|
|
116
116
|
build: 'build',
|
|
117
117
|
start: 'start',
|
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'\n\nexport type BunderstackBlueprint = {\n version: 1\n generator: { name: 'bunderstack'; version: string }\n application: {\n framework: 'tanstack-start'\n scripts: { build: 'build'; start: 'start'; worker?: 'worker' }\n }\n bunderstack: { entry: string; manifestVersion: 3 }\n resources: {\n database: BunderstackManifest['database'] & { migrationMode: MigrationMode }\n storage: BunderstackManifest['storage']\n realtime?: { required: true }\n }\n environment: BunderstackManifest['environment']\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\nconst blueprintSchema = v.strictObject({\n version: v.literal(1),\n generator: v.strictObject({\n name: v.literal('bunderstack'),\n version: nonEmpty,\n }),\n application: v.strictObject({\n framework: v.literal('tanstack-start'),\n scripts: v.strictObject({\n build: v.literal('build'),\n start: v.literal('start'),\n worker: v.optional(v.literal('worker')),\n }),\n }),\n bunderstack: v.strictObject({\n entry: relativePath,\n manifestVersion: v.literal(3),\n }),\n resources: v.strictObject({\n database: v.strictObject({\n dialect: v.picklist(['sqlite', 'pg']),\n migrationsDirectory: relativePath,\n migrationMode: v.picklist(['migrations', 'push']),\n tables: v.array(\n v.strictObject({\n exportName: nonEmpty,\n physicalName: nonEmpty,\n system: v.boolean(),\n }),\n ),\n }),\n storage: v.strictObject({\n defaultBucket: nonEmpty,\n buckets: v.array(\n v.strictObject({\n name: nonEmpty,\n visibility: v.picklist(['public', 'private']),\n }),\n ),\n }),\n realtime: v.optional(v.strictObject({ required: v.literal(true) })),\n }),\n environment: v.array(\n v.strictObject({\n key: nonEmpty,\n required: v.boolean(),\n scope: v.picklist(['server', 'client']),\n }),\n ),\n background: v.strictObject({\n worker: v.strictObject({ required: v.boolean() }),\n jobs: v.array(v.strictObject({ name: nonEmpty })),\n cron: v.array(\n v.strictObject({\n name: nonEmpty,\n schedule: cronSchedule,\n timezone: v.literal('UTC'),\n }),\n ),\n maintenance: v.array(\n v.strictObject({\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 '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\nexport function blueprintFromManifest(args: {\n manifest: BunderstackManifest\n generatorVersion: string\n entry: string\n migrationMode: MigrationMode\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: 'tanstack-start',\n scripts: {\n build: 'build',\n start: 'start',\n ...(workerRequired ? { worker: 'worker' } : {}),\n },\n },\n bunderstack: { entry: args.entry, manifestVersion: 3 },\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 },\n environment: sortBy(args.manifest.environment, (entry) => entry.key),\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 ApplicationFramework =\n | 'tanstack-start'\n | 'solid'\n | 'bun-ssr'\n | 'custom'\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: 3 }\n resources: {\n database: BunderstackManifest['database'] & { migrationMode: MigrationMode }\n storage: BunderstackManifest['storage']\n realtime?: { required: true }\n }\n environment: BunderstackManifest['environment']\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\nconst blueprintSchema = v.strictObject({\n version: v.literal(1),\n generator: v.strictObject({\n name: v.literal('bunderstack'),\n version: nonEmpty,\n }),\n application: v.strictObject({\n framework: v.picklist(['tanstack-start', 'solid', 'bun-ssr', 'custom']),\n scripts: v.strictObject({\n build: v.literal('build'),\n start: v.literal('start'),\n worker: v.optional(v.literal('worker')),\n }),\n }),\n bunderstack: v.strictObject({\n entry: relativePath,\n manifestVersion: v.literal(3),\n }),\n resources: v.strictObject({\n database: v.strictObject({\n dialect: v.picklist(['sqlite', 'pg']),\n migrationsDirectory: relativePath,\n migrationMode: v.picklist(['migrations', 'push']),\n tables: v.array(\n v.strictObject({\n exportName: nonEmpty,\n physicalName: nonEmpty,\n system: v.boolean(),\n }),\n ),\n }),\n storage: v.strictObject({\n defaultBucket: nonEmpty,\n buckets: v.array(\n v.strictObject({\n name: nonEmpty,\n visibility: v.picklist(['public', 'private']),\n }),\n ),\n }),\n realtime: v.optional(v.strictObject({ required: v.literal(true) })),\n }),\n environment: v.array(\n v.strictObject({\n key: nonEmpty,\n required: v.boolean(),\n scope: v.picklist(['server', 'client']),\n }),\n ),\n background: v.strictObject({\n worker: v.strictObject({ required: v.boolean() }),\n jobs: v.array(v.strictObject({ name: nonEmpty })),\n cron: v.array(\n v.strictObject({\n name: nonEmpty,\n schedule: cronSchedule,\n timezone: v.literal('UTC'),\n }),\n ),\n maintenance: v.array(\n v.strictObject({\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 '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\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: 3 },\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 },\n environment: sortBy(args.manifest.environment, (entry) => entry.key),\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/package.json
CHANGED