create-better-t-stack 3.46.0 → 3.47.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.mjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{src-_HMF_A8q.mjs → src-CC7QNkfh.mjs} +61 -42
- package/package.json +3 -3
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { D as setProcessMode, i as SchemaNameSchema, l as create, m as getSchemaResult, s as add, u as createBtsCli, v as types_exports, y as getLatestCLIVersion } from "./src-
|
|
2
|
+
import { D as setProcessMode, i as SchemaNameSchema, l as create, m as getSchemaResult, s as add, u as createBtsCli, v as types_exports, y as getLatestCLIVersion } from "./src-CC7QNkfh.mjs";
|
|
3
3
|
import { lineByLineConsoleLogger } from "trpc-cli";
|
|
4
4
|
import z from "zod";
|
|
5
5
|
import { McpServer } from "@modelcontextprotocol/server";
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { C as DirectoryConflictError, E as ValidationError, S as DatabaseSetupError, T as UserCancelledError, _ as ProjectLauncherSchema, a as TEMPLATE_COUNT, b as CLIError, c as builder, d as createVirtual, f as docs, g as sponsors, h as router, i as SchemaNameSchema, l as create, m as getSchemaResult, n as GeneratorError, o as VirtualFileSystem, p as generate, r as Result, s as add, t as EMBEDDED_TEMPLATES, u as createBtsCli, w as ProjectCreationError, x as CompatibilityError } from "./src-
|
|
2
|
+
import { C as DirectoryConflictError, E as ValidationError, S as DatabaseSetupError, T as UserCancelledError, _ as ProjectLauncherSchema, a as TEMPLATE_COUNT, b as CLIError, c as builder, d as createVirtual, f as docs, g as sponsors, h as router, i as SchemaNameSchema, l as create, m as getSchemaResult, n as GeneratorError, o as VirtualFileSystem, p as generate, r as Result, s as add, t as EMBEDDED_TEMPLATES, u as createBtsCli, w as ProjectCreationError, x as CompatibilityError } from "./src-CC7QNkfh.mjs";
|
|
3
3
|
export { CLIError, CompatibilityError, DatabaseSetupError, DirectoryConflictError, EMBEDDED_TEMPLATES, GeneratorError, ProjectCreationError, ProjectLauncherSchema, Result, SchemaNameSchema, TEMPLATE_COUNT, UserCancelledError, ValidationError, VirtualFileSystem, add, builder, create, createBtsCli, createVirtual, docs, generate, getSchemaResult, router, sponsors };
|
|
@@ -8078,19 +8078,21 @@ async function setupPrismaPostgres(config, cliInput) {
|
|
|
8078
8078
|
}
|
|
8079
8079
|
//#endregion
|
|
8080
8080
|
//#region src/helpers/database-providers/supabase-setup.ts
|
|
8081
|
+
const SUPABASE_CLI_PACKAGE = "supabase@2.121.0";
|
|
8082
|
+
const supabaseEnv = { SUPABASE_EXPERIMENTAL_STACK: "0" };
|
|
8083
|
+
const statusSchema = z$1.object({ DB_URL: z$1.url().refine((value) => ["postgres:", "postgresql:"].includes(new URL(value).protocol)) });
|
|
8084
|
+
/** Save a verified database URL in the app that consumes the database. */
|
|
8081
8085
|
async function writeSupabaseEnvFile(projectDir, backend, databaseUrl) {
|
|
8082
8086
|
return Result.tryPromise({
|
|
8083
8087
|
try: async () => {
|
|
8084
8088
|
const targetApp = backend === "self" ? "apps/web" : "apps/server";
|
|
8085
|
-
|
|
8086
|
-
const dbUrlToUse = databaseUrl || "postgresql://postgres:postgres@127.0.0.1:54322/postgres";
|
|
8087
|
-
await addEnvVariablesToFile(envPath, [{
|
|
8089
|
+
await addEnvVariablesToFile(path.join(projectDir, targetApp, ".env"), [{
|
|
8088
8090
|
key: "DATABASE_URL",
|
|
8089
|
-
value:
|
|
8091
|
+
value: databaseUrl,
|
|
8090
8092
|
condition: true
|
|
8091
8093
|
}, {
|
|
8092
8094
|
key: "DIRECT_URL",
|
|
8093
|
-
value:
|
|
8095
|
+
value: databaseUrl,
|
|
8094
8096
|
condition: true
|
|
8095
8097
|
}]);
|
|
8096
8098
|
},
|
|
@@ -8101,28 +8103,38 @@ async function writeSupabaseEnvFile(projectDir, backend, databaseUrl) {
|
|
|
8101
8103
|
})
|
|
8102
8104
|
});
|
|
8103
8105
|
}
|
|
8104
|
-
|
|
8105
|
-
return statusEnv.match(/^DB_URL="(postgresql:\/\/[^"]+)"$/m)?.[1] ?? null;
|
|
8106
|
-
}
|
|
8106
|
+
/** Read Docker status with cancellation and a bounded wait. */
|
|
8107
8107
|
async function readSupabaseStatus(serverDir, packageManager) {
|
|
8108
|
-
const statusArgs = getPackageExecutionArgs(packageManager,
|
|
8109
|
-
|
|
8108
|
+
const statusArgs = getPackageExecutionArgs(packageManager, `${SUPABASE_CLI_PACKAGE} status --agent no --output json`);
|
|
8109
|
+
return Result.tryPromise({
|
|
8110
8110
|
try: async () => {
|
|
8111
|
-
const { stdout } = await execa(statusArgs[0], statusArgs.slice(1), {
|
|
8112
|
-
|
|
8111
|
+
const { stdout } = await execa(statusArgs[0], statusArgs.slice(1), {
|
|
8112
|
+
cwd: serverDir,
|
|
8113
|
+
env: supabaseEnv,
|
|
8114
|
+
cancelSignal: getInterruptSignal(),
|
|
8115
|
+
timeout: 12e4
|
|
8116
|
+
});
|
|
8117
|
+
return statusSchema.parse(JSON.parse(stdout)).DB_URL;
|
|
8113
8118
|
},
|
|
8114
|
-
catch: () =>
|
|
8119
|
+
catch: (e) => new DatabaseSetupError({
|
|
8120
|
+
provider: "supabase",
|
|
8121
|
+
message: "Could not read the Supabase database URL. Run Supabase status and configure DATABASE_URL and DIRECT_URL manually.",
|
|
8122
|
+
cause: e
|
|
8123
|
+
})
|
|
8115
8124
|
});
|
|
8116
|
-
return result.isOk() ? result.value : "";
|
|
8117
8125
|
}
|
|
8126
|
+
/** Initialize missing configuration without overwriting an existing project. */
|
|
8118
8127
|
async function initializeSupabase(serverDir, packageManager) {
|
|
8119
8128
|
cliLog.info("Initializing Supabase project...");
|
|
8120
8129
|
return Result.tryPromise({
|
|
8121
8130
|
try: async () => {
|
|
8122
|
-
|
|
8131
|
+
if (await fs.pathExists(path.join(serverDir, "supabase/config.toml"))) return;
|
|
8132
|
+
const supabaseInitArgs = getPackageExecutionArgs(packageManager, `${SUPABASE_CLI_PACKAGE} init --agent no`);
|
|
8123
8133
|
await execa(supabaseInitArgs[0], supabaseInitArgs.slice(1), {
|
|
8124
8134
|
cwd: serverDir,
|
|
8125
|
-
stdio: "inherit"
|
|
8135
|
+
stdio: "inherit",
|
|
8136
|
+
env: supabaseEnv,
|
|
8137
|
+
cancelSignal: getInterruptSignal()
|
|
8126
8138
|
});
|
|
8127
8139
|
cliLog.success("Supabase project initialized");
|
|
8128
8140
|
},
|
|
@@ -8130,18 +8142,23 @@ async function initializeSupabase(serverDir, packageManager) {
|
|
|
8130
8142
|
const error = e;
|
|
8131
8143
|
return new DatabaseSetupError({
|
|
8132
8144
|
provider: "supabase",
|
|
8133
|
-
message: error.message?.includes("ENOENT") ? "
|
|
8145
|
+
message: error.message?.includes("ENOENT") ? "Could not run the Supabase CLI. Ensure your selected package manager is installed and available in PATH." : `Failed to initialize Supabase project: ${error.message ?? String(e)}`,
|
|
8134
8146
|
cause: e
|
|
8135
8147
|
});
|
|
8136
8148
|
}
|
|
8137
8149
|
});
|
|
8138
8150
|
}
|
|
8151
|
+
/** Start the standard Docker runtime and stream its progress to the CLI. */
|
|
8139
8152
|
async function startSupabase(serverDir, packageManager) {
|
|
8140
8153
|
cliLog.info("Starting Supabase services (this may take a moment)...");
|
|
8141
|
-
const supabaseStartArgs = getPackageExecutionArgs(packageManager,
|
|
8154
|
+
const supabaseStartArgs = getPackageExecutionArgs(packageManager, `${SUPABASE_CLI_PACKAGE} start --agent no`);
|
|
8142
8155
|
return Result.tryPromise({
|
|
8143
8156
|
try: async () => {
|
|
8144
|
-
const subprocess = execa(supabaseStartArgs[0], supabaseStartArgs.slice(1), {
|
|
8157
|
+
const subprocess = execa(supabaseStartArgs[0], supabaseStartArgs.slice(1), {
|
|
8158
|
+
cwd: serverDir,
|
|
8159
|
+
env: supabaseEnv,
|
|
8160
|
+
cancelSignal: getInterruptSignal()
|
|
8161
|
+
});
|
|
8145
8162
|
let stdoutData = "";
|
|
8146
8163
|
if (subprocess.stdout) subprocess.stdout.on("data", (data) => {
|
|
8147
8164
|
const text = data.toString();
|
|
@@ -8150,7 +8167,6 @@ async function startSupabase(serverDir, packageManager) {
|
|
|
8150
8167
|
});
|
|
8151
8168
|
if (subprocess.stderr) subprocess.stderr.pipe(process.stderr);
|
|
8152
8169
|
await subprocess;
|
|
8153
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
8154
8170
|
return stdoutData;
|
|
8155
8171
|
},
|
|
8156
8172
|
catch: (e) => {
|
|
@@ -8163,18 +8179,21 @@ async function startSupabase(serverDir, packageManager) {
|
|
|
8163
8179
|
}
|
|
8164
8180
|
});
|
|
8165
8181
|
}
|
|
8166
|
-
|
|
8182
|
+
/** Print pinned setup commands without changing configuration or credentials. */
|
|
8183
|
+
function displayManualSupabaseInstructions(targetApp, packageManager, output) {
|
|
8184
|
+
const command = getPackageExecutionCommand(packageManager, SUPABASE_CLI_PACKAGE);
|
|
8167
8185
|
cliLog.info(`"Manual Supabase Setup Instructions:"
|
|
8168
|
-
1.
|
|
8169
|
-
2.
|
|
8170
|
-
3.
|
|
8171
|
-
4. Run
|
|
8172
|
-
5.
|
|
8186
|
+
1. Open your project's \`packages/db\` directory.
|
|
8187
|
+
2. Run \`${command} init\` if \`supabase/config.toml\` does not exist.
|
|
8188
|
+
3. Ensure Docker or a Docker-compatible container runtime is installed and running.
|
|
8189
|
+
4. Run \`${command} start\`.
|
|
8190
|
+
5. Run \`${command} status --output json\` and copy \`DB_URL\`.${output ? `
|
|
8173
8191
|
${pc.bold("Relevant output from `supabase start`:")}
|
|
8174
8192
|
${pc.dim(output)}` : ""}
|
|
8175
|
-
6. Add the database URL to the .env file in \`${targetApp}/.env\` as \`DATABASE_URL\`:
|
|
8176
|
-
${pc.gray("DATABASE_URL=\"your_supabase_db_url\"")}`);
|
|
8193
|
+
6. Add the database URL to the .env file in \`${targetApp}/.env\` as \`DATABASE_URL\` and \`DIRECT_URL\`:
|
|
8194
|
+
${pc.gray("DATABASE_URL=\"your_supabase_db_url\"\nDIRECT_URL=\"your_supabase_db_url\"")}`);
|
|
8177
8195
|
}
|
|
8196
|
+
/** Configure local Supabase, preserving credentials until automatic setup succeeds. */
|
|
8178
8197
|
async function setupSupabase(config, cliInput) {
|
|
8179
8198
|
const { projectDir, packageManager, backend } = config;
|
|
8180
8199
|
const targetApp = backend === "self" ? "apps/web" : "apps/server";
|
|
@@ -8193,8 +8212,8 @@ async function setupSupabase(config, cliInput) {
|
|
|
8193
8212
|
});
|
|
8194
8213
|
if (ensureDirResult.isErr()) return ensureDirResult;
|
|
8195
8214
|
if (setupMode === "manual") {
|
|
8196
|
-
displayManualSupabaseInstructions(targetApp);
|
|
8197
|
-
return
|
|
8215
|
+
displayManualSupabaseInstructions(targetApp, packageManager);
|
|
8216
|
+
return Result.ok();
|
|
8198
8217
|
}
|
|
8199
8218
|
let mode = setupMode;
|
|
8200
8219
|
if (!mode) {
|
|
@@ -8218,35 +8237,35 @@ async function setupSupabase(config, cliInput) {
|
|
|
8218
8237
|
}
|
|
8219
8238
|
}
|
|
8220
8239
|
if (mode === "manual") {
|
|
8221
|
-
displayManualSupabaseInstructions(targetApp);
|
|
8222
|
-
return
|
|
8240
|
+
displayManualSupabaseInstructions(targetApp, packageManager);
|
|
8241
|
+
return Result.ok();
|
|
8223
8242
|
}
|
|
8224
8243
|
const initResult = await initializeSupabase(serverDir, packageManager);
|
|
8225
8244
|
if (initResult.isErr()) {
|
|
8226
8245
|
cliLog.error(pc.red(initResult.error.message));
|
|
8227
|
-
displayManualSupabaseInstructions(targetApp);
|
|
8228
|
-
return
|
|
8246
|
+
displayManualSupabaseInstructions(targetApp, packageManager);
|
|
8247
|
+
return initResult;
|
|
8229
8248
|
}
|
|
8230
8249
|
const startResult = await startSupabase(serverDir, packageManager);
|
|
8231
8250
|
if (startResult.isErr()) {
|
|
8232
8251
|
cliLog.error(pc.red(startResult.error.message));
|
|
8233
|
-
displayManualSupabaseInstructions(targetApp);
|
|
8234
|
-
return
|
|
8252
|
+
displayManualSupabaseInstructions(targetApp, packageManager);
|
|
8253
|
+
return startResult;
|
|
8235
8254
|
}
|
|
8236
8255
|
const supabaseOutput = startResult.value;
|
|
8237
|
-
const
|
|
8238
|
-
if (
|
|
8239
|
-
const envResult = await writeSupabaseEnvFile(projectDir, backend,
|
|
8256
|
+
const statusResult = await readSupabaseStatus(serverDir, packageManager);
|
|
8257
|
+
if (statusResult.isOk()) {
|
|
8258
|
+
const envResult = await writeSupabaseEnvFile(projectDir, backend, statusResult.value);
|
|
8240
8259
|
if (envResult.isOk()) cliLog.success(pc.green("Supabase local development setup ready!"));
|
|
8241
8260
|
else {
|
|
8242
8261
|
cliLog.error(pc.red("Supabase setup completed, but failed to update .env automatically."));
|
|
8243
|
-
displayManualSupabaseInstructions(targetApp, supabaseOutput);
|
|
8262
|
+
displayManualSupabaseInstructions(targetApp, packageManager, supabaseOutput);
|
|
8244
8263
|
}
|
|
8245
8264
|
return envResult;
|
|
8246
8265
|
}
|
|
8247
8266
|
cliLog.error(pc.yellow("Supabase started, but could not extract DB URL automatically."));
|
|
8248
|
-
displayManualSupabaseInstructions(targetApp, supabaseOutput);
|
|
8249
|
-
return
|
|
8267
|
+
displayManualSupabaseInstructions(targetApp, packageManager, supabaseOutput);
|
|
8268
|
+
return statusResult;
|
|
8250
8269
|
}
|
|
8251
8270
|
//#endregion
|
|
8252
8271
|
//#region src/helpers/database-providers/turso-setup.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-better-t-stack",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.47.0",
|
|
4
4
|
"description": "A modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with best practices and customizable configurations",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"better-auth",
|
|
@@ -70,8 +70,8 @@
|
|
|
70
70
|
"prepublishOnly": "npm run build"
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|
|
73
|
-
"@better-t-stack/template-generator": "^3.
|
|
74
|
-
"@better-t-stack/types": "^3.
|
|
73
|
+
"@better-t-stack/template-generator": "^3.47.0",
|
|
74
|
+
"@better-t-stack/types": "^3.47.0",
|
|
75
75
|
"@clack/core": "^1.5.0",
|
|
76
76
|
"@clack/prompts": "^1.8.0",
|
|
77
77
|
"@modelcontextprotocol/server": "2.0.0",
|