everything-dev 1.40.0 → 1.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/db-studio.cjs +123 -0
- package/dist/cli/db-studio.cjs.map +1 -0
- package/dist/cli/db-studio.mjs +119 -0
- package/dist/cli/db-studio.mjs.map +1 -0
- package/dist/cli/init.cjs +1 -1
- package/dist/cli/init.cjs.map +1 -1
- package/dist/cli/init.mjs +1 -1
- package/dist/cli/init.mjs.map +1 -1
- package/dist/cli/upgrade.cjs +1 -0
- package/dist/cli/upgrade.cjs.map +1 -1
- package/dist/cli/upgrade.mjs +1 -0
- package/dist/cli/upgrade.mjs.map +1 -1
- package/dist/cli.cjs +28 -0
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +28 -0
- package/dist/cli.mjs.map +1 -1
- package/dist/config.cjs +2 -0
- package/dist/config.cjs.map +1 -1
- package/dist/config.d.cts.map +1 -1
- package/dist/config.d.mts.map +1 -1
- package/dist/config.mjs +2 -0
- package/dist/config.mjs.map +1 -1
- package/dist/contract.cjs +18 -1
- package/dist/contract.cjs.map +1 -1
- package/dist/contract.d.cts +42 -3
- package/dist/contract.d.cts.map +1 -1
- package/dist/contract.d.mts +42 -3
- package/dist/contract.d.mts.map +1 -1
- package/dist/contract.meta.cjs +8 -0
- package/dist/contract.meta.cjs.map +1 -1
- package/dist/contract.meta.d.cts +10 -0
- package/dist/contract.meta.d.mts +10 -0
- package/dist/contract.meta.mjs +8 -0
- package/dist/contract.meta.mjs.map +1 -1
- package/dist/contract.mjs +17 -2
- package/dist/contract.mjs.map +1 -1
- package/dist/index.cjs +2 -0
- package/dist/index.d.cts +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +2 -2
- package/dist/plugin.cjs +40 -0
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.d.cts +22 -2
- package/dist/plugin.d.mts +22 -2
- package/dist/plugin.mjs +40 -0
- package/dist/plugin.mjs.map +1 -1
- package/dist/types.cjs +2 -0
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +5 -2
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +5 -2
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs +2 -0
- package/dist/types.mjs.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
|
|
2
|
+
let node_fs = require("node:fs");
|
|
3
|
+
let node_path = require("node:path");
|
|
4
|
+
let _clack_prompts = require("@clack/prompts");
|
|
5
|
+
_clack_prompts = require_runtime.__toESM(_clack_prompts, 1);
|
|
6
|
+
let node_child_process = require("node:child_process");
|
|
7
|
+
|
|
8
|
+
//#region src/cli/db-studio.ts
|
|
9
|
+
function resolvePluginDbInfo(pluginKey, runtimeConfig, projectDir) {
|
|
10
|
+
let source;
|
|
11
|
+
let section;
|
|
12
|
+
let secrets;
|
|
13
|
+
let localPath;
|
|
14
|
+
let key;
|
|
15
|
+
if (pluginKey === "api" && runtimeConfig.api) {
|
|
16
|
+
source = runtimeConfig.api.source;
|
|
17
|
+
section = "app.api";
|
|
18
|
+
secrets = runtimeConfig.api.secrets;
|
|
19
|
+
localPath = runtimeConfig.api.localPath;
|
|
20
|
+
key = "api";
|
|
21
|
+
} else if (pluginKey === "auth" && runtimeConfig.auth) {
|
|
22
|
+
source = runtimeConfig.auth.source;
|
|
23
|
+
section = "app.auth";
|
|
24
|
+
secrets = runtimeConfig.auth.secrets;
|
|
25
|
+
localPath = runtimeConfig.auth.localPath;
|
|
26
|
+
key = "auth";
|
|
27
|
+
} else if (runtimeConfig.plugins?.[pluginKey]) {
|
|
28
|
+
const plugin = runtimeConfig.plugins[pluginKey];
|
|
29
|
+
source = plugin.source;
|
|
30
|
+
section = "plugins";
|
|
31
|
+
secrets = plugin.secrets;
|
|
32
|
+
localPath = plugin.localPath;
|
|
33
|
+
key = pluginKey;
|
|
34
|
+
} else throw new Error(`Plugin "${pluginKey}" not found in app.api, app.auth, or plugins. Available: ${[
|
|
35
|
+
"api",
|
|
36
|
+
...runtimeConfig.auth ? ["auth"] : [],
|
|
37
|
+
...Object.keys(runtimeConfig.plugins ?? {})
|
|
38
|
+
].join(", ")}`);
|
|
39
|
+
const dbSecret = secrets?.find((s) => s.endsWith("_DATABASE_URL"));
|
|
40
|
+
if (!dbSecret) throw new Error(`Plugin "${pluginKey}" has no database secret (no secret ending in _DATABASE_URL). Secrets: ${(secrets ?? []).join(", ") || "none"}`);
|
|
41
|
+
const dbUrl = process.env[dbSecret];
|
|
42
|
+
if (!dbUrl) throw new Error(`.env missing ${dbSecret} for plugin "${pluginKey}". Add it to your .env file (see .env.example).`);
|
|
43
|
+
return {
|
|
44
|
+
key,
|
|
45
|
+
source: source ?? "remote",
|
|
46
|
+
section,
|
|
47
|
+
databaseSecret: dbSecret,
|
|
48
|
+
databaseUrl: dbUrl,
|
|
49
|
+
workspaceDir: localPath,
|
|
50
|
+
projectDir
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
async function runStudioLocal(info) {
|
|
54
|
+
const workspaceRoot = info.workspaceDir ? (0, node_path.resolve)(info.projectDir, info.workspaceDir) : (0, node_path.resolve)(info.projectDir, info.key);
|
|
55
|
+
const configPath = (0, node_path.join)(workspaceRoot, "drizzle.config.ts");
|
|
56
|
+
if (!(0, node_fs.existsSync)(configPath)) throw new Error(`No drizzle.config.ts found in ${workspaceRoot}. Run 'drizzle-kit init' first in the plugin workspace.`);
|
|
57
|
+
_clack_prompts.log.info(`Starting Drizzle Studio for ${info.key} (local)...`);
|
|
58
|
+
await spawnAsync("npx", [
|
|
59
|
+
"drizzle-kit",
|
|
60
|
+
"studio",
|
|
61
|
+
"--config",
|
|
62
|
+
configPath
|
|
63
|
+
], { cwd: workspaceRoot });
|
|
64
|
+
}
|
|
65
|
+
async function runStudioRemote(info) {
|
|
66
|
+
const dbDir = (0, node_path.resolve)(info.projectDir, ".bos", "db", info.key);
|
|
67
|
+
(0, node_fs.mkdirSync)(dbDir, { recursive: true });
|
|
68
|
+
const configPath = (0, node_path.join)(dbDir, "drizzle.config.ts");
|
|
69
|
+
(0, node_fs.writeFileSync)(configPath, `import { defineConfig } from "drizzle-kit";
|
|
70
|
+
|
|
71
|
+
export default defineConfig({
|
|
72
|
+
schema: "./drizzle/schema.ts",
|
|
73
|
+
out: "./drizzle",
|
|
74
|
+
dialect: "postgresql",
|
|
75
|
+
dbCredentials: {
|
|
76
|
+
url: "${info.databaseUrl}",
|
|
77
|
+
},
|
|
78
|
+
verbose: true,
|
|
79
|
+
strict: true,
|
|
80
|
+
});
|
|
81
|
+
`);
|
|
82
|
+
_clack_prompts.log.info(`Introspecting database schema for ${info.key}...`);
|
|
83
|
+
try {
|
|
84
|
+
await spawnAsync("npx", [
|
|
85
|
+
"drizzle-kit",
|
|
86
|
+
"pull",
|
|
87
|
+
"--config",
|
|
88
|
+
configPath
|
|
89
|
+
], { cwd: dbDir });
|
|
90
|
+
} catch {
|
|
91
|
+
throw new Error(`Failed to introspect database for "${info.key}". Check that ${info.databaseSecret} is correct and the database is reachable.`);
|
|
92
|
+
}
|
|
93
|
+
_clack_prompts.log.info(`Starting Drizzle Studio for ${info.key}...`);
|
|
94
|
+
await spawnAsync("npx", [
|
|
95
|
+
"drizzle-kit",
|
|
96
|
+
"studio",
|
|
97
|
+
"--config",
|
|
98
|
+
configPath
|
|
99
|
+
], { cwd: dbDir });
|
|
100
|
+
}
|
|
101
|
+
function spawnAsync(cmd, args, options) {
|
|
102
|
+
return new Promise((resolvePromise, reject) => {
|
|
103
|
+
const child = (0, node_child_process.spawn)(cmd, args, {
|
|
104
|
+
cwd: options.cwd,
|
|
105
|
+
stdio: "inherit",
|
|
106
|
+
shell: true
|
|
107
|
+
});
|
|
108
|
+
child.on("error", (err) => {
|
|
109
|
+
if (err.code === "ENOENT") reject(/* @__PURE__ */ new Error(`"${cmd}" not found. Ensure it is installed (e.g. 'npm install -g drizzle-kit').`));
|
|
110
|
+
else reject(/* @__PURE__ */ new Error(`Failed to start ${cmd}: ${err.message}`));
|
|
111
|
+
});
|
|
112
|
+
child.on("exit", (code) => {
|
|
113
|
+
if (code === 0 || code === null) resolvePromise();
|
|
114
|
+
else reject(/* @__PURE__ */ new Error(`"${cmd}" exited with code ${code}`));
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
//#endregion
|
|
120
|
+
exports.resolvePluginDbInfo = resolvePluginDbInfo;
|
|
121
|
+
exports.runStudioLocal = runStudioLocal;
|
|
122
|
+
exports.runStudioRemote = runStudioRemote;
|
|
123
|
+
//# sourceMappingURL=db-studio.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db-studio.cjs","names":[],"sources":["../../src/cli/db-studio.ts"],"sourcesContent":["import { spawn } from \"node:child_process\";\nimport { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport type { RuntimeConfig } from \"../types\";\n\nexport interface PluginDbInfo {\n key: string;\n source: \"local\" | \"remote\";\n section: \"app.api\" | \"app.auth\" | \"plugins\";\n databaseSecret: string;\n databaseUrl: string;\n workspaceDir?: string;\n projectDir: string;\n}\n\nexport function resolvePluginDbInfo(\n pluginKey: string,\n runtimeConfig: RuntimeConfig,\n projectDir: string,\n): PluginDbInfo {\n let source: \"local\" | \"remote\" | undefined;\n let section: PluginDbInfo[\"section\"];\n let secrets: string[] | undefined;\n let localPath: string | undefined;\n let key: string;\n\n if (pluginKey === \"api\" && runtimeConfig.api) {\n source = runtimeConfig.api.source;\n section = \"app.api\";\n secrets = runtimeConfig.api.secrets;\n localPath = runtimeConfig.api.localPath;\n key = \"api\";\n } else if (pluginKey === \"auth\" && runtimeConfig.auth) {\n source = runtimeConfig.auth.source;\n section = \"app.auth\";\n secrets = runtimeConfig.auth.secrets;\n localPath = runtimeConfig.auth.localPath;\n key = \"auth\";\n } else if (runtimeConfig.plugins?.[pluginKey]) {\n const plugin = runtimeConfig.plugins[pluginKey];\n source = plugin.source;\n section = \"plugins\";\n secrets = plugin.secrets;\n localPath = plugin.localPath;\n key = pluginKey;\n } else {\n throw new Error(\n `Plugin \"${pluginKey}\" not found in app.api, app.auth, or plugins. ` +\n `Available: ${[\n \"api\",\n ...(runtimeConfig.auth ? [\"auth\"] : []),\n ...Object.keys(runtimeConfig.plugins ?? {}),\n ].join(\", \")}`,\n );\n }\n\n const dbSecret = secrets?.find((s) => s.endsWith(\"_DATABASE_URL\"));\n if (!dbSecret) {\n throw new Error(\n `Plugin \"${pluginKey}\" has no database secret (no secret ending in _DATABASE_URL). ` +\n `Secrets: ${(secrets ?? []).join(\", \") || \"none\"}`,\n );\n }\n\n const dbUrl = process.env[dbSecret];\n if (!dbUrl) {\n throw new Error(\n `.env missing ${dbSecret} for plugin \"${pluginKey}\". ` +\n `Add it to your .env file (see .env.example).`,\n );\n }\n\n return {\n key,\n source: source ?? \"remote\",\n section,\n databaseSecret: dbSecret,\n databaseUrl: dbUrl,\n workspaceDir: localPath,\n projectDir,\n };\n}\n\nexport async function runStudioLocal(info: PluginDbInfo): Promise<void> {\n const workspaceRoot = info.workspaceDir\n ? resolve(info.projectDir, info.workspaceDir)\n : resolve(info.projectDir, info.key);\n const configPath = join(workspaceRoot, \"drizzle.config.ts\");\n\n if (!existsSync(configPath)) {\n throw new Error(\n `No drizzle.config.ts found in ${workspaceRoot}. ` +\n `Run 'drizzle-kit init' first in the plugin workspace.`,\n );\n }\n\n p.log.info(`Starting Drizzle Studio for ${info.key} (local)...`);\n\n await spawnAsync(\"npx\", [\"drizzle-kit\", \"studio\", \"--config\", configPath], {\n cwd: workspaceRoot,\n });\n}\n\nexport async function runStudioRemote(info: PluginDbInfo): Promise<void> {\n const dbDir = resolve(info.projectDir, \".bos\", \"db\", info.key);\n\n mkdirSync(dbDir, { recursive: true });\n\n const configPath = join(dbDir, \"drizzle.config.ts\");\n const configContent = `import { defineConfig } from \"drizzle-kit\";\n\nexport default defineConfig({\n schema: \"./drizzle/schema.ts\",\n out: \"./drizzle\",\n dialect: \"postgresql\",\n dbCredentials: {\n url: \"${info.databaseUrl}\",\n },\n verbose: true,\n strict: true,\n});\n`;\n\n writeFileSync(configPath, configContent);\n\n p.log.info(`Introspecting database schema for ${info.key}...`);\n try {\n await spawnAsync(\"npx\", [\"drizzle-kit\", \"pull\", \"--config\", configPath], {\n cwd: dbDir,\n });\n } catch {\n throw new Error(\n `Failed to introspect database for \"${info.key}\". ` +\n `Check that ${info.databaseSecret} is correct and the database is reachable.`,\n );\n }\n\n p.log.info(`Starting Drizzle Studio for ${info.key}...`);\n await spawnAsync(\"npx\", [\"drizzle-kit\", \"studio\", \"--config\", configPath], {\n cwd: dbDir,\n });\n}\n\nfunction spawnAsync(cmd: string, args: string[], options: { cwd: string }): Promise<void> {\n return new Promise((resolvePromise, reject) => {\n const child = spawn(cmd, args, {\n cwd: options.cwd,\n stdio: \"inherit\",\n shell: true,\n });\n\n child.on(\"error\", (err) => {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n reject(\n new Error(\n `\"${cmd}\" not found. Ensure it is installed (e.g. 'npm install -g drizzle-kit').`,\n ),\n );\n } else {\n reject(new Error(`Failed to start ${cmd}: ${err.message}`));\n }\n });\n\n child.on(\"exit\", (code) => {\n if (code === 0 || code === null) {\n resolvePromise();\n } else {\n reject(new Error(`\"${cmd}\" exited with code ${code}`));\n }\n });\n });\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
import * as p from "@clack/prompts";
|
|
4
|
+
import { spawn } from "node:child_process";
|
|
5
|
+
|
|
6
|
+
//#region src/cli/db-studio.ts
|
|
7
|
+
function resolvePluginDbInfo(pluginKey, runtimeConfig, projectDir) {
|
|
8
|
+
let source;
|
|
9
|
+
let section;
|
|
10
|
+
let secrets;
|
|
11
|
+
let localPath;
|
|
12
|
+
let key;
|
|
13
|
+
if (pluginKey === "api" && runtimeConfig.api) {
|
|
14
|
+
source = runtimeConfig.api.source;
|
|
15
|
+
section = "app.api";
|
|
16
|
+
secrets = runtimeConfig.api.secrets;
|
|
17
|
+
localPath = runtimeConfig.api.localPath;
|
|
18
|
+
key = "api";
|
|
19
|
+
} else if (pluginKey === "auth" && runtimeConfig.auth) {
|
|
20
|
+
source = runtimeConfig.auth.source;
|
|
21
|
+
section = "app.auth";
|
|
22
|
+
secrets = runtimeConfig.auth.secrets;
|
|
23
|
+
localPath = runtimeConfig.auth.localPath;
|
|
24
|
+
key = "auth";
|
|
25
|
+
} else if (runtimeConfig.plugins?.[pluginKey]) {
|
|
26
|
+
const plugin = runtimeConfig.plugins[pluginKey];
|
|
27
|
+
source = plugin.source;
|
|
28
|
+
section = "plugins";
|
|
29
|
+
secrets = plugin.secrets;
|
|
30
|
+
localPath = plugin.localPath;
|
|
31
|
+
key = pluginKey;
|
|
32
|
+
} else throw new Error(`Plugin "${pluginKey}" not found in app.api, app.auth, or plugins. Available: ${[
|
|
33
|
+
"api",
|
|
34
|
+
...runtimeConfig.auth ? ["auth"] : [],
|
|
35
|
+
...Object.keys(runtimeConfig.plugins ?? {})
|
|
36
|
+
].join(", ")}`);
|
|
37
|
+
const dbSecret = secrets?.find((s) => s.endsWith("_DATABASE_URL"));
|
|
38
|
+
if (!dbSecret) throw new Error(`Plugin "${pluginKey}" has no database secret (no secret ending in _DATABASE_URL). Secrets: ${(secrets ?? []).join(", ") || "none"}`);
|
|
39
|
+
const dbUrl = process.env[dbSecret];
|
|
40
|
+
if (!dbUrl) throw new Error(`.env missing ${dbSecret} for plugin "${pluginKey}". Add it to your .env file (see .env.example).`);
|
|
41
|
+
return {
|
|
42
|
+
key,
|
|
43
|
+
source: source ?? "remote",
|
|
44
|
+
section,
|
|
45
|
+
databaseSecret: dbSecret,
|
|
46
|
+
databaseUrl: dbUrl,
|
|
47
|
+
workspaceDir: localPath,
|
|
48
|
+
projectDir
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
async function runStudioLocal(info) {
|
|
52
|
+
const workspaceRoot = info.workspaceDir ? resolve(info.projectDir, info.workspaceDir) : resolve(info.projectDir, info.key);
|
|
53
|
+
const configPath = join(workspaceRoot, "drizzle.config.ts");
|
|
54
|
+
if (!existsSync(configPath)) throw new Error(`No drizzle.config.ts found in ${workspaceRoot}. Run 'drizzle-kit init' first in the plugin workspace.`);
|
|
55
|
+
p.log.info(`Starting Drizzle Studio for ${info.key} (local)...`);
|
|
56
|
+
await spawnAsync("npx", [
|
|
57
|
+
"drizzle-kit",
|
|
58
|
+
"studio",
|
|
59
|
+
"--config",
|
|
60
|
+
configPath
|
|
61
|
+
], { cwd: workspaceRoot });
|
|
62
|
+
}
|
|
63
|
+
async function runStudioRemote(info) {
|
|
64
|
+
const dbDir = resolve(info.projectDir, ".bos", "db", info.key);
|
|
65
|
+
mkdirSync(dbDir, { recursive: true });
|
|
66
|
+
const configPath = join(dbDir, "drizzle.config.ts");
|
|
67
|
+
writeFileSync(configPath, `import { defineConfig } from "drizzle-kit";
|
|
68
|
+
|
|
69
|
+
export default defineConfig({
|
|
70
|
+
schema: "./drizzle/schema.ts",
|
|
71
|
+
out: "./drizzle",
|
|
72
|
+
dialect: "postgresql",
|
|
73
|
+
dbCredentials: {
|
|
74
|
+
url: "${info.databaseUrl}",
|
|
75
|
+
},
|
|
76
|
+
verbose: true,
|
|
77
|
+
strict: true,
|
|
78
|
+
});
|
|
79
|
+
`);
|
|
80
|
+
p.log.info(`Introspecting database schema for ${info.key}...`);
|
|
81
|
+
try {
|
|
82
|
+
await spawnAsync("npx", [
|
|
83
|
+
"drizzle-kit",
|
|
84
|
+
"pull",
|
|
85
|
+
"--config",
|
|
86
|
+
configPath
|
|
87
|
+
], { cwd: dbDir });
|
|
88
|
+
} catch {
|
|
89
|
+
throw new Error(`Failed to introspect database for "${info.key}". Check that ${info.databaseSecret} is correct and the database is reachable.`);
|
|
90
|
+
}
|
|
91
|
+
p.log.info(`Starting Drizzle Studio for ${info.key}...`);
|
|
92
|
+
await spawnAsync("npx", [
|
|
93
|
+
"drizzle-kit",
|
|
94
|
+
"studio",
|
|
95
|
+
"--config",
|
|
96
|
+
configPath
|
|
97
|
+
], { cwd: dbDir });
|
|
98
|
+
}
|
|
99
|
+
function spawnAsync(cmd, args, options) {
|
|
100
|
+
return new Promise((resolvePromise, reject) => {
|
|
101
|
+
const child = spawn(cmd, args, {
|
|
102
|
+
cwd: options.cwd,
|
|
103
|
+
stdio: "inherit",
|
|
104
|
+
shell: true
|
|
105
|
+
});
|
|
106
|
+
child.on("error", (err) => {
|
|
107
|
+
if (err.code === "ENOENT") reject(/* @__PURE__ */ new Error(`"${cmd}" not found. Ensure it is installed (e.g. 'npm install -g drizzle-kit').`));
|
|
108
|
+
else reject(/* @__PURE__ */ new Error(`Failed to start ${cmd}: ${err.message}`));
|
|
109
|
+
});
|
|
110
|
+
child.on("exit", (code) => {
|
|
111
|
+
if (code === 0 || code === null) resolvePromise();
|
|
112
|
+
else reject(/* @__PURE__ */ new Error(`"${cmd}" exited with code ${code}`));
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
//#endregion
|
|
118
|
+
export { resolvePluginDbInfo, runStudioLocal, runStudioRemote };
|
|
119
|
+
//# sourceMappingURL=db-studio.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db-studio.mjs","names":[],"sources":["../../src/cli/db-studio.ts"],"sourcesContent":["import { spawn } from \"node:child_process\";\nimport { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport type { RuntimeConfig } from \"../types\";\n\nexport interface PluginDbInfo {\n key: string;\n source: \"local\" | \"remote\";\n section: \"app.api\" | \"app.auth\" | \"plugins\";\n databaseSecret: string;\n databaseUrl: string;\n workspaceDir?: string;\n projectDir: string;\n}\n\nexport function resolvePluginDbInfo(\n pluginKey: string,\n runtimeConfig: RuntimeConfig,\n projectDir: string,\n): PluginDbInfo {\n let source: \"local\" | \"remote\" | undefined;\n let section: PluginDbInfo[\"section\"];\n let secrets: string[] | undefined;\n let localPath: string | undefined;\n let key: string;\n\n if (pluginKey === \"api\" && runtimeConfig.api) {\n source = runtimeConfig.api.source;\n section = \"app.api\";\n secrets = runtimeConfig.api.secrets;\n localPath = runtimeConfig.api.localPath;\n key = \"api\";\n } else if (pluginKey === \"auth\" && runtimeConfig.auth) {\n source = runtimeConfig.auth.source;\n section = \"app.auth\";\n secrets = runtimeConfig.auth.secrets;\n localPath = runtimeConfig.auth.localPath;\n key = \"auth\";\n } else if (runtimeConfig.plugins?.[pluginKey]) {\n const plugin = runtimeConfig.plugins[pluginKey];\n source = plugin.source;\n section = \"plugins\";\n secrets = plugin.secrets;\n localPath = plugin.localPath;\n key = pluginKey;\n } else {\n throw new Error(\n `Plugin \"${pluginKey}\" not found in app.api, app.auth, or plugins. ` +\n `Available: ${[\n \"api\",\n ...(runtimeConfig.auth ? [\"auth\"] : []),\n ...Object.keys(runtimeConfig.plugins ?? {}),\n ].join(\", \")}`,\n );\n }\n\n const dbSecret = secrets?.find((s) => s.endsWith(\"_DATABASE_URL\"));\n if (!dbSecret) {\n throw new Error(\n `Plugin \"${pluginKey}\" has no database secret (no secret ending in _DATABASE_URL). ` +\n `Secrets: ${(secrets ?? []).join(\", \") || \"none\"}`,\n );\n }\n\n const dbUrl = process.env[dbSecret];\n if (!dbUrl) {\n throw new Error(\n `.env missing ${dbSecret} for plugin \"${pluginKey}\". ` +\n `Add it to your .env file (see .env.example).`,\n );\n }\n\n return {\n key,\n source: source ?? \"remote\",\n section,\n databaseSecret: dbSecret,\n databaseUrl: dbUrl,\n workspaceDir: localPath,\n projectDir,\n };\n}\n\nexport async function runStudioLocal(info: PluginDbInfo): Promise<void> {\n const workspaceRoot = info.workspaceDir\n ? resolve(info.projectDir, info.workspaceDir)\n : resolve(info.projectDir, info.key);\n const configPath = join(workspaceRoot, \"drizzle.config.ts\");\n\n if (!existsSync(configPath)) {\n throw new Error(\n `No drizzle.config.ts found in ${workspaceRoot}. ` +\n `Run 'drizzle-kit init' first in the plugin workspace.`,\n );\n }\n\n p.log.info(`Starting Drizzle Studio for ${info.key} (local)...`);\n\n await spawnAsync(\"npx\", [\"drizzle-kit\", \"studio\", \"--config\", configPath], {\n cwd: workspaceRoot,\n });\n}\n\nexport async function runStudioRemote(info: PluginDbInfo): Promise<void> {\n const dbDir = resolve(info.projectDir, \".bos\", \"db\", info.key);\n\n mkdirSync(dbDir, { recursive: true });\n\n const configPath = join(dbDir, \"drizzle.config.ts\");\n const configContent = `import { defineConfig } from \"drizzle-kit\";\n\nexport default defineConfig({\n schema: \"./drizzle/schema.ts\",\n out: \"./drizzle\",\n dialect: \"postgresql\",\n dbCredentials: {\n url: \"${info.databaseUrl}\",\n },\n verbose: true,\n strict: true,\n});\n`;\n\n writeFileSync(configPath, configContent);\n\n p.log.info(`Introspecting database schema for ${info.key}...`);\n try {\n await spawnAsync(\"npx\", [\"drizzle-kit\", \"pull\", \"--config\", configPath], {\n cwd: dbDir,\n });\n } catch {\n throw new Error(\n `Failed to introspect database for \"${info.key}\". ` +\n `Check that ${info.databaseSecret} is correct and the database is reachable.`,\n );\n }\n\n p.log.info(`Starting Drizzle Studio for ${info.key}...`);\n await spawnAsync(\"npx\", [\"drizzle-kit\", \"studio\", \"--config\", configPath], {\n cwd: dbDir,\n });\n}\n\nfunction spawnAsync(cmd: string, args: string[], options: { cwd: string }): Promise<void> {\n return new Promise((resolvePromise, reject) => {\n const child = spawn(cmd, args, {\n cwd: options.cwd,\n stdio: \"inherit\",\n shell: true,\n });\n\n child.on(\"error\", (err) => {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n reject(\n new Error(\n `\"${cmd}\" not found. Ensure it is installed (e.g. 'npm install -g drizzle-kit').`,\n ),\n );\n } else {\n reject(new Error(`Failed to start ${cmd}: ${err.message}`));\n }\n });\n\n child.on(\"exit\", (code) => {\n if (code === 0 || code === null) {\n resolvePromise();\n } else {\n reject(new Error(`\"${cmd}\" exited with code ${code}`));\n }\n });\n });\n}\n"],"mappings":"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"}
|
package/dist/cli/init.cjs
CHANGED
|
@@ -342,7 +342,7 @@ function buildChildRootScripts(sections) {
|
|
|
342
342
|
};
|
|
343
343
|
if (sections.api) {
|
|
344
344
|
scripts["db:push"] = "bun run --cwd api drizzle-kit push";
|
|
345
|
-
scripts["db:studio"] = "
|
|
345
|
+
scripts["db:studio"] = "node_modules/.bin/bos db:studio";
|
|
346
346
|
scripts["db:generate"] = "bun run --cwd api drizzle-kit generate";
|
|
347
347
|
scripts["db:migrate"] = "bun run --cwd api drizzle-kit migrate";
|
|
348
348
|
scripts["test:api"] = "cd api && bun run test tests/integration/ tests/unit/";
|