@raftlabs/raftstack 1.2.0 → 1.3.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/README.md +23 -0
- package/dist/cli.js +345 -115
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -12,9 +12,111 @@ import * as p from "@clack/prompts";
|
|
|
12
12
|
import pc from "picocolors";
|
|
13
13
|
|
|
14
14
|
// src/utils/detect-project.ts
|
|
15
|
-
import { existsSync } from "fs";
|
|
15
|
+
import { existsSync as existsSync2 } from "fs";
|
|
16
16
|
import { readFile } from "fs/promises";
|
|
17
|
+
import { join as join2 } from "path";
|
|
18
|
+
|
|
19
|
+
// src/utils/detect-package-manager.ts
|
|
20
|
+
import { existsSync, readFileSync } from "fs";
|
|
17
21
|
import { join } from "path";
|
|
22
|
+
var PACKAGE_MANAGERS = {
|
|
23
|
+
npm: {
|
|
24
|
+
name: "npm",
|
|
25
|
+
install: "npm install",
|
|
26
|
+
run: "npm run",
|
|
27
|
+
exec: "npx",
|
|
28
|
+
lockfile: "package-lock.json",
|
|
29
|
+
installFrozen: "npm ci",
|
|
30
|
+
needsSetupAction: false,
|
|
31
|
+
cacheKey: "npm-${{ hashFiles('**/package-lock.json') }}"
|
|
32
|
+
},
|
|
33
|
+
pnpm: {
|
|
34
|
+
name: "pnpm",
|
|
35
|
+
install: "pnpm install",
|
|
36
|
+
run: "pnpm",
|
|
37
|
+
exec: "pnpm dlx",
|
|
38
|
+
lockfile: "pnpm-lock.yaml",
|
|
39
|
+
installFrozen: "pnpm install --frozen-lockfile",
|
|
40
|
+
needsSetupAction: true,
|
|
41
|
+
cacheKey: "pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}"
|
|
42
|
+
},
|
|
43
|
+
yarn: {
|
|
44
|
+
name: "yarn",
|
|
45
|
+
install: "yarn install",
|
|
46
|
+
run: "yarn",
|
|
47
|
+
exec: "yarn",
|
|
48
|
+
lockfile: "yarn.lock",
|
|
49
|
+
installFrozen: "yarn install --frozen-lockfile",
|
|
50
|
+
needsSetupAction: false,
|
|
51
|
+
cacheKey: "yarn-${{ hashFiles('**/yarn.lock') }}"
|
|
52
|
+
},
|
|
53
|
+
"yarn-berry": {
|
|
54
|
+
name: "yarn-berry",
|
|
55
|
+
install: "yarn install",
|
|
56
|
+
run: "yarn",
|
|
57
|
+
exec: "yarn dlx",
|
|
58
|
+
lockfile: "yarn.lock",
|
|
59
|
+
installFrozen: "yarn install --immutable",
|
|
60
|
+
needsSetupAction: false,
|
|
61
|
+
cacheKey: "yarn-${{ hashFiles('**/yarn.lock') }}"
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
function detectYarnVersion(targetDir) {
|
|
65
|
+
const packageJsonPath = join(targetDir, "package.json");
|
|
66
|
+
if (!existsSync(packageJsonPath)) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
71
|
+
const packageManager = packageJson.packageManager;
|
|
72
|
+
if (!packageManager) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
const match = packageManager.match(/^yarn@(\d+)\./);
|
|
76
|
+
if (match) {
|
|
77
|
+
const majorVersion = Number.parseInt(match[1], 10);
|
|
78
|
+
return majorVersion >= 2 ? "yarn-berry" : "yarn";
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
81
|
+
} catch {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function detectPackageManager(targetDir) {
|
|
86
|
+
if (existsSync(join(targetDir, "pnpm-lock.yaml"))) {
|
|
87
|
+
return PACKAGE_MANAGERS.pnpm;
|
|
88
|
+
}
|
|
89
|
+
if (existsSync(join(targetDir, "yarn.lock"))) {
|
|
90
|
+
const yarnVersion = detectYarnVersion(targetDir);
|
|
91
|
+
if (yarnVersion === "yarn-berry") {
|
|
92
|
+
return PACKAGE_MANAGERS["yarn-berry"];
|
|
93
|
+
}
|
|
94
|
+
return PACKAGE_MANAGERS.yarn;
|
|
95
|
+
}
|
|
96
|
+
if (existsSync(join(targetDir, "package-lock.json"))) {
|
|
97
|
+
return PACKAGE_MANAGERS.npm;
|
|
98
|
+
}
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
function getPackageManagerInfo(name) {
|
|
102
|
+
return PACKAGE_MANAGERS[name];
|
|
103
|
+
}
|
|
104
|
+
function getPackageManagerDescription(pm) {
|
|
105
|
+
switch (pm.name) {
|
|
106
|
+
case "npm":
|
|
107
|
+
return "npm (Node Package Manager)";
|
|
108
|
+
case "pnpm":
|
|
109
|
+
return "pnpm (Performant npm)";
|
|
110
|
+
case "yarn":
|
|
111
|
+
return "Yarn Classic (1.x)";
|
|
112
|
+
case "yarn-berry":
|
|
113
|
+
return "Yarn Berry (2+)";
|
|
114
|
+
default:
|
|
115
|
+
return pm.name;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// src/utils/detect-project.ts
|
|
18
120
|
var INDICATORS = [
|
|
19
121
|
{ file: "nx.json", type: "nx", confidence: "high" },
|
|
20
122
|
{ file: "turbo.json", type: "turbo", confidence: "high" },
|
|
@@ -26,8 +128,8 @@ async function detectProjectType(targetDir = process.cwd()) {
|
|
|
26
128
|
let detectedType = "single";
|
|
27
129
|
let confidence = "low";
|
|
28
130
|
for (const indicator of INDICATORS) {
|
|
29
|
-
const filePath =
|
|
30
|
-
if (
|
|
131
|
+
const filePath = join2(targetDir, indicator.file);
|
|
132
|
+
if (existsSync2(filePath)) {
|
|
31
133
|
foundIndicators.push(indicator.file);
|
|
32
134
|
if (confidence === "low" || confidence === "medium" && indicator.confidence === "high") {
|
|
33
135
|
detectedType = indicator.type;
|
|
@@ -45,8 +147,8 @@ async function detectProjectType(targetDir = process.cwd()) {
|
|
|
45
147
|
};
|
|
46
148
|
}
|
|
47
149
|
async function hasTypeScript(targetDir = process.cwd()) {
|
|
48
|
-
const tsConfigPath =
|
|
49
|
-
return
|
|
150
|
+
const tsConfigPath = join2(targetDir, "tsconfig.json");
|
|
151
|
+
return existsSync2(tsConfigPath);
|
|
50
152
|
}
|
|
51
153
|
async function hasEslint(targetDir = process.cwd()) {
|
|
52
154
|
const eslintFiles = [
|
|
@@ -61,13 +163,13 @@ async function hasEslint(targetDir = process.cwd()) {
|
|
|
61
163
|
"eslint.config.cjs"
|
|
62
164
|
];
|
|
63
165
|
for (const file of eslintFiles) {
|
|
64
|
-
if (
|
|
166
|
+
if (existsSync2(join2(targetDir, file))) {
|
|
65
167
|
return true;
|
|
66
168
|
}
|
|
67
169
|
}
|
|
68
170
|
try {
|
|
69
|
-
const pkgPath =
|
|
70
|
-
if (
|
|
171
|
+
const pkgPath = join2(targetDir, "package.json");
|
|
172
|
+
if (existsSync2(pkgPath)) {
|
|
71
173
|
const content = await readFile(pkgPath, "utf-8");
|
|
72
174
|
const pkg = JSON.parse(content);
|
|
73
175
|
if (pkg.eslintConfig) {
|
|
@@ -92,13 +194,13 @@ async function hasPrettier(targetDir = process.cwd()) {
|
|
|
92
194
|
"prettier.config.mjs"
|
|
93
195
|
];
|
|
94
196
|
for (const file of prettierFiles) {
|
|
95
|
-
if (
|
|
197
|
+
if (existsSync2(join2(targetDir, file))) {
|
|
96
198
|
return true;
|
|
97
199
|
}
|
|
98
200
|
}
|
|
99
201
|
try {
|
|
100
|
-
const pkgPath =
|
|
101
|
-
if (
|
|
202
|
+
const pkgPath = join2(targetDir, "package.json");
|
|
203
|
+
if (existsSync2(pkgPath)) {
|
|
102
204
|
const content = await readFile(pkgPath, "utf-8");
|
|
103
205
|
const pkg = JSON.parse(content);
|
|
104
206
|
if (pkg.prettier) {
|
|
@@ -241,11 +343,51 @@ async function promptCodeowners() {
|
|
|
241
343
|
}
|
|
242
344
|
return owners.split(",").map((u) => u.trim()).filter(Boolean).map((u) => u.startsWith("@") ? u : `@${u}`);
|
|
243
345
|
}
|
|
346
|
+
async function promptPackageManager(targetDir) {
|
|
347
|
+
const detected = detectPackageManager(targetDir);
|
|
348
|
+
if (detected) {
|
|
349
|
+
const description = getPackageManagerDescription(detected);
|
|
350
|
+
p.log.info(`Detected ${pc.cyan(description)} from lockfile`);
|
|
351
|
+
return detected;
|
|
352
|
+
}
|
|
353
|
+
p.log.warn("No package manager lockfile detected");
|
|
354
|
+
const selected = await p.select({
|
|
355
|
+
message: "Select your package manager:",
|
|
356
|
+
options: [
|
|
357
|
+
{
|
|
358
|
+
value: "npm",
|
|
359
|
+
label: "npm",
|
|
360
|
+
hint: "Node Package Manager (default)"
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
value: "pnpm",
|
|
364
|
+
label: "pnpm",
|
|
365
|
+
hint: "Performant npm"
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
value: "yarn",
|
|
369
|
+
label: "Yarn Classic (1.x)",
|
|
370
|
+
hint: "Classic Yarn"
|
|
371
|
+
},
|
|
372
|
+
{
|
|
373
|
+
value: "yarn-berry",
|
|
374
|
+
label: "Yarn Berry (2+)",
|
|
375
|
+
hint: "Modern Yarn"
|
|
376
|
+
}
|
|
377
|
+
]
|
|
378
|
+
});
|
|
379
|
+
if (p.isCancel(selected)) {
|
|
380
|
+
p.cancel("Setup cancelled.");
|
|
381
|
+
process.exit(0);
|
|
382
|
+
}
|
|
383
|
+
return getPackageManagerInfo(selected);
|
|
384
|
+
}
|
|
244
385
|
async function promptConfirmation(config) {
|
|
245
386
|
console.log();
|
|
246
387
|
p.note(
|
|
247
388
|
[
|
|
248
389
|
`${pc.cyan("Project Type:")} ${getProjectTypeDescription(config.projectType)}`,
|
|
390
|
+
`${pc.cyan("Package Manager:")} ${getPackageManagerDescription(config.packageManager)}`,
|
|
249
391
|
`${pc.cyan("TypeScript:")} ${config.usesTypeScript ? "Yes" : "No"}`,
|
|
250
392
|
`${pc.cyan("ESLint:")} ${config.usesEslint ? "Yes" : "No"}`,
|
|
251
393
|
`${pc.cyan("Prettier:")} ${config.usesPrettier ? "Yes" : "No"}`,
|
|
@@ -269,6 +411,7 @@ async function collectConfig(targetDir = process.cwd()) {
|
|
|
269
411
|
showWelcome();
|
|
270
412
|
const detection = await detectProjectType(targetDir);
|
|
271
413
|
const projectType = await promptProjectType(detection);
|
|
414
|
+
const packageManager = await promptPackageManager(targetDir);
|
|
272
415
|
const usesTypeScript = await hasTypeScript(targetDir);
|
|
273
416
|
const usesEslint = await hasEslint(targetDir);
|
|
274
417
|
const usesPrettier = await hasPrettier(targetDir);
|
|
@@ -277,6 +420,7 @@ async function collectConfig(targetDir = process.cwd()) {
|
|
|
277
420
|
const codeowners = await promptCodeowners();
|
|
278
421
|
const config = {
|
|
279
422
|
projectType,
|
|
423
|
+
packageManager,
|
|
280
424
|
asanaBaseUrl,
|
|
281
425
|
aiReviewTool,
|
|
282
426
|
codeowners,
|
|
@@ -293,10 +437,10 @@ async function collectConfig(targetDir = process.cwd()) {
|
|
|
293
437
|
}
|
|
294
438
|
|
|
295
439
|
// src/generators/husky.ts
|
|
296
|
-
import { join as
|
|
440
|
+
import { join as join4 } from "path";
|
|
297
441
|
|
|
298
442
|
// src/utils/file-system.ts
|
|
299
|
-
import { existsSync as
|
|
443
|
+
import { existsSync as existsSync3 } from "fs";
|
|
300
444
|
import {
|
|
301
445
|
mkdir,
|
|
302
446
|
readFile as readFile2,
|
|
@@ -304,14 +448,14 @@ import {
|
|
|
304
448
|
copyFile,
|
|
305
449
|
chmod
|
|
306
450
|
} from "fs/promises";
|
|
307
|
-
import { dirname, join as
|
|
451
|
+
import { dirname, join as join3 } from "path";
|
|
308
452
|
async function ensureDir(dirPath) {
|
|
309
|
-
if (!
|
|
453
|
+
if (!existsSync3(dirPath)) {
|
|
310
454
|
await mkdir(dirPath, { recursive: true });
|
|
311
455
|
}
|
|
312
456
|
}
|
|
313
457
|
async function backupFile(filePath) {
|
|
314
|
-
if (!
|
|
458
|
+
if (!existsSync3(filePath)) {
|
|
315
459
|
return null;
|
|
316
460
|
}
|
|
317
461
|
const backupPath = `${filePath}.backup`;
|
|
@@ -320,7 +464,7 @@ async function backupFile(filePath) {
|
|
|
320
464
|
}
|
|
321
465
|
async function writeFileSafe(filePath, content, options = {}) {
|
|
322
466
|
const { backup = true, overwrite = true, executable = false } = options;
|
|
323
|
-
const exists =
|
|
467
|
+
const exists = existsSync3(filePath);
|
|
324
468
|
if (exists && !overwrite) {
|
|
325
469
|
return { created: false, backedUp: null };
|
|
326
470
|
}
|
|
@@ -336,51 +480,51 @@ async function writeFileSafe(filePath, content, options = {}) {
|
|
|
336
480
|
return { created: true, backedUp };
|
|
337
481
|
}
|
|
338
482
|
function fileExists(filePath) {
|
|
339
|
-
return
|
|
483
|
+
return existsSync3(filePath);
|
|
340
484
|
}
|
|
341
485
|
|
|
342
486
|
// src/generators/husky.ts
|
|
343
|
-
function getPreCommitHook(projectType) {
|
|
487
|
+
function getPreCommitHook(projectType, pm) {
|
|
344
488
|
if (projectType === "nx") {
|
|
345
489
|
return `#!/usr/bin/env sh
|
|
346
490
|
. "$(dirname -- "$0")/_/husky.sh"
|
|
347
491
|
|
|
348
|
-
|
|
492
|
+
${pm.exec} lint-staged
|
|
349
493
|
`;
|
|
350
494
|
}
|
|
351
495
|
return `#!/usr/bin/env sh
|
|
352
496
|
. "$(dirname -- "$0")/_/husky.sh"
|
|
353
497
|
|
|
354
|
-
|
|
498
|
+
${pm.exec} lint-staged
|
|
355
499
|
`;
|
|
356
500
|
}
|
|
357
|
-
function getCommitMsgHook() {
|
|
501
|
+
function getCommitMsgHook(pm) {
|
|
358
502
|
return `#!/usr/bin/env sh
|
|
359
503
|
. "$(dirname -- "$0")/_/husky.sh"
|
|
360
504
|
|
|
361
|
-
|
|
505
|
+
${pm.exec} --no -- commitlint --edit "$1"
|
|
362
506
|
`;
|
|
363
507
|
}
|
|
364
|
-
function getPrePushHook() {
|
|
508
|
+
function getPrePushHook(pm) {
|
|
365
509
|
return `#!/usr/bin/env sh
|
|
366
510
|
. "$(dirname -- "$0")/_/husky.sh"
|
|
367
511
|
|
|
368
|
-
|
|
512
|
+
${pm.exec} validate-branch-name
|
|
369
513
|
`;
|
|
370
514
|
}
|
|
371
|
-
async function generateHuskyHooks(targetDir, projectType) {
|
|
515
|
+
async function generateHuskyHooks(targetDir, projectType, pm) {
|
|
372
516
|
const result = {
|
|
373
517
|
created: [],
|
|
374
518
|
modified: [],
|
|
375
519
|
skipped: [],
|
|
376
520
|
backedUp: []
|
|
377
521
|
};
|
|
378
|
-
const huskyDir =
|
|
522
|
+
const huskyDir = join4(targetDir, ".husky");
|
|
379
523
|
await ensureDir(huskyDir);
|
|
380
|
-
const preCommitPath =
|
|
524
|
+
const preCommitPath = join4(huskyDir, "pre-commit");
|
|
381
525
|
const preCommitResult = await writeFileSafe(
|
|
382
526
|
preCommitPath,
|
|
383
|
-
getPreCommitHook(projectType),
|
|
527
|
+
getPreCommitHook(projectType, pm),
|
|
384
528
|
{ executable: true, backup: true }
|
|
385
529
|
);
|
|
386
530
|
if (preCommitResult.created) {
|
|
@@ -389,10 +533,10 @@ async function generateHuskyHooks(targetDir, projectType) {
|
|
|
389
533
|
result.backedUp.push(preCommitResult.backedUp);
|
|
390
534
|
}
|
|
391
535
|
}
|
|
392
|
-
const commitMsgPath =
|
|
536
|
+
const commitMsgPath = join4(huskyDir, "commit-msg");
|
|
393
537
|
const commitMsgResult = await writeFileSafe(
|
|
394
538
|
commitMsgPath,
|
|
395
|
-
getCommitMsgHook(),
|
|
539
|
+
getCommitMsgHook(pm),
|
|
396
540
|
{ executable: true, backup: true }
|
|
397
541
|
);
|
|
398
542
|
if (commitMsgResult.created) {
|
|
@@ -401,8 +545,8 @@ async function generateHuskyHooks(targetDir, projectType) {
|
|
|
401
545
|
result.backedUp.push(commitMsgResult.backedUp);
|
|
402
546
|
}
|
|
403
547
|
}
|
|
404
|
-
const prePushPath =
|
|
405
|
-
const prePushResult = await writeFileSafe(prePushPath, getPrePushHook(), {
|
|
548
|
+
const prePushPath = join4(huskyDir, "pre-push");
|
|
549
|
+
const prePushResult = await writeFileSafe(prePushPath, getPrePushHook(pm), {
|
|
406
550
|
executable: true,
|
|
407
551
|
backup: true
|
|
408
552
|
});
|
|
@@ -416,7 +560,7 @@ async function generateHuskyHooks(targetDir, projectType) {
|
|
|
416
560
|
}
|
|
417
561
|
|
|
418
562
|
// src/generators/commitlint.ts
|
|
419
|
-
import { join as
|
|
563
|
+
import { join as join5 } from "path";
|
|
420
564
|
function getCommitlintConfig(asanaBaseUrl) {
|
|
421
565
|
const baseConfig = `// @ts-check
|
|
422
566
|
|
|
@@ -492,7 +636,7 @@ async function generateCommitlint(targetDir, asanaBaseUrl) {
|
|
|
492
636
|
skipped: [],
|
|
493
637
|
backedUp: []
|
|
494
638
|
};
|
|
495
|
-
const configPath =
|
|
639
|
+
const configPath = join5(targetDir, "commitlint.config.js");
|
|
496
640
|
const writeResult = await writeFileSafe(
|
|
497
641
|
configPath,
|
|
498
642
|
getCommitlintConfig(asanaBaseUrl),
|
|
@@ -508,7 +652,7 @@ async function generateCommitlint(targetDir, asanaBaseUrl) {
|
|
|
508
652
|
}
|
|
509
653
|
|
|
510
654
|
// src/generators/cz-git.ts
|
|
511
|
-
import { join as
|
|
655
|
+
import { join as join6 } from "path";
|
|
512
656
|
function getCzGitConfig(asanaBaseUrl) {
|
|
513
657
|
const asanaSection = asanaBaseUrl ? `
|
|
514
658
|
// Asana task reference settings
|
|
@@ -591,7 +735,7 @@ async function generateCzGit(targetDir, asanaBaseUrl) {
|
|
|
591
735
|
skipped: [],
|
|
592
736
|
backedUp: []
|
|
593
737
|
};
|
|
594
|
-
const configPath =
|
|
738
|
+
const configPath = join6(targetDir, ".czrc");
|
|
595
739
|
const writeResult = await writeFileSafe(
|
|
596
740
|
configPath,
|
|
597
741
|
JSON.stringify({ path: "node_modules/cz-git" }, null, 2) + "\n",
|
|
@@ -603,7 +747,7 @@ async function generateCzGit(targetDir, asanaBaseUrl) {
|
|
|
603
747
|
result.backedUp.push(writeResult.backedUp);
|
|
604
748
|
}
|
|
605
749
|
}
|
|
606
|
-
const czConfigPath =
|
|
750
|
+
const czConfigPath = join6(targetDir, "cz.config.js");
|
|
607
751
|
const czConfigResult = await writeFileSafe(
|
|
608
752
|
czConfigPath,
|
|
609
753
|
getCzGitConfig(asanaBaseUrl),
|
|
@@ -619,7 +763,7 @@ async function generateCzGit(targetDir, asanaBaseUrl) {
|
|
|
619
763
|
}
|
|
620
764
|
|
|
621
765
|
// src/generators/lint-staged.ts
|
|
622
|
-
import { join as
|
|
766
|
+
import { join as join7 } from "path";
|
|
623
767
|
function getLintStagedConfig(projectType, usesEslint, usesPrettier, usesTypeScript) {
|
|
624
768
|
const rules = {};
|
|
625
769
|
if (usesTypeScript) {
|
|
@@ -684,7 +828,7 @@ async function generateLintStaged(targetDir, projectType, usesEslint, usesPretti
|
|
|
684
828
|
skipped: [],
|
|
685
829
|
backedUp: []
|
|
686
830
|
};
|
|
687
|
-
const configPath =
|
|
831
|
+
const configPath = join7(targetDir, ".lintstagedrc.js");
|
|
688
832
|
const writeResult = await writeFileSafe(
|
|
689
833
|
configPath,
|
|
690
834
|
getLintStagedConfig(projectType, usesEslint, usesPrettier, usesTypeScript),
|
|
@@ -701,18 +845,18 @@ async function generateLintStaged(targetDir, projectType, usesEslint, usesPretti
|
|
|
701
845
|
|
|
702
846
|
// src/utils/package-json.ts
|
|
703
847
|
import { readFile as readFile3, writeFile as writeFile2 } from "fs/promises";
|
|
704
|
-
import { existsSync as
|
|
705
|
-
import { join as
|
|
848
|
+
import { existsSync as existsSync4 } from "fs";
|
|
849
|
+
import { join as join8 } from "path";
|
|
706
850
|
async function readPackageJson(targetDir = process.cwd()) {
|
|
707
|
-
const pkgPath =
|
|
708
|
-
if (!
|
|
851
|
+
const pkgPath = join8(targetDir, "package.json");
|
|
852
|
+
if (!existsSync4(pkgPath)) {
|
|
709
853
|
throw new Error(`No package.json found in ${targetDir}`);
|
|
710
854
|
}
|
|
711
855
|
const content = await readFile3(pkgPath, "utf-8");
|
|
712
856
|
return JSON.parse(content);
|
|
713
857
|
}
|
|
714
858
|
async function writePackageJson(pkg, targetDir = process.cwd()) {
|
|
715
|
-
const pkgPath =
|
|
859
|
+
const pkgPath = join8(targetDir, "package.json");
|
|
716
860
|
const content = JSON.stringify(pkg, null, 2) + "\n";
|
|
717
861
|
await writeFile2(pkgPath, content, "utf-8");
|
|
718
862
|
}
|
|
@@ -795,7 +939,7 @@ async function generateBranchValidation(targetDir) {
|
|
|
795
939
|
}
|
|
796
940
|
|
|
797
941
|
// src/generators/pr-template.ts
|
|
798
|
-
import { join as
|
|
942
|
+
import { join as join9 } from "path";
|
|
799
943
|
function getPRTemplate(hasAsana) {
|
|
800
944
|
const asanaSection = hasAsana ? `## Asana Task
|
|
801
945
|
<!-- Link to the Asana task -->
|
|
@@ -847,9 +991,9 @@ async function generatePRTemplate(targetDir, hasAsana) {
|
|
|
847
991
|
skipped: [],
|
|
848
992
|
backedUp: []
|
|
849
993
|
};
|
|
850
|
-
const githubDir =
|
|
994
|
+
const githubDir = join9(targetDir, ".github");
|
|
851
995
|
await ensureDir(githubDir);
|
|
852
|
-
const templatePath =
|
|
996
|
+
const templatePath = join9(githubDir, "PULL_REQUEST_TEMPLATE.md");
|
|
853
997
|
const writeResult = await writeFileSafe(
|
|
854
998
|
templatePath,
|
|
855
999
|
getPRTemplate(hasAsana),
|
|
@@ -865,8 +1009,8 @@ async function generatePRTemplate(targetDir, hasAsana) {
|
|
|
865
1009
|
}
|
|
866
1010
|
|
|
867
1011
|
// src/generators/github-workflows.ts
|
|
868
|
-
import { join as
|
|
869
|
-
function getPRChecksWorkflow(projectType, usesTypeScript, usesEslint) {
|
|
1012
|
+
import { join as join10 } from "path";
|
|
1013
|
+
function getPRChecksWorkflow(projectType, usesTypeScript, usesEslint, pm) {
|
|
870
1014
|
const steps = [];
|
|
871
1015
|
steps.push(` - name: Checkout
|
|
872
1016
|
uses: actions/checkout@v4`);
|
|
@@ -875,49 +1019,51 @@ function getPRChecksWorkflow(projectType, usesTypeScript, usesEslint) {
|
|
|
875
1019
|
uses: actions/setup-node@v4
|
|
876
1020
|
with:
|
|
877
1021
|
node-version: '20'`);
|
|
878
|
-
|
|
1022
|
+
if (pm.needsSetupAction) {
|
|
1023
|
+
steps.push(`
|
|
879
1024
|
- name: Setup pnpm
|
|
880
1025
|
uses: pnpm/action-setup@v3
|
|
881
1026
|
with:
|
|
882
1027
|
version: 9`);
|
|
1028
|
+
}
|
|
883
1029
|
steps.push(`
|
|
884
1030
|
- name: Install dependencies
|
|
885
|
-
run:
|
|
1031
|
+
run: ${pm.installFrozen}`);
|
|
886
1032
|
if (usesTypeScript) {
|
|
887
1033
|
steps.push(`
|
|
888
1034
|
- name: Type check
|
|
889
|
-
run:
|
|
1035
|
+
run: ${pm.run} typecheck`);
|
|
890
1036
|
}
|
|
891
1037
|
if (usesEslint) {
|
|
892
1038
|
steps.push(`
|
|
893
1039
|
- name: Lint
|
|
894
|
-
run:
|
|
1040
|
+
run: ${pm.run} lint`);
|
|
895
1041
|
}
|
|
896
1042
|
if (projectType === "nx") {
|
|
897
1043
|
steps.push(`
|
|
898
1044
|
- name: Build
|
|
899
|
-
run:
|
|
1045
|
+
run: ${pm.run} nx affected --target=build --parallel=3`);
|
|
900
1046
|
} else if (projectType === "turbo") {
|
|
901
1047
|
steps.push(`
|
|
902
1048
|
- name: Build
|
|
903
|
-
run:
|
|
1049
|
+
run: ${pm.run} turbo build`);
|
|
904
1050
|
} else {
|
|
905
1051
|
steps.push(`
|
|
906
1052
|
- name: Build
|
|
907
|
-
run:
|
|
1053
|
+
run: ${pm.run} build`);
|
|
908
1054
|
}
|
|
909
1055
|
if (projectType === "nx") {
|
|
910
1056
|
steps.push(`
|
|
911
1057
|
- name: Test
|
|
912
|
-
run:
|
|
1058
|
+
run: ${pm.run} nx affected --target=test --parallel=3`);
|
|
913
1059
|
} else if (projectType === "turbo") {
|
|
914
1060
|
steps.push(`
|
|
915
1061
|
- name: Test
|
|
916
|
-
run:
|
|
1062
|
+
run: ${pm.run} turbo test`);
|
|
917
1063
|
} else {
|
|
918
1064
|
steps.push(`
|
|
919
1065
|
- name: Test
|
|
920
|
-
run:
|
|
1066
|
+
run: ${pm.run} test`);
|
|
921
1067
|
}
|
|
922
1068
|
return `name: PR Checks
|
|
923
1069
|
|
|
@@ -937,19 +1083,19 @@ jobs:
|
|
|
937
1083
|
${steps.join("\n")}
|
|
938
1084
|
`;
|
|
939
1085
|
}
|
|
940
|
-
async function generateGitHubWorkflows(targetDir, projectType, usesTypeScript, usesEslint) {
|
|
1086
|
+
async function generateGitHubWorkflows(targetDir, projectType, usesTypeScript, usesEslint, pm) {
|
|
941
1087
|
const result = {
|
|
942
1088
|
created: [],
|
|
943
1089
|
modified: [],
|
|
944
1090
|
skipped: [],
|
|
945
1091
|
backedUp: []
|
|
946
1092
|
};
|
|
947
|
-
const workflowsDir =
|
|
1093
|
+
const workflowsDir = join10(targetDir, ".github", "workflows");
|
|
948
1094
|
await ensureDir(workflowsDir);
|
|
949
|
-
const prChecksPath =
|
|
1095
|
+
const prChecksPath = join10(workflowsDir, "pr-checks.yml");
|
|
950
1096
|
const writeResult = await writeFileSafe(
|
|
951
1097
|
prChecksPath,
|
|
952
|
-
getPRChecksWorkflow(projectType, usesTypeScript, usesEslint),
|
|
1098
|
+
getPRChecksWorkflow(projectType, usesTypeScript, usesEslint, pm),
|
|
953
1099
|
{ backup: true }
|
|
954
1100
|
);
|
|
955
1101
|
if (writeResult.created) {
|
|
@@ -962,7 +1108,7 @@ async function generateGitHubWorkflows(targetDir, projectType, usesTypeScript, u
|
|
|
962
1108
|
}
|
|
963
1109
|
|
|
964
1110
|
// src/generators/codeowners.ts
|
|
965
|
-
import { join as
|
|
1111
|
+
import { join as join11 } from "path";
|
|
966
1112
|
function getCodeownersContent(owners) {
|
|
967
1113
|
if (owners.length === 0) {
|
|
968
1114
|
return `# CODEOWNERS file
|
|
@@ -994,9 +1140,9 @@ async function generateCodeowners(targetDir, owners) {
|
|
|
994
1140
|
skipped: [],
|
|
995
1141
|
backedUp: []
|
|
996
1142
|
};
|
|
997
|
-
const githubDir =
|
|
1143
|
+
const githubDir = join11(targetDir, ".github");
|
|
998
1144
|
await ensureDir(githubDir);
|
|
999
|
-
const codeownersPath =
|
|
1145
|
+
const codeownersPath = join11(githubDir, "CODEOWNERS");
|
|
1000
1146
|
const writeResult = await writeFileSafe(
|
|
1001
1147
|
codeownersPath,
|
|
1002
1148
|
getCodeownersContent(owners),
|
|
@@ -1012,7 +1158,7 @@ async function generateCodeowners(targetDir, owners) {
|
|
|
1012
1158
|
}
|
|
1013
1159
|
|
|
1014
1160
|
// src/generators/ai-review.ts
|
|
1015
|
-
import { join as
|
|
1161
|
+
import { join as join12 } from "path";
|
|
1016
1162
|
function getCodeRabbitConfig() {
|
|
1017
1163
|
return `# CodeRabbit Configuration
|
|
1018
1164
|
# Learn more: https://docs.coderabbit.ai/guides/configure-coderabbit
|
|
@@ -1076,7 +1222,7 @@ async function generateAIReview(targetDir, tool) {
|
|
|
1076
1222
|
return result;
|
|
1077
1223
|
}
|
|
1078
1224
|
if (tool === "coderabbit") {
|
|
1079
|
-
const configPath =
|
|
1225
|
+
const configPath = join12(targetDir, ".coderabbit.yaml");
|
|
1080
1226
|
const writeResult = await writeFileSafe(configPath, getCodeRabbitConfig(), {
|
|
1081
1227
|
backup: true
|
|
1082
1228
|
});
|
|
@@ -1088,9 +1234,9 @@ async function generateAIReview(targetDir, tool) {
|
|
|
1088
1234
|
}
|
|
1089
1235
|
}
|
|
1090
1236
|
if (tool === "copilot") {
|
|
1091
|
-
const workflowsDir =
|
|
1237
|
+
const workflowsDir = join12(targetDir, ".github", "workflows");
|
|
1092
1238
|
await ensureDir(workflowsDir);
|
|
1093
|
-
const workflowPath =
|
|
1239
|
+
const workflowPath = join12(workflowsDir, "copilot-review.yml");
|
|
1094
1240
|
const writeResult = await writeFileSafe(workflowPath, getCopilotWorkflow(), {
|
|
1095
1241
|
backup: true
|
|
1096
1242
|
});
|
|
@@ -1105,7 +1251,7 @@ async function generateAIReview(targetDir, tool) {
|
|
|
1105
1251
|
}
|
|
1106
1252
|
|
|
1107
1253
|
// src/generators/branch-protection.ts
|
|
1108
|
-
import { join as
|
|
1254
|
+
import { join as join13 } from "path";
|
|
1109
1255
|
function getBranchProtectionDocs() {
|
|
1110
1256
|
return `# Branch Protection Setup Guide
|
|
1111
1257
|
|
|
@@ -1222,9 +1368,9 @@ async function generateBranchProtectionDocs(targetDir) {
|
|
|
1222
1368
|
skipped: [],
|
|
1223
1369
|
backedUp: []
|
|
1224
1370
|
};
|
|
1225
|
-
const docsDir =
|
|
1371
|
+
const docsDir = join13(targetDir, ".github");
|
|
1226
1372
|
await ensureDir(docsDir);
|
|
1227
|
-
const docsPath =
|
|
1373
|
+
const docsPath = join13(docsDir, "BRANCH_PROTECTION_SETUP.md");
|
|
1228
1374
|
const writeResult = await writeFileSafe(docsPath, getBranchProtectionDocs(), {
|
|
1229
1375
|
backup: true
|
|
1230
1376
|
});
|
|
@@ -1238,8 +1384,8 @@ async function generateBranchProtectionDocs(targetDir) {
|
|
|
1238
1384
|
}
|
|
1239
1385
|
|
|
1240
1386
|
// src/generators/contributing.ts
|
|
1241
|
-
import { join as
|
|
1242
|
-
function getContributingContent(hasAsana) {
|
|
1387
|
+
import { join as join14 } from "path";
|
|
1388
|
+
function getContributingContent(hasAsana, pm) {
|
|
1243
1389
|
const asanaSection = hasAsana ? `
|
|
1244
1390
|
## Linking to Asana
|
|
1245
1391
|
|
|
@@ -1264,7 +1410,7 @@ Thank you for your interest in contributing! This document outlines our developm
|
|
|
1264
1410
|
## Getting Started
|
|
1265
1411
|
|
|
1266
1412
|
1. Clone the repository
|
|
1267
|
-
2. Install dependencies:
|
|
1413
|
+
2. Install dependencies: \`${pm.install}\`
|
|
1268
1414
|
3. Create a new branch following our naming convention
|
|
1269
1415
|
|
|
1270
1416
|
## Branch Naming Convention
|
|
@@ -1289,7 +1435,7 @@ We use structured branch names to keep our repository organized:
|
|
|
1289
1435
|
We follow [Conventional Commits](https://www.conventionalcommits.org/). Use the interactive commit tool:
|
|
1290
1436
|
|
|
1291
1437
|
\`\`\`bash
|
|
1292
|
-
|
|
1438
|
+
${pm.run} commit
|
|
1293
1439
|
\`\`\`
|
|
1294
1440
|
|
|
1295
1441
|
### Commit Types
|
|
@@ -1370,17 +1516,17 @@ Before committing, the following checks run automatically:
|
|
|
1370
1516
|
If you have questions, please open an issue or reach out to the maintainers.
|
|
1371
1517
|
`;
|
|
1372
1518
|
}
|
|
1373
|
-
async function generateContributing(targetDir, hasAsana) {
|
|
1519
|
+
async function generateContributing(targetDir, hasAsana, pm) {
|
|
1374
1520
|
const result = {
|
|
1375
1521
|
created: [],
|
|
1376
1522
|
modified: [],
|
|
1377
1523
|
skipped: [],
|
|
1378
1524
|
backedUp: []
|
|
1379
1525
|
};
|
|
1380
|
-
const contributingPath =
|
|
1526
|
+
const contributingPath = join14(targetDir, "CONTRIBUTING.md");
|
|
1381
1527
|
const writeResult = await writeFileSafe(
|
|
1382
1528
|
contributingPath,
|
|
1383
|
-
getContributingContent(hasAsana),
|
|
1529
|
+
getContributingContent(hasAsana, pm),
|
|
1384
1530
|
{ backup: true }
|
|
1385
1531
|
);
|
|
1386
1532
|
if (writeResult.created) {
|
|
@@ -1393,7 +1539,7 @@ async function generateContributing(targetDir, hasAsana) {
|
|
|
1393
1539
|
}
|
|
1394
1540
|
|
|
1395
1541
|
// src/generators/prettier.ts
|
|
1396
|
-
import { join as
|
|
1542
|
+
import { join as join15 } from "path";
|
|
1397
1543
|
function getPrettierConfig() {
|
|
1398
1544
|
return JSON.stringify(
|
|
1399
1545
|
{
|
|
@@ -1451,7 +1597,7 @@ function hasPrettierConfig(targetDir) {
|
|
|
1451
1597
|
"prettier.config.cjs",
|
|
1452
1598
|
"prettier.config.mjs"
|
|
1453
1599
|
];
|
|
1454
|
-
return prettierFiles.some((file) => fileExists(
|
|
1600
|
+
return prettierFiles.some((file) => fileExists(join15(targetDir, file)));
|
|
1455
1601
|
}
|
|
1456
1602
|
async function generatePrettier(targetDir) {
|
|
1457
1603
|
const result = {
|
|
@@ -1464,7 +1610,7 @@ async function generatePrettier(targetDir) {
|
|
|
1464
1610
|
result.skipped.push(".prettierrc (already exists)");
|
|
1465
1611
|
return result;
|
|
1466
1612
|
}
|
|
1467
|
-
const configPath =
|
|
1613
|
+
const configPath = join15(targetDir, ".prettierrc");
|
|
1468
1614
|
const configResult = await writeFileSafe(configPath, getPrettierConfig(), {
|
|
1469
1615
|
backup: true
|
|
1470
1616
|
});
|
|
@@ -1474,7 +1620,7 @@ async function generatePrettier(targetDir) {
|
|
|
1474
1620
|
result.backedUp.push(configResult.backedUp);
|
|
1475
1621
|
}
|
|
1476
1622
|
}
|
|
1477
|
-
const ignorePath =
|
|
1623
|
+
const ignorePath = join15(targetDir, ".prettierignore");
|
|
1478
1624
|
const ignoreResult = await writeFileSafe(ignorePath, getPrettierIgnore(), {
|
|
1479
1625
|
backup: true,
|
|
1480
1626
|
overwrite: false
|
|
@@ -1492,26 +1638,26 @@ async function generatePrettier(targetDir) {
|
|
|
1492
1638
|
}
|
|
1493
1639
|
|
|
1494
1640
|
// src/generators/claude-skills.ts
|
|
1495
|
-
import { existsSync as
|
|
1641
|
+
import { existsSync as existsSync5 } from "fs";
|
|
1496
1642
|
import { readdir, copyFile as copyFile2 } from "fs/promises";
|
|
1497
|
-
import { join as
|
|
1643
|
+
import { join as join16, dirname as dirname2 } from "path";
|
|
1498
1644
|
import { fileURLToPath } from "url";
|
|
1499
1645
|
function getPackageSkillsDir() {
|
|
1500
1646
|
const currentFilePath = fileURLToPath(import.meta.url);
|
|
1501
|
-
const packageRoot =
|
|
1502
|
-
return
|
|
1647
|
+
const packageRoot = join16(dirname2(currentFilePath), "..");
|
|
1648
|
+
return join16(packageRoot, ".claude", "skills");
|
|
1503
1649
|
}
|
|
1504
1650
|
async function copyDirectory(srcDir, destDir, result, baseDir) {
|
|
1505
1651
|
await ensureDir(destDir);
|
|
1506
1652
|
const entries = await readdir(srcDir, { withFileTypes: true });
|
|
1507
1653
|
for (const entry of entries) {
|
|
1508
|
-
const srcPath =
|
|
1509
|
-
const destPath =
|
|
1654
|
+
const srcPath = join16(srcDir, entry.name);
|
|
1655
|
+
const destPath = join16(destDir, entry.name);
|
|
1510
1656
|
const relativePath = destPath.replace(baseDir + "/", "");
|
|
1511
1657
|
if (entry.isDirectory()) {
|
|
1512
1658
|
await copyDirectory(srcPath, destPath, result, baseDir);
|
|
1513
1659
|
} else {
|
|
1514
|
-
if (
|
|
1660
|
+
if (existsSync5(destPath)) {
|
|
1515
1661
|
const backupPath = await backupFile(destPath);
|
|
1516
1662
|
if (backupPath) {
|
|
1517
1663
|
result.backedUp.push(relativePath);
|
|
@@ -1530,33 +1676,33 @@ async function generateClaudeSkills(targetDir) {
|
|
|
1530
1676
|
backedUp: []
|
|
1531
1677
|
};
|
|
1532
1678
|
const packageSkillsDir = getPackageSkillsDir();
|
|
1533
|
-
const targetSkillsDir =
|
|
1534
|
-
if (!
|
|
1679
|
+
const targetSkillsDir = join16(targetDir, ".claude", "skills");
|
|
1680
|
+
if (!existsSync5(packageSkillsDir)) {
|
|
1535
1681
|
console.warn(
|
|
1536
1682
|
"Warning: Skills directory not found in package. Skipping skills generation."
|
|
1537
1683
|
);
|
|
1538
1684
|
return result;
|
|
1539
1685
|
}
|
|
1540
|
-
await ensureDir(
|
|
1686
|
+
await ensureDir(join16(targetDir, ".claude"));
|
|
1541
1687
|
await copyDirectory(packageSkillsDir, targetSkillsDir, result, targetDir);
|
|
1542
1688
|
return result;
|
|
1543
1689
|
}
|
|
1544
1690
|
|
|
1545
1691
|
// src/generators/eslint.ts
|
|
1546
|
-
import { existsSync as
|
|
1692
|
+
import { existsSync as existsSync6 } from "fs";
|
|
1547
1693
|
import { readFile as readFile4 } from "fs/promises";
|
|
1548
|
-
import { join as
|
|
1694
|
+
import { join as join17 } from "path";
|
|
1549
1695
|
|
|
1550
1696
|
// src/generators/quick-reference.ts
|
|
1551
|
-
import { join as
|
|
1552
|
-
async function generateQuickReference(targetDir) {
|
|
1697
|
+
import { join as join18 } from "path";
|
|
1698
|
+
async function generateQuickReference(targetDir, pm) {
|
|
1553
1699
|
const result = {
|
|
1554
1700
|
created: [],
|
|
1555
1701
|
modified: [],
|
|
1556
1702
|
skipped: [],
|
|
1557
1703
|
backedUp: []
|
|
1558
1704
|
};
|
|
1559
|
-
const quickRefPath =
|
|
1705
|
+
const quickRefPath = join18(targetDir, ".github", "QUICK_REFERENCE.md");
|
|
1560
1706
|
const content = `# RaftStack Quick Reference
|
|
1561
1707
|
|
|
1562
1708
|
> One-page guide for the RaftStack Git workflow
|
|
@@ -1578,7 +1724,7 @@ git checkout -b hotfix/payment-timeout
|
|
|
1578
1724
|
|
|
1579
1725
|
\`\`\`bash
|
|
1580
1726
|
# Use the interactive commit tool
|
|
1581
|
-
|
|
1727
|
+
${pm.run} commit
|
|
1582
1728
|
\`\`\`
|
|
1583
1729
|
|
|
1584
1730
|
This will prompt you for:
|
|
@@ -1641,16 +1787,16 @@ Before submitting:
|
|
|
1641
1787
|
|
|
1642
1788
|
\`\`\`bash
|
|
1643
1789
|
# Interactive commit
|
|
1644
|
-
|
|
1790
|
+
${pm.run} commit
|
|
1645
1791
|
|
|
1646
1792
|
# Check compliance metrics
|
|
1647
|
-
|
|
1793
|
+
${pm.exec} @raftlabs/raftstack metrics
|
|
1648
1794
|
|
|
1649
1795
|
# Run linting
|
|
1650
|
-
|
|
1796
|
+
${pm.run} lint
|
|
1651
1797
|
|
|
1652
1798
|
# Run tests
|
|
1653
|
-
|
|
1799
|
+
${pm.run} test
|
|
1654
1800
|
\`\`\`
|
|
1655
1801
|
|
|
1656
1802
|
---
|
|
@@ -1691,10 +1837,10 @@ pnpm test
|
|
|
1691
1837
|
|
|
1692
1838
|
// src/utils/git.ts
|
|
1693
1839
|
import { execa } from "execa";
|
|
1694
|
-
import { existsSync as
|
|
1695
|
-
import { join as
|
|
1840
|
+
import { existsSync as existsSync7 } from "fs";
|
|
1841
|
+
import { join as join19 } from "path";
|
|
1696
1842
|
async function isGitRepo(targetDir = process.cwd()) {
|
|
1697
|
-
if (
|
|
1843
|
+
if (existsSync7(join19(targetDir, ".git"))) {
|
|
1698
1844
|
return true;
|
|
1699
1845
|
}
|
|
1700
1846
|
try {
|
|
@@ -1786,7 +1932,9 @@ async function runInit(targetDir = process.cwd()) {
|
|
|
1786
1932
|
spinner4.start("Generating configuration files...");
|
|
1787
1933
|
const results = [];
|
|
1788
1934
|
try {
|
|
1789
|
-
results.push(
|
|
1935
|
+
results.push(
|
|
1936
|
+
await generateHuskyHooks(targetDir, config.projectType, config.packageManager)
|
|
1937
|
+
);
|
|
1790
1938
|
results.push(await generateCommitlint(targetDir, config.asanaBaseUrl));
|
|
1791
1939
|
results.push(await generateCzGit(targetDir, config.asanaBaseUrl));
|
|
1792
1940
|
results.push(
|
|
@@ -1808,14 +1956,17 @@ async function runInit(targetDir = process.cwd()) {
|
|
|
1808
1956
|
targetDir,
|
|
1809
1957
|
config.projectType,
|
|
1810
1958
|
config.usesTypeScript,
|
|
1811
|
-
config.usesEslint
|
|
1959
|
+
config.usesEslint,
|
|
1960
|
+
config.packageManager
|
|
1812
1961
|
)
|
|
1813
1962
|
);
|
|
1814
1963
|
results.push(await generateCodeowners(targetDir, config.codeowners));
|
|
1815
1964
|
results.push(await generateAIReview(targetDir, config.aiReviewTool));
|
|
1816
1965
|
results.push(await generateBranchProtectionDocs(targetDir));
|
|
1817
|
-
results.push(
|
|
1818
|
-
|
|
1966
|
+
results.push(
|
|
1967
|
+
await generateContributing(targetDir, !!config.asanaBaseUrl, config.packageManager)
|
|
1968
|
+
);
|
|
1969
|
+
results.push(await generateQuickReference(targetDir, config.packageManager));
|
|
1819
1970
|
results.push(await generateClaudeSkills(targetDir));
|
|
1820
1971
|
results.push(await updateProjectPackageJson(targetDir, config));
|
|
1821
1972
|
spinner4.stop("Configuration files generated!");
|
|
@@ -1860,9 +2011,9 @@ async function runInit(targetDir = process.cwd()) {
|
|
|
1860
2011
|
console.log();
|
|
1861
2012
|
p2.note(
|
|
1862
2013
|
[
|
|
1863
|
-
`${pc2.cyan("1.")} Run ${pc2.yellow(
|
|
2014
|
+
`${pc2.cyan("1.")} Run ${pc2.yellow(config.packageManager.install)} to install dependencies`,
|
|
1864
2015
|
`${pc2.cyan("2.")} Review the generated configuration files`,
|
|
1865
|
-
`${pc2.cyan("3.")} Use ${pc2.yellow(
|
|
2016
|
+
`${pc2.cyan("3.")} Use ${pc2.yellow(`${config.packageManager.run} commit`)} for interactive commits`,
|
|
1866
2017
|
`${pc2.cyan("4.")} Set up branch protection rules (see .github/BRANCH_PROTECTION_SETUP.md)`
|
|
1867
2018
|
].join("\n"),
|
|
1868
2019
|
"Next Steps"
|
|
@@ -2272,11 +2423,90 @@ ${pc4.bold("Branches")}
|
|
|
2272
2423
|
}
|
|
2273
2424
|
}
|
|
2274
2425
|
|
|
2426
|
+
// package.json
|
|
2427
|
+
var package_default = {
|
|
2428
|
+
name: "@raftlabs/raftstack",
|
|
2429
|
+
version: "1.3.0",
|
|
2430
|
+
description: "CLI tool for setting up Git hooks, commit conventions, and GitHub integration",
|
|
2431
|
+
type: "module",
|
|
2432
|
+
main: "./dist/index.js",
|
|
2433
|
+
types: "./dist/index.d.ts",
|
|
2434
|
+
bin: {
|
|
2435
|
+
raftstack: "./dist/cli.js"
|
|
2436
|
+
},
|
|
2437
|
+
exports: {
|
|
2438
|
+
".": {
|
|
2439
|
+
types: "./dist/index.d.ts",
|
|
2440
|
+
import: "./dist/index.js"
|
|
2441
|
+
}
|
|
2442
|
+
},
|
|
2443
|
+
files: [
|
|
2444
|
+
"dist",
|
|
2445
|
+
"templates",
|
|
2446
|
+
".claude/skills"
|
|
2447
|
+
],
|
|
2448
|
+
scripts: {
|
|
2449
|
+
build: "tsup",
|
|
2450
|
+
dev: "tsup --watch",
|
|
2451
|
+
typecheck: "tsc --noEmit",
|
|
2452
|
+
test: "vitest",
|
|
2453
|
+
"test:run": "vitest run",
|
|
2454
|
+
prepublishOnly: "pnpm build",
|
|
2455
|
+
prepublish: "pnpm test:run && pnpm build",
|
|
2456
|
+
"pack:test": "pnpm pack --dry-run",
|
|
2457
|
+
"publish:test": "pnpm pack && tar -xvzf raftlabs-raftstack-*.tgz && rm -rf package raftlabs-raftstack-*.tgz",
|
|
2458
|
+
release: "standard-version",
|
|
2459
|
+
"release:patch": "standard-version --release-as patch",
|
|
2460
|
+
"release:minor": "standard-version --release-as minor",
|
|
2461
|
+
"release:major": "standard-version --release-as major",
|
|
2462
|
+
"release:first": "standard-version --first-release"
|
|
2463
|
+
},
|
|
2464
|
+
keywords: [
|
|
2465
|
+
"cli",
|
|
2466
|
+
"git-hooks",
|
|
2467
|
+
"husky",
|
|
2468
|
+
"commitlint",
|
|
2469
|
+
"lint-staged",
|
|
2470
|
+
"developer-experience"
|
|
2471
|
+
],
|
|
2472
|
+
author: "Aravind Jaimon <dev@aravindjaimon.com>",
|
|
2473
|
+
license: "MIT",
|
|
2474
|
+
repository: {
|
|
2475
|
+
type: "git",
|
|
2476
|
+
url: "git+https://github.com/Raft-Labs/raftstack.git"
|
|
2477
|
+
},
|
|
2478
|
+
homepage: "https://github.com/Raft-Labs/raftstack#readme",
|
|
2479
|
+
bugs: {
|
|
2480
|
+
url: "https://github.com/Raft-Labs/raftstack/issues"
|
|
2481
|
+
},
|
|
2482
|
+
publishConfig: {
|
|
2483
|
+
access: "public",
|
|
2484
|
+
registry: "https://registry.npmjs.org/"
|
|
2485
|
+
},
|
|
2486
|
+
packageManager: "pnpm@10.23.0",
|
|
2487
|
+
engines: {
|
|
2488
|
+
node: ">=18"
|
|
2489
|
+
},
|
|
2490
|
+
devDependencies: {
|
|
2491
|
+
"@types/node": "^20.10.0",
|
|
2492
|
+
"standard-version": "^9.5.0",
|
|
2493
|
+
tsup: "^8.0.0",
|
|
2494
|
+
typescript: "^5.3.0",
|
|
2495
|
+
vitest: "^1.0.0"
|
|
2496
|
+
},
|
|
2497
|
+
dependencies: {
|
|
2498
|
+
"@clack/prompts": "^0.7.0",
|
|
2499
|
+
commander: "^12.0.0",
|
|
2500
|
+
execa: "^8.0.0",
|
|
2501
|
+
picocolors: "^1.0.0"
|
|
2502
|
+
}
|
|
2503
|
+
};
|
|
2504
|
+
|
|
2275
2505
|
// src/cli.ts
|
|
2276
2506
|
var program = new Command();
|
|
2277
2507
|
program.name("raftstack").description(
|
|
2278
2508
|
"CLI tool for setting up Git hooks, commit conventions, and GitHub integration"
|
|
2279
|
-
).version(
|
|
2509
|
+
).version(package_default.version);
|
|
2280
2510
|
program.command("init").description("Initialize RaftStack configuration in your project").action(async () => {
|
|
2281
2511
|
await runInit(process.cwd());
|
|
2282
2512
|
});
|