create-morax 2.0.3 → 2.0.5
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 +419 -439
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4,10 +4,36 @@
|
|
|
4
4
|
import pc29 from "picocolors";
|
|
5
5
|
|
|
6
6
|
// src/core/runner.ts
|
|
7
|
-
import
|
|
7
|
+
import path36 from "path";
|
|
8
8
|
import { spinner as spinner20 } from "@clack/prompts";
|
|
9
9
|
import pc28 from "picocolors";
|
|
10
10
|
|
|
11
|
+
// src/utils/cleanBunLock.ts
|
|
12
|
+
import fsPromises from "fs/promises";
|
|
13
|
+
import path from "path";
|
|
14
|
+
var BUN_LOCK_NAMES = ["bun.lock", "bun.lockb"];
|
|
15
|
+
async function removeBunLockfiles(...targetDirs) {
|
|
16
|
+
for (const dir of targetDirs) {
|
|
17
|
+
if (!dir) continue;
|
|
18
|
+
const pathsToCheck = [
|
|
19
|
+
dir,
|
|
20
|
+
path.join(dir, "apps"),
|
|
21
|
+
path.join(dir, "apps", "web")
|
|
22
|
+
];
|
|
23
|
+
for (const targetPath of pathsToCheck) {
|
|
24
|
+
for (const lockFileName of BUN_LOCK_NAMES) {
|
|
25
|
+
try {
|
|
26
|
+
await fsPromises.rm(path.join(targetPath, lockFileName), {
|
|
27
|
+
force: true,
|
|
28
|
+
recursive: true
|
|
29
|
+
});
|
|
30
|
+
} catch {
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
11
37
|
// src/core/startcli.ts
|
|
12
38
|
import gradient from "gradient-string";
|
|
13
39
|
import pc from "picocolors";
|
|
@@ -44,7 +70,7 @@ function startCli() {
|
|
|
44
70
|
// src/core/preflight.ts
|
|
45
71
|
import ora from "ora";
|
|
46
72
|
import pc3 from "picocolors";
|
|
47
|
-
import
|
|
73
|
+
import fsPromises2 from "fs/promises";
|
|
48
74
|
|
|
49
75
|
// src/utils/exec.ts
|
|
50
76
|
import { exec, spawn } from "child_process";
|
|
@@ -59,7 +85,11 @@ async function runCommand(command, options = {}) {
|
|
|
59
85
|
try {
|
|
60
86
|
const { stdout, stderr } = await execAsync(command, {
|
|
61
87
|
cwd: options.cwd,
|
|
62
|
-
env: {
|
|
88
|
+
env: {
|
|
89
|
+
...process.env,
|
|
90
|
+
NODE_NO_WARNINGS: "1",
|
|
91
|
+
NODE_OPTIONS: `${process.env.NODE_OPTIONS || ""} --no-deprecation`.trim()
|
|
92
|
+
}
|
|
63
93
|
});
|
|
64
94
|
if (!isSilent) {
|
|
65
95
|
if (stdout && stdout.trim()) {
|
|
@@ -88,11 +118,15 @@ ${error.stderr.trim()}`;
|
|
|
88
118
|
function runInteractiveCommand(command, args, cwd) {
|
|
89
119
|
return new Promise((resolve, reject) => {
|
|
90
120
|
const fullCommand = args.length > 0 ? `${command} ${args.join(" ")}` : command;
|
|
91
|
-
const child = spawn(fullCommand,
|
|
121
|
+
const child = spawn(fullCommand, {
|
|
92
122
|
cwd,
|
|
93
123
|
stdio: "inherit",
|
|
94
124
|
shell: true,
|
|
95
|
-
env: {
|
|
125
|
+
env: {
|
|
126
|
+
...process.env,
|
|
127
|
+
NODE_NO_WARNINGS: "1",
|
|
128
|
+
NODE_OPTIONS: `${process.env.NODE_OPTIONS || ""} --no-deprecation`.trim()
|
|
129
|
+
}
|
|
96
130
|
});
|
|
97
131
|
child.on("close", (code) => {
|
|
98
132
|
if (code === 0) {
|
|
@@ -179,7 +213,7 @@ async function runPreflightChecks() {
|
|
|
179
213
|
color: "cyan"
|
|
180
214
|
}).start();
|
|
181
215
|
await sleep(150);
|
|
182
|
-
let bunVersion =
|
|
216
|
+
let bunVersion = "";
|
|
183
217
|
try {
|
|
184
218
|
const { stdout } = await runCommand("bun --version", { silent: true });
|
|
185
219
|
bunVersion = stdout.trim();
|
|
@@ -192,9 +226,19 @@ async function runPreflightChecks() {
|
|
|
192
226
|
});
|
|
193
227
|
} catch {
|
|
194
228
|
bunSpinner.stopAndPersist({
|
|
195
|
-
symbol:
|
|
196
|
-
text:
|
|
229
|
+
symbol: cross,
|
|
230
|
+
text: "Verifying Bun runtime. Not found."
|
|
197
231
|
});
|
|
232
|
+
console.log(
|
|
233
|
+
"\n" + pc3.red(
|
|
234
|
+
"\u2716 Error: Bun is required to scaffold and execute high-performance Morax apps.\n"
|
|
235
|
+
) + pc3.cyan(" \u2022 Install Bun: https://bun.sh\n") + pc3.cyan(
|
|
236
|
+
' \u2022 Windows: powershell -c "irm bun.sh/install.ps1 | iex"\n'
|
|
237
|
+
) + pc3.cyan(
|
|
238
|
+
" \u2022 macOS / Linux: curl -fsSL https://bun.sh/install | bash\n"
|
|
239
|
+
)
|
|
240
|
+
);
|
|
241
|
+
process.exit(1);
|
|
198
242
|
}
|
|
199
243
|
const dockerSpinner = ora({
|
|
200
244
|
text: "Verifying Docker installation...",
|
|
@@ -247,7 +291,7 @@ async function runPreflightChecks() {
|
|
|
247
291
|
}
|
|
248
292
|
async function checkTargetDirectory(projectPath, name) {
|
|
249
293
|
try {
|
|
250
|
-
const files = await
|
|
294
|
+
const files = await fsPromises2.readdir(projectPath);
|
|
251
295
|
if (files.length > 0) {
|
|
252
296
|
console.log(
|
|
253
297
|
"\n" + pc3.red(
|
|
@@ -313,8 +357,8 @@ import { select as select2 } from "@clack/prompts";
|
|
|
313
357
|
// src/modules/packages/db/drizzle.ts
|
|
314
358
|
import { select, spinner } from "@clack/prompts";
|
|
315
359
|
import pc5 from "picocolors";
|
|
316
|
-
import
|
|
317
|
-
import
|
|
360
|
+
import fsPromises3 from "fs/promises";
|
|
361
|
+
import path2 from "path";
|
|
318
362
|
async function promptDrizzle() {
|
|
319
363
|
const dialectChoice = await select({
|
|
320
364
|
message: "Which database dialect would you like to use with Drizzle?",
|
|
@@ -379,15 +423,15 @@ async function promptDrizzle() {
|
|
|
379
423
|
return { dialect };
|
|
380
424
|
}
|
|
381
425
|
async function setupDrizzle(projectPath, dialect = "postgresql", linter = "none", postgresProvider = "docker", neonMode = "serverless") {
|
|
382
|
-
const dbDir =
|
|
383
|
-
const srcDir =
|
|
384
|
-
const schemaDir =
|
|
385
|
-
const seedDir =
|
|
386
|
-
await
|
|
387
|
-
await
|
|
426
|
+
const dbDir = path2.join(projectPath, "packages", "db");
|
|
427
|
+
const srcDir = path2.join(dbDir, "src");
|
|
428
|
+
const schemaDir = path2.join(srcDir, "schema");
|
|
429
|
+
const seedDir = path2.join(srcDir, "seed");
|
|
430
|
+
await fsPromises3.mkdir(schemaDir, { recursive: true });
|
|
431
|
+
await fsPromises3.mkdir(seedDir, { recursive: true });
|
|
388
432
|
await runCommand("pnpm init", { cwd: dbDir, silent: true });
|
|
389
|
-
const dbPackagePath =
|
|
390
|
-
const dbPackageRaw = await
|
|
433
|
+
const dbPackagePath = path2.join(dbDir, "package.json");
|
|
434
|
+
const dbPackageRaw = await fsPromises3.readFile(dbPackagePath, "utf8");
|
|
391
435
|
const dbPkg = JSON.parse(dbPackageRaw);
|
|
392
436
|
const providerLabel = dialect === "sqlite" ? "SQLite" : postgresProvider === "neon" ? `PostgreSQL (Neon ${neonMode === "pool" ? "Pool" : "Serverless"})` : "PostgreSQL (Docker)";
|
|
393
437
|
dbPkg.name = "@repo/db";
|
|
@@ -427,7 +471,7 @@ async function setupDrizzle(projectPath, dialect = "postgresql", linter = "none"
|
|
|
427
471
|
delete dbPkg.keywords;
|
|
428
472
|
delete dbPkg.author;
|
|
429
473
|
delete dbPkg.license;
|
|
430
|
-
await
|
|
474
|
+
await fsPromises3.writeFile(
|
|
431
475
|
dbPackagePath,
|
|
432
476
|
JSON.stringify(dbPkg, null, 2),
|
|
433
477
|
"utf8"
|
|
@@ -442,8 +486,8 @@ async function setupDrizzle(projectPath, dialect = "postgresql", linter = "none"
|
|
|
442
486
|
},
|
|
443
487
|
include: ["src/**/*", "drizzle.config.ts"]
|
|
444
488
|
};
|
|
445
|
-
await
|
|
446
|
-
|
|
489
|
+
await fsPromises3.writeFile(
|
|
490
|
+
path2.join(dbDir, "tsconfig.json"),
|
|
447
491
|
JSON.stringify(tsconfigContent, null, 2),
|
|
448
492
|
"utf8"
|
|
449
493
|
);
|
|
@@ -499,8 +543,8 @@ async function setupDrizzle(projectPath, dialect = "postgresql", linter = "none"
|
|
|
499
543
|
"});",
|
|
500
544
|
""
|
|
501
545
|
].join("\n");
|
|
502
|
-
await
|
|
503
|
-
|
|
546
|
+
await fsPromises3.writeFile(
|
|
547
|
+
path2.join(dbDir, "drizzle.config.ts"),
|
|
504
548
|
drizzleConfigContent,
|
|
505
549
|
"utf8"
|
|
506
550
|
);
|
|
@@ -542,8 +586,8 @@ async function setupDrizzle(projectPath, dialect = "postgresql", linter = "none"
|
|
|
542
586
|
""
|
|
543
587
|
].join("\n");
|
|
544
588
|
}
|
|
545
|
-
await
|
|
546
|
-
|
|
589
|
+
await fsPromises3.writeFile(
|
|
590
|
+
path2.join(schemaDir, "index.ts"),
|
|
547
591
|
schemaContent,
|
|
548
592
|
"utf8"
|
|
549
593
|
);
|
|
@@ -653,8 +697,8 @@ async function setupDrizzle(projectPath, dialect = "postgresql", linter = "none"
|
|
|
653
697
|
""
|
|
654
698
|
].join("\n");
|
|
655
699
|
}
|
|
656
|
-
await
|
|
657
|
-
|
|
700
|
+
await fsPromises3.writeFile(
|
|
701
|
+
path2.join(srcDir, "client.ts"),
|
|
658
702
|
clientContent,
|
|
659
703
|
"utf8"
|
|
660
704
|
);
|
|
@@ -672,8 +716,8 @@ async function setupDrizzle(projectPath, dialect = "postgresql", linter = "none"
|
|
|
672
716
|
"export * from 'drizzle-orm';",
|
|
673
717
|
""
|
|
674
718
|
].join("\n");
|
|
675
|
-
await
|
|
676
|
-
|
|
719
|
+
await fsPromises3.writeFile(
|
|
720
|
+
path2.join(srcDir, "index.ts"),
|
|
677
721
|
indexContent,
|
|
678
722
|
"utf8"
|
|
679
723
|
);
|
|
@@ -725,14 +769,14 @@ async function setupDrizzle(projectPath, dialect = "postgresql", linter = "none"
|
|
|
725
769
|
"});",
|
|
726
770
|
""
|
|
727
771
|
].join("\n");
|
|
728
|
-
await
|
|
729
|
-
|
|
772
|
+
await fsPromises3.writeFile(
|
|
773
|
+
path2.join(seedDir, "seed.ts"),
|
|
730
774
|
seedScriptContent,
|
|
731
775
|
"utf8"
|
|
732
776
|
);
|
|
733
777
|
const seedIndexContent = ["export { seed } from './seed.js';", ""].join("\n");
|
|
734
|
-
await
|
|
735
|
-
|
|
778
|
+
await fsPromises3.writeFile(
|
|
779
|
+
path2.join(seedDir, "index.ts"),
|
|
736
780
|
seedIndexContent,
|
|
737
781
|
"utf8"
|
|
738
782
|
);
|
|
@@ -745,8 +789,8 @@ async function setupDrizzle(projectPath, dialect = "postgresql", linter = "none"
|
|
|
745
789
|
"*.db-journal",
|
|
746
790
|
""
|
|
747
791
|
].join("\n");
|
|
748
|
-
await
|
|
749
|
-
|
|
792
|
+
await fsPromises3.writeFile(
|
|
793
|
+
path2.join(dbDir, ".gitignore"),
|
|
750
794
|
gitignoreContent,
|
|
751
795
|
"utf8"
|
|
752
796
|
);
|
|
@@ -773,16 +817,16 @@ async function setupDrizzle(projectPath, dialect = "postgresql", linter = "none"
|
|
|
773
817
|
"- `pnpm db:check` \u2014 Check migration history and verify consistency.",
|
|
774
818
|
""
|
|
775
819
|
].filter(Boolean).join("\n");
|
|
776
|
-
await
|
|
777
|
-
|
|
820
|
+
await fsPromises3.writeFile(
|
|
821
|
+
path2.join(dbDir, "README.md"),
|
|
778
822
|
readmeContent,
|
|
779
823
|
"utf8"
|
|
780
824
|
);
|
|
781
825
|
}
|
|
782
826
|
async function runDrizzleSetup(projectPath, dialect = "postgresql", linter = "none", postgresProvider = "docker", neonMode = "serverless") {
|
|
783
|
-
const packagesDir =
|
|
827
|
+
const packagesDir = path2.join(projectPath, "packages");
|
|
784
828
|
try {
|
|
785
|
-
await
|
|
829
|
+
await fsPromises3.access(packagesDir);
|
|
786
830
|
} catch {
|
|
787
831
|
return;
|
|
788
832
|
}
|
|
@@ -1043,43 +1087,17 @@ ${pc6.bold("Database commands (packages/db - Drizzle ORM):")}
|
|
|
1043
1087
|
}
|
|
1044
1088
|
|
|
1045
1089
|
// src/standalone/react-runner.ts
|
|
1046
|
-
import
|
|
1090
|
+
import path6 from "path";
|
|
1047
1091
|
import { spinner as spinner4 } from "@clack/prompts";
|
|
1048
1092
|
import pc9 from "picocolors";
|
|
1049
1093
|
|
|
1050
1094
|
// src/modules/apps/web/react.ts
|
|
1051
1095
|
import pc7 from "picocolors";
|
|
1052
|
-
import
|
|
1053
|
-
import
|
|
1054
|
-
import { spawn as spawn2 } from "child_process";
|
|
1096
|
+
import fsPromises4 from "fs/promises";
|
|
1097
|
+
import path3 from "path";
|
|
1055
1098
|
import { confirm, spinner as spinner2, text as text2 } from "@clack/prompts";
|
|
1056
|
-
function runInteractiveCommand2(command, args, cwd) {
|
|
1057
|
-
return new Promise((resolve, reject) => {
|
|
1058
|
-
const fullCommand = args.length > 0 ? `${command} ${args.join(" ")}` : command;
|
|
1059
|
-
const child = spawn2(fullCommand, [], {
|
|
1060
|
-
cwd,
|
|
1061
|
-
stdio: "inherit",
|
|
1062
|
-
shell: true,
|
|
1063
|
-
env: { ...process.env, NODE_NO_WARNINGS: "1" }
|
|
1064
|
-
});
|
|
1065
|
-
child.on("close", (code) => {
|
|
1066
|
-
if (code === 0) {
|
|
1067
|
-
resolve();
|
|
1068
|
-
} else {
|
|
1069
|
-
reject(
|
|
1070
|
-
new Error(
|
|
1071
|
-
`Command "${command} ${args.join(" ")}" exited with code ${code}`
|
|
1072
|
-
)
|
|
1073
|
-
);
|
|
1074
|
-
}
|
|
1075
|
-
});
|
|
1076
|
-
child.on("error", (err) => {
|
|
1077
|
-
reject(err);
|
|
1078
|
-
});
|
|
1079
|
-
});
|
|
1080
|
-
}
|
|
1081
1099
|
async function setupReact(projectPath, isMonorepo = true) {
|
|
1082
|
-
const appsDir = isMonorepo ?
|
|
1100
|
+
const appsDir = isMonorepo ? path3.join(projectPath, "apps") : path3.dirname(projectPath);
|
|
1083
1101
|
console.log(pc7.magentaBright("\n\u{1F537} IMPORTANT INSTRUCTIONS:"));
|
|
1084
1102
|
console.log(
|
|
1085
1103
|
pc7.magentaBright(
|
|
@@ -1101,14 +1119,14 @@ async function setupReact(projectPath, isMonorepo = true) {
|
|
|
1101
1119
|
);
|
|
1102
1120
|
let beforeDirs = [];
|
|
1103
1121
|
try {
|
|
1104
|
-
beforeDirs = await
|
|
1122
|
+
beforeDirs = await fsPromises4.readdir(appsDir);
|
|
1105
1123
|
} catch {
|
|
1106
1124
|
}
|
|
1107
1125
|
try {
|
|
1108
|
-
await
|
|
1126
|
+
await runInteractiveCommand("bunx", ["create-vite@latest"], appsDir);
|
|
1109
1127
|
let afterDirs = [];
|
|
1110
1128
|
try {
|
|
1111
|
-
afterDirs = await
|
|
1129
|
+
afterDirs = await fsPromises4.readdir(appsDir);
|
|
1112
1130
|
} catch {
|
|
1113
1131
|
}
|
|
1114
1132
|
const newDirs = afterDirs.filter((d) => !beforeDirs.includes(d));
|
|
@@ -1116,17 +1134,18 @@ async function setupReact(projectPath, isMonorepo = true) {
|
|
|
1116
1134
|
if (newDirs.length > 0) {
|
|
1117
1135
|
createdDirName = newDirs[0];
|
|
1118
1136
|
}
|
|
1119
|
-
const webDir =
|
|
1137
|
+
const webDir = path3.join(appsDir, createdDirName);
|
|
1120
1138
|
try {
|
|
1121
|
-
await
|
|
1139
|
+
await fsPromises4.access(webDir);
|
|
1122
1140
|
} catch {
|
|
1123
1141
|
throw new Error(
|
|
1124
1142
|
`Vite React application directory "apps/${createdDirName}" was not found. Please ensure you complete the Vite installation.`
|
|
1125
1143
|
);
|
|
1126
1144
|
}
|
|
1127
|
-
|
|
1145
|
+
await removeBunLockfiles(webDir, projectPath);
|
|
1146
|
+
const pkgPath = path3.join(webDir, "package.json");
|
|
1128
1147
|
try {
|
|
1129
|
-
const pkgRaw = await
|
|
1148
|
+
const pkgRaw = await fsPromises4.readFile(pkgPath, "utf8");
|
|
1130
1149
|
const pkg = JSON.parse(pkgRaw);
|
|
1131
1150
|
if (isMonorepo) {
|
|
1132
1151
|
pkg.name = "web";
|
|
@@ -1136,7 +1155,7 @@ async function setupReact(projectPath, isMonorepo = true) {
|
|
|
1136
1155
|
onlyBuiltDependencies: ["esbuild"]
|
|
1137
1156
|
};
|
|
1138
1157
|
}
|
|
1139
|
-
await
|
|
1158
|
+
await fsPromises4.writeFile(pkgPath, JSON.stringify(pkg, null, 2), "utf8");
|
|
1140
1159
|
} catch {
|
|
1141
1160
|
}
|
|
1142
1161
|
const aliasSpinner = spinner2();
|
|
@@ -1147,12 +1166,12 @@ async function setupReact(projectPath, isMonorepo = true) {
|
|
|
1147
1166
|
silent: true
|
|
1148
1167
|
});
|
|
1149
1168
|
const tsconfigPaths = [
|
|
1150
|
-
|
|
1151
|
-
|
|
1169
|
+
path3.join(webDir, "tsconfig.json"),
|
|
1170
|
+
path3.join(webDir, "tsconfig.app.json")
|
|
1152
1171
|
];
|
|
1153
1172
|
for (const tsPath of tsconfigPaths) {
|
|
1154
1173
|
try {
|
|
1155
|
-
let content = await
|
|
1174
|
+
let content = await fsPromises4.readFile(tsPath, "utf8");
|
|
1156
1175
|
if (content.includes('"compilerOptions"')) {
|
|
1157
1176
|
if (!content.includes('"paths"')) {
|
|
1158
1177
|
content = content.replace(
|
|
@@ -1163,7 +1182,7 @@ async function setupReact(projectPath, isMonorepo = true) {
|
|
|
1163
1182
|
"@/*": ["./src/*"]
|
|
1164
1183
|
},`
|
|
1165
1184
|
);
|
|
1166
|
-
await
|
|
1185
|
+
await fsPromises4.writeFile(tsPath, content, "utf8");
|
|
1167
1186
|
}
|
|
1168
1187
|
} else {
|
|
1169
1188
|
content = content.replace(
|
|
@@ -1176,14 +1195,14 @@ async function setupReact(projectPath, isMonorepo = true) {
|
|
|
1176
1195
|
}
|
|
1177
1196
|
},`
|
|
1178
1197
|
);
|
|
1179
|
-
await
|
|
1198
|
+
await fsPromises4.writeFile(tsPath, content, "utf8");
|
|
1180
1199
|
}
|
|
1181
1200
|
} catch {
|
|
1182
1201
|
}
|
|
1183
1202
|
}
|
|
1184
|
-
const viteConfigPath =
|
|
1203
|
+
const viteConfigPath = path3.join(webDir, "vite.config.ts");
|
|
1185
1204
|
try {
|
|
1186
|
-
let content = await
|
|
1205
|
+
let content = await fsPromises4.readFile(viteConfigPath, "utf8");
|
|
1187
1206
|
if (!content.includes("import path from 'path'")) {
|
|
1188
1207
|
content = "import path from 'path';\n" + content;
|
|
1189
1208
|
}
|
|
@@ -1198,7 +1217,7 @@ async function setupReact(projectPath, isMonorepo = true) {
|
|
|
1198
1217
|
}`
|
|
1199
1218
|
);
|
|
1200
1219
|
}
|
|
1201
|
-
await
|
|
1220
|
+
await fsPromises4.writeFile(viteConfigPath, content, "utf8");
|
|
1202
1221
|
} catch {
|
|
1203
1222
|
}
|
|
1204
1223
|
aliasSpinner.stop(
|
|
@@ -1242,9 +1261,9 @@ async function setupReact(projectPath, isMonorepo = true) {
|
|
|
1242
1261
|
silent: true
|
|
1243
1262
|
});
|
|
1244
1263
|
s.message("Configuring Vite plugins and Tailwind CSS imports...");
|
|
1245
|
-
const viteConfigPath =
|
|
1264
|
+
const viteConfigPath = path3.join(webDir, "vite.config.ts");
|
|
1246
1265
|
try {
|
|
1247
|
-
let content = await
|
|
1266
|
+
let content = await fsPromises4.readFile(viteConfigPath, "utf8");
|
|
1248
1267
|
const hasReactCompiler = content.includes("reactCompilerPreset") || content.includes("@rolldown/plugin-babel") || content.includes("babel({");
|
|
1249
1268
|
if (hasReactCompiler) {
|
|
1250
1269
|
content = [
|
|
@@ -1271,7 +1290,7 @@ async function setupReact(projectPath, isMonorepo = true) {
|
|
|
1271
1290
|
"});",
|
|
1272
1291
|
""
|
|
1273
1292
|
].join("\n");
|
|
1274
|
-
await
|
|
1293
|
+
await fsPromises4.writeFile(viteConfigPath, content, "utf8");
|
|
1275
1294
|
} else if (!content.includes("@tailwindcss/vite")) {
|
|
1276
1295
|
content = "import tailwindcss from '@tailwindcss/vite';\n" + content;
|
|
1277
1296
|
if (content.includes("plugins: [react()]")) {
|
|
@@ -1290,13 +1309,13 @@ async function setupReact(projectPath, isMonorepo = true) {
|
|
|
1290
1309
|
"$1\n tailwindcss(),\n $2"
|
|
1291
1310
|
);
|
|
1292
1311
|
}
|
|
1293
|
-
await
|
|
1312
|
+
await fsPromises4.writeFile(viteConfigPath, content, "utf8");
|
|
1294
1313
|
}
|
|
1295
1314
|
} catch {
|
|
1296
1315
|
}
|
|
1297
|
-
const indexCssPath =
|
|
1316
|
+
const indexCssPath = path3.join(webDir, "src", "index.css");
|
|
1298
1317
|
try {
|
|
1299
|
-
await
|
|
1318
|
+
await fsPromises4.writeFile(
|
|
1300
1319
|
indexCssPath,
|
|
1301
1320
|
'@import "tailwindcss";\n',
|
|
1302
1321
|
"utf8"
|
|
@@ -1330,7 +1349,7 @@ async function setupReact(projectPath, isMonorepo = true) {
|
|
|
1330
1349
|
handleCancel(enteredPreset);
|
|
1331
1350
|
presetCode = enteredPreset.trim();
|
|
1332
1351
|
}
|
|
1333
|
-
const args = ["
|
|
1352
|
+
const args = ["shadcn@latest", "init"];
|
|
1334
1353
|
if (presetCode) {
|
|
1335
1354
|
args.push("--preset", presetCode);
|
|
1336
1355
|
}
|
|
@@ -1338,7 +1357,8 @@ async function setupReact(projectPath, isMonorepo = true) {
|
|
|
1338
1357
|
console.log(
|
|
1339
1358
|
pc7.cyan("\nStarting interactive shadcn UI initialization...")
|
|
1340
1359
|
);
|
|
1341
|
-
await
|
|
1360
|
+
await runInteractiveCommand("bunx", args, webDir);
|
|
1361
|
+
await removeBunLockfiles(webDir, projectPath);
|
|
1342
1362
|
console.log(
|
|
1343
1363
|
pc7.green(
|
|
1344
1364
|
isMonorepo ? `
|
|
@@ -1362,8 +1382,8 @@ async function setupReact(projectPath, isMonorepo = true) {
|
|
|
1362
1382
|
// src/modules/git/git.ts
|
|
1363
1383
|
import { confirm as confirm2, spinner as spinner3 } from "@clack/prompts";
|
|
1364
1384
|
import pc8 from "picocolors";
|
|
1365
|
-
import
|
|
1366
|
-
import
|
|
1385
|
+
import fsPromises5 from "fs/promises";
|
|
1386
|
+
import path4 from "path";
|
|
1367
1387
|
async function promptGit() {
|
|
1368
1388
|
return await confirm2({
|
|
1369
1389
|
message: "Do you want to initialize a local Git repository?",
|
|
@@ -1408,8 +1428,8 @@ async function gitInit(projectPath) {
|
|
|
1408
1428
|
"Thumbs.db",
|
|
1409
1429
|
""
|
|
1410
1430
|
].join("\n");
|
|
1411
|
-
await
|
|
1412
|
-
|
|
1431
|
+
await fsPromises5.writeFile(
|
|
1432
|
+
path4.join(projectPath, ".gitignore"),
|
|
1413
1433
|
gitignore,
|
|
1414
1434
|
"utf8"
|
|
1415
1435
|
);
|
|
@@ -1436,10 +1456,10 @@ Error details: ${error.message || error}`));
|
|
|
1436
1456
|
}
|
|
1437
1457
|
|
|
1438
1458
|
// src/modules/workspace/readme.ts
|
|
1439
|
-
import
|
|
1440
|
-
import
|
|
1459
|
+
import fsPromises6 from "fs/promises";
|
|
1460
|
+
import path5 from "path";
|
|
1441
1461
|
async function setupReadme(projectPath, workspaceName, options = {}) {
|
|
1442
|
-
const readmePath =
|
|
1462
|
+
const readmePath = path5.join(projectPath, "README.md");
|
|
1443
1463
|
let dockerDocs = [];
|
|
1444
1464
|
if (options.hasDocker) {
|
|
1445
1465
|
if (options.hasDockerScripts) {
|
|
@@ -1558,14 +1578,15 @@ async function setupReadme(projectPath, workspaceName, options = {}) {
|
|
|
1558
1578
|
"*Generated with love by [Morax Scaffolder CLI](https://github.com/Elitedv/morax).*",
|
|
1559
1579
|
""
|
|
1560
1580
|
].join("\n");
|
|
1561
|
-
await
|
|
1581
|
+
await fsPromises6.writeFile(readmePath, readmeContent, "utf8");
|
|
1562
1582
|
}
|
|
1563
1583
|
|
|
1564
1584
|
// src/standalone/react-runner.ts
|
|
1565
1585
|
async function runReactScaffolder(name, projectPath) {
|
|
1566
1586
|
const finalProjectPath = await setupReact(projectPath, false);
|
|
1567
|
-
await setupReadme(finalProjectPath,
|
|
1587
|
+
await setupReadme(finalProjectPath, path6.basename(finalProjectPath));
|
|
1568
1588
|
await runGitSetup(finalProjectPath);
|
|
1589
|
+
await removeBunLockfiles(finalProjectPath);
|
|
1569
1590
|
const installSpinner = spinner4();
|
|
1570
1591
|
installSpinner.start("Running final package installation...");
|
|
1571
1592
|
try {
|
|
@@ -1578,67 +1599,46 @@ async function runReactScaffolder(name, projectPath) {
|
|
|
1578
1599
|
console.error(pc9.red(`
|
|
1579
1600
|
Error details: ${error.message || error}`));
|
|
1580
1601
|
}
|
|
1581
|
-
endCli(
|
|
1602
|
+
endCli(path6.basename(finalProjectPath), finalProjectPath);
|
|
1582
1603
|
}
|
|
1583
1604
|
|
|
1584
1605
|
// src/standalone/next-runner.ts
|
|
1585
|
-
import
|
|
1606
|
+
import path9 from "path";
|
|
1586
1607
|
import { spinner as spinner5 } from "@clack/prompts";
|
|
1587
1608
|
import pc12 from "picocolors";
|
|
1588
1609
|
|
|
1589
1610
|
// src/modules/apps/web/nextjs.ts
|
|
1590
1611
|
import { confirm as confirm3 } from "@clack/prompts";
|
|
1591
1612
|
import pc10 from "picocolors";
|
|
1592
|
-
import
|
|
1593
|
-
import
|
|
1594
|
-
import { spawn as spawn3 } from "child_process";
|
|
1595
|
-
function runInteractiveCommand3(command, args, cwd) {
|
|
1596
|
-
return new Promise((resolve, reject) => {
|
|
1597
|
-
const fullCommand = args.length > 0 ? `${command} ${args.join(" ")}` : command;
|
|
1598
|
-
const child = spawn3(fullCommand, [], {
|
|
1599
|
-
cwd,
|
|
1600
|
-
stdio: "inherit",
|
|
1601
|
-
shell: true,
|
|
1602
|
-
env: { ...process.env, NODE_NO_WARNINGS: "1" }
|
|
1603
|
-
});
|
|
1604
|
-
child.on("close", (code) => {
|
|
1605
|
-
if (code === 0) {
|
|
1606
|
-
resolve();
|
|
1607
|
-
} else {
|
|
1608
|
-
reject(new Error(`Command "${fullCommand}" exited with code ${code}`));
|
|
1609
|
-
}
|
|
1610
|
-
});
|
|
1611
|
-
child.on("error", (err) => {
|
|
1612
|
-
reject(err);
|
|
1613
|
-
});
|
|
1614
|
-
});
|
|
1615
|
-
}
|
|
1613
|
+
import fsPromises7 from "fs/promises";
|
|
1614
|
+
import path7 from "path";
|
|
1616
1615
|
async function setupNextjs(projectPath, isMonorepo = true) {
|
|
1617
|
-
const appsDir = isMonorepo ?
|
|
1618
|
-
const targetName = isMonorepo ? "web" :
|
|
1619
|
-
const webDir =
|
|
1616
|
+
const appsDir = isMonorepo ? path7.join(projectPath, "apps") : path7.dirname(projectPath);
|
|
1617
|
+
const targetName = isMonorepo ? "web" : path7.basename(projectPath);
|
|
1618
|
+
const webDir = path7.join(appsDir, targetName);
|
|
1620
1619
|
try {
|
|
1621
|
-
await
|
|
1620
|
+
await fsPromises7.rm(webDir, { recursive: true, force: true });
|
|
1622
1621
|
} catch {
|
|
1623
1622
|
}
|
|
1624
1623
|
console.log(pc10.cyan("\nStarting interactive Next.js application setup..."));
|
|
1625
|
-
await
|
|
1626
|
-
"
|
|
1627
|
-
["
|
|
1624
|
+
await runInteractiveCommand(
|
|
1625
|
+
"bunx",
|
|
1626
|
+
["create-next-app@latest", targetName],
|
|
1628
1627
|
appsDir
|
|
1629
1628
|
);
|
|
1629
|
+
await removeBunLockfiles(webDir, projectPath);
|
|
1630
1630
|
if (isMonorepo) {
|
|
1631
1631
|
try {
|
|
1632
|
-
await
|
|
1632
|
+
await fsPromises7.rm(path7.join(webDir, ".git"), {
|
|
1633
1633
|
recursive: true,
|
|
1634
1634
|
force: true
|
|
1635
1635
|
});
|
|
1636
1636
|
} catch {
|
|
1637
1637
|
}
|
|
1638
1638
|
}
|
|
1639
|
-
const webPkgPath =
|
|
1639
|
+
const webPkgPath = path7.join(webDir, "package.json");
|
|
1640
1640
|
try {
|
|
1641
|
-
const webPkgRaw = await
|
|
1641
|
+
const webPkgRaw = await fsPromises7.readFile(webPkgPath, "utf8");
|
|
1642
1642
|
const webPkg = JSON.parse(webPkgRaw);
|
|
1643
1643
|
if (isMonorepo) {
|
|
1644
1644
|
webPkg.name = "web";
|
|
@@ -1648,7 +1648,7 @@ async function setupNextjs(projectPath, isMonorepo = true) {
|
|
|
1648
1648
|
onlyBuiltDependencies: ["sharp"]
|
|
1649
1649
|
};
|
|
1650
1650
|
}
|
|
1651
|
-
await
|
|
1651
|
+
await fsPromises7.writeFile(
|
|
1652
1652
|
webPkgPath,
|
|
1653
1653
|
JSON.stringify(webPkg, null, 2),
|
|
1654
1654
|
"utf8"
|
|
@@ -1661,52 +1661,28 @@ async function setupNextjs(projectPath, isMonorepo = true) {
|
|
|
1661
1661
|
// src/modules/apps/web/shadcn.ts
|
|
1662
1662
|
import { confirm as confirm4 } from "@clack/prompts";
|
|
1663
1663
|
import pc11 from "picocolors";
|
|
1664
|
-
import
|
|
1665
|
-
import
|
|
1666
|
-
import { spawn as spawn4 } from "child_process";
|
|
1664
|
+
import fsPromises8 from "fs/promises";
|
|
1665
|
+
import path8 from "path";
|
|
1667
1666
|
async function promptShadcn() {
|
|
1668
1667
|
return await confirm4({
|
|
1669
1668
|
message: "Do you want to setup shadcn UI in your Next.js website (apps/web)?",
|
|
1670
1669
|
initialValue: true
|
|
1671
1670
|
});
|
|
1672
1671
|
}
|
|
1673
|
-
function runInteractiveCommand4(command, args, cwd) {
|
|
1674
|
-
return new Promise((resolve, reject) => {
|
|
1675
|
-
const child = spawn4(command, args, {
|
|
1676
|
-
cwd,
|
|
1677
|
-
stdio: "inherit",
|
|
1678
|
-
shell: true,
|
|
1679
|
-
env: { ...process.env, NODE_NO_WARNINGS: "1" }
|
|
1680
|
-
});
|
|
1681
|
-
child.on("close", (code) => {
|
|
1682
|
-
if (code === 0) {
|
|
1683
|
-
resolve();
|
|
1684
|
-
} else {
|
|
1685
|
-
reject(
|
|
1686
|
-
new Error(
|
|
1687
|
-
`Command "${command} ${args.join(" ")}" exited with code ${code}`
|
|
1688
|
-
)
|
|
1689
|
-
);
|
|
1690
|
-
}
|
|
1691
|
-
});
|
|
1692
|
-
child.on("error", (err) => {
|
|
1693
|
-
reject(err);
|
|
1694
|
-
});
|
|
1695
|
-
});
|
|
1696
|
-
}
|
|
1697
1672
|
async function setupShadcn(projectPath, isMonorepo = true) {
|
|
1698
|
-
const webDir = isMonorepo ?
|
|
1673
|
+
const webDir = isMonorepo ? path8.join(projectPath, "apps", "web") : projectPath;
|
|
1699
1674
|
console.log(pc11.cyan("\nStarting interactive shadcn UI initialization..."));
|
|
1700
|
-
await
|
|
1701
|
-
"
|
|
1702
|
-
["
|
|
1675
|
+
await runInteractiveCommand(
|
|
1676
|
+
"bunx",
|
|
1677
|
+
["shadcn@latest", "init", "--template", "next"],
|
|
1703
1678
|
webDir
|
|
1704
1679
|
);
|
|
1680
|
+
await removeBunLockfiles(webDir, projectPath);
|
|
1705
1681
|
}
|
|
1706
1682
|
async function runShadcnSetup(projectPath, isMonorepo = true) {
|
|
1707
|
-
const webDir = isMonorepo ?
|
|
1683
|
+
const webDir = isMonorepo ? path8.join(projectPath, "apps", "web") : projectPath;
|
|
1708
1684
|
try {
|
|
1709
|
-
await
|
|
1685
|
+
await fsPromises8.access(webDir);
|
|
1710
1686
|
} catch {
|
|
1711
1687
|
return;
|
|
1712
1688
|
}
|
|
@@ -1734,8 +1710,9 @@ async function runShadcnSetup(projectPath, isMonorepo = true) {
|
|
|
1734
1710
|
async function runNextScaffolder(name, projectPath) {
|
|
1735
1711
|
const finalProjectPath = await setupNextjs(projectPath, false);
|
|
1736
1712
|
await runShadcnSetup(finalProjectPath, false);
|
|
1737
|
-
await setupReadme(finalProjectPath,
|
|
1713
|
+
await setupReadme(finalProjectPath, path9.basename(finalProjectPath));
|
|
1738
1714
|
await runGitSetup(finalProjectPath);
|
|
1715
|
+
await removeBunLockfiles(finalProjectPath);
|
|
1739
1716
|
const installSpinner = spinner5();
|
|
1740
1717
|
installSpinner.start("Running final package installation...");
|
|
1741
1718
|
try {
|
|
@@ -1748,20 +1725,20 @@ async function runNextScaffolder(name, projectPath) {
|
|
|
1748
1725
|
console.error(pc12.red(`
|
|
1749
1726
|
Error details: ${error.message || error}`));
|
|
1750
1727
|
}
|
|
1751
|
-
endCli(
|
|
1728
|
+
endCli(path9.basename(finalProjectPath), finalProjectPath);
|
|
1752
1729
|
}
|
|
1753
1730
|
|
|
1754
1731
|
// src/modules/workspace/directories.ts
|
|
1755
1732
|
import { spinner as spinner6 } from "@clack/prompts";
|
|
1756
|
-
import
|
|
1757
|
-
import
|
|
1733
|
+
import fsPromises10 from "fs/promises";
|
|
1734
|
+
import path11 from "path";
|
|
1758
1735
|
import pc13 from "picocolors";
|
|
1759
1736
|
|
|
1760
1737
|
// src/modules/workspace/config.ts
|
|
1761
|
-
import
|
|
1762
|
-
import
|
|
1738
|
+
import fsPromises9 from "fs/promises";
|
|
1739
|
+
import path10 from "path";
|
|
1763
1740
|
async function generateWorkspaceConfig(name, directories, projectPath) {
|
|
1764
|
-
await
|
|
1741
|
+
await fsPromises9.mkdir(projectPath, { recursive: true });
|
|
1765
1742
|
const defaultOnlyBuiltDeps = [
|
|
1766
1743
|
"esbuild",
|
|
1767
1744
|
"@biomejs/biome",
|
|
@@ -1779,14 +1756,14 @@ async function generateWorkspaceConfig(name, directories, projectPath) {
|
|
|
1779
1756
|
),
|
|
1780
1757
|
""
|
|
1781
1758
|
].join("\n");
|
|
1782
|
-
await
|
|
1783
|
-
|
|
1759
|
+
await fsPromises9.writeFile(
|
|
1760
|
+
path10.join(projectPath, "pnpm-workspace.yaml"),
|
|
1784
1761
|
workspaceYamlContent,
|
|
1785
1762
|
"utf8"
|
|
1786
1763
|
);
|
|
1787
1764
|
await runCommand("pnpm init", { cwd: projectPath, silent: true });
|
|
1788
|
-
const packageJsonPath =
|
|
1789
|
-
const packageJsonRaw = await
|
|
1765
|
+
const packageJsonPath = path10.join(projectPath, "package.json");
|
|
1766
|
+
const packageJsonRaw = await fsPromises9.readFile(packageJsonPath, "utf8");
|
|
1790
1767
|
const pkg = JSON.parse(packageJsonRaw);
|
|
1791
1768
|
pkg.name = name;
|
|
1792
1769
|
pkg.description = "High-performance monorepo workspace generated by Morax";
|
|
@@ -1806,7 +1783,7 @@ async function generateWorkspaceConfig(name, directories, projectPath) {
|
|
|
1806
1783
|
dev: "pnpm -r --parallel dev"
|
|
1807
1784
|
};
|
|
1808
1785
|
delete pkg.main;
|
|
1809
|
-
await
|
|
1786
|
+
await fsPromises9.writeFile(
|
|
1810
1787
|
packageJsonPath,
|
|
1811
1788
|
JSON.stringify(pkg, null, 2),
|
|
1812
1789
|
"utf8"
|
|
@@ -1816,10 +1793,10 @@ async function generateWorkspaceConfig(name, directories, projectPath) {
|
|
|
1816
1793
|
// src/modules/workspace/directories.ts
|
|
1817
1794
|
async function createDirectories(directories, projectPath) {
|
|
1818
1795
|
for (const dir of directories) {
|
|
1819
|
-
const dirPath =
|
|
1820
|
-
await
|
|
1821
|
-
await
|
|
1822
|
-
|
|
1796
|
+
const dirPath = path11.join(projectPath, dir);
|
|
1797
|
+
await fsPromises10.mkdir(dirPath, { recursive: true });
|
|
1798
|
+
await fsPromises10.writeFile(
|
|
1799
|
+
path11.join(dirPath, ".gitkeep"),
|
|
1823
1800
|
`# Placeholder to ensure git tracks the empty ${dir}/ folder
|
|
1824
1801
|
`,
|
|
1825
1802
|
"utf8"
|
|
@@ -1848,11 +1825,11 @@ import { multiselect as multiselect2, select as select4, spinner as spinner7 } f
|
|
|
1848
1825
|
import pc14 from "picocolors";
|
|
1849
1826
|
|
|
1850
1827
|
// src/modules/workspace/docs.ts
|
|
1851
|
-
import
|
|
1852
|
-
import
|
|
1828
|
+
import fsPromises11 from "fs/promises";
|
|
1829
|
+
import path12 from "path";
|
|
1853
1830
|
async function setupProjectDocs(projectPath, options) {
|
|
1854
|
-
const docsDir =
|
|
1855
|
-
await
|
|
1831
|
+
const docsDir = path12.join(projectPath, "docs");
|
|
1832
|
+
await fsPromises11.mkdir(docsDir, { recursive: true });
|
|
1856
1833
|
const {
|
|
1857
1834
|
projectName,
|
|
1858
1835
|
hasServer,
|
|
@@ -1910,8 +1887,8 @@ async function setupProjectDocs(projectPath, options) {
|
|
|
1910
1887
|
"Internal workspace dependencies are linked using pnpm workspace protocols (`workspace:*`).",
|
|
1911
1888
|
""
|
|
1912
1889
|
].join("\n");
|
|
1913
|
-
await
|
|
1914
|
-
|
|
1890
|
+
await fsPromises11.writeFile(
|
|
1891
|
+
path12.join(docsDir, "ARCHITECTURE.md"),
|
|
1915
1892
|
architectureMd,
|
|
1916
1893
|
"utf8"
|
|
1917
1894
|
);
|
|
@@ -1949,7 +1926,7 @@ async function setupProjectDocs(projectPath, options) {
|
|
|
1949
1926
|
"```",
|
|
1950
1927
|
""
|
|
1951
1928
|
].join("\n");
|
|
1952
|
-
await
|
|
1929
|
+
await fsPromises11.writeFile(path12.join(docsDir, "DATABASE.md"), dbMd, "utf8");
|
|
1953
1930
|
}
|
|
1954
1931
|
if (hasServer) {
|
|
1955
1932
|
const serverMd = [
|
|
@@ -1972,8 +1949,8 @@ async function setupProjectDocs(projectPath, options) {
|
|
|
1972
1949
|
"```",
|
|
1973
1950
|
""
|
|
1974
1951
|
].join("\n");
|
|
1975
|
-
await
|
|
1976
|
-
|
|
1952
|
+
await fsPromises11.writeFile(
|
|
1953
|
+
path12.join(docsDir, "SERVER.md"),
|
|
1977
1954
|
serverMd,
|
|
1978
1955
|
"utf8"
|
|
1979
1956
|
);
|
|
@@ -2008,7 +1985,7 @@ async function setupProjectDocs(projectPath, options) {
|
|
|
2008
1985
|
"2. Update the corresponding schema in `packages/env/src/schema/*.ts`.",
|
|
2009
1986
|
""
|
|
2010
1987
|
].join("\n");
|
|
2011
|
-
await
|
|
1988
|
+
await fsPromises11.writeFile(path12.join(docsDir, "ENV.md"), envMd, "utf8");
|
|
2012
1989
|
}
|
|
2013
1990
|
if (hasDocker) {
|
|
2014
1991
|
const dockerMd = [
|
|
@@ -2056,8 +2033,8 @@ async function setupProjectDocs(projectPath, options) {
|
|
|
2056
2033
|
"Docker Compose automatically loads root variables using `--env-file .env`.",
|
|
2057
2034
|
""
|
|
2058
2035
|
].join("\n");
|
|
2059
|
-
await
|
|
2060
|
-
|
|
2036
|
+
await fsPromises11.writeFile(
|
|
2037
|
+
path12.join(docsDir, "DOCKER.md"),
|
|
2061
2038
|
dockerMd,
|
|
2062
2039
|
"utf8"
|
|
2063
2040
|
);
|
|
@@ -2079,7 +2056,7 @@ async function setupProjectDocs(projectPath, options) {
|
|
|
2079
2056
|
"```",
|
|
2080
2057
|
""
|
|
2081
2058
|
].join("\n");
|
|
2082
|
-
await
|
|
2059
|
+
await fsPromises11.writeFile(path12.join(docsDir, "WEB.md"), webMd, "utf8");
|
|
2083
2060
|
}
|
|
2084
2061
|
if (hasAuth) {
|
|
2085
2062
|
const authMd = [
|
|
@@ -2122,13 +2099,13 @@ async function setupProjectDocs(projectPath, options) {
|
|
|
2122
2099
|
"- `verification`: Email verification and password reset tokens",
|
|
2123
2100
|
""
|
|
2124
2101
|
].join("\n");
|
|
2125
|
-
await
|
|
2102
|
+
await fsPromises11.writeFile(path12.join(docsDir, "AUTH.md"), authMd, "utf8");
|
|
2126
2103
|
}
|
|
2127
2104
|
}
|
|
2128
2105
|
|
|
2129
2106
|
// src/modules/workspace/agents.ts
|
|
2130
|
-
import
|
|
2131
|
-
import
|
|
2107
|
+
import fsPromises12 from "fs/promises";
|
|
2108
|
+
import path13 from "path";
|
|
2132
2109
|
function generateClaudeMd(options) {
|
|
2133
2110
|
const {
|
|
2134
2111
|
projectName,
|
|
@@ -2318,21 +2295,21 @@ function generateAgentsMd(options) {
|
|
|
2318
2295
|
async function setupAgentDocs(projectPath, options) {
|
|
2319
2296
|
const claudeContent = generateClaudeMd(options);
|
|
2320
2297
|
const agentsContent = generateAgentsMd(options);
|
|
2321
|
-
await
|
|
2322
|
-
|
|
2298
|
+
await fsPromises12.writeFile(
|
|
2299
|
+
path13.join(projectPath, "CLAUDE.md"),
|
|
2323
2300
|
claudeContent,
|
|
2324
2301
|
"utf8"
|
|
2325
2302
|
);
|
|
2326
|
-
await
|
|
2327
|
-
|
|
2303
|
+
await fsPromises12.writeFile(
|
|
2304
|
+
path13.join(projectPath, "AGENTS.md"),
|
|
2328
2305
|
agentsContent,
|
|
2329
2306
|
"utf8"
|
|
2330
2307
|
);
|
|
2331
2308
|
}
|
|
2332
2309
|
|
|
2333
2310
|
// src/modules/workspace/license.ts
|
|
2334
|
-
import
|
|
2335
|
-
import
|
|
2311
|
+
import fsPromises13 from "fs/promises";
|
|
2312
|
+
import path14 from "path";
|
|
2336
2313
|
function getLicenseText(licenseType, year, author) {
|
|
2337
2314
|
switch (licenseType) {
|
|
2338
2315
|
case "MIT":
|
|
@@ -2461,19 +2438,19 @@ For more information, please refer to <https://unlicense.org>
|
|
|
2461
2438
|
async function setupLicense(projectPath, licenseType, author) {
|
|
2462
2439
|
const year = (/* @__PURE__ */ new Date()).getFullYear();
|
|
2463
2440
|
const licenseContent = getLicenseText(licenseType, year, author);
|
|
2464
|
-
await
|
|
2465
|
-
|
|
2441
|
+
await fsPromises13.writeFile(
|
|
2442
|
+
path14.join(projectPath, "LICENSE"),
|
|
2466
2443
|
licenseContent,
|
|
2467
2444
|
"utf8"
|
|
2468
2445
|
);
|
|
2469
2446
|
}
|
|
2470
2447
|
|
|
2471
2448
|
// src/modules/workspace/scripts.ts
|
|
2472
|
-
import
|
|
2473
|
-
import
|
|
2449
|
+
import fsPromises14 from "fs/promises";
|
|
2450
|
+
import path15 from "path";
|
|
2474
2451
|
async function setupDockerScripts(projectPath, options = {}) {
|
|
2475
|
-
const scriptsDir =
|
|
2476
|
-
await
|
|
2452
|
+
const scriptsDir = path15.join(projectPath, "scripts");
|
|
2453
|
+
await fsPromises14.mkdir(scriptsDir, { recursive: true });
|
|
2477
2454
|
const hasPostgres = !!options.postgres;
|
|
2478
2455
|
const hasRedis = !!options.redis;
|
|
2479
2456
|
const validActions = ["infra-up", "infra-down"];
|
|
@@ -2525,8 +2502,8 @@ async function setupDockerScripts(projectPath, options = {}) {
|
|
|
2525
2502
|
"esac",
|
|
2526
2503
|
""
|
|
2527
2504
|
);
|
|
2528
|
-
await
|
|
2529
|
-
|
|
2505
|
+
await fsPromises14.writeFile(
|
|
2506
|
+
path15.join(scriptsDir, "command.sh"),
|
|
2530
2507
|
shellLines.join("\n"),
|
|
2531
2508
|
{ encoding: "utf8", mode: 493 }
|
|
2532
2509
|
);
|
|
@@ -2644,8 +2621,8 @@ async function promptAndSetupExtras(projectPath, options) {
|
|
|
2644
2621
|
// src/modules/skills/index.ts
|
|
2645
2622
|
import { confirm as confirm5 } from "@clack/prompts";
|
|
2646
2623
|
import pc15 from "picocolors";
|
|
2647
|
-
import
|
|
2648
|
-
import
|
|
2624
|
+
import fsPromises15 from "fs/promises";
|
|
2625
|
+
import path16 from "path";
|
|
2649
2626
|
async function promptSkills() {
|
|
2650
2627
|
const result = await confirm5({
|
|
2651
2628
|
message: "Install AI Agent Skills (skills.sh)?",
|
|
@@ -2655,31 +2632,31 @@ async function promptSkills() {
|
|
|
2655
2632
|
return result;
|
|
2656
2633
|
}
|
|
2657
2634
|
async function moveRulesToAgentRoot(projectPath) {
|
|
2658
|
-
const targetRulesDir =
|
|
2635
|
+
const targetRulesDir = path16.join(projectPath, ".agents", "rules");
|
|
2659
2636
|
const sourceCandidates = [
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2637
|
+
path16.join(projectPath, ".agents", "skills", "rules"),
|
|
2638
|
+
path16.join(projectPath, ".agent", "skills", "rules"),
|
|
2639
|
+
path16.join(projectPath, ".agent", "rules")
|
|
2663
2640
|
];
|
|
2664
2641
|
let moved = false;
|
|
2665
2642
|
for (const sourceDir of sourceCandidates) {
|
|
2666
2643
|
try {
|
|
2667
|
-
await
|
|
2644
|
+
await fsPromises15.access(sourceDir);
|
|
2668
2645
|
} catch {
|
|
2669
2646
|
continue;
|
|
2670
2647
|
}
|
|
2671
|
-
await
|
|
2648
|
+
await fsPromises15.mkdir(targetRulesDir, { recursive: true });
|
|
2672
2649
|
try {
|
|
2673
|
-
const entries = await
|
|
2650
|
+
const entries = await fsPromises15.readdir(sourceDir);
|
|
2674
2651
|
for (const entry of entries) {
|
|
2675
|
-
const srcPath =
|
|
2676
|
-
const destPath =
|
|
2677
|
-
await
|
|
2652
|
+
const srcPath = path16.join(sourceDir, entry);
|
|
2653
|
+
const destPath = path16.join(targetRulesDir, entry);
|
|
2654
|
+
await fsPromises15.cp(srcPath, destPath, {
|
|
2678
2655
|
recursive: true,
|
|
2679
2656
|
force: true
|
|
2680
2657
|
});
|
|
2681
2658
|
}
|
|
2682
|
-
await
|
|
2659
|
+
await fsPromises15.rm(sourceDir, { recursive: true, force: true });
|
|
2683
2660
|
moved = true;
|
|
2684
2661
|
} catch (err) {
|
|
2685
2662
|
console.log(
|
|
@@ -2690,17 +2667,17 @@ async function moveRulesToAgentRoot(projectPath) {
|
|
|
2690
2667
|
);
|
|
2691
2668
|
}
|
|
2692
2669
|
}
|
|
2693
|
-
const agentDir =
|
|
2670
|
+
const agentDir = path16.join(projectPath, ".agent");
|
|
2694
2671
|
try {
|
|
2695
|
-
const remaining = await
|
|
2672
|
+
const remaining = await fsPromises15.readdir(agentDir);
|
|
2696
2673
|
if (remaining.length === 0) {
|
|
2697
|
-
await
|
|
2674
|
+
await fsPromises15.rm(agentDir, { recursive: true, force: true });
|
|
2698
2675
|
} else if (remaining.length === 1 && remaining[0] === "skills") {
|
|
2699
|
-
const skillsRemaining = await
|
|
2700
|
-
|
|
2676
|
+
const skillsRemaining = await fsPromises15.readdir(
|
|
2677
|
+
path16.join(agentDir, "skills")
|
|
2701
2678
|
);
|
|
2702
2679
|
if (skillsRemaining.length === 0) {
|
|
2703
|
-
await
|
|
2680
|
+
await fsPromises15.rm(agentDir, { recursive: true, force: true });
|
|
2704
2681
|
}
|
|
2705
2682
|
}
|
|
2706
2683
|
} catch {
|
|
@@ -2731,22 +2708,22 @@ async function installSkills(projectPath) {
|
|
|
2731
2708
|
);
|
|
2732
2709
|
}
|
|
2733
2710
|
await moveRulesToAgentRoot(projectPath);
|
|
2734
|
-
const claudeDir =
|
|
2711
|
+
const claudeDir = path16.join(projectPath, ".claude");
|
|
2735
2712
|
try {
|
|
2736
|
-
await
|
|
2713
|
+
await fsPromises15.rm(claudeDir, { recursive: true, force: true });
|
|
2737
2714
|
} catch {
|
|
2738
2715
|
}
|
|
2739
|
-
const gitignorePath =
|
|
2716
|
+
const gitignorePath = path16.join(projectPath, ".gitignore");
|
|
2740
2717
|
try {
|
|
2741
2718
|
let gitignoreContent = "";
|
|
2742
2719
|
try {
|
|
2743
|
-
gitignoreContent = await
|
|
2720
|
+
gitignoreContent = await fsPromises15.readFile(gitignorePath, "utf8");
|
|
2744
2721
|
} catch {
|
|
2745
2722
|
gitignoreContent = "";
|
|
2746
2723
|
}
|
|
2747
2724
|
if (!gitignoreContent.includes(".agents")) {
|
|
2748
2725
|
const entry = gitignoreContent ? "\n# AI Agent Skills & Tooling\n.agents/\n.agent/\n" : "# AI Agent Skills & Tooling\n.agents/\n.agent/\n";
|
|
2749
|
-
await
|
|
2726
|
+
await fsPromises15.appendFile(gitignorePath, entry, "utf8");
|
|
2750
2727
|
}
|
|
2751
2728
|
} catch {
|
|
2752
2729
|
}
|
|
@@ -2759,8 +2736,8 @@ async function promptAndInstallSkills(projectPath) {
|
|
|
2759
2736
|
}
|
|
2760
2737
|
|
|
2761
2738
|
// src/modules/workspace/env.ts
|
|
2762
|
-
import
|
|
2763
|
-
import
|
|
2739
|
+
import fsPromises16 from "fs/promises";
|
|
2740
|
+
import path17 from "path";
|
|
2764
2741
|
async function setupRootEnv(projectPath, options = {}) {
|
|
2765
2742
|
const envLines = [
|
|
2766
2743
|
"# ==============================================================================",
|
|
@@ -2835,13 +2812,13 @@ async function setupRootEnv(projectPath, options = {}) {
|
|
|
2835
2812
|
}
|
|
2836
2813
|
}
|
|
2837
2814
|
const envContent = envLines.join("\n");
|
|
2838
|
-
await
|
|
2839
|
-
|
|
2815
|
+
await fsPromises16.writeFile(
|
|
2816
|
+
path17.join(projectPath, ".env"),
|
|
2840
2817
|
envContent,
|
|
2841
2818
|
"utf8"
|
|
2842
2819
|
);
|
|
2843
|
-
await
|
|
2844
|
-
|
|
2820
|
+
await fsPromises16.writeFile(
|
|
2821
|
+
path17.join(projectPath, ".env.example"),
|
|
2845
2822
|
envContent,
|
|
2846
2823
|
"utf8"
|
|
2847
2824
|
);
|
|
@@ -2850,8 +2827,8 @@ async function setupRootEnv(projectPath, options = {}) {
|
|
|
2850
2827
|
// src/modules/git/husky.ts
|
|
2851
2828
|
import { confirm as confirm6, spinner as spinner8 } from "@clack/prompts";
|
|
2852
2829
|
import pc16 from "picocolors";
|
|
2853
|
-
import
|
|
2854
|
-
import
|
|
2830
|
+
import fsPromises17 from "fs/promises";
|
|
2831
|
+
import path18 from "path";
|
|
2855
2832
|
async function setupHusky(projectPath) {
|
|
2856
2833
|
await runCommand("pnpm add -D -E husky -w", {
|
|
2857
2834
|
cwd: projectPath,
|
|
@@ -2861,10 +2838,10 @@ async function setupHusky(projectPath) {
|
|
|
2861
2838
|
cwd: projectPath,
|
|
2862
2839
|
silent: true
|
|
2863
2840
|
});
|
|
2864
|
-
const preCommitPath =
|
|
2841
|
+
const preCommitPath = path18.join(projectPath, ".husky", "pre-commit");
|
|
2865
2842
|
let hookContent = "";
|
|
2866
2843
|
try {
|
|
2867
|
-
hookContent = await
|
|
2844
|
+
hookContent = await fsPromises17.readFile(preCommitPath, "utf8");
|
|
2868
2845
|
} catch {
|
|
2869
2846
|
hookContent = "pnpm test";
|
|
2870
2847
|
}
|
|
@@ -2872,9 +2849,9 @@ async function setupHusky(projectPath) {
|
|
|
2872
2849
|
if (!hookContent.includes("git add .")) {
|
|
2873
2850
|
hookContent = hookContent.trim() + "\ngit add .\n";
|
|
2874
2851
|
}
|
|
2875
|
-
await
|
|
2852
|
+
await fsPromises17.writeFile(preCommitPath, hookContent, "utf8");
|
|
2876
2853
|
try {
|
|
2877
|
-
await
|
|
2854
|
+
await fsPromises17.chmod(preCommitPath, 493);
|
|
2878
2855
|
} catch {
|
|
2879
2856
|
}
|
|
2880
2857
|
}
|
|
@@ -2896,8 +2873,8 @@ Error details: ${error.message || error}`));
|
|
|
2896
2873
|
// src/modules/git/lefthook.ts
|
|
2897
2874
|
import { spinner as spinner9 } from "@clack/prompts";
|
|
2898
2875
|
import pc17 from "picocolors";
|
|
2899
|
-
import
|
|
2900
|
-
import
|
|
2876
|
+
import fsPromises18 from "fs/promises";
|
|
2877
|
+
import path19 from "path";
|
|
2901
2878
|
async function setupLefthook(projectPath, hasFormatter, hasLinter) {
|
|
2902
2879
|
await runCommand("pnpm add -D lefthook -w", {
|
|
2903
2880
|
cwd: projectPath,
|
|
@@ -2927,17 +2904,17 @@ async function setupLefthook(projectPath, hasFormatter, hasLinter) {
|
|
|
2927
2904
|
...commands,
|
|
2928
2905
|
""
|
|
2929
2906
|
].join("\n");
|
|
2930
|
-
await
|
|
2931
|
-
|
|
2907
|
+
await fsPromises18.writeFile(
|
|
2908
|
+
path19.join(projectPath, "lefthook.yml"),
|
|
2932
2909
|
lefthookConfig,
|
|
2933
2910
|
"utf8"
|
|
2934
2911
|
);
|
|
2935
|
-
const rootPackagePath =
|
|
2936
|
-
const rootPackageRaw = await
|
|
2912
|
+
const rootPackagePath = path19.join(projectPath, "package.json");
|
|
2913
|
+
const rootPackageRaw = await fsPromises18.readFile(rootPackagePath, "utf8");
|
|
2937
2914
|
const rootPkg = JSON.parse(rootPackageRaw);
|
|
2938
2915
|
rootPkg.scripts = rootPkg.scripts || {};
|
|
2939
2916
|
rootPkg.scripts.prepare = "lefthook install";
|
|
2940
|
-
await
|
|
2917
|
+
await fsPromises18.writeFile(
|
|
2941
2918
|
rootPackagePath,
|
|
2942
2919
|
JSON.stringify(rootPkg, null, 2),
|
|
2943
2920
|
"utf8"
|
|
@@ -2965,8 +2942,8 @@ Error details: ${error.message || error}`));
|
|
|
2965
2942
|
// src/modules/quality/biome.ts
|
|
2966
2943
|
import { spinner as spinner10 } from "@clack/prompts";
|
|
2967
2944
|
import pc18 from "picocolors";
|
|
2968
|
-
import
|
|
2969
|
-
import
|
|
2945
|
+
import fsPromises19 from "fs/promises";
|
|
2946
|
+
import path20 from "path";
|
|
2970
2947
|
async function setupBiome(projectPath, options) {
|
|
2971
2948
|
await runCommand("pnpm add -D -E @biomejs/biome -w", {
|
|
2972
2949
|
cwd: projectPath,
|
|
@@ -2995,8 +2972,8 @@ async function setupBiome(projectPath, options) {
|
|
|
2995
2972
|
}
|
|
2996
2973
|
}
|
|
2997
2974
|
};
|
|
2998
|
-
await
|
|
2999
|
-
|
|
2975
|
+
await fsPromises19.writeFile(
|
|
2976
|
+
path20.join(projectPath, "biome.json"),
|
|
3000
2977
|
JSON.stringify(biomeConfig, null, 2),
|
|
3001
2978
|
"utf8"
|
|
3002
2979
|
);
|
|
@@ -3007,8 +2984,8 @@ async function setupBiome(projectPath, options) {
|
|
|
3007
2984
|
});
|
|
3008
2985
|
} catch {
|
|
3009
2986
|
}
|
|
3010
|
-
const rootPackagePath =
|
|
3011
|
-
const rootPackageRaw = await
|
|
2987
|
+
const rootPackagePath = path20.join(projectPath, "package.json");
|
|
2988
|
+
const rootPackageRaw = await fsPromises19.readFile(rootPackagePath, "utf8");
|
|
3012
2989
|
const rootPkg = JSON.parse(rootPackageRaw);
|
|
3013
2990
|
rootPkg.scripts = rootPkg.scripts || {};
|
|
3014
2991
|
if (options.linter) {
|
|
@@ -3021,7 +2998,7 @@ async function setupBiome(projectPath, options) {
|
|
|
3021
2998
|
if (options.linter && options.formatter) {
|
|
3022
2999
|
rootPkg.scripts.check = "biome check --write .";
|
|
3023
3000
|
}
|
|
3024
|
-
await
|
|
3001
|
+
await fsPromises19.writeFile(
|
|
3025
3002
|
rootPackagePath,
|
|
3026
3003
|
JSON.stringify(rootPkg, null, 2),
|
|
3027
3004
|
"utf8"
|
|
@@ -3045,8 +3022,8 @@ Error details: ${error.message || error}`));
|
|
|
3045
3022
|
// src/modules/quality/oxlint.ts
|
|
3046
3023
|
import { spinner as spinner11 } from "@clack/prompts";
|
|
3047
3024
|
import pc19 from "picocolors";
|
|
3048
|
-
import
|
|
3049
|
-
import
|
|
3025
|
+
import fsPromises20 from "fs/promises";
|
|
3026
|
+
import path21 from "path";
|
|
3050
3027
|
async function setupOxlint(projectPath) {
|
|
3051
3028
|
await runCommand("pnpm add -D -E oxlint -w", {
|
|
3052
3029
|
cwd: projectPath,
|
|
@@ -3063,19 +3040,19 @@ async function setupOxlint(projectPath) {
|
|
|
3063
3040
|
"no-debugger": "error"
|
|
3064
3041
|
}
|
|
3065
3042
|
};
|
|
3066
|
-
await
|
|
3067
|
-
|
|
3043
|
+
await fsPromises20.writeFile(
|
|
3044
|
+
path21.join(projectPath, ".oxlintrc.json"),
|
|
3068
3045
|
JSON.stringify(oxlintConfig, null, 2),
|
|
3069
3046
|
"utf8"
|
|
3070
3047
|
);
|
|
3071
|
-
const rootPackagePath =
|
|
3072
|
-
const rootPackageContent = await
|
|
3048
|
+
const rootPackagePath = path21.join(projectPath, "package.json");
|
|
3049
|
+
const rootPackageContent = await fsPromises20.readFile(rootPackagePath, "utf8");
|
|
3073
3050
|
const rootPkg = JSON.parse(rootPackageContent);
|
|
3074
3051
|
rootPkg.scripts = {
|
|
3075
3052
|
...rootPkg.scripts || {},
|
|
3076
3053
|
lint: "oxlint ."
|
|
3077
3054
|
};
|
|
3078
|
-
await
|
|
3055
|
+
await fsPromises20.writeFile(
|
|
3079
3056
|
rootPackagePath,
|
|
3080
3057
|
JSON.stringify(rootPkg, null, 2),
|
|
3081
3058
|
"utf8"
|
|
@@ -3100,8 +3077,8 @@ Error details: ${error.message || error}`));
|
|
|
3100
3077
|
// src/modules/quality/prettier.ts
|
|
3101
3078
|
import { confirm as confirm7, spinner as spinner12 } from "@clack/prompts";
|
|
3102
3079
|
import pc20 from "picocolors";
|
|
3103
|
-
import
|
|
3104
|
-
import
|
|
3080
|
+
import fsPromises21 from "fs/promises";
|
|
3081
|
+
import path22 from "path";
|
|
3105
3082
|
async function setupPrettier(projectPath) {
|
|
3106
3083
|
await runCommand("pnpm add -D -E prettier -w", {
|
|
3107
3084
|
cwd: projectPath,
|
|
@@ -3114,8 +3091,8 @@ async function setupPrettier(projectPath) {
|
|
|
3114
3091
|
tabWidth: 2,
|
|
3115
3092
|
printWidth: 80
|
|
3116
3093
|
};
|
|
3117
|
-
await
|
|
3118
|
-
|
|
3094
|
+
await fsPromises21.writeFile(
|
|
3095
|
+
path22.join(projectPath, ".prettierrc"),
|
|
3119
3096
|
JSON.stringify(prettierConfig, null, 2),
|
|
3120
3097
|
"utf8"
|
|
3121
3098
|
);
|
|
@@ -3127,19 +3104,19 @@ async function setupPrettier(projectPath) {
|
|
|
3127
3104
|
"pnpm-lock.yaml",
|
|
3128
3105
|
""
|
|
3129
3106
|
].join("\n");
|
|
3130
|
-
await
|
|
3131
|
-
|
|
3107
|
+
await fsPromises21.writeFile(
|
|
3108
|
+
path22.join(projectPath, ".prettierignore"),
|
|
3132
3109
|
prettierIgnore,
|
|
3133
3110
|
"utf8"
|
|
3134
3111
|
);
|
|
3135
|
-
const rootPackagePath =
|
|
3136
|
-
const rootPackageRaw = await
|
|
3112
|
+
const rootPackagePath = path22.join(projectPath, "package.json");
|
|
3113
|
+
const rootPackageRaw = await fsPromises21.readFile(rootPackagePath, "utf8");
|
|
3137
3114
|
const pkg = JSON.parse(rootPackageRaw);
|
|
3138
3115
|
pkg.scripts = {
|
|
3139
3116
|
...pkg.scripts || {},
|
|
3140
3117
|
format: "prettier --write ."
|
|
3141
3118
|
};
|
|
3142
|
-
await
|
|
3119
|
+
await fsPromises21.writeFile(
|
|
3143
3120
|
rootPackagePath,
|
|
3144
3121
|
JSON.stringify(pkg, null, 2),
|
|
3145
3122
|
"utf8"
|
|
@@ -3163,14 +3140,14 @@ Error details: ${error.message || error}`));
|
|
|
3163
3140
|
// src/modules/packages/typescript.ts
|
|
3164
3141
|
import { spinner as spinner13 } from "@clack/prompts";
|
|
3165
3142
|
import pc21 from "picocolors";
|
|
3166
|
-
import
|
|
3167
|
-
import
|
|
3143
|
+
import fsPromises22 from "fs/promises";
|
|
3144
|
+
import path23 from "path";
|
|
3168
3145
|
async function setupTypescript(projectPath) {
|
|
3169
|
-
const tsDir =
|
|
3170
|
-
await
|
|
3146
|
+
const tsDir = path23.join(projectPath, "packages", "typescript");
|
|
3147
|
+
await fsPromises22.mkdir(tsDir, { recursive: true });
|
|
3171
3148
|
await runCommand("pnpm init", { cwd: tsDir, silent: true });
|
|
3172
|
-
const tsPackagePath =
|
|
3173
|
-
const tsPackageRaw = await
|
|
3149
|
+
const tsPackagePath = path23.join(tsDir, "package.json");
|
|
3150
|
+
const tsPackageRaw = await fsPromises22.readFile(tsPackagePath, "utf8");
|
|
3174
3151
|
const tsPkg = JSON.parse(tsPackageRaw);
|
|
3175
3152
|
tsPkg.name = "@config/typescript";
|
|
3176
3153
|
tsPkg.version = "1.0.0";
|
|
@@ -3181,7 +3158,7 @@ async function setupTypescript(projectPath) {
|
|
|
3181
3158
|
delete tsPkg.keywords;
|
|
3182
3159
|
delete tsPkg.author;
|
|
3183
3160
|
delete tsPkg.license;
|
|
3184
|
-
await
|
|
3161
|
+
await fsPromises22.writeFile(
|
|
3185
3162
|
tsPackagePath,
|
|
3186
3163
|
JSON.stringify(tsPkg, null, 2),
|
|
3187
3164
|
"utf8"
|
|
@@ -3200,16 +3177,16 @@ async function setupTypescript(projectPath) {
|
|
|
3200
3177
|
isolatedModules: true
|
|
3201
3178
|
}
|
|
3202
3179
|
};
|
|
3203
|
-
await
|
|
3204
|
-
|
|
3180
|
+
await fsPromises22.writeFile(
|
|
3181
|
+
path23.join(tsDir, "tsconfig.json"),
|
|
3205
3182
|
JSON.stringify(tsconfigContent, null, 2),
|
|
3206
3183
|
"utf8"
|
|
3207
3184
|
);
|
|
3208
3185
|
}
|
|
3209
3186
|
async function runTypescriptSetup(projectPath) {
|
|
3210
|
-
const packagesDir =
|
|
3187
|
+
const packagesDir = path23.join(projectPath, "packages");
|
|
3211
3188
|
try {
|
|
3212
|
-
await
|
|
3189
|
+
await fsPromises22.access(packagesDir);
|
|
3213
3190
|
} catch {
|
|
3214
3191
|
return;
|
|
3215
3192
|
}
|
|
@@ -3231,14 +3208,14 @@ Error details: ${error.message || error}`));
|
|
|
3231
3208
|
}
|
|
3232
3209
|
|
|
3233
3210
|
// src/modules/apps/server/index.ts
|
|
3234
|
-
import
|
|
3235
|
-
import
|
|
3211
|
+
import fsPromises29 from "fs/promises";
|
|
3212
|
+
import path32 from "path";
|
|
3236
3213
|
import { spinner as spinner16 } from "@clack/prompts";
|
|
3237
3214
|
import pc24 from "picocolors";
|
|
3238
3215
|
|
|
3239
3216
|
// src/modules/apps/server/frameworks/express/index.ts
|
|
3240
|
-
import
|
|
3241
|
-
import
|
|
3217
|
+
import fsPromises23 from "fs/promises";
|
|
3218
|
+
import path24 from "path";
|
|
3242
3219
|
|
|
3243
3220
|
// src/modules/apps/server/frameworks/express/package.ts
|
|
3244
3221
|
function getExpressDependencies() {
|
|
@@ -3404,13 +3381,13 @@ function renderExpressBunTemplate(hasDb) {
|
|
|
3404
3381
|
// src/modules/apps/server/frameworks/express/index.ts
|
|
3405
3382
|
async function setupExpress(options) {
|
|
3406
3383
|
const { projectPath, runtime, linter, orm } = options;
|
|
3407
|
-
const serverDir =
|
|
3408
|
-
const srcDir =
|
|
3384
|
+
const serverDir = path24.join(projectPath, "apps", "server");
|
|
3385
|
+
const srcDir = path24.join(serverDir, "src");
|
|
3409
3386
|
const hasDb = orm !== "none";
|
|
3410
|
-
await
|
|
3387
|
+
await fsPromises23.mkdir(srcDir, { recursive: true });
|
|
3411
3388
|
await runCommand("pnpm init", { cwd: serverDir, silent: true });
|
|
3412
|
-
const serverPackagePath =
|
|
3413
|
-
const serverPackageRaw = await
|
|
3389
|
+
const serverPackagePath = path24.join(serverDir, "package.json");
|
|
3390
|
+
const serverPackageRaw = await fsPromises23.readFile(serverPackagePath, "utf8");
|
|
3414
3391
|
const serverPkg = JSON.parse(serverPackageRaw);
|
|
3415
3392
|
serverPkg.name = "server";
|
|
3416
3393
|
serverPkg.version = "1.0.0";
|
|
@@ -3430,7 +3407,7 @@ async function setupExpress(options) {
|
|
|
3430
3407
|
delete serverPkg.keywords;
|
|
3431
3408
|
delete serverPkg.author;
|
|
3432
3409
|
delete serverPkg.license;
|
|
3433
|
-
await
|
|
3410
|
+
await fsPromises23.writeFile(
|
|
3434
3411
|
serverPackagePath,
|
|
3435
3412
|
JSON.stringify(serverPkg, null, 2),
|
|
3436
3413
|
"utf8"
|
|
@@ -3443,8 +3420,8 @@ async function setupExpress(options) {
|
|
|
3443
3420
|
},
|
|
3444
3421
|
include: ["src/**/*"]
|
|
3445
3422
|
};
|
|
3446
|
-
await
|
|
3447
|
-
|
|
3423
|
+
await fsPromises23.writeFile(
|
|
3424
|
+
path24.join(serverDir, "tsconfig.json"),
|
|
3448
3425
|
JSON.stringify(tsconfigContent, null, 2),
|
|
3449
3426
|
"utf8"
|
|
3450
3427
|
);
|
|
@@ -3459,8 +3436,8 @@ async function setupExpress(options) {
|
|
|
3459
3436
|
"});",
|
|
3460
3437
|
""
|
|
3461
3438
|
].join("\n");
|
|
3462
|
-
await
|
|
3463
|
-
|
|
3439
|
+
await fsPromises23.writeFile(
|
|
3440
|
+
path24.join(serverDir, "tsdown.config.ts"),
|
|
3464
3441
|
tsdownConfigContent,
|
|
3465
3442
|
"utf8"
|
|
3466
3443
|
);
|
|
@@ -3475,16 +3452,16 @@ async function setupExpress(options) {
|
|
|
3475
3452
|
silent: true
|
|
3476
3453
|
});
|
|
3477
3454
|
const indexTsContent = runtime === "bun" ? renderExpressBunTemplate(hasDb) : renderExpressNodeTemplate(hasDb);
|
|
3478
|
-
await
|
|
3479
|
-
|
|
3455
|
+
await fsPromises23.writeFile(
|
|
3456
|
+
path24.join(srcDir, "index.ts"),
|
|
3480
3457
|
indexTsContent,
|
|
3481
3458
|
"utf8"
|
|
3482
3459
|
);
|
|
3483
3460
|
}
|
|
3484
3461
|
|
|
3485
3462
|
// src/modules/apps/server/frameworks/hono/index.ts
|
|
3486
|
-
import
|
|
3487
|
-
import
|
|
3463
|
+
import fsPromises24 from "fs/promises";
|
|
3464
|
+
import path25 from "path";
|
|
3488
3465
|
|
|
3489
3466
|
// src/modules/apps/server/frameworks/hono/package.ts
|
|
3490
3467
|
function getHonoDependencies(runtime) {
|
|
@@ -3655,13 +3632,13 @@ function renderHonoBunTemplate(hasDb) {
|
|
|
3655
3632
|
// src/modules/apps/server/frameworks/hono/index.ts
|
|
3656
3633
|
async function setupHono(options) {
|
|
3657
3634
|
const { projectPath, runtime, linter, orm } = options;
|
|
3658
|
-
const serverDir =
|
|
3659
|
-
const srcDir =
|
|
3635
|
+
const serverDir = path25.join(projectPath, "apps", "server");
|
|
3636
|
+
const srcDir = path25.join(serverDir, "src");
|
|
3660
3637
|
const hasDb = orm !== "none";
|
|
3661
|
-
await
|
|
3638
|
+
await fsPromises24.mkdir(srcDir, { recursive: true });
|
|
3662
3639
|
await runCommand("pnpm init", { cwd: serverDir, silent: true });
|
|
3663
|
-
const serverPackagePath =
|
|
3664
|
-
const serverPackageRaw = await
|
|
3640
|
+
const serverPackagePath = path25.join(serverDir, "package.json");
|
|
3641
|
+
const serverPackageRaw = await fsPromises24.readFile(serverPackagePath, "utf8");
|
|
3665
3642
|
const serverPkg = JSON.parse(serverPackageRaw);
|
|
3666
3643
|
serverPkg.name = "server";
|
|
3667
3644
|
serverPkg.version = "1.0.0";
|
|
@@ -3681,7 +3658,7 @@ async function setupHono(options) {
|
|
|
3681
3658
|
delete serverPkg.keywords;
|
|
3682
3659
|
delete serverPkg.author;
|
|
3683
3660
|
delete serverPkg.license;
|
|
3684
|
-
await
|
|
3661
|
+
await fsPromises24.writeFile(
|
|
3685
3662
|
serverPackagePath,
|
|
3686
3663
|
JSON.stringify(serverPkg, null, 2),
|
|
3687
3664
|
"utf8"
|
|
@@ -3694,8 +3671,8 @@ async function setupHono(options) {
|
|
|
3694
3671
|
},
|
|
3695
3672
|
include: ["src/**/*"]
|
|
3696
3673
|
};
|
|
3697
|
-
await
|
|
3698
|
-
|
|
3674
|
+
await fsPromises24.writeFile(
|
|
3675
|
+
path25.join(serverDir, "tsconfig.json"),
|
|
3699
3676
|
JSON.stringify(tsconfigContent, null, 2),
|
|
3700
3677
|
"utf8"
|
|
3701
3678
|
);
|
|
@@ -3710,8 +3687,8 @@ async function setupHono(options) {
|
|
|
3710
3687
|
"});",
|
|
3711
3688
|
""
|
|
3712
3689
|
].join("\n");
|
|
3713
|
-
await
|
|
3714
|
-
|
|
3690
|
+
await fsPromises24.writeFile(
|
|
3691
|
+
path25.join(serverDir, "tsdown.config.ts"),
|
|
3715
3692
|
tsdownConfigContent,
|
|
3716
3693
|
"utf8"
|
|
3717
3694
|
);
|
|
@@ -3726,8 +3703,8 @@ async function setupHono(options) {
|
|
|
3726
3703
|
silent: true
|
|
3727
3704
|
});
|
|
3728
3705
|
const indexTsContent = runtime === "bun" ? renderHonoBunTemplate(hasDb) : renderHonoNodeTemplate(hasDb);
|
|
3729
|
-
await
|
|
3730
|
-
|
|
3706
|
+
await fsPromises24.writeFile(
|
|
3707
|
+
path25.join(srcDir, "index.ts"),
|
|
3731
3708
|
indexTsContent,
|
|
3732
3709
|
"utf8"
|
|
3733
3710
|
);
|
|
@@ -3788,13 +3765,13 @@ async function promptServerDeployment(framework) {
|
|
|
3788
3765
|
}
|
|
3789
3766
|
|
|
3790
3767
|
// src/modules/apps/server/deployment/docker/index.ts
|
|
3791
|
-
import
|
|
3768
|
+
import path28 from "path";
|
|
3792
3769
|
import { spinner as spinner14 } from "@clack/prompts";
|
|
3793
3770
|
import pc22 from "picocolors";
|
|
3794
3771
|
|
|
3795
3772
|
// src/modules/apps/server/deployment/docker/express-docker.ts
|
|
3796
|
-
import
|
|
3797
|
-
import
|
|
3773
|
+
import fsPromises25 from "fs/promises";
|
|
3774
|
+
import path26 from "path";
|
|
3798
3775
|
function getExpressDockerfile(runtime) {
|
|
3799
3776
|
if (runtime === "bun") {
|
|
3800
3777
|
return [
|
|
@@ -3860,8 +3837,8 @@ function getExpressDockerfile(runtime) {
|
|
|
3860
3837
|
}
|
|
3861
3838
|
async function setupExpressDocker(serverDir, runtime) {
|
|
3862
3839
|
const dockerfileContent = getExpressDockerfile(runtime);
|
|
3863
|
-
await
|
|
3864
|
-
|
|
3840
|
+
await fsPromises25.writeFile(
|
|
3841
|
+
path26.join(serverDir, "Dockerfile"),
|
|
3865
3842
|
dockerfileContent,
|
|
3866
3843
|
"utf8"
|
|
3867
3844
|
);
|
|
@@ -3872,16 +3849,16 @@ async function setupExpressDocker(serverDir, runtime) {
|
|
|
3872
3849
|
".env.local",
|
|
3873
3850
|
""
|
|
3874
3851
|
].join("\n");
|
|
3875
|
-
await
|
|
3876
|
-
|
|
3852
|
+
await fsPromises25.writeFile(
|
|
3853
|
+
path26.join(serverDir, ".dockerignore"),
|
|
3877
3854
|
dockerignoreContent,
|
|
3878
3855
|
"utf8"
|
|
3879
3856
|
);
|
|
3880
3857
|
}
|
|
3881
3858
|
|
|
3882
3859
|
// src/modules/apps/server/deployment/docker/hono-docker.ts
|
|
3883
|
-
import
|
|
3884
|
-
import
|
|
3860
|
+
import fsPromises26 from "fs/promises";
|
|
3861
|
+
import path27 from "path";
|
|
3885
3862
|
function getHonoDockerfile(runtime) {
|
|
3886
3863
|
if (runtime === "bun") {
|
|
3887
3864
|
return [
|
|
@@ -3947,8 +3924,8 @@ function getHonoDockerfile(runtime) {
|
|
|
3947
3924
|
}
|
|
3948
3925
|
async function setupHonoDocker(serverDir, runtime) {
|
|
3949
3926
|
const dockerfileContent = getHonoDockerfile(runtime);
|
|
3950
|
-
await
|
|
3951
|
-
|
|
3927
|
+
await fsPromises26.writeFile(
|
|
3928
|
+
path27.join(serverDir, "Dockerfile"),
|
|
3952
3929
|
dockerfileContent,
|
|
3953
3930
|
"utf8"
|
|
3954
3931
|
);
|
|
@@ -3959,8 +3936,8 @@ async function setupHonoDocker(serverDir, runtime) {
|
|
|
3959
3936
|
".env.local",
|
|
3960
3937
|
""
|
|
3961
3938
|
].join("\n");
|
|
3962
|
-
await
|
|
3963
|
-
|
|
3939
|
+
await fsPromises26.writeFile(
|
|
3940
|
+
path27.join(serverDir, ".dockerignore"),
|
|
3964
3941
|
dockerignoreContent,
|
|
3965
3942
|
"utf8"
|
|
3966
3943
|
);
|
|
@@ -3969,7 +3946,7 @@ async function setupHonoDocker(serverDir, runtime) {
|
|
|
3969
3946
|
// src/modules/apps/server/deployment/docker/index.ts
|
|
3970
3947
|
async function setupDockerDeployment(options) {
|
|
3971
3948
|
const { projectPath, framework, runtime } = options;
|
|
3972
|
-
const serverDir =
|
|
3949
|
+
const serverDir = path28.join(projectPath, "apps", "server");
|
|
3973
3950
|
const frameworkLabel = framework === "express" ? "Express" : "Hono";
|
|
3974
3951
|
const runtimeLabel = runtime === "bun" ? "Bun" : "Node.js";
|
|
3975
3952
|
const s = spinner14();
|
|
@@ -3994,13 +3971,13 @@ async function setupDockerDeployment(options) {
|
|
|
3994
3971
|
}
|
|
3995
3972
|
|
|
3996
3973
|
// src/modules/apps/server/deployment/vercel/index.ts
|
|
3997
|
-
import
|
|
3974
|
+
import path31 from "path";
|
|
3998
3975
|
import { spinner as spinner15 } from "@clack/prompts";
|
|
3999
3976
|
import pc23 from "picocolors";
|
|
4000
3977
|
|
|
4001
3978
|
// src/modules/apps/server/deployment/vercel/express-vercel.ts
|
|
4002
|
-
import
|
|
4003
|
-
import
|
|
3979
|
+
import fsPromises27 from "fs/promises";
|
|
3980
|
+
import path29 from "path";
|
|
4004
3981
|
async function setupExpressVercel(serverDir, _runtime) {
|
|
4005
3982
|
const vercelConfig = {
|
|
4006
3983
|
version: 2,
|
|
@@ -4017,16 +3994,16 @@ async function setupExpressVercel(serverDir, _runtime) {
|
|
|
4017
3994
|
}
|
|
4018
3995
|
]
|
|
4019
3996
|
};
|
|
4020
|
-
await
|
|
4021
|
-
|
|
3997
|
+
await fsPromises27.writeFile(
|
|
3998
|
+
path29.join(serverDir, "vercel.json"),
|
|
4022
3999
|
JSON.stringify(vercelConfig, null, 2),
|
|
4023
4000
|
"utf8"
|
|
4024
4001
|
);
|
|
4025
4002
|
}
|
|
4026
4003
|
|
|
4027
4004
|
// src/modules/apps/server/deployment/vercel/hono-vercel.ts
|
|
4028
|
-
import
|
|
4029
|
-
import
|
|
4005
|
+
import fsPromises28 from "fs/promises";
|
|
4006
|
+
import path30 from "path";
|
|
4030
4007
|
async function setupHonoVercel(serverDir, runtime) {
|
|
4031
4008
|
const vercelConfig = {
|
|
4032
4009
|
version: 2,
|
|
@@ -4043,8 +4020,8 @@ async function setupHonoVercel(serverDir, runtime) {
|
|
|
4043
4020
|
}
|
|
4044
4021
|
]
|
|
4045
4022
|
};
|
|
4046
|
-
await
|
|
4047
|
-
|
|
4023
|
+
await fsPromises28.writeFile(
|
|
4024
|
+
path30.join(serverDir, "vercel.json"),
|
|
4048
4025
|
JSON.stringify(vercelConfig, null, 2),
|
|
4049
4026
|
"utf8"
|
|
4050
4027
|
);
|
|
@@ -4053,9 +4030,9 @@ async function setupHonoVercel(serverDir, runtime) {
|
|
|
4053
4030
|
cwd: serverDir,
|
|
4054
4031
|
silent: true
|
|
4055
4032
|
});
|
|
4056
|
-
const indexTsPath =
|
|
4033
|
+
const indexTsPath = path30.join(serverDir, "src", "index.ts");
|
|
4057
4034
|
try {
|
|
4058
|
-
let content = await
|
|
4035
|
+
let content = await fsPromises28.readFile(indexTsPath, "utf8");
|
|
4059
4036
|
if (!content.includes("@hono/node-server")) {
|
|
4060
4037
|
content = "import { getRequestListener } from '@hono/node-server';\n" + content;
|
|
4061
4038
|
}
|
|
@@ -4065,7 +4042,7 @@ async function setupHonoVercel(serverDir, runtime) {
|
|
|
4065
4042
|
"export default process.env.VERCEL\n ? getRequestListener(app.fetch)\n : {\n port,\n fetch: app.fetch,\n };"
|
|
4066
4043
|
);
|
|
4067
4044
|
}
|
|
4068
|
-
await
|
|
4045
|
+
await fsPromises28.writeFile(indexTsPath, content, "utf8");
|
|
4069
4046
|
} catch {
|
|
4070
4047
|
}
|
|
4071
4048
|
}
|
|
@@ -4074,7 +4051,7 @@ async function setupHonoVercel(serverDir, runtime) {
|
|
|
4074
4051
|
// src/modules/apps/server/deployment/vercel/index.ts
|
|
4075
4052
|
async function setupVercelDeployment(options) {
|
|
4076
4053
|
const { projectPath, framework, runtime } = options;
|
|
4077
|
-
const serverDir =
|
|
4054
|
+
const serverDir = path31.join(projectPath, "apps", "server");
|
|
4078
4055
|
const frameworkLabel = framework === "express" ? "Express" : "Hono";
|
|
4079
4056
|
const s = spinner15();
|
|
4080
4057
|
s.start(
|
|
@@ -4108,9 +4085,9 @@ async function setupServerDeployment(options) {
|
|
|
4108
4085
|
|
|
4109
4086
|
// src/modules/apps/server/index.ts
|
|
4110
4087
|
async function runServerSetup(projectPath, framework, linter = "none", orm = "none", runtime = "node") {
|
|
4111
|
-
const appsDir =
|
|
4088
|
+
const appsDir = path32.join(projectPath, "apps");
|
|
4112
4089
|
try {
|
|
4113
|
-
await
|
|
4090
|
+
await fsPromises29.access(appsDir);
|
|
4114
4091
|
} catch {
|
|
4115
4092
|
return;
|
|
4116
4093
|
}
|
|
@@ -4181,8 +4158,8 @@ async function addWeb(projectPath) {
|
|
|
4181
4158
|
}
|
|
4182
4159
|
|
|
4183
4160
|
// src/modules/packages/env/index.ts
|
|
4184
|
-
import
|
|
4185
|
-
import
|
|
4161
|
+
import fsPromises30 from "fs/promises";
|
|
4162
|
+
import path33 from "path";
|
|
4186
4163
|
import { confirm as confirm8, spinner as spinner17 } from "@clack/prompts";
|
|
4187
4164
|
import pc25 from "picocolors";
|
|
4188
4165
|
|
|
@@ -4546,13 +4523,13 @@ async function promptEnv() {
|
|
|
4546
4523
|
}
|
|
4547
4524
|
async function addDependencyToPackage(pkgJsonPath, depName, depVersion) {
|
|
4548
4525
|
try {
|
|
4549
|
-
const raw = await
|
|
4526
|
+
const raw = await fsPromises30.readFile(pkgJsonPath, "utf8");
|
|
4550
4527
|
const pkg = JSON.parse(raw);
|
|
4551
4528
|
pkg.dependencies = {
|
|
4552
4529
|
...pkg.dependencies || {},
|
|
4553
4530
|
[depName]: depVersion
|
|
4554
4531
|
};
|
|
4555
|
-
await
|
|
4532
|
+
await fsPromises30.writeFile(
|
|
4556
4533
|
pkgJsonPath,
|
|
4557
4534
|
JSON.stringify(pkg, null, 2),
|
|
4558
4535
|
"utf8"
|
|
@@ -4561,11 +4538,11 @@ async function addDependencyToPackage(pkgJsonPath, depName, depVersion) {
|
|
|
4561
4538
|
}
|
|
4562
4539
|
}
|
|
4563
4540
|
async function updateDbForEnv(projectPath, dialect) {
|
|
4564
|
-
const dbDir =
|
|
4565
|
-
const clientFile =
|
|
4566
|
-
const drizzleConfigFile =
|
|
4541
|
+
const dbDir = path33.join(projectPath, "packages", "db");
|
|
4542
|
+
const clientFile = path33.join(dbDir, "src", "client.ts");
|
|
4543
|
+
const drizzleConfigFile = path33.join(dbDir, "drizzle.config.ts");
|
|
4567
4544
|
try {
|
|
4568
|
-
const content = await
|
|
4545
|
+
const content = await fsPromises30.readFile(clientFile, "utf8");
|
|
4569
4546
|
let newContent = "";
|
|
4570
4547
|
if (content.includes("drizzle-orm/libsql")) {
|
|
4571
4548
|
newContent = [
|
|
@@ -4623,7 +4600,7 @@ async function updateDbForEnv(projectPath, dialect) {
|
|
|
4623
4600
|
].join("\n");
|
|
4624
4601
|
}
|
|
4625
4602
|
if (newContent) {
|
|
4626
|
-
await
|
|
4603
|
+
await fsPromises30.writeFile(clientFile, newContent, "utf8");
|
|
4627
4604
|
}
|
|
4628
4605
|
} catch {
|
|
4629
4606
|
}
|
|
@@ -4645,14 +4622,14 @@ async function updateDbForEnv(projectPath, dialect) {
|
|
|
4645
4622
|
"});",
|
|
4646
4623
|
""
|
|
4647
4624
|
].join("\n");
|
|
4648
|
-
await
|
|
4625
|
+
await fsPromises30.writeFile(drizzleConfigFile, newDrizzleConfig, "utf8");
|
|
4649
4626
|
} catch {
|
|
4650
4627
|
}
|
|
4651
4628
|
}
|
|
4652
4629
|
async function updateServerEntryForEnv(projectPath) {
|
|
4653
|
-
const indexFile =
|
|
4630
|
+
const indexFile = path33.join(projectPath, "apps", "server", "src", "index.ts");
|
|
4654
4631
|
try {
|
|
4655
|
-
let content = await
|
|
4632
|
+
let content = await fsPromises30.readFile(indexFile, "utf8");
|
|
4656
4633
|
if (!content.includes("@repo/env")) {
|
|
4657
4634
|
content = "import { env } from '@repo/env';\n" + content;
|
|
4658
4635
|
}
|
|
@@ -4668,7 +4645,7 @@ async function updateServerEntryForEnv(projectPath) {
|
|
|
4668
4645
|
/app\.use\('\*', cors\(\)\);/,
|
|
4669
4646
|
"app.use('*', cors({ origin: env.server.CORS_ORIGIN }));"
|
|
4670
4647
|
);
|
|
4671
|
-
await
|
|
4648
|
+
await fsPromises30.writeFile(indexFile, content, "utf8");
|
|
4672
4649
|
} catch {
|
|
4673
4650
|
}
|
|
4674
4651
|
}
|
|
@@ -4683,13 +4660,13 @@ async function setupEnvPackage(options) {
|
|
|
4683
4660
|
webFramework
|
|
4684
4661
|
} = options;
|
|
4685
4662
|
const hasWebEnv = webFramework !== "skip" || Boolean(hasAuth);
|
|
4686
|
-
const envDir =
|
|
4687
|
-
const srcDir =
|
|
4688
|
-
const schemaDir =
|
|
4689
|
-
await
|
|
4663
|
+
const envDir = path33.join(projectPath, "packages", "env");
|
|
4664
|
+
const srcDir = path33.join(envDir, "src");
|
|
4665
|
+
const schemaDir = path33.join(srcDir, "schema");
|
|
4666
|
+
await fsPromises30.mkdir(schemaDir, { recursive: true });
|
|
4690
4667
|
const pkgContent = getEnvPackageJson(options);
|
|
4691
|
-
await
|
|
4692
|
-
|
|
4668
|
+
await fsPromises30.writeFile(
|
|
4669
|
+
path33.join(envDir, "package.json"),
|
|
4693
4670
|
JSON.stringify(pkgContent, null, 2),
|
|
4694
4671
|
"utf8"
|
|
4695
4672
|
);
|
|
@@ -4701,56 +4678,56 @@ async function setupEnvPackage(options) {
|
|
|
4701
4678
|
},
|
|
4702
4679
|
include: ["src/**/*"]
|
|
4703
4680
|
};
|
|
4704
|
-
await
|
|
4705
|
-
|
|
4681
|
+
await fsPromises30.writeFile(
|
|
4682
|
+
path33.join(envDir, "tsconfig.json"),
|
|
4706
4683
|
JSON.stringify(tsconfig, null, 2),
|
|
4707
4684
|
"utf8"
|
|
4708
4685
|
);
|
|
4709
4686
|
const createEnvCode = renderCreateEnvTemplate();
|
|
4710
|
-
await
|
|
4711
|
-
|
|
4687
|
+
await fsPromises30.writeFile(
|
|
4688
|
+
path33.join(srcDir, "create-env.ts"),
|
|
4712
4689
|
createEnvCode,
|
|
4713
4690
|
"utf8"
|
|
4714
4691
|
);
|
|
4715
4692
|
if (hasDb) {
|
|
4716
4693
|
const dbCode = renderDbEnvTemplate(options);
|
|
4717
|
-
await
|
|
4694
|
+
await fsPromises30.writeFile(path33.join(schemaDir, "db.ts"), dbCode, "utf8");
|
|
4718
4695
|
}
|
|
4719
4696
|
if (hasDocker) {
|
|
4720
4697
|
const dockerCode = renderDockerEnvTemplate(options);
|
|
4721
|
-
await
|
|
4722
|
-
|
|
4698
|
+
await fsPromises30.writeFile(
|
|
4699
|
+
path33.join(schemaDir, "docker.ts"),
|
|
4723
4700
|
dockerCode,
|
|
4724
4701
|
"utf8"
|
|
4725
4702
|
);
|
|
4726
4703
|
}
|
|
4727
4704
|
if (hasServer || hasDb) {
|
|
4728
4705
|
const serverCode = renderServerEnvTemplate(options);
|
|
4729
|
-
await
|
|
4730
|
-
|
|
4706
|
+
await fsPromises30.writeFile(
|
|
4707
|
+
path33.join(schemaDir, "server.ts"),
|
|
4731
4708
|
serverCode,
|
|
4732
4709
|
"utf8"
|
|
4733
4710
|
);
|
|
4734
4711
|
}
|
|
4735
4712
|
if (hasAuth) {
|
|
4736
4713
|
const authCode = renderAuthEnvTemplate(options);
|
|
4737
|
-
await
|
|
4738
|
-
|
|
4714
|
+
await fsPromises30.writeFile(
|
|
4715
|
+
path33.join(schemaDir, "auth.ts"),
|
|
4739
4716
|
authCode,
|
|
4740
4717
|
"utf8"
|
|
4741
4718
|
);
|
|
4742
4719
|
}
|
|
4743
4720
|
if (hasWebEnv) {
|
|
4744
4721
|
const webCode = renderWebEnvTemplate(options);
|
|
4745
|
-
await
|
|
4722
|
+
await fsPromises30.writeFile(path33.join(schemaDir, "web.ts"), webCode, "utf8");
|
|
4746
4723
|
}
|
|
4747
4724
|
const checkCode = renderCheckEnvTemplate(options);
|
|
4748
|
-
await
|
|
4725
|
+
await fsPromises30.writeFile(path33.join(srcDir, "check.ts"), checkCode, "utf8");
|
|
4749
4726
|
const indexCode = renderIndexEnvTemplate(options);
|
|
4750
|
-
await
|
|
4727
|
+
await fsPromises30.writeFile(path33.join(srcDir, "index.ts"), indexCode, "utf8");
|
|
4751
4728
|
if (hasDb) {
|
|
4752
4729
|
await addDependencyToPackage(
|
|
4753
|
-
|
|
4730
|
+
path33.join(projectPath, "packages", "db", "package.json"),
|
|
4754
4731
|
"@repo/env",
|
|
4755
4732
|
"workspace:*"
|
|
4756
4733
|
);
|
|
@@ -4758,7 +4735,7 @@ async function setupEnvPackage(options) {
|
|
|
4758
4735
|
}
|
|
4759
4736
|
if (hasServer) {
|
|
4760
4737
|
await addDependencyToPackage(
|
|
4761
|
-
|
|
4738
|
+
path33.join(projectPath, "apps", "server", "package.json"),
|
|
4762
4739
|
"@repo/env",
|
|
4763
4740
|
"workspace:*"
|
|
4764
4741
|
);
|
|
@@ -4766,21 +4743,21 @@ async function setupEnvPackage(options) {
|
|
|
4766
4743
|
}
|
|
4767
4744
|
if (hasAuth) {
|
|
4768
4745
|
await addDependencyToPackage(
|
|
4769
|
-
|
|
4746
|
+
path33.join(projectPath, "packages", "auth", "package.json"),
|
|
4770
4747
|
"@repo/env",
|
|
4771
4748
|
"workspace:*"
|
|
4772
4749
|
);
|
|
4773
4750
|
}
|
|
4774
4751
|
if (webFramework !== "skip") {
|
|
4775
|
-
const appsDir =
|
|
4752
|
+
const appsDir = path33.join(projectPath, "apps");
|
|
4776
4753
|
try {
|
|
4777
|
-
const entries = await
|
|
4754
|
+
const entries = await fsPromises30.readdir(appsDir, {
|
|
4778
4755
|
withFileTypes: true
|
|
4779
4756
|
});
|
|
4780
4757
|
for (const entry of entries) {
|
|
4781
4758
|
if (entry.isDirectory() && entry.name !== "server") {
|
|
4782
4759
|
await addDependencyToPackage(
|
|
4783
|
-
|
|
4760
|
+
path33.join(appsDir, entry.name, "package.json"),
|
|
4784
4761
|
"@repo/env",
|
|
4785
4762
|
"workspace:*"
|
|
4786
4763
|
);
|
|
@@ -4809,8 +4786,8 @@ Error details: ${error.message || error}`));
|
|
|
4809
4786
|
}
|
|
4810
4787
|
|
|
4811
4788
|
// src/modules/packages/auth/index.ts
|
|
4812
|
-
import
|
|
4813
|
-
import
|
|
4789
|
+
import fsPromises31 from "fs/promises";
|
|
4790
|
+
import path34 from "path";
|
|
4814
4791
|
import { confirm as confirm9, spinner as spinner18 } from "@clack/prompts";
|
|
4815
4792
|
import pc26 from "picocolors";
|
|
4816
4793
|
async function promptAuth() {
|
|
@@ -4826,11 +4803,11 @@ async function setupAuth(options) {
|
|
|
4826
4803
|
const s = spinner18();
|
|
4827
4804
|
s.start("Configuring shared Better Auth package (@repo/auth)...");
|
|
4828
4805
|
try {
|
|
4829
|
-
const authDir =
|
|
4830
|
-
const authSrcDir =
|
|
4831
|
-
await
|
|
4832
|
-
const authLibDir =
|
|
4833
|
-
await
|
|
4806
|
+
const authDir = path34.join(projectPath, "packages", "auth");
|
|
4807
|
+
const authSrcDir = path34.join(authDir, "src");
|
|
4808
|
+
await fsPromises31.mkdir(authSrcDir, { recursive: true });
|
|
4809
|
+
const authLibDir = path34.join(authSrcDir, "lib");
|
|
4810
|
+
await fsPromises31.mkdir(authLibDir, { recursive: true });
|
|
4834
4811
|
const authPkg = {
|
|
4835
4812
|
name: "@repo/auth",
|
|
4836
4813
|
version: "1.0.0",
|
|
@@ -4866,8 +4843,8 @@ async function setupAuth(options) {
|
|
|
4866
4843
|
typescript: "^5.7.3"
|
|
4867
4844
|
}
|
|
4868
4845
|
};
|
|
4869
|
-
await
|
|
4870
|
-
|
|
4846
|
+
await fsPromises31.writeFile(
|
|
4847
|
+
path34.join(authDir, "package.json"),
|
|
4871
4848
|
JSON.stringify(authPkg, null, 2),
|
|
4872
4849
|
"utf8"
|
|
4873
4850
|
);
|
|
@@ -4879,8 +4856,8 @@ async function setupAuth(options) {
|
|
|
4879
4856
|
},
|
|
4880
4857
|
include: ["src/**/*"]
|
|
4881
4858
|
};
|
|
4882
|
-
await
|
|
4883
|
-
|
|
4859
|
+
await fsPromises31.writeFile(
|
|
4860
|
+
path34.join(authDir, "tsconfig.json"),
|
|
4884
4861
|
JSON.stringify(tsconfig, null, 2),
|
|
4885
4862
|
"utf8"
|
|
4886
4863
|
);
|
|
@@ -4924,8 +4901,8 @@ async function setupAuth(options) {
|
|
|
4924
4901
|
`export const isProduction = ${isProdExpr};`,
|
|
4925
4902
|
""
|
|
4926
4903
|
);
|
|
4927
|
-
await
|
|
4928
|
-
|
|
4904
|
+
await fsPromises31.writeFile(
|
|
4905
|
+
path34.join(authLibDir, "origins.ts"),
|
|
4929
4906
|
originsLibLines.join("\n"),
|
|
4930
4907
|
"utf8"
|
|
4931
4908
|
);
|
|
@@ -4995,8 +4972,8 @@ async function setupAuth(options) {
|
|
|
4995
4972
|
"export type Auth = typeof auth;",
|
|
4996
4973
|
""
|
|
4997
4974
|
);
|
|
4998
|
-
await
|
|
4999
|
-
|
|
4975
|
+
await fsPromises31.writeFile(
|
|
4976
|
+
path34.join(authLibDir, "auth.ts"),
|
|
5000
4977
|
authLibLines.join("\n"),
|
|
5001
4978
|
"utf8"
|
|
5002
4979
|
);
|
|
@@ -5007,8 +4984,8 @@ async function setupAuth(options) {
|
|
|
5007
4984
|
"export { origins, trustedOrigins, isProduction } from './lib/origins.js';",
|
|
5008
4985
|
""
|
|
5009
4986
|
].join("\n");
|
|
5010
|
-
await
|
|
5011
|
-
|
|
4987
|
+
await fsPromises31.writeFile(
|
|
4988
|
+
path34.join(authSrcDir, "origins.ts"),
|
|
5012
4989
|
originsReexport,
|
|
5013
4990
|
"utf8"
|
|
5014
4991
|
);
|
|
@@ -5021,14 +4998,14 @@ async function setupAuth(options) {
|
|
|
5021
4998
|
"export { origins, trustedOrigins, isProduction } from './lib/origins.js';",
|
|
5022
4999
|
""
|
|
5023
5000
|
].join("\n");
|
|
5024
|
-
await
|
|
5025
|
-
|
|
5001
|
+
await fsPromises31.writeFile(
|
|
5002
|
+
path34.join(authSrcDir, "index.ts"),
|
|
5026
5003
|
authIndexContent,
|
|
5027
5004
|
"utf8"
|
|
5028
5005
|
);
|
|
5029
|
-
const dbDir =
|
|
5030
|
-
const schemaDir =
|
|
5031
|
-
await
|
|
5006
|
+
const dbDir = path34.join(projectPath, "packages", "db");
|
|
5007
|
+
const schemaDir = path34.join(dbDir, "src", "schema");
|
|
5008
|
+
await fsPromises31.mkdir(schemaDir, { recursive: true });
|
|
5032
5009
|
let authSchemaContent;
|
|
5033
5010
|
if (isSqlite) {
|
|
5034
5011
|
authSchemaContent = [
|
|
@@ -5151,43 +5128,43 @@ async function setupAuth(options) {
|
|
|
5151
5128
|
""
|
|
5152
5129
|
].join("\n");
|
|
5153
5130
|
}
|
|
5154
|
-
await
|
|
5155
|
-
|
|
5131
|
+
await fsPromises31.writeFile(
|
|
5132
|
+
path34.join(schemaDir, "auth.ts"),
|
|
5156
5133
|
authSchemaContent,
|
|
5157
5134
|
"utf8"
|
|
5158
5135
|
);
|
|
5159
|
-
const schemaIndexPath =
|
|
5136
|
+
const schemaIndexPath = path34.join(schemaDir, "index.ts");
|
|
5160
5137
|
try {
|
|
5161
|
-
const existing = await
|
|
5138
|
+
const existing = await fsPromises31.readFile(schemaIndexPath, "utf8");
|
|
5162
5139
|
if (!existing.includes("from './auth.js'") && !existing.includes("from './auth'")) {
|
|
5163
5140
|
const updated = `${existing}
|
|
5164
5141
|
export * from './auth.js';
|
|
5165
5142
|
`;
|
|
5166
|
-
await
|
|
5143
|
+
await fsPromises31.writeFile(schemaIndexPath, updated, "utf8");
|
|
5167
5144
|
}
|
|
5168
5145
|
} catch {
|
|
5169
5146
|
}
|
|
5170
5147
|
if (hasServer && serverFramework !== "none") {
|
|
5171
|
-
const serverDir =
|
|
5172
|
-
const serverPkgPath =
|
|
5148
|
+
const serverDir = path34.join(projectPath, "apps", "server");
|
|
5149
|
+
const serverPkgPath = path34.join(serverDir, "package.json");
|
|
5173
5150
|
try {
|
|
5174
|
-
const rawPkg = await
|
|
5151
|
+
const rawPkg = await fsPromises31.readFile(serverPkgPath, "utf8");
|
|
5175
5152
|
const pkg = JSON.parse(rawPkg);
|
|
5176
5153
|
pkg.dependencies = pkg.dependencies || {};
|
|
5177
5154
|
pkg.dependencies["@repo/auth"] = "workspace:*";
|
|
5178
5155
|
if (serverFramework === "express") {
|
|
5179
5156
|
pkg.dependencies["better-auth"] = "^1.1.21";
|
|
5180
5157
|
}
|
|
5181
|
-
await
|
|
5158
|
+
await fsPromises31.writeFile(
|
|
5182
5159
|
serverPkgPath,
|
|
5183
5160
|
JSON.stringify(pkg, null, 2),
|
|
5184
5161
|
"utf8"
|
|
5185
5162
|
);
|
|
5186
5163
|
} catch {
|
|
5187
5164
|
}
|
|
5188
|
-
const serverIndexPath =
|
|
5165
|
+
const serverIndexPath = path34.join(serverDir, "src", "index.ts");
|
|
5189
5166
|
try {
|
|
5190
|
-
let content = await
|
|
5167
|
+
let content = await fsPromises31.readFile(serverIndexPath, "utf8");
|
|
5191
5168
|
if (serverFramework === "express") {
|
|
5192
5169
|
if (!content.includes("@repo/auth")) {
|
|
5193
5170
|
content = content.replace(
|
|
@@ -5202,7 +5179,7 @@ export * from './auth.js';
|
|
|
5202
5179
|
"app.use(express.json());",
|
|
5203
5180
|
"// Mount Better Auth endpoints (/api/auth/*)\napp.all('/api/auth/*', toNodeHandler(auth));\n\napp.use(express.json());"
|
|
5204
5181
|
);
|
|
5205
|
-
await
|
|
5182
|
+
await fsPromises31.writeFile(serverIndexPath, content, "utf8");
|
|
5206
5183
|
}
|
|
5207
5184
|
} else if (serverFramework === "hono") {
|
|
5208
5185
|
if (!content.includes("@repo/auth")) {
|
|
@@ -5218,7 +5195,7 @@ export * from './auth.js';
|
|
|
5218
5195
|
"const app = new Hono();",
|
|
5219
5196
|
"const app = new Hono();\n\n// Mount Better Auth API handler\napp.on(['POST', 'GET'], '/api/auth/**', (c) => {\n return auth.handler(c.req.raw);\n});"
|
|
5220
5197
|
);
|
|
5221
|
-
await
|
|
5198
|
+
await fsPromises31.writeFile(serverIndexPath, content, "utf8");
|
|
5222
5199
|
}
|
|
5223
5200
|
}
|
|
5224
5201
|
} catch {
|
|
@@ -5232,11 +5209,11 @@ export * from './auth.js';
|
|
|
5232
5209
|
""
|
|
5233
5210
|
].join("\n");
|
|
5234
5211
|
for (const envFileName of [".env", ".env.example"]) {
|
|
5235
|
-
const envFilePath =
|
|
5212
|
+
const envFilePath = path34.join(projectPath, envFileName);
|
|
5236
5213
|
try {
|
|
5237
|
-
const raw = await
|
|
5214
|
+
const raw = await fsPromises31.readFile(envFilePath, "utf8");
|
|
5238
5215
|
if (!raw.includes("BETTER_AUTH_SECRET")) {
|
|
5239
|
-
await
|
|
5216
|
+
await fsPromises31.appendFile(
|
|
5240
5217
|
envFilePath,
|
|
5241
5218
|
`
|
|
5242
5219
|
${envLinesToAdd}`,
|
|
@@ -5261,8 +5238,8 @@ Error details: ${error.message || error}`));
|
|
|
5261
5238
|
// src/modules/docker/index.ts
|
|
5262
5239
|
import { spinner as spinner19 } from "@clack/prompts";
|
|
5263
5240
|
import pc27 from "picocolors";
|
|
5264
|
-
import
|
|
5265
|
-
import
|
|
5241
|
+
import fsPromises32 from "fs/promises";
|
|
5242
|
+
import path35 from "path";
|
|
5266
5243
|
async function setupDocker(projectPath, options) {
|
|
5267
5244
|
if (!options.postgres && !options.redis) {
|
|
5268
5245
|
return;
|
|
@@ -5270,8 +5247,8 @@ async function setupDocker(projectPath, options) {
|
|
|
5270
5247
|
const s = spinner19();
|
|
5271
5248
|
s.start("Configuring root Docker infrastructure in docker/...");
|
|
5272
5249
|
try {
|
|
5273
|
-
const dockerDir =
|
|
5274
|
-
await
|
|
5250
|
+
const dockerDir = path35.join(projectPath, "docker");
|
|
5251
|
+
await fsPromises32.mkdir(dockerDir, { recursive: true });
|
|
5275
5252
|
const safeName = options.projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
5276
5253
|
const services = [];
|
|
5277
5254
|
const volumes = [];
|
|
@@ -5333,8 +5310,8 @@ async function setupDocker(projectPath, options) {
|
|
|
5333
5310
|
volumes.join("\n"),
|
|
5334
5311
|
""
|
|
5335
5312
|
].join("\n");
|
|
5336
|
-
await
|
|
5337
|
-
|
|
5313
|
+
await fsPromises32.writeFile(
|
|
5314
|
+
path35.join(dockerDir, "docker-compose.yml"),
|
|
5338
5315
|
composeContent,
|
|
5339
5316
|
"utf8"
|
|
5340
5317
|
);
|
|
@@ -5360,7 +5337,7 @@ async function runWorkspaceScaffolder(options = {}) {
|
|
|
5360
5337
|
await runPreflightChecks();
|
|
5361
5338
|
const isMonorepo = !options.react && !options.next;
|
|
5362
5339
|
const name = await promptWorkspaceName(isMonorepo);
|
|
5363
|
-
const projectPath =
|
|
5340
|
+
const projectPath = path36.join(process.cwd(), name);
|
|
5364
5341
|
await checkTargetDirectory(projectPath, name);
|
|
5365
5342
|
if (options.react) {
|
|
5366
5343
|
await runReactScaffolder(name, projectPath);
|
|
@@ -5507,6 +5484,7 @@ async function runWorkspaceScaffolder(options = {}) {
|
|
|
5507
5484
|
}
|
|
5508
5485
|
});
|
|
5509
5486
|
await promptAndInstallSkills(projectPath);
|
|
5487
|
+
await removeBunLockfiles(projectPath);
|
|
5510
5488
|
const s = spinner20();
|
|
5511
5489
|
s.start("Running final workspace package installation...");
|
|
5512
5490
|
try {
|
|
@@ -5534,6 +5512,8 @@ Error details: ${error.message || error}`));
|
|
|
5534
5512
|
}
|
|
5535
5513
|
|
|
5536
5514
|
// src/index.ts
|
|
5515
|
+
process.env.NODE_OPTIONS = `${process.env.NODE_OPTIONS || ""} --no-deprecation`.trim();
|
|
5516
|
+
process.env.NODE_NO_WARNINGS = "1";
|
|
5537
5517
|
async function main() {
|
|
5538
5518
|
const isReactOnly = process.argv.includes("--react") || process.argv.includes("-r");
|
|
5539
5519
|
const isNextOnly = process.argv.includes("--nextjs") || process.argv.includes("--next") || process.argv.includes("-n");
|