create-better-t-stack 2.19.0 → 2.20.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 +173 -173
- package/package.json +1 -1
- package/templates/addons/biome/biome.json.hbs +83 -0
- package/templates/auth/web/solid/src/components/{user-menu.tsx → user-menu.tsx.hbs} +1 -0
- package/templates/runtime/workers/apps/server/wrangler.jsonc.hbs +18 -0
- package/templates/addons/biome/biome.json +0 -52
- package/templates/runtime/workers/apps/server/wrangler.toml.hbs +0 -18
package/dist/index.js
CHANGED
|
@@ -60,7 +60,7 @@ const dependencyVersionMap = {
|
|
|
60
60
|
"vite-plugin-pwa": "^0.21.2",
|
|
61
61
|
"@vite-pwa/assets-generator": "^0.2.6",
|
|
62
62
|
"@tauri-apps/cli": "^2.4.0",
|
|
63
|
-
"@biomejs/biome": "
|
|
63
|
+
"@biomejs/biome": "^2.0.0",
|
|
64
64
|
husky: "^9.1.7",
|
|
65
65
|
"lint-staged": "^15.5.0",
|
|
66
66
|
"@hono/node-server": "^1.14.0",
|
|
@@ -885,6 +885,163 @@ async function setupMongoDBAtlas(config) {
|
|
|
885
885
|
}
|
|
886
886
|
}
|
|
887
887
|
|
|
888
|
+
//#endregion
|
|
889
|
+
//#region src/helpers/database-providers/neon-setup.ts
|
|
890
|
+
const NEON_REGIONS = [
|
|
891
|
+
{
|
|
892
|
+
label: "AWS US East (N. Virginia)",
|
|
893
|
+
value: "aws-us-east-1"
|
|
894
|
+
},
|
|
895
|
+
{
|
|
896
|
+
label: "AWS US East (Ohio)",
|
|
897
|
+
value: "aws-us-east-2"
|
|
898
|
+
},
|
|
899
|
+
{
|
|
900
|
+
label: "AWS US West (Oregon)",
|
|
901
|
+
value: "aws-us-west-2"
|
|
902
|
+
},
|
|
903
|
+
{
|
|
904
|
+
label: "AWS Europe (Frankfurt)",
|
|
905
|
+
value: "aws-eu-central-1"
|
|
906
|
+
},
|
|
907
|
+
{
|
|
908
|
+
label: "AWS Asia Pacific (Singapore)",
|
|
909
|
+
value: "aws-ap-southeast-1"
|
|
910
|
+
},
|
|
911
|
+
{
|
|
912
|
+
label: "AWS Asia Pacific (Sydney)",
|
|
913
|
+
value: "aws-ap-southeast-2"
|
|
914
|
+
},
|
|
915
|
+
{
|
|
916
|
+
label: "Azure East US 2 region (Virginia)",
|
|
917
|
+
value: "azure-eastus2"
|
|
918
|
+
}
|
|
919
|
+
];
|
|
920
|
+
async function executeNeonCommand(packageManager, commandArgsString, spinnerText) {
|
|
921
|
+
const s = spinner();
|
|
922
|
+
try {
|
|
923
|
+
const fullCommand = getPackageExecutionCommand(packageManager, commandArgsString);
|
|
924
|
+
if (spinnerText) s.start(spinnerText);
|
|
925
|
+
const result = await execa(fullCommand, { shell: true });
|
|
926
|
+
if (spinnerText) s.stop(pc.green(spinnerText.replace("...", "").replace("ing ", "ed ").trim()));
|
|
927
|
+
return result;
|
|
928
|
+
} catch (error) {
|
|
929
|
+
if (s) s.stop(pc.red(`Failed: ${spinnerText || "Command execution"}`));
|
|
930
|
+
throw error;
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
async function createNeonProject(projectName, regionId, packageManager) {
|
|
934
|
+
try {
|
|
935
|
+
const commandArgsString = `neonctl projects create --name ${projectName} --region-id ${regionId} --output json`;
|
|
936
|
+
const { stdout } = await executeNeonCommand(packageManager, commandArgsString, `Creating Neon project "${projectName}"...`);
|
|
937
|
+
const response = JSON.parse(stdout);
|
|
938
|
+
if (response.project && response.connection_uris && response.connection_uris.length > 0) {
|
|
939
|
+
const projectId = response.project.id;
|
|
940
|
+
const connectionUri = response.connection_uris[0].connection_uri;
|
|
941
|
+
const params = response.connection_uris[0].connection_parameters;
|
|
942
|
+
return {
|
|
943
|
+
connectionString: connectionUri,
|
|
944
|
+
projectId,
|
|
945
|
+
dbName: params.database,
|
|
946
|
+
roleName: params.role
|
|
947
|
+
};
|
|
948
|
+
}
|
|
949
|
+
consola$1.error(pc.red("Failed to extract connection information from response"));
|
|
950
|
+
return null;
|
|
951
|
+
} catch (_error) {
|
|
952
|
+
consola$1.error(pc.red("Failed to create Neon project"));
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
async function writeEnvFile$2(projectDir, config) {
|
|
956
|
+
const envPath = path.join(projectDir, "apps/server", ".env");
|
|
957
|
+
const variables = [{
|
|
958
|
+
key: "DATABASE_URL",
|
|
959
|
+
value: config?.connectionString ?? "postgresql://postgres:postgres@localhost:5432/mydb?schema=public",
|
|
960
|
+
condition: true
|
|
961
|
+
}];
|
|
962
|
+
await addEnvVariablesToFile(envPath, variables);
|
|
963
|
+
return true;
|
|
964
|
+
}
|
|
965
|
+
async function setupWithNeonDb(projectDir, packageManager) {
|
|
966
|
+
try {
|
|
967
|
+
const s = spinner();
|
|
968
|
+
s.start("Creating Neon database using neondb...");
|
|
969
|
+
const serverDir = path.join(projectDir, "apps/server");
|
|
970
|
+
await fs.ensureDir(serverDir);
|
|
971
|
+
const packageCmd = getPackageExecutionCommand(packageManager, "neondb --yes");
|
|
972
|
+
await execa(packageCmd, {
|
|
973
|
+
shell: true,
|
|
974
|
+
cwd: serverDir
|
|
975
|
+
});
|
|
976
|
+
s.stop(pc.green("Neon database created successfully!"));
|
|
977
|
+
return true;
|
|
978
|
+
} catch (error) {
|
|
979
|
+
consola$1.error(pc.red("Failed to create database with neondb"));
|
|
980
|
+
throw error;
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
function displayManualSetupInstructions$2() {
|
|
984
|
+
log.info(`Manual Neon PostgreSQL Setup Instructions:
|
|
985
|
+
|
|
986
|
+
1. Visit https://neon.tech and create an account
|
|
987
|
+
2. Create a new project from the dashboard
|
|
988
|
+
3. Get your connection string
|
|
989
|
+
4. Add the database URL to the .env file in apps/server/.env
|
|
990
|
+
|
|
991
|
+
DATABASE_URL="your_connection_string"`);
|
|
992
|
+
}
|
|
993
|
+
async function setupNeonPostgres(config) {
|
|
994
|
+
const { packageManager, projectDir } = config;
|
|
995
|
+
try {
|
|
996
|
+
const setupMethod = await select({
|
|
997
|
+
message: "Choose your Neon setup method:",
|
|
998
|
+
options: [{
|
|
999
|
+
label: "Quick setup with neondb",
|
|
1000
|
+
value: "neondb",
|
|
1001
|
+
hint: "fastest, no auth required"
|
|
1002
|
+
}, {
|
|
1003
|
+
label: "Custom setup with neonctl",
|
|
1004
|
+
value: "neonctl",
|
|
1005
|
+
hint: "More control - choose project name and region"
|
|
1006
|
+
}],
|
|
1007
|
+
initialValue: "neondb"
|
|
1008
|
+
});
|
|
1009
|
+
if (isCancel(setupMethod)) {
|
|
1010
|
+
cancel(pc.red("Operation cancelled"));
|
|
1011
|
+
process.exit(0);
|
|
1012
|
+
}
|
|
1013
|
+
if (setupMethod === "neondb") await setupWithNeonDb(projectDir, packageManager);
|
|
1014
|
+
else {
|
|
1015
|
+
const suggestedProjectName = path.basename(projectDir);
|
|
1016
|
+
const projectName = await text({
|
|
1017
|
+
message: "Enter a name for your Neon project:",
|
|
1018
|
+
defaultValue: suggestedProjectName,
|
|
1019
|
+
initialValue: suggestedProjectName
|
|
1020
|
+
});
|
|
1021
|
+
const regionId = await select({
|
|
1022
|
+
message: "Select a region for your Neon project:",
|
|
1023
|
+
options: NEON_REGIONS,
|
|
1024
|
+
initialValue: NEON_REGIONS[0].value
|
|
1025
|
+
});
|
|
1026
|
+
if (isCancel(projectName) || isCancel(regionId)) {
|
|
1027
|
+
cancel(pc.red("Operation cancelled"));
|
|
1028
|
+
process.exit(0);
|
|
1029
|
+
}
|
|
1030
|
+
const neonConfig = await createNeonProject(projectName, regionId, packageManager);
|
|
1031
|
+
if (!neonConfig) throw new Error("Failed to create project - couldn't get connection information");
|
|
1032
|
+
const finalSpinner = spinner();
|
|
1033
|
+
finalSpinner.start("Configuring database connection");
|
|
1034
|
+
await fs.ensureDir(path.join(projectDir, "apps/server"));
|
|
1035
|
+
await writeEnvFile$2(projectDir, neonConfig);
|
|
1036
|
+
finalSpinner.stop("Neon database configured!");
|
|
1037
|
+
}
|
|
1038
|
+
} catch (error) {
|
|
1039
|
+
if (error instanceof Error) consola$1.error(pc.red(error.message));
|
|
1040
|
+
await writeEnvFile$2(projectDir);
|
|
1041
|
+
displayManualSetupInstructions$2();
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
|
|
888
1045
|
//#endregion
|
|
889
1046
|
//#region src/helpers/database-providers/prisma-postgres-setup.ts
|
|
890
1047
|
async function initPrismaDatabase(serverDir, packageManager) {
|
|
@@ -919,7 +1076,7 @@ async function initPrismaDatabase(serverDir, packageManager) {
|
|
|
919
1076
|
return null;
|
|
920
1077
|
}
|
|
921
1078
|
}
|
|
922
|
-
async function writeEnvFile$
|
|
1079
|
+
async function writeEnvFile$1(projectDir, config) {
|
|
923
1080
|
try {
|
|
924
1081
|
const envPath = path.join(projectDir, "apps/server", ".env");
|
|
925
1082
|
const variables = [{
|
|
@@ -932,7 +1089,7 @@ async function writeEnvFile$2(projectDir, config) {
|
|
|
932
1089
|
consola$1.error("Failed to update environment configuration");
|
|
933
1090
|
}
|
|
934
1091
|
}
|
|
935
|
-
function displayManualSetupInstructions$
|
|
1092
|
+
function displayManualSetupInstructions$1() {
|
|
936
1093
|
log.info(`Manual Prisma PostgreSQL Setup Instructions:
|
|
937
1094
|
|
|
938
1095
|
1. Visit https://console.prisma.io and create an account
|
|
@@ -983,23 +1140,23 @@ async function setupPrismaPostgres(config) {
|
|
|
983
1140
|
s.stop("Prisma PostgreSQL setup ready");
|
|
984
1141
|
const config$1 = await initPrismaDatabase(serverDir, packageManager);
|
|
985
1142
|
if (config$1) {
|
|
986
|
-
await writeEnvFile$
|
|
1143
|
+
await writeEnvFile$1(projectDir, config$1);
|
|
987
1144
|
await addPrismaAccelerateExtension(serverDir);
|
|
988
1145
|
log.success(pc.green("Prisma PostgreSQL database configured successfully!"));
|
|
989
1146
|
log.info(pc.cyan("NOTE: Make sure to uncomment `import \"dotenv/config\";` in `apps/server/src/prisma.config.ts` to load environment variables."));
|
|
990
1147
|
} else {
|
|
991
1148
|
const fallbackSpinner = spinner();
|
|
992
1149
|
fallbackSpinner.start("Setting up fallback configuration...");
|
|
993
|
-
await writeEnvFile$
|
|
1150
|
+
await writeEnvFile$1(projectDir);
|
|
994
1151
|
fallbackSpinner.stop("Fallback configuration ready");
|
|
995
|
-
displayManualSetupInstructions$
|
|
1152
|
+
displayManualSetupInstructions$1();
|
|
996
1153
|
}
|
|
997
1154
|
} catch (error) {
|
|
998
1155
|
s.stop(pc.red("Prisma PostgreSQL setup failed"));
|
|
999
1156
|
consola$1.error(pc.red(`Error during Prisma PostgreSQL setup: ${error instanceof Error ? error.message : String(error)}`));
|
|
1000
1157
|
try {
|
|
1001
|
-
await writeEnvFile$
|
|
1002
|
-
displayManualSetupInstructions$
|
|
1158
|
+
await writeEnvFile$1(projectDir);
|
|
1159
|
+
displayManualSetupInstructions$1();
|
|
1003
1160
|
} catch {}
|
|
1004
1161
|
log.info("Setup completed with manual configuration required.");
|
|
1005
1162
|
}
|
|
@@ -1246,7 +1403,7 @@ async function createTursoDatabase(dbName, groupName) {
|
|
|
1246
1403
|
s.stop(pc.red("Failed to retrieve database connection details"));
|
|
1247
1404
|
}
|
|
1248
1405
|
}
|
|
1249
|
-
async function writeEnvFile
|
|
1406
|
+
async function writeEnvFile(projectDir, config) {
|
|
1250
1407
|
const envPath = path.join(projectDir, "apps/server", ".env");
|
|
1251
1408
|
const variables = [{
|
|
1252
1409
|
key: "DATABASE_URL",
|
|
@@ -1259,7 +1416,7 @@ async function writeEnvFile$1(projectDir, config) {
|
|
|
1259
1416
|
}];
|
|
1260
1417
|
await addEnvVariablesToFile(envPath, variables);
|
|
1261
1418
|
}
|
|
1262
|
-
function displayManualSetupInstructions
|
|
1419
|
+
function displayManualSetupInstructions() {
|
|
1263
1420
|
log.info(`Manual Turso Setup Instructions:
|
|
1264
1421
|
|
|
1265
1422
|
1. Visit https://turso.tech and create an account
|
|
@@ -1283,8 +1440,8 @@ async function setupTurso(config) {
|
|
|
1283
1440
|
if (isWindows) {
|
|
1284
1441
|
setupSpinner.stop(pc.yellow("Turso setup not supported on Windows"));
|
|
1285
1442
|
log.warn(pc.yellow("Automatic Turso setup is not supported on Windows."));
|
|
1286
|
-
await writeEnvFile
|
|
1287
|
-
displayManualSetupInstructions
|
|
1443
|
+
await writeEnvFile(projectDir);
|
|
1444
|
+
displayManualSetupInstructions();
|
|
1288
1445
|
return;
|
|
1289
1446
|
}
|
|
1290
1447
|
setupSpinner.stop("Turso CLI availability checked");
|
|
@@ -1299,8 +1456,8 @@ async function setupTurso(config) {
|
|
|
1299
1456
|
process.exit(0);
|
|
1300
1457
|
}
|
|
1301
1458
|
if (!shouldInstall) {
|
|
1302
|
-
await writeEnvFile
|
|
1303
|
-
displayManualSetupInstructions
|
|
1459
|
+
await writeEnvFile(projectDir);
|
|
1460
|
+
displayManualSetupInstructions();
|
|
1304
1461
|
return;
|
|
1305
1462
|
}
|
|
1306
1463
|
await installTursoCLI(isMac);
|
|
@@ -1325,7 +1482,7 @@ async function setupTurso(config) {
|
|
|
1325
1482
|
dbName = dbNameResponse;
|
|
1326
1483
|
try {
|
|
1327
1484
|
const config$1 = await createTursoDatabase(dbName, selectedGroup);
|
|
1328
|
-
await writeEnvFile
|
|
1485
|
+
await writeEnvFile(projectDir, config$1);
|
|
1329
1486
|
success = true;
|
|
1330
1487
|
} catch (error) {
|
|
1331
1488
|
if (error instanceof Error && error.message === "DATABASE_EXISTS") {
|
|
@@ -1338,166 +1495,9 @@ async function setupTurso(config) {
|
|
|
1338
1495
|
} catch (error) {
|
|
1339
1496
|
setupSpinner.stop(pc.red("Turso CLI availability check failed"));
|
|
1340
1497
|
consola.error(pc.red(`Error during Turso setup: ${error instanceof Error ? error.message : String(error)}`));
|
|
1341
|
-
await writeEnvFile$1(projectDir);
|
|
1342
|
-
displayManualSetupInstructions$1();
|
|
1343
|
-
log.success("Setup completed with manual configuration required.");
|
|
1344
|
-
}
|
|
1345
|
-
}
|
|
1346
|
-
|
|
1347
|
-
//#endregion
|
|
1348
|
-
//#region src/helpers/database-providers/neon-setup.ts
|
|
1349
|
-
const NEON_REGIONS = [
|
|
1350
|
-
{
|
|
1351
|
-
label: "AWS US East (N. Virginia)",
|
|
1352
|
-
value: "aws-us-east-1"
|
|
1353
|
-
},
|
|
1354
|
-
{
|
|
1355
|
-
label: "AWS US East (Ohio)",
|
|
1356
|
-
value: "aws-us-east-2"
|
|
1357
|
-
},
|
|
1358
|
-
{
|
|
1359
|
-
label: "AWS US West (Oregon)",
|
|
1360
|
-
value: "aws-us-west-2"
|
|
1361
|
-
},
|
|
1362
|
-
{
|
|
1363
|
-
label: "AWS Europe (Frankfurt)",
|
|
1364
|
-
value: "aws-eu-central-1"
|
|
1365
|
-
},
|
|
1366
|
-
{
|
|
1367
|
-
label: "AWS Asia Pacific (Singapore)",
|
|
1368
|
-
value: "aws-ap-southeast-1"
|
|
1369
|
-
},
|
|
1370
|
-
{
|
|
1371
|
-
label: "AWS Asia Pacific (Sydney)",
|
|
1372
|
-
value: "aws-ap-southeast-2"
|
|
1373
|
-
},
|
|
1374
|
-
{
|
|
1375
|
-
label: "Azure East US 2 region (Virginia)",
|
|
1376
|
-
value: "azure-eastus2"
|
|
1377
|
-
}
|
|
1378
|
-
];
|
|
1379
|
-
async function executeNeonCommand(packageManager, commandArgsString, spinnerText) {
|
|
1380
|
-
const s = spinner();
|
|
1381
|
-
try {
|
|
1382
|
-
const fullCommand = getPackageExecutionCommand(packageManager, commandArgsString);
|
|
1383
|
-
if (spinnerText) s.start(spinnerText);
|
|
1384
|
-
const result = await execa(fullCommand, { shell: true });
|
|
1385
|
-
if (spinnerText) s.stop(pc.green(spinnerText.replace("...", "").replace("ing ", "ed ").trim()));
|
|
1386
|
-
return result;
|
|
1387
|
-
} catch (error) {
|
|
1388
|
-
if (s) s.stop(pc.red(`Failed: ${spinnerText || "Command execution"}`));
|
|
1389
|
-
throw error;
|
|
1390
|
-
}
|
|
1391
|
-
}
|
|
1392
|
-
async function createNeonProject(projectName, regionId, packageManager) {
|
|
1393
|
-
try {
|
|
1394
|
-
const commandArgsString = `neonctl projects create --name ${projectName} --region-id ${regionId} --output json`;
|
|
1395
|
-
const { stdout } = await executeNeonCommand(packageManager, commandArgsString, `Creating Neon project "${projectName}"...`);
|
|
1396
|
-
const response = JSON.parse(stdout);
|
|
1397
|
-
if (response.project && response.connection_uris && response.connection_uris.length > 0) {
|
|
1398
|
-
const projectId = response.project.id;
|
|
1399
|
-
const connectionUri = response.connection_uris[0].connection_uri;
|
|
1400
|
-
const params = response.connection_uris[0].connection_parameters;
|
|
1401
|
-
return {
|
|
1402
|
-
connectionString: connectionUri,
|
|
1403
|
-
projectId,
|
|
1404
|
-
dbName: params.database,
|
|
1405
|
-
roleName: params.role
|
|
1406
|
-
};
|
|
1407
|
-
}
|
|
1408
|
-
consola$1.error(pc.red("Failed to extract connection information from response"));
|
|
1409
|
-
return null;
|
|
1410
|
-
} catch (_error) {
|
|
1411
|
-
consola$1.error(pc.red("Failed to create Neon project"));
|
|
1412
|
-
}
|
|
1413
|
-
}
|
|
1414
|
-
async function writeEnvFile(projectDir, config) {
|
|
1415
|
-
const envPath = path.join(projectDir, "apps/server", ".env");
|
|
1416
|
-
const variables = [{
|
|
1417
|
-
key: "DATABASE_URL",
|
|
1418
|
-
value: config?.connectionString ?? "postgresql://postgres:postgres@localhost:5432/mydb?schema=public",
|
|
1419
|
-
condition: true
|
|
1420
|
-
}];
|
|
1421
|
-
await addEnvVariablesToFile(envPath, variables);
|
|
1422
|
-
return true;
|
|
1423
|
-
}
|
|
1424
|
-
async function setupWithNeonDb(projectDir, packageManager) {
|
|
1425
|
-
try {
|
|
1426
|
-
const s = spinner();
|
|
1427
|
-
s.start("Creating Neon database using neondb...");
|
|
1428
|
-
const serverDir = path.join(projectDir, "apps/server");
|
|
1429
|
-
await fs.ensureDir(serverDir);
|
|
1430
|
-
const packageCmd = getPackageExecutionCommand(packageManager, "neondb --yes");
|
|
1431
|
-
await execa(packageCmd, {
|
|
1432
|
-
shell: true,
|
|
1433
|
-
cwd: serverDir
|
|
1434
|
-
});
|
|
1435
|
-
s.stop(pc.green("Neon database created successfully!"));
|
|
1436
|
-
return true;
|
|
1437
|
-
} catch (error) {
|
|
1438
|
-
consola$1.error(pc.red("Failed to create database with neondb"));
|
|
1439
|
-
throw error;
|
|
1440
|
-
}
|
|
1441
|
-
}
|
|
1442
|
-
function displayManualSetupInstructions() {
|
|
1443
|
-
log.info(`Manual Neon PostgreSQL Setup Instructions:
|
|
1444
|
-
|
|
1445
|
-
1. Visit https://neon.tech and create an account
|
|
1446
|
-
2. Create a new project from the dashboard
|
|
1447
|
-
3. Get your connection string
|
|
1448
|
-
4. Add the database URL to the .env file in apps/server/.env
|
|
1449
|
-
|
|
1450
|
-
DATABASE_URL="your_connection_string"`);
|
|
1451
|
-
}
|
|
1452
|
-
async function setupNeonPostgres(config) {
|
|
1453
|
-
const { packageManager, projectDir } = config;
|
|
1454
|
-
try {
|
|
1455
|
-
const setupMethod = await select({
|
|
1456
|
-
message: "Choose your Neon setup method:",
|
|
1457
|
-
options: [{
|
|
1458
|
-
label: "Quick setup with neondb",
|
|
1459
|
-
value: "neondb",
|
|
1460
|
-
hint: "fastest, no auth required"
|
|
1461
|
-
}, {
|
|
1462
|
-
label: "Custom setup with neonctl",
|
|
1463
|
-
value: "neonctl",
|
|
1464
|
-
hint: "More control - choose project name and region"
|
|
1465
|
-
}],
|
|
1466
|
-
initialValue: "neondb"
|
|
1467
|
-
});
|
|
1468
|
-
if (isCancel(setupMethod)) {
|
|
1469
|
-
cancel(pc.red("Operation cancelled"));
|
|
1470
|
-
process.exit(0);
|
|
1471
|
-
}
|
|
1472
|
-
if (setupMethod === "neondb") await setupWithNeonDb(projectDir, packageManager);
|
|
1473
|
-
else {
|
|
1474
|
-
const suggestedProjectName = path.basename(projectDir);
|
|
1475
|
-
const projectName = await text({
|
|
1476
|
-
message: "Enter a name for your Neon project:",
|
|
1477
|
-
defaultValue: suggestedProjectName,
|
|
1478
|
-
initialValue: suggestedProjectName
|
|
1479
|
-
});
|
|
1480
|
-
const regionId = await select({
|
|
1481
|
-
message: "Select a region for your Neon project:",
|
|
1482
|
-
options: NEON_REGIONS,
|
|
1483
|
-
initialValue: NEON_REGIONS[0].value
|
|
1484
|
-
});
|
|
1485
|
-
if (isCancel(projectName) || isCancel(regionId)) {
|
|
1486
|
-
cancel(pc.red("Operation cancelled"));
|
|
1487
|
-
process.exit(0);
|
|
1488
|
-
}
|
|
1489
|
-
const neonConfig = await createNeonProject(projectName, regionId, packageManager);
|
|
1490
|
-
if (!neonConfig) throw new Error("Failed to create project - couldn't get connection information");
|
|
1491
|
-
const finalSpinner = spinner();
|
|
1492
|
-
finalSpinner.start("Configuring database connection");
|
|
1493
|
-
await fs.ensureDir(path.join(projectDir, "apps/server"));
|
|
1494
|
-
await writeEnvFile(projectDir, neonConfig);
|
|
1495
|
-
finalSpinner.stop("Neon database configured!");
|
|
1496
|
-
}
|
|
1497
|
-
} catch (error) {
|
|
1498
|
-
if (error instanceof Error) consola$1.error(pc.red(error.message));
|
|
1499
1498
|
await writeEnvFile(projectDir);
|
|
1500
1499
|
displayManualSetupInstructions();
|
|
1500
|
+
log.success("Setup completed with manual configuration required.");
|
|
1501
1501
|
}
|
|
1502
1502
|
}
|
|
1503
1503
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-better-t-stack",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.20.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",
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://biomejs.dev/schemas/2.0.0/schema.json",
|
|
3
|
+
"vcs": {
|
|
4
|
+
"enabled": false,
|
|
5
|
+
"clientKind": "git",
|
|
6
|
+
"useIgnoreFile": false
|
|
7
|
+
},
|
|
8
|
+
"files": {
|
|
9
|
+
"ignoreUnknown": false,
|
|
10
|
+
"includes": [
|
|
11
|
+
"**",
|
|
12
|
+
"!**/.next",
|
|
13
|
+
"!**/dist",
|
|
14
|
+
"!**/.turbo",
|
|
15
|
+
"!**/dev-dist",
|
|
16
|
+
"!**/.zed",
|
|
17
|
+
"!**/.vscode",
|
|
18
|
+
"!**/routeTree.gen.ts",
|
|
19
|
+
"!**/src-tauri",
|
|
20
|
+
"!**/.nuxt"
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
"formatter": {
|
|
24
|
+
"enabled": true,
|
|
25
|
+
"indentStyle": "tab"
|
|
26
|
+
},
|
|
27
|
+
"assist": { "actions": { "source": { "organizeImports": "on" } } },
|
|
28
|
+
"linter": {
|
|
29
|
+
"enabled": true,
|
|
30
|
+
"rules": {
|
|
31
|
+
"recommended": true,
|
|
32
|
+
"correctness": {
|
|
33
|
+
"useExhaustiveDependencies": "info"
|
|
34
|
+
},
|
|
35
|
+
"nursery": {
|
|
36
|
+
"useSortedClasses": {
|
|
37
|
+
"level": "warn",
|
|
38
|
+
"fix": "safe",
|
|
39
|
+
"options": {
|
|
40
|
+
"functions": ["clsx", "cva", "cn"]
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"style": {
|
|
45
|
+
"noParameterAssign": "error",
|
|
46
|
+
"useAsConstAssertion": "error",
|
|
47
|
+
"useDefaultParameterLast": "error",
|
|
48
|
+
"useEnumInitializers": "error",
|
|
49
|
+
"useSelfClosingElements": "error",
|
|
50
|
+
"useSingleVarDeclarator": "error",
|
|
51
|
+
"noUnusedTemplateLiteral": "error",
|
|
52
|
+
"useNumberNamespace": "error",
|
|
53
|
+
"noInferrableTypes": "error",
|
|
54
|
+
"noUselessElse": "error"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"javascript": {
|
|
59
|
+
"formatter": {
|
|
60
|
+
"quoteStyle": "double"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
{{#if (or (eq frontend "svelte") (eq frontend "nuxt"))}}
|
|
64
|
+
,
|
|
65
|
+
"overrides": [
|
|
66
|
+
{
|
|
67
|
+
"includes": ["**/*.svelte", "**/*.vue"],
|
|
68
|
+
"linter": {
|
|
69
|
+
"rules": {
|
|
70
|
+
"style": {
|
|
71
|
+
"useConst": "off",
|
|
72
|
+
"useImportType": "off"
|
|
73
|
+
},
|
|
74
|
+
"correctness": {
|
|
75
|
+
"noUnusedVariables": "off",
|
|
76
|
+
"noUnusedImports": "off"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
]
|
|
82
|
+
{{/if}}
|
|
83
|
+
}
|
|
@@ -32,6 +32,7 @@ export default function UserMenu() {
|
|
|
32
32
|
<div class="absolute right-0 mt-2 w-56 rounded p-1 shadow-sm">
|
|
33
33
|
<div class="px-4 text-sm">{session().data?.user.email}</div>
|
|
34
34
|
<button
|
|
35
|
+
type="button"
|
|
35
36
|
class="mt-1 w-full border rounded px-4 text-center text-sm"
|
|
36
37
|
onClick={() => {
|
|
37
38
|
setIsMenuOpen(false);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{projectName}}-server",
|
|
3
|
+
"main": "src/index.ts",
|
|
4
|
+
"compatibility_date": "2025-06-15",
|
|
5
|
+
"compatibility_flags": ["nodejs_compat"],
|
|
6
|
+
"vars": {
|
|
7
|
+
"NODE_ENV": "production"
|
|
8
|
+
// Non-sensitive environment variables (visible in dashboard)
|
|
9
|
+
// "CORS_ORIGIN": "https://your-frontend-domain.com",
|
|
10
|
+
// "BETTER_AUTH_URL": "https://your-worker-domain.workers.dev"
|
|
11
|
+
}
|
|
12
|
+
// ⚠️ SENSITIVE DATA: Use `wrangler secret put` instead of adding here
|
|
13
|
+
// Don't put these in "vars" - they'll be visible in the dashboard!
|
|
14
|
+
// - DATABASE_URL
|
|
15
|
+
// - DATABASE_AUTH_TOKEN
|
|
16
|
+
// - GOOGLE_GENERATIVE_AI_API_KEY
|
|
17
|
+
// - BETTER_AUTH_SECRET
|
|
18
|
+
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
|
|
3
|
-
"vcs": {
|
|
4
|
-
"enabled": false,
|
|
5
|
-
"clientKind": "git",
|
|
6
|
-
"useIgnoreFile": false
|
|
7
|
-
},
|
|
8
|
-
"files": {
|
|
9
|
-
"ignoreUnknown": false,
|
|
10
|
-
"ignore": [
|
|
11
|
-
".next",
|
|
12
|
-
"dist",
|
|
13
|
-
".turbo",
|
|
14
|
-
"dev-dist",
|
|
15
|
-
".zed",
|
|
16
|
-
".vscode",
|
|
17
|
-
"routeTree.gen.ts",
|
|
18
|
-
"src-tauri",
|
|
19
|
-
".nuxt"
|
|
20
|
-
]
|
|
21
|
-
},
|
|
22
|
-
"formatter": {
|
|
23
|
-
"enabled": true,
|
|
24
|
-
"indentStyle": "tab"
|
|
25
|
-
},
|
|
26
|
-
"organizeImports": {
|
|
27
|
-
"enabled": true
|
|
28
|
-
},
|
|
29
|
-
"linter": {
|
|
30
|
-
"enabled": true,
|
|
31
|
-
"rules": {
|
|
32
|
-
"recommended": true,
|
|
33
|
-
"correctness": {
|
|
34
|
-
"useExhaustiveDependencies": "info"
|
|
35
|
-
},
|
|
36
|
-
"nursery": {
|
|
37
|
-
"useSortedClasses": {
|
|
38
|
-
"level": "warn",
|
|
39
|
-
"fix": "safe",
|
|
40
|
-
"options": {
|
|
41
|
-
"functions": ["clsx", "cva", "cn"]
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
},
|
|
47
|
-
"javascript": {
|
|
48
|
-
"formatter": {
|
|
49
|
-
"quoteStyle": "double"
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
name = "{{projectName}}-server"
|
|
2
|
-
main = "src/index.ts"
|
|
3
|
-
compatibility_date = "2025-06-15"
|
|
4
|
-
compatibility_flags = ["nodejs_compat"]
|
|
5
|
-
|
|
6
|
-
[vars]
|
|
7
|
-
NODE_ENV = "production"
|
|
8
|
-
|
|
9
|
-
# Non-sensitive environment variables (visible in dashboard)
|
|
10
|
-
# CORS_ORIGIN = "https://your-frontend-domain.com"
|
|
11
|
-
# BETTER_AUTH_URL = "https://your-worker-domain.workers.dev"
|
|
12
|
-
|
|
13
|
-
# ⚠️ SENSITIVE DATA: Use `wrangler secret put` instead of adding here
|
|
14
|
-
# Don't put these in [vars] - they'll be visible in the dashboard!
|
|
15
|
-
# - DATABASE_URL
|
|
16
|
-
# - DATABASE_AUTH_TOKEN
|
|
17
|
-
# - GOOGLE_GENERATIVE_AI_API_KEY
|
|
18
|
-
# - BETTER_AUTH_SECRET
|