@raftlabs/raftstack 1.4.2 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +409 -218
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -27,6 +27,7 @@ var PACKAGE_MANAGERS = {
|
|
|
27
27
|
exec: "npx",
|
|
28
28
|
lockfile: "package-lock.json",
|
|
29
29
|
installFrozen: "npm ci",
|
|
30
|
+
addDev: "install -D",
|
|
30
31
|
needsSetupAction: false,
|
|
31
32
|
cacheKey: "npm-${{ hashFiles('**/package-lock.json') }}"
|
|
32
33
|
},
|
|
@@ -37,6 +38,7 @@ var PACKAGE_MANAGERS = {
|
|
|
37
38
|
exec: "pnpm dlx",
|
|
38
39
|
lockfile: "pnpm-lock.yaml",
|
|
39
40
|
installFrozen: "pnpm install --frozen-lockfile",
|
|
41
|
+
addDev: "add -D",
|
|
40
42
|
needsSetupAction: true,
|
|
41
43
|
cacheKey: "pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}"
|
|
42
44
|
},
|
|
@@ -47,6 +49,7 @@ var PACKAGE_MANAGERS = {
|
|
|
47
49
|
exec: "yarn",
|
|
48
50
|
lockfile: "yarn.lock",
|
|
49
51
|
installFrozen: "yarn install --frozen-lockfile",
|
|
52
|
+
addDev: "add -D",
|
|
50
53
|
needsSetupAction: false,
|
|
51
54
|
cacheKey: "yarn-${{ hashFiles('**/yarn.lock') }}"
|
|
52
55
|
},
|
|
@@ -57,6 +60,7 @@ var PACKAGE_MANAGERS = {
|
|
|
57
60
|
exec: "yarn dlx",
|
|
58
61
|
lockfile: "yarn.lock",
|
|
59
62
|
installFrozen: "yarn install --immutable",
|
|
63
|
+
addDev: "add -D",
|
|
60
64
|
needsSetupAction: false,
|
|
61
65
|
cacheKey: "yarn-${{ hashFiles('**/yarn.lock') }}"
|
|
62
66
|
}
|
|
@@ -484,35 +488,19 @@ function fileExists(filePath) {
|
|
|
484
488
|
}
|
|
485
489
|
|
|
486
490
|
// src/generators/husky.ts
|
|
487
|
-
function getPreCommitHook(
|
|
488
|
-
|
|
489
|
-
return `#!/usr/bin/env sh
|
|
490
|
-
. "$(dirname -- "$0")/_/husky.sh"
|
|
491
|
-
|
|
492
|
-
${pm.exec} lint-staged
|
|
493
|
-
`;
|
|
494
|
-
}
|
|
495
|
-
return `#!/usr/bin/env sh
|
|
496
|
-
. "$(dirname -- "$0")/_/husky.sh"
|
|
497
|
-
|
|
498
|
-
${pm.exec} lint-staged
|
|
491
|
+
function getPreCommitHook(_projectType) {
|
|
492
|
+
return `lint-staged
|
|
499
493
|
`;
|
|
500
494
|
}
|
|
501
|
-
function getCommitMsgHook(
|
|
502
|
-
return
|
|
503
|
-
. "$(dirname -- "$0")/_/husky.sh"
|
|
504
|
-
|
|
505
|
-
${pm.exec} --no -- commitlint --edit "$1"
|
|
495
|
+
function getCommitMsgHook() {
|
|
496
|
+
return `commitlint --edit "$1"
|
|
506
497
|
`;
|
|
507
498
|
}
|
|
508
|
-
function getPrePushHook(
|
|
509
|
-
return
|
|
510
|
-
. "$(dirname -- "$0")/_/husky.sh"
|
|
511
|
-
|
|
512
|
-
${pm.exec} validate-branch-name
|
|
499
|
+
function getPrePushHook() {
|
|
500
|
+
return `validate-branch-name
|
|
513
501
|
`;
|
|
514
502
|
}
|
|
515
|
-
async function generateHuskyHooks(targetDir, projectType,
|
|
503
|
+
async function generateHuskyHooks(targetDir, projectType, _pm) {
|
|
516
504
|
const result = {
|
|
517
505
|
created: [],
|
|
518
506
|
modified: [],
|
|
@@ -524,7 +512,7 @@ async function generateHuskyHooks(targetDir, projectType, pm) {
|
|
|
524
512
|
const preCommitPath = join4(huskyDir, "pre-commit");
|
|
525
513
|
const preCommitResult = await writeFileSafe(
|
|
526
514
|
preCommitPath,
|
|
527
|
-
getPreCommitHook(projectType
|
|
515
|
+
getPreCommitHook(projectType),
|
|
528
516
|
{ executable: true, backup: true }
|
|
529
517
|
);
|
|
530
518
|
if (preCommitResult.created) {
|
|
@@ -536,7 +524,7 @@ async function generateHuskyHooks(targetDir, projectType, pm) {
|
|
|
536
524
|
const commitMsgPath = join4(huskyDir, "commit-msg");
|
|
537
525
|
const commitMsgResult = await writeFileSafe(
|
|
538
526
|
commitMsgPath,
|
|
539
|
-
getCommitMsgHook(
|
|
527
|
+
getCommitMsgHook(),
|
|
540
528
|
{ executable: true, backup: true }
|
|
541
529
|
);
|
|
542
530
|
if (commitMsgResult.created) {
|
|
@@ -546,7 +534,7 @@ async function generateHuskyHooks(targetDir, projectType, pm) {
|
|
|
546
534
|
}
|
|
547
535
|
}
|
|
548
536
|
const prePushPath = join4(huskyDir, "pre-push");
|
|
549
|
-
const prePushResult = await writeFileSafe(prePushPath, getPrePushHook(
|
|
537
|
+
const prePushResult = await writeFileSafe(prePushPath, getPrePushHook(), {
|
|
550
538
|
executable: true,
|
|
551
539
|
backup: true
|
|
552
540
|
});
|
|
@@ -562,10 +550,8 @@ async function generateHuskyHooks(targetDir, projectType, pm) {
|
|
|
562
550
|
// src/generators/commitlint.ts
|
|
563
551
|
import { join as join5 } from "path";
|
|
564
552
|
function getCommitlintConfig(asanaBaseUrl) {
|
|
565
|
-
const baseConfig =
|
|
566
|
-
|
|
567
|
-
/** @type {import('@commitlint/types').UserConfig} */
|
|
568
|
-
const config = {
|
|
553
|
+
const baseConfig = `/** @type {import('@commitlint/types').UserConfig} */
|
|
554
|
+
export default {
|
|
569
555
|
extends: ['@commitlint/config-conventional'],
|
|
570
556
|
rules: {
|
|
571
557
|
// Type must be one of the conventional types
|
|
@@ -593,10 +579,12 @@ const config = {
|
|
|
593
579
|
// Subject should be lowercase
|
|
594
580
|
'subject-case': [2, 'always', 'lower-case'],
|
|
595
581
|
// Header max length
|
|
596
|
-
'header-max-length': [2, 'always', 100]
|
|
597
|
-
},`;
|
|
582
|
+
'header-max-length': [2, 'always', 100],`;
|
|
598
583
|
if (asanaBaseUrl) {
|
|
599
584
|
return `${baseConfig}
|
|
585
|
+
// Asana task link (warning only - won't block commits)
|
|
586
|
+
'asana-task-link': [1, 'always'],
|
|
587
|
+
},
|
|
600
588
|
plugins: [
|
|
601
589
|
{
|
|
602
590
|
rules: {
|
|
@@ -615,18 +603,11 @@ const config = {
|
|
|
615
603
|
},
|
|
616
604
|
],
|
|
617
605
|
};
|
|
618
|
-
|
|
619
|
-
// Enable the Asana task link rule as a WARNING (level 1)
|
|
620
|
-
// Change to level 2 if you want to BLOCK commits without Asana links
|
|
621
|
-
config.rules['asana-task-link'] = [1, 'always'];
|
|
622
|
-
|
|
623
|
-
module.exports = config;
|
|
624
606
|
`;
|
|
625
607
|
}
|
|
626
608
|
return `${baseConfig}
|
|
609
|
+
},
|
|
627
610
|
};
|
|
628
|
-
|
|
629
|
-
module.exports = config;
|
|
630
611
|
`;
|
|
631
612
|
}
|
|
632
613
|
async function generateCommitlint(targetDir, asanaBaseUrl) {
|
|
@@ -763,92 +744,37 @@ async function generateCzGit(targetDir, asanaBaseUrl) {
|
|
|
763
744
|
}
|
|
764
745
|
|
|
765
746
|
// src/generators/lint-staged.ts
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
const
|
|
747
|
+
function getLintStagedConfig(usesEslint, usesPrettier, usesTypeScript) {
|
|
748
|
+
const config = {};
|
|
749
|
+
const codePatterns = [];
|
|
769
750
|
if (usesTypeScript) {
|
|
770
|
-
|
|
771
|
-
if (usesEslint) {
|
|
772
|
-
tsCommands.push("eslint --fix");
|
|
773
|
-
}
|
|
774
|
-
if (usesPrettier) {
|
|
775
|
-
tsCommands.push("prettier --write");
|
|
776
|
-
}
|
|
777
|
-
if (tsCommands.length > 0) {
|
|
778
|
-
rules["*.{ts,tsx}"] = tsCommands;
|
|
779
|
-
}
|
|
751
|
+
codePatterns.push("ts", "mts", "cts", "tsx");
|
|
780
752
|
}
|
|
781
|
-
|
|
753
|
+
codePatterns.push("js", "mjs", "cjs", "jsx");
|
|
754
|
+
const codeCommands = [];
|
|
782
755
|
if (usesEslint) {
|
|
783
|
-
|
|
756
|
+
codeCommands.push("eslint --fix");
|
|
784
757
|
}
|
|
785
758
|
if (usesPrettier) {
|
|
786
|
-
|
|
759
|
+
codeCommands.push("prettier --write");
|
|
787
760
|
}
|
|
788
|
-
if (
|
|
789
|
-
|
|
761
|
+
if (codeCommands.length > 0) {
|
|
762
|
+
const pattern = `*.{${codePatterns.join(",")}}`;
|
|
763
|
+
config[pattern] = codeCommands;
|
|
790
764
|
}
|
|
791
765
|
if (usesPrettier) {
|
|
792
|
-
|
|
793
|
-
}
|
|
794
|
-
if (usesPrettier) {
|
|
795
|
-
rules["*.{css,scss,less}"] = "prettier --write";
|
|
796
|
-
}
|
|
797
|
-
if (projectType === "nx") {
|
|
798
|
-
return `// @ts-check
|
|
799
|
-
|
|
800
|
-
/**
|
|
801
|
-
* @type {import('lint-staged').Config}
|
|
802
|
-
*/
|
|
803
|
-
module.exports = {
|
|
804
|
-
${Object.entries(rules).map(([pattern, commands]) => {
|
|
805
|
-
const cmdStr = Array.isArray(commands) ? JSON.stringify(commands) : JSON.stringify([commands]);
|
|
806
|
-
return ` '${pattern}': ${cmdStr},`;
|
|
807
|
-
}).join("\n")}
|
|
808
|
-
};
|
|
809
|
-
`;
|
|
810
|
-
}
|
|
811
|
-
return `// @ts-check
|
|
812
|
-
|
|
813
|
-
/**
|
|
814
|
-
* @type {import('lint-staged').Config}
|
|
815
|
-
*/
|
|
816
|
-
module.exports = {
|
|
817
|
-
${Object.entries(rules).map(([pattern, commands]) => {
|
|
818
|
-
const cmdStr = Array.isArray(commands) ? JSON.stringify(commands) : JSON.stringify([commands]);
|
|
819
|
-
return ` '${pattern}': ${cmdStr},`;
|
|
820
|
-
}).join("\n")}
|
|
821
|
-
};
|
|
822
|
-
`;
|
|
823
|
-
}
|
|
824
|
-
async function generateLintStaged(targetDir, projectType, usesEslint, usesPrettier, usesTypeScript) {
|
|
825
|
-
const result = {
|
|
826
|
-
created: [],
|
|
827
|
-
modified: [],
|
|
828
|
-
skipped: [],
|
|
829
|
-
backedUp: []
|
|
830
|
-
};
|
|
831
|
-
const configPath = join7(targetDir, ".lintstagedrc.js");
|
|
832
|
-
const writeResult = await writeFileSafe(
|
|
833
|
-
configPath,
|
|
834
|
-
getLintStagedConfig(projectType, usesEslint, usesPrettier, usesTypeScript),
|
|
835
|
-
{ backup: true }
|
|
836
|
-
);
|
|
837
|
-
if (writeResult.created) {
|
|
838
|
-
result.created.push(".lintstagedrc.js");
|
|
839
|
-
if (writeResult.backedUp) {
|
|
840
|
-
result.backedUp.push(writeResult.backedUp);
|
|
841
|
-
}
|
|
766
|
+
config["*.{json,css,md}"] = ["prettier --write"];
|
|
842
767
|
}
|
|
843
|
-
return
|
|
768
|
+
return config;
|
|
844
769
|
}
|
|
845
770
|
|
|
846
771
|
// src/utils/package-json.ts
|
|
847
772
|
import { readFile as readFile3, writeFile as writeFile2 } from "fs/promises";
|
|
848
773
|
import { existsSync as existsSync4 } from "fs";
|
|
849
|
-
import { join as
|
|
774
|
+
import { join as join7 } from "path";
|
|
775
|
+
import { spawn } from "child_process";
|
|
850
776
|
async function readPackageJson(targetDir = process.cwd()) {
|
|
851
|
-
const pkgPath =
|
|
777
|
+
const pkgPath = join7(targetDir, "package.json");
|
|
852
778
|
if (!existsSync4(pkgPath)) {
|
|
853
779
|
throw new Error(`No package.json found in ${targetDir}`);
|
|
854
780
|
}
|
|
@@ -856,7 +782,7 @@ async function readPackageJson(targetDir = process.cwd()) {
|
|
|
856
782
|
return JSON.parse(content);
|
|
857
783
|
}
|
|
858
784
|
async function writePackageJson(pkg, targetDir = process.cwd()) {
|
|
859
|
-
const pkgPath =
|
|
785
|
+
const pkgPath = join7(targetDir, "package.json");
|
|
860
786
|
const content = JSON.stringify(pkg, null, 2) + "\n";
|
|
861
787
|
await writeFile2(pkgPath, content, "utf-8");
|
|
862
788
|
}
|
|
@@ -873,16 +799,6 @@ function mergeScripts(pkg, scripts, overwrite = false) {
|
|
|
873
799
|
scripts: newScripts
|
|
874
800
|
};
|
|
875
801
|
}
|
|
876
|
-
function mergeDevDependencies(pkg, deps) {
|
|
877
|
-
const existingDeps = pkg.devDependencies || {};
|
|
878
|
-
return {
|
|
879
|
-
...pkg,
|
|
880
|
-
devDependencies: {
|
|
881
|
-
...existingDeps,
|
|
882
|
-
...deps
|
|
883
|
-
}
|
|
884
|
-
};
|
|
885
|
-
}
|
|
886
802
|
function addPackageJsonConfig(pkg, key, config, overwrite = false) {
|
|
887
803
|
if (!overwrite && pkg[key]) {
|
|
888
804
|
return pkg;
|
|
@@ -892,15 +808,62 @@ function addPackageJsonConfig(pkg, key, config, overwrite = false) {
|
|
|
892
808
|
[key]: config
|
|
893
809
|
};
|
|
894
810
|
}
|
|
895
|
-
var
|
|
896
|
-
|
|
897
|
-
"@commitlint/
|
|
898
|
-
"
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
"
|
|
902
|
-
"
|
|
903
|
-
|
|
811
|
+
var RAFTSTACK_PACKAGES = [
|
|
812
|
+
// Commit tooling
|
|
813
|
+
"@commitlint/cli",
|
|
814
|
+
"@commitlint/config-conventional",
|
|
815
|
+
"cz-git",
|
|
816
|
+
"czg",
|
|
817
|
+
"husky",
|
|
818
|
+
"lint-staged",
|
|
819
|
+
"validate-branch-name",
|
|
820
|
+
// Linting & formatting
|
|
821
|
+
"eslint",
|
|
822
|
+
"@eslint/js",
|
|
823
|
+
"typescript-eslint",
|
|
824
|
+
"eslint-config-prettier",
|
|
825
|
+
"prettier",
|
|
826
|
+
"globals"
|
|
827
|
+
];
|
|
828
|
+
var REACT_ESLINT_PACKAGES = [
|
|
829
|
+
"eslint-plugin-react",
|
|
830
|
+
"eslint-plugin-react-hooks"
|
|
831
|
+
];
|
|
832
|
+
async function installPackages(pm, packages, targetDir) {
|
|
833
|
+
if (packages.length === 0) {
|
|
834
|
+
return { success: true };
|
|
835
|
+
}
|
|
836
|
+
return new Promise((resolve) => {
|
|
837
|
+
const addDevArgs = pm.addDev.split(" ");
|
|
838
|
+
const pmCommand = pm.name === "npm" ? "npm" : pm.name.replace("-berry", "");
|
|
839
|
+
const args = [...addDevArgs, ...packages];
|
|
840
|
+
const child = spawn(pmCommand, args, {
|
|
841
|
+
cwd: targetDir,
|
|
842
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
843
|
+
shell: process.platform === "win32"
|
|
844
|
+
});
|
|
845
|
+
let stderr = "";
|
|
846
|
+
child.stderr?.on("data", (data) => {
|
|
847
|
+
stderr += data.toString();
|
|
848
|
+
});
|
|
849
|
+
child.on("close", (code) => {
|
|
850
|
+
if (code === 0) {
|
|
851
|
+
resolve({ success: true });
|
|
852
|
+
} else {
|
|
853
|
+
resolve({
|
|
854
|
+
success: false,
|
|
855
|
+
error: stderr || `Installation failed with exit code ${code}`
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
});
|
|
859
|
+
child.on("error", (err) => {
|
|
860
|
+
resolve({
|
|
861
|
+
success: false,
|
|
862
|
+
error: err.message
|
|
863
|
+
});
|
|
864
|
+
});
|
|
865
|
+
});
|
|
866
|
+
}
|
|
904
867
|
|
|
905
868
|
// src/generators/branch-validation.ts
|
|
906
869
|
function getBranchValidationConfig() {
|
|
@@ -939,7 +902,7 @@ async function generateBranchValidation(targetDir) {
|
|
|
939
902
|
}
|
|
940
903
|
|
|
941
904
|
// src/generators/pr-template.ts
|
|
942
|
-
import { join as
|
|
905
|
+
import { join as join8 } from "path";
|
|
943
906
|
function getPRTemplate(hasAsana) {
|
|
944
907
|
const asanaSection = hasAsana ? `## Asana Task
|
|
945
908
|
<!-- Link to the Asana task -->
|
|
@@ -991,9 +954,9 @@ async function generatePRTemplate(targetDir, hasAsana) {
|
|
|
991
954
|
skipped: [],
|
|
992
955
|
backedUp: []
|
|
993
956
|
};
|
|
994
|
-
const githubDir =
|
|
957
|
+
const githubDir = join8(targetDir, ".github");
|
|
995
958
|
await ensureDir(githubDir);
|
|
996
|
-
const templatePath =
|
|
959
|
+
const templatePath = join8(githubDir, "PULL_REQUEST_TEMPLATE.md");
|
|
997
960
|
const writeResult = await writeFileSafe(
|
|
998
961
|
templatePath,
|
|
999
962
|
getPRTemplate(hasAsana),
|
|
@@ -1009,7 +972,7 @@ async function generatePRTemplate(targetDir, hasAsana) {
|
|
|
1009
972
|
}
|
|
1010
973
|
|
|
1011
974
|
// src/generators/github-workflows.ts
|
|
1012
|
-
import { join as
|
|
975
|
+
import { join as join9 } from "path";
|
|
1013
976
|
function getPRChecksWorkflow(projectType, usesTypeScript, usesEslint, pm) {
|
|
1014
977
|
const steps = [];
|
|
1015
978
|
steps.push(` - name: Checkout
|
|
@@ -1090,9 +1053,9 @@ async function generateGitHubWorkflows(targetDir, projectType, usesTypeScript, u
|
|
|
1090
1053
|
skipped: [],
|
|
1091
1054
|
backedUp: []
|
|
1092
1055
|
};
|
|
1093
|
-
const workflowsDir =
|
|
1056
|
+
const workflowsDir = join9(targetDir, ".github", "workflows");
|
|
1094
1057
|
await ensureDir(workflowsDir);
|
|
1095
|
-
const prChecksPath =
|
|
1058
|
+
const prChecksPath = join9(workflowsDir, "pr-checks.yml");
|
|
1096
1059
|
const writeResult = await writeFileSafe(
|
|
1097
1060
|
prChecksPath,
|
|
1098
1061
|
getPRChecksWorkflow(projectType, usesTypeScript, usesEslint, pm),
|
|
@@ -1108,7 +1071,7 @@ async function generateGitHubWorkflows(targetDir, projectType, usesTypeScript, u
|
|
|
1108
1071
|
}
|
|
1109
1072
|
|
|
1110
1073
|
// src/generators/codeowners.ts
|
|
1111
|
-
import { join as
|
|
1074
|
+
import { join as join10 } from "path";
|
|
1112
1075
|
function getCodeownersContent(owners) {
|
|
1113
1076
|
if (owners.length === 0) {
|
|
1114
1077
|
return `# CODEOWNERS file
|
|
@@ -1140,9 +1103,9 @@ async function generateCodeowners(targetDir, owners) {
|
|
|
1140
1103
|
skipped: [],
|
|
1141
1104
|
backedUp: []
|
|
1142
1105
|
};
|
|
1143
|
-
const githubDir =
|
|
1106
|
+
const githubDir = join10(targetDir, ".github");
|
|
1144
1107
|
await ensureDir(githubDir);
|
|
1145
|
-
const codeownersPath =
|
|
1108
|
+
const codeownersPath = join10(githubDir, "CODEOWNERS");
|
|
1146
1109
|
const writeResult = await writeFileSafe(
|
|
1147
1110
|
codeownersPath,
|
|
1148
1111
|
getCodeownersContent(owners),
|
|
@@ -1158,7 +1121,7 @@ async function generateCodeowners(targetDir, owners) {
|
|
|
1158
1121
|
}
|
|
1159
1122
|
|
|
1160
1123
|
// src/generators/ai-review.ts
|
|
1161
|
-
import { join as
|
|
1124
|
+
import { join as join11 } from "path";
|
|
1162
1125
|
function getCodeRabbitConfig() {
|
|
1163
1126
|
return `# CodeRabbit Configuration
|
|
1164
1127
|
# Learn more: https://docs.coderabbit.ai/guides/configure-coderabbit
|
|
@@ -1222,7 +1185,7 @@ async function generateAIReview(targetDir, tool) {
|
|
|
1222
1185
|
return result;
|
|
1223
1186
|
}
|
|
1224
1187
|
if (tool === "coderabbit") {
|
|
1225
|
-
const configPath =
|
|
1188
|
+
const configPath = join11(targetDir, ".coderabbit.yaml");
|
|
1226
1189
|
const writeResult = await writeFileSafe(configPath, getCodeRabbitConfig(), {
|
|
1227
1190
|
backup: true
|
|
1228
1191
|
});
|
|
@@ -1234,9 +1197,9 @@ async function generateAIReview(targetDir, tool) {
|
|
|
1234
1197
|
}
|
|
1235
1198
|
}
|
|
1236
1199
|
if (tool === "copilot") {
|
|
1237
|
-
const workflowsDir =
|
|
1200
|
+
const workflowsDir = join11(targetDir, ".github", "workflows");
|
|
1238
1201
|
await ensureDir(workflowsDir);
|
|
1239
|
-
const workflowPath =
|
|
1202
|
+
const workflowPath = join11(workflowsDir, "copilot-review.yml");
|
|
1240
1203
|
const writeResult = await writeFileSafe(workflowPath, getCopilotWorkflow(), {
|
|
1241
1204
|
backup: true
|
|
1242
1205
|
});
|
|
@@ -1251,7 +1214,7 @@ async function generateAIReview(targetDir, tool) {
|
|
|
1251
1214
|
}
|
|
1252
1215
|
|
|
1253
1216
|
// src/generators/branch-protection.ts
|
|
1254
|
-
import { join as
|
|
1217
|
+
import { join as join12 } from "path";
|
|
1255
1218
|
function getBranchProtectionDocs() {
|
|
1256
1219
|
return `# Branch Protection Setup Guide
|
|
1257
1220
|
|
|
@@ -1368,9 +1331,9 @@ async function generateBranchProtectionDocs(targetDir) {
|
|
|
1368
1331
|
skipped: [],
|
|
1369
1332
|
backedUp: []
|
|
1370
1333
|
};
|
|
1371
|
-
const docsDir =
|
|
1334
|
+
const docsDir = join12(targetDir, ".github");
|
|
1372
1335
|
await ensureDir(docsDir);
|
|
1373
|
-
const docsPath =
|
|
1336
|
+
const docsPath = join12(docsDir, "BRANCH_PROTECTION_SETUP.md");
|
|
1374
1337
|
const writeResult = await writeFileSafe(docsPath, getBranchProtectionDocs(), {
|
|
1375
1338
|
backup: true
|
|
1376
1339
|
});
|
|
@@ -1384,7 +1347,7 @@ async function generateBranchProtectionDocs(targetDir) {
|
|
|
1384
1347
|
}
|
|
1385
1348
|
|
|
1386
1349
|
// src/generators/contributing.ts
|
|
1387
|
-
import { join as
|
|
1350
|
+
import { join as join13 } from "path";
|
|
1388
1351
|
function getContributingContent(hasAsana, pm) {
|
|
1389
1352
|
const asanaSection = hasAsana ? `
|
|
1390
1353
|
## Linking to Asana
|
|
@@ -1523,7 +1486,7 @@ async function generateContributing(targetDir, hasAsana, pm) {
|
|
|
1523
1486
|
skipped: [],
|
|
1524
1487
|
backedUp: []
|
|
1525
1488
|
};
|
|
1526
|
-
const contributingPath =
|
|
1489
|
+
const contributingPath = join13(targetDir, "CONTRIBUTING.md");
|
|
1527
1490
|
const writeResult = await writeFileSafe(
|
|
1528
1491
|
contributingPath,
|
|
1529
1492
|
getContributingContent(hasAsana, pm),
|
|
@@ -1539,16 +1502,16 @@ async function generateContributing(targetDir, hasAsana, pm) {
|
|
|
1539
1502
|
}
|
|
1540
1503
|
|
|
1541
1504
|
// src/generators/prettier.ts
|
|
1542
|
-
import { join as
|
|
1505
|
+
import { join as join14 } from "path";
|
|
1543
1506
|
function getPrettierConfig() {
|
|
1544
1507
|
return JSON.stringify(
|
|
1545
1508
|
{
|
|
1546
1509
|
semi: true,
|
|
1547
|
-
singleQuote: true,
|
|
1548
|
-
tabWidth: 2,
|
|
1549
1510
|
trailingComma: "es5",
|
|
1550
|
-
|
|
1551
|
-
|
|
1511
|
+
singleQuote: false,
|
|
1512
|
+
printWidth: 80,
|
|
1513
|
+
tabWidth: 2,
|
|
1514
|
+
useTabs: false,
|
|
1552
1515
|
arrowParens: "always",
|
|
1553
1516
|
endOfLine: "lf"
|
|
1554
1517
|
},
|
|
@@ -1557,31 +1520,14 @@ function getPrettierConfig() {
|
|
|
1557
1520
|
) + "\n";
|
|
1558
1521
|
}
|
|
1559
1522
|
function getPrettierIgnore() {
|
|
1560
|
-
return
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
.next/
|
|
1567
|
-
out/
|
|
1568
|
-
|
|
1569
|
-
# Coverage
|
|
1570
|
-
coverage/
|
|
1571
|
-
|
|
1572
|
-
# IDE
|
|
1573
|
-
.idea/
|
|
1574
|
-
.vscode/
|
|
1575
|
-
|
|
1576
|
-
# Generated files
|
|
1577
|
-
*.min.js
|
|
1578
|
-
*.min.css
|
|
1579
|
-
package-lock.json
|
|
1523
|
+
return `node_modules
|
|
1524
|
+
dist
|
|
1525
|
+
build
|
|
1526
|
+
.turbo
|
|
1527
|
+
.next
|
|
1528
|
+
*.lock
|
|
1580
1529
|
pnpm-lock.yaml
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
# Other
|
|
1584
|
-
.git/
|
|
1530
|
+
coverage
|
|
1585
1531
|
`;
|
|
1586
1532
|
}
|
|
1587
1533
|
function hasPrettierConfig(targetDir) {
|
|
@@ -1597,7 +1543,7 @@ function hasPrettierConfig(targetDir) {
|
|
|
1597
1543
|
"prettier.config.cjs",
|
|
1598
1544
|
"prettier.config.mjs"
|
|
1599
1545
|
];
|
|
1600
|
-
return prettierFiles.some((file) => fileExists(
|
|
1546
|
+
return prettierFiles.some((file) => fileExists(join14(targetDir, file)));
|
|
1601
1547
|
}
|
|
1602
1548
|
async function generatePrettier(targetDir) {
|
|
1603
1549
|
const result = {
|
|
@@ -1610,7 +1556,7 @@ async function generatePrettier(targetDir) {
|
|
|
1610
1556
|
result.skipped.push(".prettierrc (already exists)");
|
|
1611
1557
|
return result;
|
|
1612
1558
|
}
|
|
1613
|
-
const configPath =
|
|
1559
|
+
const configPath = join14(targetDir, ".prettierrc");
|
|
1614
1560
|
const configResult = await writeFileSafe(configPath, getPrettierConfig(), {
|
|
1615
1561
|
backup: true
|
|
1616
1562
|
});
|
|
@@ -1620,7 +1566,7 @@ async function generatePrettier(targetDir) {
|
|
|
1620
1566
|
result.backedUp.push(configResult.backedUp);
|
|
1621
1567
|
}
|
|
1622
1568
|
}
|
|
1623
|
-
const ignorePath =
|
|
1569
|
+
const ignorePath = join14(targetDir, ".prettierignore");
|
|
1624
1570
|
const ignoreResult = await writeFileSafe(ignorePath, getPrettierIgnore(), {
|
|
1625
1571
|
backup: true,
|
|
1626
1572
|
overwrite: false
|
|
@@ -1640,19 +1586,19 @@ async function generatePrettier(targetDir) {
|
|
|
1640
1586
|
// src/generators/claude-skills.ts
|
|
1641
1587
|
import { existsSync as existsSync5 } from "fs";
|
|
1642
1588
|
import { readdir, copyFile as copyFile2 } from "fs/promises";
|
|
1643
|
-
import { join as
|
|
1589
|
+
import { join as join15, dirname as dirname2 } from "path";
|
|
1644
1590
|
import { fileURLToPath } from "url";
|
|
1645
1591
|
function getPackageSkillsDir() {
|
|
1646
1592
|
const currentFilePath = fileURLToPath(import.meta.url);
|
|
1647
|
-
const packageRoot =
|
|
1648
|
-
return
|
|
1593
|
+
const packageRoot = join15(dirname2(currentFilePath), "..");
|
|
1594
|
+
return join15(packageRoot, ".claude", "skills");
|
|
1649
1595
|
}
|
|
1650
1596
|
async function copyDirectory(srcDir, destDir, result, baseDir) {
|
|
1651
1597
|
await ensureDir(destDir);
|
|
1652
1598
|
const entries = await readdir(srcDir, { withFileTypes: true });
|
|
1653
1599
|
for (const entry of entries) {
|
|
1654
|
-
const srcPath =
|
|
1655
|
-
const destPath =
|
|
1600
|
+
const srcPath = join15(srcDir, entry.name);
|
|
1601
|
+
const destPath = join15(destDir, entry.name);
|
|
1656
1602
|
const relativePath = destPath.replace(baseDir + "/", "");
|
|
1657
1603
|
if (entry.isDirectory()) {
|
|
1658
1604
|
await copyDirectory(srcPath, destPath, result, baseDir);
|
|
@@ -1676,14 +1622,14 @@ async function generateClaudeSkills(targetDir) {
|
|
|
1676
1622
|
backedUp: []
|
|
1677
1623
|
};
|
|
1678
1624
|
const packageSkillsDir = getPackageSkillsDir();
|
|
1679
|
-
const targetSkillsDir =
|
|
1625
|
+
const targetSkillsDir = join15(targetDir, ".claude", "skills");
|
|
1680
1626
|
if (!existsSync5(packageSkillsDir)) {
|
|
1681
1627
|
console.warn(
|
|
1682
1628
|
"Warning: Skills directory not found in package. Skipping skills generation."
|
|
1683
1629
|
);
|
|
1684
1630
|
return result;
|
|
1685
1631
|
}
|
|
1686
|
-
await ensureDir(
|
|
1632
|
+
await ensureDir(join15(targetDir, ".claude"));
|
|
1687
1633
|
await copyDirectory(packageSkillsDir, targetSkillsDir, result, targetDir);
|
|
1688
1634
|
return result;
|
|
1689
1635
|
}
|
|
@@ -1691,10 +1637,229 @@ async function generateClaudeSkills(targetDir) {
|
|
|
1691
1637
|
// src/generators/eslint.ts
|
|
1692
1638
|
import { existsSync as existsSync6 } from "fs";
|
|
1693
1639
|
import { readFile as readFile4 } from "fs/promises";
|
|
1694
|
-
import { join as
|
|
1640
|
+
import { join as join16 } from "path";
|
|
1641
|
+
async function hasReact(targetDir) {
|
|
1642
|
+
try {
|
|
1643
|
+
const pkgPath = join16(targetDir, "package.json");
|
|
1644
|
+
if (existsSync6(pkgPath)) {
|
|
1645
|
+
const content = await readFile4(pkgPath, "utf-8");
|
|
1646
|
+
const pkg = JSON.parse(content);
|
|
1647
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
1648
|
+
return "react" in deps || "react-dom" in deps;
|
|
1649
|
+
}
|
|
1650
|
+
} catch {
|
|
1651
|
+
}
|
|
1652
|
+
return false;
|
|
1653
|
+
}
|
|
1654
|
+
function generateTsConfig(hasReactDep) {
|
|
1655
|
+
if (hasReactDep) {
|
|
1656
|
+
return `import eslint from "@eslint/js";
|
|
1657
|
+
import tseslint from "typescript-eslint";
|
|
1658
|
+
import eslintConfigPrettier from "eslint-config-prettier";
|
|
1659
|
+
import reactPlugin from "eslint-plugin-react";
|
|
1660
|
+
import reactHooksPlugin from "eslint-plugin-react-hooks";
|
|
1661
|
+
import globals from "globals";
|
|
1662
|
+
|
|
1663
|
+
export default tseslint.config(
|
|
1664
|
+
eslint.configs.recommended,
|
|
1665
|
+
...tseslint.configs.strict,
|
|
1666
|
+
eslintConfigPrettier,
|
|
1667
|
+
{
|
|
1668
|
+
files: ["**/*.{ts,tsx}"],
|
|
1669
|
+
languageOptions: {
|
|
1670
|
+
parserOptions: {
|
|
1671
|
+
ecmaFeatures: {
|
|
1672
|
+
jsx: true,
|
|
1673
|
+
},
|
|
1674
|
+
},
|
|
1675
|
+
globals: {
|
|
1676
|
+
...globals.browser,
|
|
1677
|
+
...globals.node,
|
|
1678
|
+
},
|
|
1679
|
+
},
|
|
1680
|
+
plugins: {
|
|
1681
|
+
react: reactPlugin,
|
|
1682
|
+
"react-hooks": reactHooksPlugin,
|
|
1683
|
+
},
|
|
1684
|
+
rules: {
|
|
1685
|
+
// TypeScript rules
|
|
1686
|
+
"@typescript-eslint/no-unused-vars": [
|
|
1687
|
+
"error",
|
|
1688
|
+
{ argsIgnorePattern: "^_", varsIgnorePattern: "^_" },
|
|
1689
|
+
],
|
|
1690
|
+
"@typescript-eslint/no-explicit-any": "warn",
|
|
1691
|
+
"@typescript-eslint/consistent-type-imports": [
|
|
1692
|
+
"warn",
|
|
1693
|
+
{ prefer: "type-imports" },
|
|
1694
|
+
],
|
|
1695
|
+
|
|
1696
|
+
// React rules
|
|
1697
|
+
"react/react-in-jsx-scope": "off",
|
|
1698
|
+
"react/prop-types": "off",
|
|
1699
|
+
"react-hooks/rules-of-hooks": "error",
|
|
1700
|
+
"react-hooks/exhaustive-deps": "warn",
|
|
1701
|
+
|
|
1702
|
+
// General rules
|
|
1703
|
+
"no-console": ["warn", { allow: ["warn", "error"] }],
|
|
1704
|
+
},
|
|
1705
|
+
settings: {
|
|
1706
|
+
react: {
|
|
1707
|
+
version: "detect",
|
|
1708
|
+
},
|
|
1709
|
+
},
|
|
1710
|
+
},
|
|
1711
|
+
{
|
|
1712
|
+
ignores: ["node_modules/", "dist/", "build/", ".next/", "coverage/", ".turbo/"],
|
|
1713
|
+
}
|
|
1714
|
+
);
|
|
1715
|
+
`;
|
|
1716
|
+
}
|
|
1717
|
+
return `import eslint from "@eslint/js";
|
|
1718
|
+
import tseslint from "typescript-eslint";
|
|
1719
|
+
import eslintConfigPrettier from "eslint-config-prettier";
|
|
1720
|
+
import globals from "globals";
|
|
1721
|
+
|
|
1722
|
+
export default tseslint.config(
|
|
1723
|
+
eslint.configs.recommended,
|
|
1724
|
+
...tseslint.configs.strict,
|
|
1725
|
+
eslintConfigPrettier,
|
|
1726
|
+
{
|
|
1727
|
+
files: ["**/*.{ts,tsx}"],
|
|
1728
|
+
languageOptions: {
|
|
1729
|
+
globals: {
|
|
1730
|
+
...globals.node,
|
|
1731
|
+
},
|
|
1732
|
+
},
|
|
1733
|
+
rules: {
|
|
1734
|
+
// TypeScript rules
|
|
1735
|
+
"@typescript-eslint/no-unused-vars": [
|
|
1736
|
+
"error",
|
|
1737
|
+
{ argsIgnorePattern: "^_", varsIgnorePattern: "^_" },
|
|
1738
|
+
],
|
|
1739
|
+
"@typescript-eslint/no-explicit-any": "warn",
|
|
1740
|
+
"@typescript-eslint/consistent-type-imports": [
|
|
1741
|
+
"warn",
|
|
1742
|
+
{ prefer: "type-imports" },
|
|
1743
|
+
],
|
|
1744
|
+
|
|
1745
|
+
// General rules
|
|
1746
|
+
"no-console": ["warn", { allow: ["warn", "error"] }],
|
|
1747
|
+
},
|
|
1748
|
+
},
|
|
1749
|
+
{
|
|
1750
|
+
ignores: ["node_modules/", "dist/", "build/", "coverage/", ".turbo/"],
|
|
1751
|
+
}
|
|
1752
|
+
);
|
|
1753
|
+
`;
|
|
1754
|
+
}
|
|
1755
|
+
function generateJsConfig(hasReactDep) {
|
|
1756
|
+
if (hasReactDep) {
|
|
1757
|
+
return `import eslint from "@eslint/js";
|
|
1758
|
+
import eslintConfigPrettier from "eslint-config-prettier";
|
|
1759
|
+
import reactPlugin from "eslint-plugin-react";
|
|
1760
|
+
import reactHooksPlugin from "eslint-plugin-react-hooks";
|
|
1761
|
+
import globals from "globals";
|
|
1762
|
+
|
|
1763
|
+
export default [
|
|
1764
|
+
eslint.configs.recommended,
|
|
1765
|
+
eslintConfigPrettier,
|
|
1766
|
+
{
|
|
1767
|
+
files: ["**/*.{js,jsx}"],
|
|
1768
|
+
languageOptions: {
|
|
1769
|
+
ecmaVersion: "latest",
|
|
1770
|
+
sourceType: "module",
|
|
1771
|
+
parserOptions: {
|
|
1772
|
+
ecmaFeatures: {
|
|
1773
|
+
jsx: true,
|
|
1774
|
+
},
|
|
1775
|
+
},
|
|
1776
|
+
globals: {
|
|
1777
|
+
...globals.browser,
|
|
1778
|
+
...globals.node,
|
|
1779
|
+
},
|
|
1780
|
+
},
|
|
1781
|
+
plugins: {
|
|
1782
|
+
react: reactPlugin,
|
|
1783
|
+
"react-hooks": reactHooksPlugin,
|
|
1784
|
+
},
|
|
1785
|
+
rules: {
|
|
1786
|
+
// React rules
|
|
1787
|
+
"react/react-in-jsx-scope": "off",
|
|
1788
|
+
"react/prop-types": "warn",
|
|
1789
|
+
"react-hooks/rules-of-hooks": "error",
|
|
1790
|
+
"react-hooks/exhaustive-deps": "warn",
|
|
1791
|
+
|
|
1792
|
+
// General rules
|
|
1793
|
+
"no-console": ["warn", { allow: ["warn", "error"] }],
|
|
1794
|
+
"no-unused-vars": ["error", { argsIgnorePattern: "^_", varsIgnorePattern: "^_" }],
|
|
1795
|
+
},
|
|
1796
|
+
settings: {
|
|
1797
|
+
react: {
|
|
1798
|
+
version: "detect",
|
|
1799
|
+
},
|
|
1800
|
+
},
|
|
1801
|
+
},
|
|
1802
|
+
{
|
|
1803
|
+
ignores: ["node_modules/", "dist/", "build/", ".next/", "coverage/", ".turbo/"],
|
|
1804
|
+
},
|
|
1805
|
+
];
|
|
1806
|
+
`;
|
|
1807
|
+
}
|
|
1808
|
+
return `import eslint from "@eslint/js";
|
|
1809
|
+
import eslintConfigPrettier from "eslint-config-prettier";
|
|
1810
|
+
import globals from "globals";
|
|
1811
|
+
|
|
1812
|
+
export default [
|
|
1813
|
+
eslint.configs.recommended,
|
|
1814
|
+
eslintConfigPrettier,
|
|
1815
|
+
{
|
|
1816
|
+
files: ["**/*.js"],
|
|
1817
|
+
languageOptions: {
|
|
1818
|
+
ecmaVersion: "latest",
|
|
1819
|
+
sourceType: "module",
|
|
1820
|
+
globals: {
|
|
1821
|
+
...globals.node,
|
|
1822
|
+
},
|
|
1823
|
+
},
|
|
1824
|
+
rules: {
|
|
1825
|
+
// General rules
|
|
1826
|
+
"no-console": ["warn", { allow: ["warn", "error"] }],
|
|
1827
|
+
"no-unused-vars": ["error", { argsIgnorePattern: "^_", varsIgnorePattern: "^_" }],
|
|
1828
|
+
},
|
|
1829
|
+
},
|
|
1830
|
+
{
|
|
1831
|
+
ignores: ["node_modules/", "dist/", "build/", "coverage/", ".turbo/"],
|
|
1832
|
+
},
|
|
1833
|
+
];
|
|
1834
|
+
`;
|
|
1835
|
+
}
|
|
1836
|
+
async function detectReact(targetDir) {
|
|
1837
|
+
return hasReact(targetDir);
|
|
1838
|
+
}
|
|
1839
|
+
async function generateEslint(targetDir, usesTypeScript, force = false) {
|
|
1840
|
+
const result = {
|
|
1841
|
+
created: [],
|
|
1842
|
+
modified: [],
|
|
1843
|
+
skipped: [],
|
|
1844
|
+
backedUp: []
|
|
1845
|
+
};
|
|
1846
|
+
if (!force && await hasEslint(targetDir)) {
|
|
1847
|
+
result.skipped.push("eslint.config.js (ESLint already configured)");
|
|
1848
|
+
return result;
|
|
1849
|
+
}
|
|
1850
|
+
const usesReact = await hasReact(targetDir);
|
|
1851
|
+
const config = usesTypeScript ? generateTsConfig(usesReact) : generateJsConfig(usesReact);
|
|
1852
|
+
const configPath = join16(targetDir, "eslint.config.js");
|
|
1853
|
+
const writeResult = await writeFileSafe(configPath, config);
|
|
1854
|
+
if (writeResult.backedUp) {
|
|
1855
|
+
result.backedUp.push("eslint.config.js");
|
|
1856
|
+
}
|
|
1857
|
+
result.created.push("eslint.config.js");
|
|
1858
|
+
return result;
|
|
1859
|
+
}
|
|
1695
1860
|
|
|
1696
1861
|
// src/generators/quick-reference.ts
|
|
1697
|
-
import { join as
|
|
1862
|
+
import { join as join17 } from "path";
|
|
1698
1863
|
async function generateQuickReference(targetDir, pm) {
|
|
1699
1864
|
const result = {
|
|
1700
1865
|
created: [],
|
|
@@ -1702,7 +1867,7 @@ async function generateQuickReference(targetDir, pm) {
|
|
|
1702
1867
|
skipped: [],
|
|
1703
1868
|
backedUp: []
|
|
1704
1869
|
};
|
|
1705
|
-
const quickRefPath =
|
|
1870
|
+
const quickRefPath = join17(targetDir, ".github", "QUICK_REFERENCE.md");
|
|
1706
1871
|
const content = `# RaftStack Quick Reference
|
|
1707
1872
|
|
|
1708
1873
|
> One-page guide for the RaftStack Git workflow
|
|
@@ -1838,9 +2003,9 @@ ${pm.run} test
|
|
|
1838
2003
|
// src/utils/git.ts
|
|
1839
2004
|
import { execa } from "execa";
|
|
1840
2005
|
import { existsSync as existsSync7 } from "fs";
|
|
1841
|
-
import { join as
|
|
2006
|
+
import { join as join18 } from "path";
|
|
1842
2007
|
async function isGitRepo(targetDir = process.cwd()) {
|
|
1843
|
-
if (existsSync7(
|
|
2008
|
+
if (existsSync7(join18(targetDir, ".git"))) {
|
|
1844
2009
|
return true;
|
|
1845
2010
|
}
|
|
1846
2011
|
try {
|
|
@@ -1885,7 +2050,7 @@ function mergeResults(results) {
|
|
|
1885
2050
|
{ created: [], modified: [], skipped: [], backedUp: [] }
|
|
1886
2051
|
);
|
|
1887
2052
|
}
|
|
1888
|
-
async function updateProjectPackageJson(targetDir,
|
|
2053
|
+
async function updateProjectPackageJson(targetDir, config) {
|
|
1889
2054
|
const result = {
|
|
1890
2055
|
created: [],
|
|
1891
2056
|
modified: [],
|
|
@@ -1899,7 +2064,14 @@ async function updateProjectPackageJson(targetDir, _config) {
|
|
|
1899
2064
|
commit: "czg"
|
|
1900
2065
|
};
|
|
1901
2066
|
pkg = mergeScripts(pkg, scripts, false);
|
|
1902
|
-
|
|
2067
|
+
const lintStagedConfig = getLintStagedConfig(
|
|
2068
|
+
true,
|
|
2069
|
+
// usesEslint - always true now since we install it
|
|
2070
|
+
true,
|
|
2071
|
+
// usesPrettier - always true now since we install it
|
|
2072
|
+
config.usesTypeScript
|
|
2073
|
+
);
|
|
2074
|
+
pkg = addPackageJsonConfig(pkg, "lint-staged", lintStagedConfig, true);
|
|
1903
2075
|
await writePackageJson(pkg, targetDir);
|
|
1904
2076
|
result.modified.push("package.json");
|
|
1905
2077
|
} catch (error) {
|
|
@@ -1928,6 +2100,32 @@ async function runInit(targetDir = process.cwd()) {
|
|
|
1928
2100
|
if (!config) {
|
|
1929
2101
|
return;
|
|
1930
2102
|
}
|
|
2103
|
+
const usesReact = await detectReact(targetDir);
|
|
2104
|
+
const installSpinner = p2.spinner();
|
|
2105
|
+
const packagesToInstall = usesReact ? [...RAFTSTACK_PACKAGES, ...REACT_ESLINT_PACKAGES] : RAFTSTACK_PACKAGES;
|
|
2106
|
+
installSpinner.start("Installing dependencies...");
|
|
2107
|
+
const installResult = await installPackages(
|
|
2108
|
+
config.packageManager,
|
|
2109
|
+
packagesToInstall,
|
|
2110
|
+
targetDir
|
|
2111
|
+
);
|
|
2112
|
+
let installFailed = false;
|
|
2113
|
+
if (installResult.success) {
|
|
2114
|
+
installSpinner.stop("Dependencies installed!");
|
|
2115
|
+
} else {
|
|
2116
|
+
installSpinner.stop("Failed to install dependencies");
|
|
2117
|
+
p2.log.warn(
|
|
2118
|
+
pc2.yellow(
|
|
2119
|
+
`Could not install dependencies automatically: ${installResult.error || "Unknown error"}`
|
|
2120
|
+
)
|
|
2121
|
+
);
|
|
2122
|
+
p2.log.info(
|
|
2123
|
+
pc2.dim(
|
|
2124
|
+
`You can install them manually with: ${config.packageManager.name} ${config.packageManager.addDev} ${packagesToInstall.join(" ")}`
|
|
2125
|
+
)
|
|
2126
|
+
);
|
|
2127
|
+
installFailed = true;
|
|
2128
|
+
}
|
|
1931
2129
|
const spinner4 = p2.spinner();
|
|
1932
2130
|
spinner4.start("Generating configuration files...");
|
|
1933
2131
|
const results = [];
|
|
@@ -1937,26 +2135,17 @@ async function runInit(targetDir = process.cwd()) {
|
|
|
1937
2135
|
);
|
|
1938
2136
|
results.push(await generateCommitlint(targetDir, config.asanaBaseUrl));
|
|
1939
2137
|
results.push(await generateCzGit(targetDir, config.asanaBaseUrl));
|
|
1940
|
-
results.push(
|
|
1941
|
-
await generateLintStaged(
|
|
1942
|
-
targetDir,
|
|
1943
|
-
config.projectType,
|
|
1944
|
-
config.usesEslint,
|
|
1945
|
-
config.usesPrettier,
|
|
1946
|
-
config.usesTypeScript
|
|
1947
|
-
)
|
|
1948
|
-
);
|
|
1949
2138
|
results.push(await generateBranchValidation(targetDir));
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
}
|
|
2139
|
+
results.push(await generateEslint(targetDir, config.usesTypeScript, false));
|
|
2140
|
+
results.push(await generatePrettier(targetDir));
|
|
1953
2141
|
results.push(await generatePRTemplate(targetDir, !!config.asanaBaseUrl));
|
|
1954
2142
|
results.push(
|
|
1955
2143
|
await generateGitHubWorkflows(
|
|
1956
2144
|
targetDir,
|
|
1957
2145
|
config.projectType,
|
|
1958
2146
|
config.usesTypeScript,
|
|
1959
|
-
|
|
2147
|
+
true,
|
|
2148
|
+
// usesEslint - always true now
|
|
1960
2149
|
config.packageManager
|
|
1961
2150
|
)
|
|
1962
2151
|
);
|
|
@@ -2009,15 +2198,17 @@ async function runInit(targetDir = process.cwd()) {
|
|
|
2009
2198
|
}
|
|
2010
2199
|
}
|
|
2011
2200
|
console.log();
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
"
|
|
2020
|
-
|
|
2201
|
+
const nextSteps = installFailed ? [
|
|
2202
|
+
`${pc2.cyan("1.")} Run ${pc2.yellow(config.packageManager.install)} to install dependencies`,
|
|
2203
|
+
`${pc2.cyan("2.")} Review the generated configuration files`,
|
|
2204
|
+
`${pc2.cyan("3.")} Use ${pc2.yellow(`${config.packageManager.run} commit`)} for interactive commits`,
|
|
2205
|
+
`${pc2.cyan("4.")} Set up branch protection rules (see .github/BRANCH_PROTECTION_SETUP.md)`
|
|
2206
|
+
] : [
|
|
2207
|
+
`${pc2.cyan("1.")} Review the generated configuration files`,
|
|
2208
|
+
`${pc2.cyan("2.")} Use ${pc2.yellow(`${config.packageManager.run} commit`)} for interactive commits`,
|
|
2209
|
+
`${pc2.cyan("3.")} Set up branch protection rules (see .github/BRANCH_PROTECTION_SETUP.md)`
|
|
2210
|
+
];
|
|
2211
|
+
p2.note(nextSteps.join("\n"), "Next Steps");
|
|
2021
2212
|
p2.outro(pc2.green("RaftStack setup complete! Happy coding! \u{1F680}"));
|
|
2022
2213
|
}
|
|
2023
2214
|
|
|
@@ -2426,7 +2617,7 @@ ${pc4.bold("Branches")}
|
|
|
2426
2617
|
// package.json
|
|
2427
2618
|
var package_default = {
|
|
2428
2619
|
name: "@raftlabs/raftstack",
|
|
2429
|
-
version: "1.
|
|
2620
|
+
version: "1.6.0",
|
|
2430
2621
|
description: "CLI tool for setting up Git hooks, commit conventions, and GitHub integration",
|
|
2431
2622
|
type: "module",
|
|
2432
2623
|
main: "./dist/index.js",
|