create-better-t-stack 2.24.5 → 2.25.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/index.js +181 -10
- package/package.json +1 -1
- package/templates/addons/turborepo/turbo.json.hbs +18 -0
- package/templates/db-setup/docker-compose/mongodb/docker-compose.yml.hbs +23 -0
- package/templates/db-setup/docker-compose/mysql/docker-compose.yml.hbs +24 -0
- package/templates/db-setup/docker-compose/postgres/docker-compose.yml.hbs +23 -0
package/dist/index.js
CHANGED
|
@@ -3795,6 +3795,7 @@ const DatabaseSetupSchema = enumType([
|
|
|
3795
3795
|
"mongodb-atlas",
|
|
3796
3796
|
"supabase",
|
|
3797
3797
|
"d1",
|
|
3798
|
+
"docker",
|
|
3798
3799
|
"none"
|
|
3799
3800
|
]).describe("Database hosting setup");
|
|
3800
3801
|
const APISchema = enumType([
|
|
@@ -4135,21 +4136,43 @@ async function getDBSetupChoice(databaseType, dbSetup, orm, backend, runtime) {
|
|
|
4135
4136
|
label: "Prisma Postgres",
|
|
4136
4137
|
hint: "Instant Postgres for Global Applications"
|
|
4137
4138
|
}] : [],
|
|
4139
|
+
{
|
|
4140
|
+
value: "docker",
|
|
4141
|
+
label: "Docker",
|
|
4142
|
+
hint: "Run locally with docker compose"
|
|
4143
|
+
},
|
|
4138
4144
|
{
|
|
4139
4145
|
value: "none",
|
|
4140
4146
|
label: "None",
|
|
4141
4147
|
hint: "Manual setup"
|
|
4142
4148
|
}
|
|
4143
4149
|
];
|
|
4144
|
-
else if (databaseType === "
|
|
4145
|
-
value: "
|
|
4146
|
-
label: "
|
|
4147
|
-
hint: "
|
|
4150
|
+
else if (databaseType === "mysql") options = [{
|
|
4151
|
+
value: "docker",
|
|
4152
|
+
label: "Docker",
|
|
4153
|
+
hint: "Run locally with docker compose"
|
|
4148
4154
|
}, {
|
|
4149
4155
|
value: "none",
|
|
4150
4156
|
label: "None",
|
|
4151
4157
|
hint: "Manual setup"
|
|
4152
4158
|
}];
|
|
4159
|
+
else if (databaseType === "mongodb") options = [
|
|
4160
|
+
{
|
|
4161
|
+
value: "mongodb-atlas",
|
|
4162
|
+
label: "MongoDB Atlas",
|
|
4163
|
+
hint: "The most effective way to deploy MongoDB"
|
|
4164
|
+
},
|
|
4165
|
+
{
|
|
4166
|
+
value: "docker",
|
|
4167
|
+
label: "Docker",
|
|
4168
|
+
hint: "Run locally with docker compose"
|
|
4169
|
+
},
|
|
4170
|
+
{
|
|
4171
|
+
value: "none",
|
|
4172
|
+
label: "None",
|
|
4173
|
+
hint: "Manual setup"
|
|
4174
|
+
}
|
|
4175
|
+
];
|
|
4153
4176
|
else return "none";
|
|
4154
4177
|
const response = await select({
|
|
4155
4178
|
message: `Select ${databaseType} setup option`,
|
|
@@ -5050,6 +5073,14 @@ function processAndValidateFlags(options, providedFlags, projectName) {
|
|
|
5050
5073
|
process.exit(1);
|
|
5051
5074
|
}
|
|
5052
5075
|
}
|
|
5076
|
+
if (config.dbSetup === "docker" && config.database === "sqlite") {
|
|
5077
|
+
consola$1.fatal("Docker setup is not compatible with SQLite database. SQLite is file-based and doesn't require Docker. Please use '--database postgres', '--database mysql', '--database mongodb', or choose a different setup.");
|
|
5078
|
+
process.exit(1);
|
|
5079
|
+
}
|
|
5080
|
+
if (config.dbSetup === "docker" && config.runtime === "workers") {
|
|
5081
|
+
consola$1.fatal("Docker setup is not compatible with Cloudflare Workers runtime. Workers runtime uses serverless databases (D1) and doesn't support local Docker containers. Please use '--db-setup d1' for SQLite or choose a different runtime.");
|
|
5082
|
+
process.exit(1);
|
|
5083
|
+
}
|
|
5053
5084
|
if (providedFlags.has("runtime") && options.runtime === "workers" && config.backend && config.backend !== "hono") {
|
|
5054
5085
|
consola$1.fatal(`Cloudflare Workers runtime (--runtime workers) is only supported with Hono backend (--backend hono). Current backend: ${config.backend}. Please use '--backend hono' or choose a different runtime.`);
|
|
5055
5086
|
process.exit(1);
|
|
@@ -5070,10 +5101,18 @@ function processAndValidateFlags(options, providedFlags, projectName) {
|
|
|
5070
5101
|
consola$1.fatal("Cloudflare Workers runtime (--runtime workers) is not compatible with MongoDB database. MongoDB requires Prisma or Mongoose ORM, but Workers runtime only supports Drizzle ORM. Please use a different database or runtime.");
|
|
5071
5102
|
process.exit(1);
|
|
5072
5103
|
}
|
|
5104
|
+
if (providedFlags.has("runtime") && options.runtime === "workers" && config.dbSetup === "docker") {
|
|
5105
|
+
consola$1.fatal("Cloudflare Workers runtime (--runtime workers) is not compatible with Docker setup. Workers runtime uses serverless databases (D1) and doesn't support local Docker containers. Please use '--db-setup d1' for SQLite or choose a different runtime.");
|
|
5106
|
+
process.exit(1);
|
|
5107
|
+
}
|
|
5073
5108
|
if (providedFlags.has("database") && config.database === "mongodb" && config.runtime === "workers") {
|
|
5074
5109
|
consola$1.fatal("MongoDB database is not compatible with Cloudflare Workers runtime. MongoDB requires Prisma or Mongoose ORM, but Workers runtime only supports Drizzle ORM. Please use a different database or runtime.");
|
|
5075
5110
|
process.exit(1);
|
|
5076
5111
|
}
|
|
5112
|
+
if (providedFlags.has("db-setup") && options.dbSetup === "docker" && config.runtime === "workers") {
|
|
5113
|
+
consola$1.fatal("Docker setup (--db-setup docker) is not compatible with Cloudflare Workers runtime. Workers runtime uses serverless databases (D1) and doesn't support local Docker containers. Please use '--db-setup d1' for SQLite or choose a different runtime.");
|
|
5114
|
+
process.exit(1);
|
|
5115
|
+
}
|
|
5077
5116
|
const hasWebFrontendFlag = (config.frontend ?? []).some((f) => WEB_FRAMEWORKS.includes(f));
|
|
5078
5117
|
if (config.webDeploy && config.webDeploy !== "none" && !hasWebFrontendFlag && providedFlags.has("frontend")) {
|
|
5079
5118
|
consola$1.fatal("'--web-deploy' requires a web frontend. Please select a web frontend or set '--web-deploy none'.");
|
|
@@ -5864,6 +5903,12 @@ async function handleExtras(projectDir, context) {
|
|
|
5864
5903
|
if (await fs.pathExists(runtimeWorkersDir)) await processAndCopyFiles("**/*", runtimeWorkersDir, projectDir, context, false);
|
|
5865
5904
|
}
|
|
5866
5905
|
}
|
|
5906
|
+
async function setupDockerComposeTemplates(projectDir, context) {
|
|
5907
|
+
if (context.dbSetup !== "docker" || context.database === "none") return;
|
|
5908
|
+
const serverAppDir = path.join(projectDir, "apps/server");
|
|
5909
|
+
const dockerSrcDir = path.join(PKG_ROOT, `templates/db-setup/docker-compose/${context.database}`);
|
|
5910
|
+
if (await fs.pathExists(dockerSrcDir)) await processAndCopyFiles("**/*", dockerSrcDir, serverAppDir, context);
|
|
5911
|
+
}
|
|
5867
5912
|
async function setupDeploymentTemplates(projectDir, context) {
|
|
5868
5913
|
if (context.webDeploy === "none") return;
|
|
5869
5914
|
if (context.webDeploy === "workers") {
|
|
@@ -6613,7 +6658,7 @@ async function setupEnvironmentVariables(config) {
|
|
|
6613
6658
|
let corsOrigin = "http://localhost:3001";
|
|
6614
6659
|
if (hasReactRouter || hasSvelte) corsOrigin = "http://localhost:5173";
|
|
6615
6660
|
let databaseUrl = null;
|
|
6616
|
-
const specializedSetup = dbSetup === "turso" || dbSetup === "prisma-postgres" || dbSetup === "mongodb-atlas" || dbSetup === "neon" || dbSetup === "supabase" || dbSetup === "d1";
|
|
6661
|
+
const specializedSetup = dbSetup === "turso" || dbSetup === "prisma-postgres" || dbSetup === "mongodb-atlas" || dbSetup === "neon" || dbSetup === "supabase" || dbSetup === "d1" || dbSetup === "docker";
|
|
6617
6662
|
if (database !== "none" && !specializedSetup) switch (database) {
|
|
6618
6663
|
case "postgres":
|
|
6619
6664
|
databaseUrl = "postgresql://postgres:password@localhost:5432/postgres";
|
|
@@ -6692,6 +6737,35 @@ async function setupCloudflareD1(config) {
|
|
|
6692
6737
|
} catch (_err) {}
|
|
6693
6738
|
}
|
|
6694
6739
|
|
|
6740
|
+
//#endregion
|
|
6741
|
+
//#region src/helpers/database-providers/docker-compose-setup.ts
|
|
6742
|
+
async function setupDockerCompose(config) {
|
|
6743
|
+
const { database, projectDir, projectName } = config;
|
|
6744
|
+
if (database === "none" || database === "sqlite") return;
|
|
6745
|
+
try {
|
|
6746
|
+
await writeEnvFile$4(projectDir, database, projectName);
|
|
6747
|
+
} catch (error) {
|
|
6748
|
+
if (error instanceof Error) console.error(`Error: ${error.message}`);
|
|
6749
|
+
}
|
|
6750
|
+
}
|
|
6751
|
+
async function writeEnvFile$4(projectDir, database, projectName) {
|
|
6752
|
+
const envPath = path.join(projectDir, "apps/server", ".env");
|
|
6753
|
+
const variables = [{
|
|
6754
|
+
key: "DATABASE_URL",
|
|
6755
|
+
value: getDatabaseUrl(database, projectName),
|
|
6756
|
+
condition: true
|
|
6757
|
+
}];
|
|
6758
|
+
await addEnvVariablesToFile(envPath, variables);
|
|
6759
|
+
}
|
|
6760
|
+
function getDatabaseUrl(database, projectName) {
|
|
6761
|
+
switch (database) {
|
|
6762
|
+
case "postgres": return `postgresql://postgres:password@localhost:5432/${projectName}`;
|
|
6763
|
+
case "mysql": return `mysql://user:password@localhost:3306/${projectName}`;
|
|
6764
|
+
case "mongodb": return `mongodb://root:password@localhost:27017/${projectName}?authSource=admin`;
|
|
6765
|
+
default: return "";
|
|
6766
|
+
}
|
|
6767
|
+
}
|
|
6768
|
+
|
|
6695
6769
|
//#endregion
|
|
6696
6770
|
//#region src/utils/command-exists.ts
|
|
6697
6771
|
async function commandExists(command) {
|
|
@@ -7474,7 +7548,8 @@ async function setupDatabase(config) {
|
|
|
7474
7548
|
devDependencies: [],
|
|
7475
7549
|
projectDir: serverDir
|
|
7476
7550
|
});
|
|
7477
|
-
if (
|
|
7551
|
+
if (dbSetup === "docker") await setupDockerCompose(config);
|
|
7552
|
+
else if (database === "sqlite" && dbSetup === "turso") await setupTurso(config);
|
|
7478
7553
|
else if (database === "sqlite" && dbSetup === "d1") await setupCloudflareD1(config);
|
|
7479
7554
|
else if (database === "postgres") {
|
|
7480
7555
|
if (orm === "prisma" && dbSetup === "prisma-postgres") await setupPrismaPostgres(config);
|
|
@@ -7901,15 +7976,68 @@ async function initializeGit(projectDir, useGit) {
|
|
|
7901
7976
|
await $({ cwd: projectDir })`git commit -m ${"initial commit"}`;
|
|
7902
7977
|
}
|
|
7903
7978
|
|
|
7979
|
+
//#endregion
|
|
7980
|
+
//#region src/utils/docker-utils.ts
|
|
7981
|
+
async function isDockerInstalled() {
|
|
7982
|
+
return commandExists("docker");
|
|
7983
|
+
}
|
|
7984
|
+
async function isDockerRunning() {
|
|
7985
|
+
try {
|
|
7986
|
+
const { $: $$1 } = await import("execa");
|
|
7987
|
+
await $$1`docker info`;
|
|
7988
|
+
return true;
|
|
7989
|
+
} catch {
|
|
7990
|
+
return false;
|
|
7991
|
+
}
|
|
7992
|
+
}
|
|
7993
|
+
function getDockerInstallInstructions(platform, database) {
|
|
7994
|
+
const isMac = platform === "darwin";
|
|
7995
|
+
const isWindows = platform === "win32";
|
|
7996
|
+
const isLinux = platform === "linux";
|
|
7997
|
+
let installUrl = "";
|
|
7998
|
+
let platformName = "";
|
|
7999
|
+
if (isMac) {
|
|
8000
|
+
installUrl = "https://docs.docker.com/desktop/setup/install/mac-install/";
|
|
8001
|
+
platformName = "macOS";
|
|
8002
|
+
} else if (isWindows) {
|
|
8003
|
+
installUrl = "https://docs.docker.com/desktop/setup/install/windows-install/";
|
|
8004
|
+
platformName = "Windows";
|
|
8005
|
+
} else if (isLinux) {
|
|
8006
|
+
installUrl = "https://docs.docker.com/desktop/setup/install/linux/";
|
|
8007
|
+
platformName = "Linux";
|
|
8008
|
+
}
|
|
8009
|
+
const databaseName = database === "mongodb" ? "MongoDB" : database === "mysql" ? "MySQL" : "PostgreSQL";
|
|
8010
|
+
return `${pc.yellow("IMPORTANT:")} Docker required for ${databaseName}. Install for ${platformName}:\n${pc.blue(installUrl)}`;
|
|
8011
|
+
}
|
|
8012
|
+
async function getDockerStatus(database) {
|
|
8013
|
+
const platform = os.platform();
|
|
8014
|
+
const installed = await isDockerInstalled();
|
|
8015
|
+
if (!installed) return {
|
|
8016
|
+
installed: false,
|
|
8017
|
+
running: false,
|
|
8018
|
+
message: getDockerInstallInstructions(platform, database)
|
|
8019
|
+
};
|
|
8020
|
+
const running = await isDockerRunning();
|
|
8021
|
+
if (!running) return {
|
|
8022
|
+
installed: true,
|
|
8023
|
+
running: false,
|
|
8024
|
+
message: `${pc.yellow("IMPORTANT:")} Docker is installed but not running.`
|
|
8025
|
+
};
|
|
8026
|
+
return {
|
|
8027
|
+
installed: true,
|
|
8028
|
+
running: true
|
|
8029
|
+
};
|
|
8030
|
+
}
|
|
8031
|
+
|
|
7904
8032
|
//#endregion
|
|
7905
8033
|
//#region src/helpers/project-generation/post-installation.ts
|
|
7906
|
-
function displayPostInstallInstructions(config) {
|
|
8034
|
+
async function displayPostInstallInstructions(config) {
|
|
7907
8035
|
const { database, relativePath, packageManager, depsInstalled, orm, addons, runtime, frontend, backend, dbSetup, webDeploy } = config;
|
|
7908
8036
|
const isConvex = backend === "convex";
|
|
7909
8037
|
const runCmd = packageManager === "npm" ? "npm run" : packageManager;
|
|
7910
8038
|
const cdCmd = `cd ${relativePath}`;
|
|
7911
8039
|
const hasHuskyOrBiome = addons?.includes("husky") || addons?.includes("biome");
|
|
7912
|
-
const databaseInstructions = !isConvex && database !== "none" ? getDatabaseInstructions(database, orm, runCmd, runtime, dbSetup) : "";
|
|
8040
|
+
const databaseInstructions = !isConvex && database !== "none" ? await getDatabaseInstructions(database, orm, runCmd, runtime, dbSetup) : "";
|
|
7913
8041
|
const tauriInstructions = addons?.includes("tauri") ? getTauriInstructions(runCmd) : "";
|
|
7914
8042
|
const lintingInstructions = hasHuskyOrBiome ? getLintingInstructions(runCmd) : "";
|
|
7915
8043
|
const nativeInstructions = frontend?.includes("native-nativewind") || frontend?.includes("native-unistyles") ? getNativeInstructions(isConvex) : "";
|
|
@@ -7978,8 +8106,15 @@ function getNativeInstructions(isConvex) {
|
|
|
7978
8106
|
function getLintingInstructions(runCmd) {
|
|
7979
8107
|
return `${pc.bold("Linting and formatting:")}\n${pc.cyan("•")} Format and lint fix: ${`${runCmd} check`}\n`;
|
|
7980
8108
|
}
|
|
7981
|
-
function getDatabaseInstructions(database, orm, runCmd, runtime, dbSetup) {
|
|
8109
|
+
async function getDatabaseInstructions(database, orm, runCmd, runtime, dbSetup) {
|
|
7982
8110
|
const instructions = [];
|
|
8111
|
+
if (dbSetup === "docker") {
|
|
8112
|
+
const dockerStatus = await getDockerStatus(database);
|
|
8113
|
+
if (dockerStatus.message) {
|
|
8114
|
+
instructions.push(dockerStatus.message);
|
|
8115
|
+
instructions.push("");
|
|
8116
|
+
}
|
|
8117
|
+
}
|
|
7983
8118
|
if (runtime === "workers" && dbSetup === "d1") {
|
|
7984
8119
|
const packageManager = runCmd === "npm run" ? "npm" : runCmd || "npm";
|
|
7985
8120
|
instructions.push(`${pc.cyan("1.")} Login to Cloudflare: ${pc.white(`${packageManager} wrangler login`)}`);
|
|
@@ -7993,12 +8128,17 @@ function getDatabaseInstructions(database, orm, runCmd, runtime, dbSetup) {
|
|
|
7993
8128
|
if (orm === "prisma") {
|
|
7994
8129
|
if (database === "sqlite") instructions.push(`${pc.yellow("NOTE:")} Turso support with Prisma is in Early Access and requires additional setup.`, `Learn more at: https://www.prisma.io/docs/orm/overview/databases/turso`);
|
|
7995
8130
|
if (runtime === "bun") instructions.push(`${pc.yellow("NOTE:")} Prisma with Bun may require additional configuration. If you encounter errors,\nfollow the guidance provided in the error messages`);
|
|
8131
|
+
if (database === "mongodb" && dbSetup === "docker") instructions.push(`${pc.yellow("WARNING:")} Prisma + MongoDB + Docker combination may not work.`);
|
|
8132
|
+
if (dbSetup === "docker") instructions.push(`${pc.cyan("•")} Start docker container: ${`${runCmd} db:start`}`);
|
|
7996
8133
|
instructions.push(`${pc.cyan("•")} Apply schema: ${`${runCmd} db:push`}`);
|
|
7997
8134
|
instructions.push(`${pc.cyan("•")} Database UI: ${`${runCmd} db:studio`}`);
|
|
7998
8135
|
} else if (orm === "drizzle") {
|
|
8136
|
+
if (dbSetup === "docker") instructions.push(`${pc.cyan("•")} Start docker container: ${`${runCmd} db:start`}`);
|
|
7999
8137
|
instructions.push(`${pc.cyan("•")} Apply schema: ${`${runCmd} db:push`}`);
|
|
8000
8138
|
instructions.push(`${pc.cyan("•")} Database UI: ${`${runCmd} db:studio`}`);
|
|
8001
8139
|
if (database === "sqlite" && dbSetup !== "d1") instructions.push(`${pc.cyan("•")} Start local DB (if needed): ${`cd apps/server && ${runCmd} db:local`}`);
|
|
8140
|
+
} else if (orm === "mongoose") {
|
|
8141
|
+
if (dbSetup === "docker") instructions.push(`${pc.cyan("•")} Start docker container: ${`${runCmd} db:start`}`);
|
|
8002
8142
|
} else if (orm === "none") instructions.push(`${pc.yellow("NOTE:")} Manual database schema setup required.`);
|
|
8003
8143
|
return instructions.length ? `${pc.bold("Database commands:")}\n${instructions.join("\n")}` : "";
|
|
8004
8144
|
}
|
|
@@ -8065,6 +8205,12 @@ async function updateRootPackageJson(projectDir, options) {
|
|
|
8065
8205
|
scripts["db:migrate"] = `turbo -F ${backendPackageName} db:migrate`;
|
|
8066
8206
|
}
|
|
8067
8207
|
}
|
|
8208
|
+
if (options.dbSetup === "docker") {
|
|
8209
|
+
scripts["db:start"] = `turbo -F ${backendPackageName} db:start`;
|
|
8210
|
+
scripts["db:watch"] = `turbo -F ${backendPackageName} db:watch`;
|
|
8211
|
+
scripts["db:stop"] = `turbo -F ${backendPackageName} db:stop`;
|
|
8212
|
+
scripts["db:down"] = `turbo -F ${backendPackageName} db:down`;
|
|
8213
|
+
}
|
|
8068
8214
|
} else if (options.packageManager === "pnpm") {
|
|
8069
8215
|
scripts.dev = devScript;
|
|
8070
8216
|
scripts.build = "pnpm -r build";
|
|
@@ -8084,6 +8230,12 @@ async function updateRootPackageJson(projectDir, options) {
|
|
|
8084
8230
|
scripts["db:migrate"] = `pnpm --filter ${backendPackageName} db:migrate`;
|
|
8085
8231
|
}
|
|
8086
8232
|
}
|
|
8233
|
+
if (options.dbSetup === "docker") {
|
|
8234
|
+
scripts["db:start"] = `pnpm --filter ${backendPackageName} db:start`;
|
|
8235
|
+
scripts["db:watch"] = `pnpm --filter ${backendPackageName} db:watch`;
|
|
8236
|
+
scripts["db:stop"] = `pnpm --filter ${backendPackageName} db:stop`;
|
|
8237
|
+
scripts["db:down"] = `pnpm --filter ${backendPackageName} db:down`;
|
|
8238
|
+
}
|
|
8087
8239
|
} else if (options.packageManager === "npm") {
|
|
8088
8240
|
scripts.dev = devScript;
|
|
8089
8241
|
scripts.build = "npm run build --workspaces";
|
|
@@ -8103,6 +8255,12 @@ async function updateRootPackageJson(projectDir, options) {
|
|
|
8103
8255
|
scripts["db:migrate"] = `npm run db:migrate --workspace ${backendPackageName}`;
|
|
8104
8256
|
}
|
|
8105
8257
|
}
|
|
8258
|
+
if (options.dbSetup === "docker") {
|
|
8259
|
+
scripts["db:start"] = `npm run db:start --workspace ${backendPackageName}`;
|
|
8260
|
+
scripts["db:watch"] = `npm run db:watch --workspace ${backendPackageName}`;
|
|
8261
|
+
scripts["db:stop"] = `npm run db:stop --workspace ${backendPackageName}`;
|
|
8262
|
+
scripts["db:down"] = `npm run db:down --workspace ${backendPackageName}`;
|
|
8263
|
+
}
|
|
8106
8264
|
} else if (options.packageManager === "bun") {
|
|
8107
8265
|
scripts.dev = devScript;
|
|
8108
8266
|
scripts.build = "bun run --filter '*' build";
|
|
@@ -8122,6 +8280,12 @@ async function updateRootPackageJson(projectDir, options) {
|
|
|
8122
8280
|
scripts["db:migrate"] = `bun run --filter ${backendPackageName} db:migrate`;
|
|
8123
8281
|
}
|
|
8124
8282
|
}
|
|
8283
|
+
if (options.dbSetup === "docker") {
|
|
8284
|
+
scripts["db:start"] = `bun run --filter ${backendPackageName} db:start`;
|
|
8285
|
+
scripts["db:watch"] = `bun run --filter ${backendPackageName} db:watch`;
|
|
8286
|
+
scripts["db:stop"] = `bun run --filter ${backendPackageName} db:stop`;
|
|
8287
|
+
scripts["db:down"] = `bun run --filter ${backendPackageName} db:down`;
|
|
8288
|
+
}
|
|
8125
8289
|
}
|
|
8126
8290
|
if (options.addons.includes("biome")) scripts.check = "biome check --write .";
|
|
8127
8291
|
if (options.addons.includes("husky")) {
|
|
@@ -8166,6 +8330,12 @@ async function updateServerPackageJson(projectDir, options) {
|
|
|
8166
8330
|
scripts["db:migrate"] = "drizzle-kit migrate";
|
|
8167
8331
|
}
|
|
8168
8332
|
}
|
|
8333
|
+
if (options.dbSetup === "docker") {
|
|
8334
|
+
scripts["db:start"] = "docker compose up -d";
|
|
8335
|
+
scripts["db:watch"] = "docker compose up";
|
|
8336
|
+
scripts["db:stop"] = "docker compose stop";
|
|
8337
|
+
scripts["db:down"] = "docker compose down";
|
|
8338
|
+
}
|
|
8169
8339
|
await fs.writeJson(serverPackageJsonPath, serverPackageJson, { spaces: 2 });
|
|
8170
8340
|
}
|
|
8171
8341
|
async function updateConvexPackageJson(projectDir, options) {
|
|
@@ -8189,6 +8359,7 @@ async function createProject(options) {
|
|
|
8189
8359
|
await setupBackendFramework(projectDir, options);
|
|
8190
8360
|
if (!isConvex) {
|
|
8191
8361
|
await setupDbOrmTemplates(projectDir, options);
|
|
8362
|
+
await setupDockerComposeTemplates(projectDir, options);
|
|
8192
8363
|
await setupAuthTemplate(projectDir, options);
|
|
8193
8364
|
}
|
|
8194
8365
|
if (options.examples.length > 0 && options.examples[0] !== "none") await setupExamplesTemplate(projectDir, options);
|
|
@@ -8218,7 +8389,7 @@ async function createProject(options) {
|
|
|
8218
8389
|
await generateCloudflareWorkerTypes(options);
|
|
8219
8390
|
}
|
|
8220
8391
|
await initializeGit(projectDir, options.git);
|
|
8221
|
-
displayPostInstallInstructions({
|
|
8392
|
+
await displayPostInstallInstructions({
|
|
8222
8393
|
...options,
|
|
8223
8394
|
depsInstalled: options.install
|
|
8224
8395
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-better-t-stack",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.25.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
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -39,5 +39,23 @@
|
|
|
39
39
|
"persistent": true
|
|
40
40
|
}
|
|
41
41
|
{{/unless}}{{/if}}
|
|
42
|
+
{{#if (eq dbSetup "docker")}},
|
|
43
|
+
"db:start": {
|
|
44
|
+
"cache": false,
|
|
45
|
+
"persistent": true
|
|
46
|
+
},
|
|
47
|
+
"db:stop": {
|
|
48
|
+
"cache": false,
|
|
49
|
+
"persistent": true
|
|
50
|
+
},
|
|
51
|
+
"db:watch": {
|
|
52
|
+
"cache": false,
|
|
53
|
+
"persistent": true
|
|
54
|
+
},
|
|
55
|
+
"db:down": {
|
|
56
|
+
"cache": false,
|
|
57
|
+
"persistent": true
|
|
58
|
+
}
|
|
59
|
+
{{/if}}
|
|
42
60
|
}
|
|
43
61
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
name: {{projectName}}
|
|
2
|
+
|
|
3
|
+
services:
|
|
4
|
+
mongodb:
|
|
5
|
+
image: mongo
|
|
6
|
+
container_name: {{projectName}}-mongodb
|
|
7
|
+
environment:
|
|
8
|
+
MONGO_INITDB_ROOT_USERNAME: root
|
|
9
|
+
MONGO_INITDB_ROOT_PASSWORD: password
|
|
10
|
+
MONGO_INITDB_DATABASE: {{projectName}}
|
|
11
|
+
ports:
|
|
12
|
+
- "27017:27017"
|
|
13
|
+
volumes:
|
|
14
|
+
- {{projectName}}_mongodb_data:/data/db
|
|
15
|
+
healthcheck:
|
|
16
|
+
test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
|
|
17
|
+
interval: 10s
|
|
18
|
+
timeout: 5s
|
|
19
|
+
retries: 5
|
|
20
|
+
restart: unless-stopped
|
|
21
|
+
|
|
22
|
+
volumes:
|
|
23
|
+
{{projectName}}_mongodb_data:
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
name: {{projectName}}
|
|
2
|
+
|
|
3
|
+
services:
|
|
4
|
+
mysql:
|
|
5
|
+
image: mysql
|
|
6
|
+
container_name: {{projectName}}-mysql
|
|
7
|
+
environment:
|
|
8
|
+
MYSQL_ROOT_PASSWORD: password
|
|
9
|
+
MYSQL_DATABASE: {{projectName}}
|
|
10
|
+
MYSQL_USER: user
|
|
11
|
+
MYSQL_PASSWORD: password
|
|
12
|
+
ports:
|
|
13
|
+
- "3306:3306"
|
|
14
|
+
volumes:
|
|
15
|
+
- {{projectName}}_mysql_data:/var/lib/mysql
|
|
16
|
+
healthcheck:
|
|
17
|
+
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
|
|
18
|
+
interval: 10s
|
|
19
|
+
timeout: 5s
|
|
20
|
+
retries: 5
|
|
21
|
+
restart: unless-stopped
|
|
22
|
+
|
|
23
|
+
volumes:
|
|
24
|
+
{{projectName}}_mysql_data:
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
name: {{projectName}}
|
|
2
|
+
|
|
3
|
+
services:
|
|
4
|
+
postgres:
|
|
5
|
+
image: postgres
|
|
6
|
+
container_name: {{projectName}}-postgres
|
|
7
|
+
environment:
|
|
8
|
+
POSTGRES_DB: {{projectName}}
|
|
9
|
+
POSTGRES_USER: postgres
|
|
10
|
+
POSTGRES_PASSWORD: password
|
|
11
|
+
ports:
|
|
12
|
+
- "5432:5432"
|
|
13
|
+
volumes:
|
|
14
|
+
- {{projectName}}_postgres_data:/var/lib/postgresql/data
|
|
15
|
+
healthcheck:
|
|
16
|
+
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
|
17
|
+
interval: 10s
|
|
18
|
+
timeout: 5s
|
|
19
|
+
retries: 5
|
|
20
|
+
restart: unless-stopped
|
|
21
|
+
|
|
22
|
+
volumes:
|
|
23
|
+
{{projectName}}_postgres_data:
|