create-krispya 0.5.0 → 0.5.2
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 +106 -8
- package/dist/chunks/index.cjs +712 -325
- package/dist/chunks/index.mjs +702 -326
- package/dist/cli.cjs +1530 -587
- package/dist/cli.mjs +1534 -591
- package/dist/index.cjs +4 -0
- package/dist/index.d.cts +47 -1
- package/dist/index.d.mts +47 -1
- package/dist/index.d.ts +47 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
package/dist/chunks/index.mjs
CHANGED
|
@@ -140,10 +140,7 @@ function generateTypescriptConfig(baseTemplateOrParams) {
|
|
|
140
140
|
const tsConfig = {
|
|
141
141
|
$schema: "https://json.schemastore.org/tsconfig",
|
|
142
142
|
files: [],
|
|
143
|
-
references: [
|
|
144
|
-
{ path: "./.config/tsconfig.app.json" },
|
|
145
|
-
{ path: "./.config/tsconfig.node.json" }
|
|
146
|
-
]
|
|
143
|
+
references: [{ path: "./.config/tsconfig.app.json" }, { path: "./.config/tsconfig.node.json" }]
|
|
147
144
|
};
|
|
148
145
|
files["tsconfig.json"] = {
|
|
149
146
|
type: "text",
|
|
@@ -204,7 +201,8 @@ function generatePackageJson(params) {
|
|
|
204
201
|
devDependencies,
|
|
205
202
|
peerDependencies,
|
|
206
203
|
scripts,
|
|
207
|
-
options
|
|
204
|
+
options,
|
|
205
|
+
workspaceDependencies
|
|
208
206
|
} = params;
|
|
209
207
|
const files = {};
|
|
210
208
|
const packageManager = options.packageManager ?? "pnpm";
|
|
@@ -230,8 +228,14 @@ function generatePackageJson(params) {
|
|
|
230
228
|
packageJson.files = ["dist"];
|
|
231
229
|
}
|
|
232
230
|
const sortKeys = (obj) => Object.fromEntries(Object.entries(obj).sort(([a], [b]) => a.localeCompare(b)));
|
|
231
|
+
const allDependencies = { ...dependencies };
|
|
232
|
+
if (workspaceDependencies && workspaceDependencies.length > 0) {
|
|
233
|
+
for (const pkgName of workspaceDependencies) {
|
|
234
|
+
allDependencies[pkgName] = "workspace:*";
|
|
235
|
+
}
|
|
236
|
+
}
|
|
233
237
|
packageJson.scripts = scripts;
|
|
234
|
-
packageJson.dependencies = sortKeys(
|
|
238
|
+
packageJson.dependencies = sortKeys(allDependencies);
|
|
235
239
|
if (Object.keys(devDependencies).length > 0) {
|
|
236
240
|
packageJson.devDependencies = sortKeys(devDependencies);
|
|
237
241
|
}
|
|
@@ -246,6 +250,16 @@ function generatePackageJson(params) {
|
|
|
246
250
|
const majorVersion = pnpmVersion.split(".")[0];
|
|
247
251
|
engines.pnpm = `>=${majorVersion}.0.0`;
|
|
248
252
|
packageJson.packageManager = `pnpm@${pnpmVersion}`;
|
|
253
|
+
} else if (packageManager === "yarn") {
|
|
254
|
+
const yarnVersion = options.yarnVersion ?? "4.6.0";
|
|
255
|
+
const majorVersion = yarnVersion.split(".")[0];
|
|
256
|
+
engines.yarn = `>=${majorVersion}.0.0`;
|
|
257
|
+
packageJson.packageManager = `yarn@${yarnVersion}`;
|
|
258
|
+
} else if (packageManager === "npm") {
|
|
259
|
+
const npmVersion = options.npmVersion ?? "11.0.0";
|
|
260
|
+
const majorVersion = npmVersion.split(".")[0];
|
|
261
|
+
engines.npm = `>=${majorVersion}.0.0`;
|
|
262
|
+
packageJson.packageManager = `npm@${npmVersion}`;
|
|
249
263
|
}
|
|
250
264
|
if (options.nodeVersion) {
|
|
251
265
|
const majorVersion = options.nodeVersion.split(".")[0];
|
|
@@ -275,14 +289,7 @@ function generatePackageJson(params) {
|
|
|
275
289
|
}
|
|
276
290
|
|
|
277
291
|
function generateReadme(params) {
|
|
278
|
-
const {
|
|
279
|
-
name,
|
|
280
|
-
baseTemplate,
|
|
281
|
-
isLibrary,
|
|
282
|
-
libraryBundler,
|
|
283
|
-
packageManager,
|
|
284
|
-
codeSnippets
|
|
285
|
-
} = params;
|
|
292
|
+
const { name, baseTemplate, isLibrary, libraryBundler, packageManager, codeSnippets } = params;
|
|
286
293
|
const isVanilla = baseTemplate === "vanilla";
|
|
287
294
|
const isReact = baseTemplate === "react";
|
|
288
295
|
const isR3f = baseTemplate === "r3f";
|
|
@@ -646,168 +653,128 @@ function generateViteConfig(params) {
|
|
|
646
653
|
return { type: "text", content: viteConfigContent };
|
|
647
654
|
}
|
|
648
655
|
|
|
649
|
-
function
|
|
650
|
-
const {
|
|
656
|
+
function generateAiFiles(files, params) {
|
|
657
|
+
const { name, packageManager, linter, formatter, aiFiles } = params;
|
|
658
|
+
const content = getAiInstructionsContent({
|
|
651
659
|
name,
|
|
652
|
-
linter,
|
|
653
|
-
formatter,
|
|
654
660
|
packageManager,
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
devDependencies["prettier"] = "^3.4.2";
|
|
673
|
-
}
|
|
674
|
-
const rootPackageJson = {
|
|
675
|
-
name: "root",
|
|
676
|
-
version: "0.0.0",
|
|
677
|
-
private: true,
|
|
678
|
-
type: "module",
|
|
679
|
-
scripts: {
|
|
680
|
-
dev: "pnpm --filter './apps/*' run dev",
|
|
681
|
-
build: "pnpm --filter './packages/*' run build && pnpm --filter './apps/*' run build",
|
|
682
|
-
test: "pnpm -r run test",
|
|
683
|
-
lint: linter === "oxlint" ? "oxlint ." : linter === "biome" ? "biome check ." : "eslint .",
|
|
684
|
-
format: formatter === "oxfmt" ? "oxfmt ." : formatter === "biome" ? "biome format . --write" : "prettier --write ."
|
|
685
|
-
},
|
|
686
|
-
devDependencies
|
|
687
|
-
};
|
|
688
|
-
const engines = {};
|
|
689
|
-
if (isPnpm && pnpmVersion) {
|
|
690
|
-
const majorVersion = pnpmVersion.split(".")[0];
|
|
691
|
-
engines.pnpm = `>=${majorVersion}.0.0`;
|
|
692
|
-
rootPackageJson.packageManager = `pnpm@${pnpmVersion}`;
|
|
693
|
-
}
|
|
694
|
-
if (nodeVersion) {
|
|
695
|
-
const majorVersion = nodeVersion.split(".")[0];
|
|
696
|
-
engines.node = `>=${majorVersion}.0.0`;
|
|
697
|
-
}
|
|
698
|
-
if (Object.keys(engines).length > 0) {
|
|
699
|
-
rootPackageJson.engines = engines;
|
|
700
|
-
}
|
|
701
|
-
files["package.json"] = {
|
|
702
|
-
type: "text",
|
|
703
|
-
content: JSON.stringify(rootPackageJson, null, 2)
|
|
704
|
-
};
|
|
705
|
-
if (isPnpm) {
|
|
706
|
-
const workspaceLines = [];
|
|
707
|
-
if (pnpmManageVersions) {
|
|
708
|
-
workspaceLines.push("manage-package-manager-versions: true", "");
|
|
661
|
+
linter,
|
|
662
|
+
formatter
|
|
663
|
+
});
|
|
664
|
+
for (const fileChoice of aiFiles) {
|
|
665
|
+
switch (fileChoice) {
|
|
666
|
+
case "cursor-rules":
|
|
667
|
+
files[".cursor/rules"] = { type: "text", content };
|
|
668
|
+
break;
|
|
669
|
+
case "agents-md":
|
|
670
|
+
files["AGENTS.md"] = { type: "text", content };
|
|
671
|
+
break;
|
|
672
|
+
case "claude-md":
|
|
673
|
+
files["CLAUDE.md"] = { type: "text", content };
|
|
674
|
+
break;
|
|
675
|
+
case "copilot-md":
|
|
676
|
+
files[".github/copilot-instructions.md"] = { type: "text", content };
|
|
677
|
+
break;
|
|
709
678
|
}
|
|
710
|
-
workspaceLines.push(
|
|
711
|
-
"packages:",
|
|
712
|
-
' - ".config/*"',
|
|
713
|
-
' - "apps/*"',
|
|
714
|
-
' - "packages/*"',
|
|
715
|
-
""
|
|
716
|
-
);
|
|
717
|
-
workspaceLines.push("onlyBuiltDependencies:", " - esbuild");
|
|
718
|
-
files["pnpm-workspace.yaml"] = {
|
|
719
|
-
type: "text",
|
|
720
|
-
content: workspaceLines.join("\n")
|
|
721
|
-
};
|
|
722
679
|
}
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
type: "text",
|
|
729
|
-
content: `export default [
|
|
730
|
-
// Add your ESLint rules here
|
|
731
|
-
];
|
|
732
|
-
`
|
|
733
|
-
};
|
|
734
|
-
} else if (linter === "biome") {
|
|
735
|
-
const biomeConfig = {
|
|
736
|
-
$schema: "https://biomejs.dev/schemas/1.9.4/schema.json",
|
|
737
|
-
vcs: {
|
|
738
|
-
enabled: true,
|
|
739
|
-
clientKind: "git",
|
|
740
|
-
useIgnoreFile: true
|
|
741
|
-
},
|
|
742
|
-
linter: {
|
|
743
|
-
enabled: true,
|
|
744
|
-
rules: {
|
|
745
|
-
recommended: true
|
|
746
|
-
}
|
|
747
|
-
},
|
|
748
|
-
formatter: {
|
|
749
|
-
enabled: formatter === "biome"
|
|
750
|
-
}
|
|
751
|
-
};
|
|
752
|
-
files["biome.json"] = {
|
|
753
|
-
type: "text",
|
|
754
|
-
content: JSON.stringify(biomeConfig, null, 2)
|
|
755
|
-
};
|
|
680
|
+
}
|
|
681
|
+
function getConfigPackagesDescription(linter, formatter) {
|
|
682
|
+
const packages = ["`@config/typescript`"];
|
|
683
|
+
if (linter !== "biome") {
|
|
684
|
+
packages.push(`\`@config/${linter}\``);
|
|
756
685
|
}
|
|
757
|
-
if (formatter
|
|
758
|
-
|
|
759
|
-
} else if (formatter === "prettier") {
|
|
760
|
-
const prettierConfig = {
|
|
761
|
-
semi: true,
|
|
762
|
-
singleQuote: false,
|
|
763
|
-
trailingComma: "es5",
|
|
764
|
-
printWidth: 100
|
|
765
|
-
};
|
|
766
|
-
files[".prettierrc.json"] = {
|
|
767
|
-
type: "text",
|
|
768
|
-
content: JSON.stringify(prettierConfig, null, 2)
|
|
769
|
-
};
|
|
686
|
+
if (formatter !== "biome" && formatter !== linter) {
|
|
687
|
+
packages.push(`\`@config/${formatter}\``);
|
|
770
688
|
}
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
}
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
};
|
|
782
|
-
generateVscodeFiles(files, linter, formatter);
|
|
783
|
-
files["README.md"] = {
|
|
784
|
-
type: "text",
|
|
785
|
-
content: `# ${name}
|
|
689
|
+
let description = `- \`.config/\`: shared config packages (${packages.join(", ")})`;
|
|
690
|
+
if (linter === "biome" || formatter === "biome") {
|
|
691
|
+
description += "\n- `biome.json`: Biome configuration (root level)";
|
|
692
|
+
}
|
|
693
|
+
return description;
|
|
694
|
+
}
|
|
695
|
+
function getAiInstructionsContent(params) {
|
|
696
|
+
const { name, packageManager, linter, formatter } = params;
|
|
697
|
+
const configDescription = getConfigPackagesDescription(linter, formatter);
|
|
698
|
+
return `# ${name}
|
|
786
699
|
|
|
787
|
-
This monorepo workspace
|
|
700
|
+
This is a pnpm monorepo workspace generated with \`create-krispya\`.
|
|
788
701
|
|
|
789
|
-
##
|
|
702
|
+
## Most important rule (package creation)
|
|
790
703
|
|
|
791
|
-
|
|
792
|
-
- \`packages/\` - Shared packages and libraries
|
|
793
|
-
- \`.config/\` - Shared configuration packages
|
|
704
|
+
If you need a new app/package for any reason, **ALWAYS** create it with \`create-krispya\` (do not hand-create folders/package.json).
|
|
794
705
|
|
|
795
|
-
|
|
706
|
+
### Non-interactive (preferred for agents)
|
|
796
707
|
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
- \`${packageManager} run test\` to run tests across the workspace
|
|
801
|
-
- \`${packageManager} run lint\` to lint all code
|
|
802
|
-
- \`${packageManager} run format\` to format all code
|
|
708
|
+
\`\`\`bash
|
|
709
|
+
${packageManager} create krispya <name> --workspace [options]
|
|
710
|
+
\`\`\`
|
|
803
711
|
|
|
804
|
-
|
|
712
|
+
- The package directory will be \`apps/<name>\` (apps) or \`packages/<name>\` (libraries), unless \`--dir\` is provided.
|
|
713
|
+
- Package names default to \`@${name}/<name>\` but you can pass any name (scoped or unscoped).
|
|
805
714
|
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
715
|
+
### Workspace maintenance (non-interactive)
|
|
716
|
+
|
|
717
|
+
\`\`\`bash
|
|
718
|
+
${packageManager} create krispya --check # validate workspace
|
|
719
|
+
${packageManager} create krispya --fix --linter ${linter} --formatter ${formatter} # fix missing .config packages
|
|
720
|
+
\`\`\`
|
|
721
|
+
|
|
722
|
+
For non-interactive \`--fix\`, you MUST provide both \`--linter\` and \`--formatter\` flags.
|
|
723
|
+
|
|
724
|
+
## Package creation options (CLI truth)
|
|
725
|
+
|
|
726
|
+
| Option | Values | Notes |
|
|
727
|
+
|--------|--------|-------|
|
|
728
|
+
| \`--type\` | app, library | default: app |
|
|
729
|
+
| \`--template\` | vanilla, vanilla-js, react, react-js, r3f, r3f-js | default: vanilla |
|
|
730
|
+
| \`--dir\` | any directory | requires \`--workspace\`; default: \`apps/\` or \`packages/\` |
|
|
731
|
+
| \`--bundler\` | unbuild, tsdown | libraries only; default: unbuild |
|
|
732
|
+
|
|
733
|
+
### R3F flags (r3f templates only)
|
|
734
|
+
|
|
735
|
+
\`--drei\` \`--handle\` \`--leva\` \`--postprocessing\` \`--rapier\` \`--xr\` \`--uikit\` \`--offscreen\` \`--zustand\` \`--koota\` \`--triplex\` \`--viverse\`
|
|
736
|
+
|
|
737
|
+
### Examples
|
|
738
|
+
|
|
739
|
+
\`\`\`bash
|
|
740
|
+
# React library (@${name}/ui) in packages/ui
|
|
741
|
+
${packageManager} create krispya ui --workspace --type library --template react
|
|
742
|
+
|
|
743
|
+
# R3F app with physics + controls (@${name}/game) in apps/game
|
|
744
|
+
${packageManager} create krispya game --workspace --type app --template r3f --drei --rapier --leva
|
|
745
|
+
|
|
746
|
+
# App in a custom directory
|
|
747
|
+
${packageManager} create krispya demo --workspace --type app --template react --dir examples
|
|
748
|
+
\`\`\`
|
|
749
|
+
|
|
750
|
+
## After creating a package
|
|
751
|
+
|
|
752
|
+
\`\`\`bash
|
|
753
|
+
${packageManager} install
|
|
754
|
+
\`\`\`
|
|
755
|
+
|
|
756
|
+
- Use \`"workspace:*"\` for internal deps (e.g. \`"@${name}/ui": "workspace:*"\`).
|
|
757
|
+
|
|
758
|
+
## Workspace commands
|
|
759
|
+
|
|
760
|
+
\`\`\`bash
|
|
761
|
+
${packageManager} install # Install all dependencies
|
|
762
|
+
${packageManager} run dev # Run all apps in dev mode
|
|
763
|
+
${packageManager} run build # Build packages then apps
|
|
764
|
+
${packageManager} run test # Run all tests
|
|
765
|
+
${packageManager} run lint # Lint with ${linter}
|
|
766
|
+
${packageManager} run format # Format with ${formatter}
|
|
767
|
+
\`\`\`
|
|
768
|
+
|
|
769
|
+
## Structure + conventions
|
|
770
|
+
|
|
771
|
+
- \`apps/\`: applications (\`--type app\`)
|
|
772
|
+
- \`packages/\`: libraries (\`--type library\`)
|
|
773
|
+
${configDescription}
|
|
774
|
+
- TS configs extend \`@config/typescript/*\` (base/app/node/react)
|
|
775
|
+
`;
|
|
810
776
|
}
|
|
777
|
+
|
|
811
778
|
function generateTypescriptConfigPackage(files) {
|
|
812
779
|
const basePath = ".config/typescript";
|
|
813
780
|
files[`${basePath}/package.json`] = {
|
|
@@ -886,123 +853,504 @@ In your package's \`tsconfig.json\`:
|
|
|
886
853
|
};
|
|
887
854
|
files[`${basePath}/node.json`] = {
|
|
888
855
|
type: "text",
|
|
889
|
-
content: JSON.stringify(
|
|
890
|
-
{
|
|
891
|
-
$schema: "https://json.schemastore.org/tsconfig",
|
|
892
|
-
extends: "./base.json",
|
|
893
|
-
compilerOptions: {
|
|
894
|
-
lib: ["ESNext"]
|
|
895
|
-
}
|
|
896
|
-
},
|
|
897
|
-
null,
|
|
898
|
-
2
|
|
899
|
-
)
|
|
856
|
+
content: JSON.stringify(
|
|
857
|
+
{
|
|
858
|
+
$schema: "https://json.schemastore.org/tsconfig",
|
|
859
|
+
extends: "./base.json",
|
|
860
|
+
compilerOptions: {
|
|
861
|
+
lib: ["ESNext"]
|
|
862
|
+
}
|
|
863
|
+
},
|
|
864
|
+
null,
|
|
865
|
+
2
|
|
866
|
+
)
|
|
867
|
+
};
|
|
868
|
+
files[`${basePath}/react.json`] = {
|
|
869
|
+
type: "text",
|
|
870
|
+
content: JSON.stringify(
|
|
871
|
+
{
|
|
872
|
+
$schema: "https://json.schemastore.org/tsconfig",
|
|
873
|
+
extends: "./app.json",
|
|
874
|
+
compilerOptions: {
|
|
875
|
+
jsx: "react-jsx"
|
|
876
|
+
}
|
|
877
|
+
},
|
|
878
|
+
null,
|
|
879
|
+
2
|
|
880
|
+
)
|
|
881
|
+
};
|
|
882
|
+
}
|
|
883
|
+
function generateOxlintConfigPackage(files) {
|
|
884
|
+
const basePath = ".config/oxlint";
|
|
885
|
+
const { rules } = defaultLinterConfig;
|
|
886
|
+
files[`${basePath}/package.json`] = {
|
|
887
|
+
type: "text",
|
|
888
|
+
content: JSON.stringify(
|
|
889
|
+
{
|
|
890
|
+
name: "@config/oxlint",
|
|
891
|
+
version: "0.1.0",
|
|
892
|
+
private: true,
|
|
893
|
+
files: ["base.json", "react.json"]
|
|
894
|
+
},
|
|
895
|
+
null,
|
|
896
|
+
2
|
|
897
|
+
)
|
|
898
|
+
};
|
|
899
|
+
files[`${basePath}/README.md`] = {
|
|
900
|
+
type: "text",
|
|
901
|
+
content: `# \`@config/oxlint\`
|
|
902
|
+
|
|
903
|
+
Shared oxlint configurations for the monorepo.
|
|
904
|
+
|
|
905
|
+
## Usage
|
|
906
|
+
|
|
907
|
+
Run oxlint with a config:
|
|
908
|
+
|
|
909
|
+
\`\`\`bash
|
|
910
|
+
oxlint -c node_modules/@config/oxlint/base.json
|
|
911
|
+
\`\`\`
|
|
912
|
+
|
|
913
|
+
## Available Configs
|
|
914
|
+
|
|
915
|
+
- \`base.json\` - Base linting rules for TypeScript projects
|
|
916
|
+
- \`react.json\` - Extends base with React-specific rules
|
|
917
|
+
`
|
|
918
|
+
};
|
|
919
|
+
files[`${basePath}/base.json`] = {
|
|
920
|
+
type: "text",
|
|
921
|
+
content: JSON.stringify(
|
|
922
|
+
{
|
|
923
|
+
$schema: "./node_modules/oxlint/configuration_schema.json",
|
|
924
|
+
plugins: ["unicorn", "typescript", "oxc"],
|
|
925
|
+
rules: {
|
|
926
|
+
"no-unused-vars": [
|
|
927
|
+
rules.noUnusedVars.level,
|
|
928
|
+
{
|
|
929
|
+
argsIgnorePattern: rules.noUnusedVars.argsIgnorePattern,
|
|
930
|
+
varsIgnorePattern: rules.noUnusedVars.varsIgnorePattern,
|
|
931
|
+
caughtErrorsIgnorePattern: rules.noUnusedVars.caughtErrorsIgnorePattern
|
|
932
|
+
}
|
|
933
|
+
],
|
|
934
|
+
"no-useless-escape": "off",
|
|
935
|
+
"no-unused-expressions": [
|
|
936
|
+
rules.noUnusedExpressions.level,
|
|
937
|
+
{ allowShortCircuit: rules.noUnusedExpressions.allowShortCircuit }
|
|
938
|
+
]
|
|
939
|
+
},
|
|
940
|
+
ignorePatterns: defaultLinterConfig.ignorePatterns
|
|
941
|
+
},
|
|
942
|
+
null,
|
|
943
|
+
2
|
|
944
|
+
)
|
|
945
|
+
};
|
|
946
|
+
files[`${basePath}/react.json`] = {
|
|
947
|
+
type: "text",
|
|
948
|
+
content: JSON.stringify(
|
|
949
|
+
{
|
|
950
|
+
$schema: "./node_modules/oxlint/configuration_schema.json",
|
|
951
|
+
plugins: ["unicorn", "typescript", "oxc", "react"],
|
|
952
|
+
rules: {
|
|
953
|
+
"no-unused-vars": [
|
|
954
|
+
rules.noUnusedVars.level,
|
|
955
|
+
{
|
|
956
|
+
argsIgnorePattern: rules.noUnusedVars.argsIgnorePattern,
|
|
957
|
+
varsIgnorePattern: rules.noUnusedVars.varsIgnorePattern,
|
|
958
|
+
caughtErrorsIgnorePattern: rules.noUnusedVars.caughtErrorsIgnorePattern
|
|
959
|
+
}
|
|
960
|
+
],
|
|
961
|
+
"no-useless-escape": "off",
|
|
962
|
+
"no-unused-expressions": [
|
|
963
|
+
rules.noUnusedExpressions.level,
|
|
964
|
+
{ allowShortCircuit: rules.noUnusedExpressions.allowShortCircuit }
|
|
965
|
+
]
|
|
966
|
+
},
|
|
967
|
+
ignorePatterns: defaultLinterConfig.ignorePatterns
|
|
968
|
+
},
|
|
969
|
+
null,
|
|
970
|
+
2
|
|
971
|
+
)
|
|
972
|
+
};
|
|
973
|
+
}
|
|
974
|
+
function generateEslintConfigPackage(files) {
|
|
975
|
+
const basePath = ".config/eslint";
|
|
976
|
+
files[`${basePath}/package.json`] = {
|
|
977
|
+
type: "text",
|
|
978
|
+
content: JSON.stringify(
|
|
979
|
+
{
|
|
980
|
+
name: "@config/eslint",
|
|
981
|
+
version: "0.1.0",
|
|
982
|
+
private: true,
|
|
983
|
+
type: "module",
|
|
984
|
+
exports: {
|
|
985
|
+
"./base": "./base.js",
|
|
986
|
+
"./react": "./react.js"
|
|
987
|
+
},
|
|
988
|
+
files: ["base.js", "react.js"],
|
|
989
|
+
devDependencies: {
|
|
990
|
+
"@eslint/js": "^9.17.0",
|
|
991
|
+
"typescript-eslint": "^8.18.0"
|
|
992
|
+
}
|
|
993
|
+
},
|
|
994
|
+
null,
|
|
995
|
+
2
|
|
996
|
+
)
|
|
997
|
+
};
|
|
998
|
+
files[`${basePath}/README.md`] = {
|
|
999
|
+
type: "text",
|
|
1000
|
+
content: `# \`@config/eslint\`
|
|
1001
|
+
|
|
1002
|
+
Shared ESLint configurations for the monorepo.
|
|
1003
|
+
|
|
1004
|
+
## Usage
|
|
1005
|
+
|
|
1006
|
+
In your package's \`eslint.config.js\`:
|
|
1007
|
+
|
|
1008
|
+
\`\`\`js
|
|
1009
|
+
import base from "@config/eslint/base";
|
|
1010
|
+
|
|
1011
|
+
export default [...base];
|
|
1012
|
+
\`\`\`
|
|
1013
|
+
|
|
1014
|
+
Or for React projects:
|
|
1015
|
+
|
|
1016
|
+
\`\`\`js
|
|
1017
|
+
import react from "@config/eslint/react";
|
|
1018
|
+
|
|
1019
|
+
export default [...react];
|
|
1020
|
+
\`\`\`
|
|
1021
|
+
|
|
1022
|
+
## Available Configs
|
|
1023
|
+
|
|
1024
|
+
- \`base\` - Base linting rules for TypeScript projects
|
|
1025
|
+
- \`react\` - Extends base with React-specific rules
|
|
1026
|
+
`
|
|
1027
|
+
};
|
|
1028
|
+
files[`${basePath}/base.js`] = {
|
|
1029
|
+
type: "text",
|
|
1030
|
+
content: `import js from "@eslint/js";
|
|
1031
|
+
import tseslint from "typescript-eslint";
|
|
1032
|
+
|
|
1033
|
+
export default tseslint.config(
|
|
1034
|
+
js.configs.recommended,
|
|
1035
|
+
...tseslint.configs.recommended,
|
|
1036
|
+
{
|
|
1037
|
+
rules: {
|
|
1038
|
+
"@typescript-eslint/no-unused-vars": [
|
|
1039
|
+
"error",
|
|
1040
|
+
{
|
|
1041
|
+
argsIgnorePattern: "^_",
|
|
1042
|
+
varsIgnorePattern: "^_",
|
|
1043
|
+
caughtErrorsIgnorePattern: "^_",
|
|
1044
|
+
},
|
|
1045
|
+
],
|
|
1046
|
+
},
|
|
1047
|
+
},
|
|
1048
|
+
{
|
|
1049
|
+
ignores: ["dist/**", "node_modules/**"],
|
|
1050
|
+
}
|
|
1051
|
+
);
|
|
1052
|
+
`
|
|
1053
|
+
};
|
|
1054
|
+
files[`${basePath}/react.js`] = {
|
|
1055
|
+
type: "text",
|
|
1056
|
+
content: `import js from "@eslint/js";
|
|
1057
|
+
import tseslint from "typescript-eslint";
|
|
1058
|
+
|
|
1059
|
+
export default tseslint.config(
|
|
1060
|
+
js.configs.recommended,
|
|
1061
|
+
...tseslint.configs.recommended,
|
|
1062
|
+
{
|
|
1063
|
+
rules: {
|
|
1064
|
+
"@typescript-eslint/no-unused-vars": [
|
|
1065
|
+
"error",
|
|
1066
|
+
{
|
|
1067
|
+
argsIgnorePattern: "^_",
|
|
1068
|
+
varsIgnorePattern: "^_",
|
|
1069
|
+
caughtErrorsIgnorePattern: "^_",
|
|
1070
|
+
},
|
|
1071
|
+
],
|
|
1072
|
+
},
|
|
1073
|
+
},
|
|
1074
|
+
{
|
|
1075
|
+
ignores: ["dist/**", "node_modules/**"],
|
|
1076
|
+
}
|
|
1077
|
+
);
|
|
1078
|
+
`
|
|
1079
|
+
};
|
|
1080
|
+
}
|
|
1081
|
+
function generatePrettierConfigPackage(files) {
|
|
1082
|
+
const basePath = ".config/prettier";
|
|
1083
|
+
files[`${basePath}/package.json`] = {
|
|
1084
|
+
type: "text",
|
|
1085
|
+
content: JSON.stringify(
|
|
1086
|
+
{
|
|
1087
|
+
name: "@config/prettier",
|
|
1088
|
+
version: "0.1.0",
|
|
1089
|
+
private: true,
|
|
1090
|
+
type: "module",
|
|
1091
|
+
exports: {
|
|
1092
|
+
".": "./base.json"
|
|
1093
|
+
},
|
|
1094
|
+
files: ["base.json"]
|
|
1095
|
+
},
|
|
1096
|
+
null,
|
|
1097
|
+
2
|
|
1098
|
+
)
|
|
1099
|
+
};
|
|
1100
|
+
files[`${basePath}/README.md`] = {
|
|
1101
|
+
type: "text",
|
|
1102
|
+
content: `# \`@config/prettier\`
|
|
1103
|
+
|
|
1104
|
+
Shared Prettier configuration for the monorepo.
|
|
1105
|
+
|
|
1106
|
+
## Usage
|
|
1107
|
+
|
|
1108
|
+
In your package's \`package.json\`:
|
|
1109
|
+
|
|
1110
|
+
\`\`\`json
|
|
1111
|
+
{
|
|
1112
|
+
"prettier": "@config/prettier"
|
|
1113
|
+
}
|
|
1114
|
+
\`\`\`
|
|
1115
|
+
|
|
1116
|
+
Or in \`.prettierrc.json\`:
|
|
1117
|
+
|
|
1118
|
+
\`\`\`json
|
|
1119
|
+
"@config/prettier"
|
|
1120
|
+
\`\`\`
|
|
1121
|
+
|
|
1122
|
+
## Available Configs
|
|
1123
|
+
|
|
1124
|
+
- Default export - Base formatter settings
|
|
1125
|
+
`
|
|
1126
|
+
};
|
|
1127
|
+
files[`${basePath}/base.json`] = {
|
|
1128
|
+
type: "text",
|
|
1129
|
+
content: JSON.stringify(
|
|
1130
|
+
{
|
|
1131
|
+
printWidth: defaultFormatterConfig.printWidth,
|
|
1132
|
+
tabWidth: defaultFormatterConfig.tabWidth,
|
|
1133
|
+
useTabs: defaultFormatterConfig.useTabs,
|
|
1134
|
+
semi: defaultFormatterConfig.semi,
|
|
1135
|
+
singleQuote: defaultFormatterConfig.singleQuote,
|
|
1136
|
+
trailingComma: defaultFormatterConfig.trailingComma,
|
|
1137
|
+
bracketSpacing: defaultFormatterConfig.bracketSpacing,
|
|
1138
|
+
arrowParens: defaultFormatterConfig.arrowParens
|
|
1139
|
+
},
|
|
1140
|
+
null,
|
|
1141
|
+
2
|
|
1142
|
+
)
|
|
1143
|
+
};
|
|
1144
|
+
}
|
|
1145
|
+
function generateOxfmtConfigPackage(files) {
|
|
1146
|
+
const basePath = ".config/oxfmt";
|
|
1147
|
+
files[`${basePath}/package.json`] = {
|
|
1148
|
+
type: "text",
|
|
1149
|
+
content: JSON.stringify(
|
|
1150
|
+
{
|
|
1151
|
+
name: "@config/oxfmt",
|
|
1152
|
+
version: "0.1.0",
|
|
1153
|
+
private: true,
|
|
1154
|
+
files: ["base.json"]
|
|
1155
|
+
},
|
|
1156
|
+
null,
|
|
1157
|
+
2
|
|
1158
|
+
)
|
|
1159
|
+
};
|
|
1160
|
+
files[`${basePath}/README.md`] = {
|
|
1161
|
+
type: "text",
|
|
1162
|
+
content: `# \`@config/oxfmt\`
|
|
1163
|
+
|
|
1164
|
+
Shared oxfmt (formatter) configuration for the monorepo.
|
|
1165
|
+
|
|
1166
|
+
## Usage
|
|
1167
|
+
|
|
1168
|
+
Run oxfmt with the config:
|
|
1169
|
+
|
|
1170
|
+
\`\`\`bash
|
|
1171
|
+
oxfmt -c node_modules/@config/oxfmt/base.json --write .
|
|
1172
|
+
\`\`\`
|
|
1173
|
+
|
|
1174
|
+
## Available Configs
|
|
1175
|
+
|
|
1176
|
+
- \`base.json\` - Base formatter settings (Prettier-compatible)
|
|
1177
|
+
`
|
|
1178
|
+
};
|
|
1179
|
+
files[`${basePath}/base.json`] = {
|
|
1180
|
+
type: "text",
|
|
1181
|
+
content: JSON.stringify(
|
|
1182
|
+
{
|
|
1183
|
+
printWidth: defaultFormatterConfig.printWidth,
|
|
1184
|
+
tabWidth: defaultFormatterConfig.tabWidth,
|
|
1185
|
+
useTabs: defaultFormatterConfig.useTabs,
|
|
1186
|
+
semi: defaultFormatterConfig.semi,
|
|
1187
|
+
singleQuote: defaultFormatterConfig.singleQuote,
|
|
1188
|
+
trailingComma: defaultFormatterConfig.trailingComma,
|
|
1189
|
+
bracketSpacing: defaultFormatterConfig.bracketSpacing,
|
|
1190
|
+
arrowParens: defaultFormatterConfig.arrowParens
|
|
1191
|
+
},
|
|
1192
|
+
null,
|
|
1193
|
+
2
|
|
1194
|
+
)
|
|
1195
|
+
};
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
function generateMonorepo(params) {
|
|
1199
|
+
const {
|
|
1200
|
+
name,
|
|
1201
|
+
linter,
|
|
1202
|
+
formatter,
|
|
1203
|
+
packageManager,
|
|
1204
|
+
pnpmVersion,
|
|
1205
|
+
pnpmManageVersions,
|
|
1206
|
+
nodeVersion,
|
|
1207
|
+
aiFiles
|
|
1208
|
+
} = params;
|
|
1209
|
+
const files = {};
|
|
1210
|
+
const isPnpm = packageManager === "pnpm";
|
|
1211
|
+
const devDependencies = {};
|
|
1212
|
+
if (linter === "oxlint") {
|
|
1213
|
+
devDependencies["oxlint"] = "^1.36.0";
|
|
1214
|
+
} else if (linter === "eslint") {
|
|
1215
|
+
devDependencies["eslint"] = "^9.17.0";
|
|
1216
|
+
} else if (linter === "biome") {
|
|
1217
|
+
devDependencies["@biomejs/biome"] = "^1.9.4";
|
|
1218
|
+
}
|
|
1219
|
+
if (formatter === "oxfmt") {
|
|
1220
|
+
devDependencies["oxfmt"] = "^0.21.0";
|
|
1221
|
+
} else if (formatter === "prettier") {
|
|
1222
|
+
devDependencies["prettier"] = "^3.4.2";
|
|
1223
|
+
}
|
|
1224
|
+
const rootPackageJson = {
|
|
1225
|
+
name: "root",
|
|
1226
|
+
version: "0.0.0",
|
|
1227
|
+
private: true,
|
|
1228
|
+
type: "module",
|
|
1229
|
+
scripts: {
|
|
1230
|
+
dev: "pnpm --filter './apps/*' run dev",
|
|
1231
|
+
build: "pnpm --filter './packages/*' run build && pnpm --filter './apps/*' run build",
|
|
1232
|
+
test: "pnpm -r run test",
|
|
1233
|
+
lint: linter === "oxlint" ? "oxlint ." : linter === "biome" ? "biome check ." : "eslint .",
|
|
1234
|
+
format: formatter === "oxfmt" ? "oxfmt ." : formatter === "biome" ? "biome format . --write" : "prettier --write ."
|
|
1235
|
+
},
|
|
1236
|
+
devDependencies
|
|
1237
|
+
};
|
|
1238
|
+
const engines = {};
|
|
1239
|
+
if (isPnpm && pnpmVersion) {
|
|
1240
|
+
const majorVersion = pnpmVersion.split(".")[0];
|
|
1241
|
+
engines.pnpm = `>=${majorVersion}.0.0`;
|
|
1242
|
+
rootPackageJson.packageManager = `pnpm@${pnpmVersion}`;
|
|
1243
|
+
}
|
|
1244
|
+
if (nodeVersion) {
|
|
1245
|
+
const majorVersion = nodeVersion.split(".")[0];
|
|
1246
|
+
engines.node = `>=${majorVersion}.0.0`;
|
|
1247
|
+
}
|
|
1248
|
+
if (Object.keys(engines).length > 0) {
|
|
1249
|
+
rootPackageJson.engines = engines;
|
|
1250
|
+
}
|
|
1251
|
+
files["package.json"] = {
|
|
1252
|
+
type: "text",
|
|
1253
|
+
content: JSON.stringify(rootPackageJson, null, 2)
|
|
900
1254
|
};
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
1255
|
+
if (isPnpm) {
|
|
1256
|
+
const workspaceLines = [];
|
|
1257
|
+
if (pnpmManageVersions) {
|
|
1258
|
+
workspaceLines.push("manage-package-manager-versions: true", "");
|
|
1259
|
+
}
|
|
1260
|
+
workspaceLines.push(
|
|
1261
|
+
"packages:",
|
|
1262
|
+
' - ".config/*"',
|
|
1263
|
+
' - "apps/*"',
|
|
1264
|
+
' - "packages/*"',
|
|
1265
|
+
""
|
|
1266
|
+
);
|
|
1267
|
+
workspaceLines.push("onlyBuiltDependencies:", " - esbuild");
|
|
1268
|
+
files["pnpm-workspace.yaml"] = {
|
|
1269
|
+
type: "text",
|
|
1270
|
+
content: workspaceLines.join("\n")
|
|
1271
|
+
};
|
|
1272
|
+
}
|
|
1273
|
+
generateTypescriptConfigPackage(files);
|
|
1274
|
+
if (linter === "oxlint") {
|
|
1275
|
+
generateOxlintConfigPackage(files);
|
|
1276
|
+
} else if (linter === "eslint") {
|
|
1277
|
+
generateEslintConfigPackage(files);
|
|
1278
|
+
} else if (linter === "biome") {
|
|
1279
|
+
const biomeConfig = {
|
|
1280
|
+
$schema: "https://biomejs.dev/schemas/1.9.4/schema.json",
|
|
1281
|
+
vcs: {
|
|
1282
|
+
enabled: true,
|
|
1283
|
+
clientKind: "git",
|
|
1284
|
+
useIgnoreFile: true
|
|
1285
|
+
},
|
|
1286
|
+
linter: {
|
|
1287
|
+
enabled: true,
|
|
1288
|
+
rules: {
|
|
1289
|
+
recommended: true
|
|
909
1290
|
}
|
|
910
1291
|
},
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
1292
|
+
formatter: {
|
|
1293
|
+
enabled: formatter === "biome"
|
|
1294
|
+
}
|
|
1295
|
+
};
|
|
1296
|
+
files["biome.json"] = {
|
|
1297
|
+
type: "text",
|
|
1298
|
+
content: JSON.stringify(biomeConfig, null, 2)
|
|
1299
|
+
};
|
|
1300
|
+
}
|
|
1301
|
+
if (formatter === "oxfmt") {
|
|
1302
|
+
generateOxfmtConfigPackage(files);
|
|
1303
|
+
} else if (formatter === "prettier") {
|
|
1304
|
+
generatePrettierConfigPackage(files);
|
|
1305
|
+
}
|
|
1306
|
+
files[".gitignore"] = {
|
|
1307
|
+
type: "text",
|
|
1308
|
+
content: ["node_modules", "dist", "*.tsbuildinfo", ".DS_Store"].join("\n")
|
|
914
1309
|
};
|
|
915
|
-
|
|
916
|
-
function generateOxlintConfigPackage(files) {
|
|
917
|
-
const basePath = ".config/oxlint";
|
|
918
|
-
const { rules } = defaultLinterConfig;
|
|
919
|
-
files[`${basePath}/package.json`] = {
|
|
1310
|
+
files[".gitattributes"] = {
|
|
920
1311
|
type: "text",
|
|
921
|
-
content:
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
private: true,
|
|
926
|
-
files: ["base.json", "react.json"]
|
|
927
|
-
},
|
|
928
|
-
null,
|
|
929
|
-
2
|
|
930
|
-
)
|
|
1312
|
+
content: `* text=auto eol=lf
|
|
1313
|
+
*.{cmd,[cC][mM][dD]} text eol=crlf
|
|
1314
|
+
*.{bat,[bB][aA][tT]} text eol=crlf
|
|
1315
|
+
`
|
|
931
1316
|
};
|
|
932
|
-
files
|
|
1317
|
+
generateVscodeFiles(files, linter, formatter);
|
|
1318
|
+
files["README.md"] = {
|
|
933
1319
|
type: "text",
|
|
934
|
-
content: `#
|
|
1320
|
+
content: `# ${name}
|
|
935
1321
|
|
|
936
|
-
|
|
1322
|
+
This monorepo workspace was generated with create-krispya.
|
|
937
1323
|
|
|
938
|
-
##
|
|
1324
|
+
## Structure
|
|
939
1325
|
|
|
940
|
-
|
|
1326
|
+
- \`apps/\` - Applications
|
|
1327
|
+
- \`packages/\` - Shared packages and libraries
|
|
1328
|
+
- \`.config/\` - Shared configuration packages
|
|
941
1329
|
|
|
942
|
-
|
|
943
|
-
oxlint -c node_modules/@config/oxlint/base.json
|
|
944
|
-
\`\`\`
|
|
1330
|
+
## Development Commands
|
|
945
1331
|
|
|
946
|
-
|
|
1332
|
+
- \`${packageManager} install\` to install all dependencies
|
|
1333
|
+
- \`${packageManager} run dev\` to run all applications in development mode
|
|
1334
|
+
- \`${packageManager} run build\` to build all packages and applications
|
|
1335
|
+
- \`${packageManager} run test\` to run tests across the workspace
|
|
1336
|
+
- \`${packageManager} run lint\` to lint all code
|
|
1337
|
+
- \`${packageManager} run format\` to format all code
|
|
947
1338
|
|
|
948
|
-
|
|
949
|
-
|
|
1339
|
+
## Adding Packages
|
|
1340
|
+
|
|
1341
|
+
To add a new package to this workspace, run create-krispya from this directory and it will detect the monorepo.
|
|
950
1342
|
`
|
|
951
1343
|
};
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
argsIgnorePattern: rules.noUnusedVars.argsIgnorePattern,
|
|
963
|
-
varsIgnorePattern: rules.noUnusedVars.varsIgnorePattern,
|
|
964
|
-
caughtErrorsIgnorePattern: rules.noUnusedVars.caughtErrorsIgnorePattern
|
|
965
|
-
}
|
|
966
|
-
],
|
|
967
|
-
"no-useless-escape": "off",
|
|
968
|
-
"no-unused-expressions": [
|
|
969
|
-
rules.noUnusedExpressions.level,
|
|
970
|
-
{ allowShortCircuit: rules.noUnusedExpressions.allowShortCircuit }
|
|
971
|
-
]
|
|
972
|
-
},
|
|
973
|
-
ignorePatterns: defaultLinterConfig.ignorePatterns
|
|
974
|
-
},
|
|
975
|
-
null,
|
|
976
|
-
2
|
|
977
|
-
)
|
|
978
|
-
};
|
|
979
|
-
files[`${basePath}/react.json`] = {
|
|
980
|
-
type: "text",
|
|
981
|
-
content: JSON.stringify(
|
|
982
|
-
{
|
|
983
|
-
$schema: "./node_modules/oxlint/configuration_schema.json",
|
|
984
|
-
plugins: ["unicorn", "typescript", "oxc", "react"],
|
|
985
|
-
rules: {
|
|
986
|
-
"no-unused-vars": [
|
|
987
|
-
rules.noUnusedVars.level,
|
|
988
|
-
{
|
|
989
|
-
argsIgnorePattern: rules.noUnusedVars.argsIgnorePattern,
|
|
990
|
-
varsIgnorePattern: rules.noUnusedVars.varsIgnorePattern,
|
|
991
|
-
caughtErrorsIgnorePattern: rules.noUnusedVars.caughtErrorsIgnorePattern
|
|
992
|
-
}
|
|
993
|
-
],
|
|
994
|
-
"no-useless-escape": "off",
|
|
995
|
-
"no-unused-expressions": [
|
|
996
|
-
rules.noUnusedExpressions.level,
|
|
997
|
-
{ allowShortCircuit: rules.noUnusedExpressions.allowShortCircuit }
|
|
998
|
-
]
|
|
999
|
-
},
|
|
1000
|
-
ignorePatterns: defaultLinterConfig.ignorePatterns
|
|
1001
|
-
},
|
|
1002
|
-
null,
|
|
1003
|
-
2
|
|
1004
|
-
)
|
|
1005
|
-
};
|
|
1344
|
+
if (aiFiles && aiFiles.length > 0) {
|
|
1345
|
+
generateAiFiles(files, {
|
|
1346
|
+
name,
|
|
1347
|
+
packageManager,
|
|
1348
|
+
linter,
|
|
1349
|
+
formatter,
|
|
1350
|
+
aiFiles
|
|
1351
|
+
});
|
|
1352
|
+
}
|
|
1353
|
+
return { files };
|
|
1006
1354
|
}
|
|
1007
1355
|
function generateVscodeFiles(files, linter, formatter) {
|
|
1008
1356
|
const recommendations = [];
|
|
@@ -1028,8 +1376,12 @@ function generateVscodeFiles(files, linter, formatter) {
|
|
|
1028
1376
|
recommendations.push("oxc.oxc-vscode");
|
|
1029
1377
|
}
|
|
1030
1378
|
settings["editor.defaultFormatter"] = "oxc.oxc-vscode";
|
|
1031
|
-
settings["[json]"] = {
|
|
1032
|
-
|
|
1379
|
+
settings["[json]"] = {
|
|
1380
|
+
"editor.defaultFormatter": "vscode.json-language-features"
|
|
1381
|
+
};
|
|
1382
|
+
settings["[jsonc]"] = {
|
|
1383
|
+
"editor.defaultFormatter": "vscode.json-language-features"
|
|
1384
|
+
};
|
|
1033
1385
|
} else if (formatter === "prettier") {
|
|
1034
1386
|
recommendations.push("esbenp.prettier-vscode");
|
|
1035
1387
|
settings["editor.defaultFormatter"] = "esbenp.prettier-vscode";
|
|
@@ -1048,62 +1400,16 @@ function generateVscodeFiles(files, linter, formatter) {
|
|
|
1048
1400
|
content: JSON.stringify(settings, null, " ")
|
|
1049
1401
|
};
|
|
1050
1402
|
}
|
|
1051
|
-
function generateOxfmtConfigPackage(files) {
|
|
1052
|
-
const basePath = ".config/oxfmt";
|
|
1053
|
-
files[`${basePath}/package.json`] = {
|
|
1054
|
-
type: "text",
|
|
1055
|
-
content: JSON.stringify(
|
|
1056
|
-
{
|
|
1057
|
-
name: "@config/oxfmt",
|
|
1058
|
-
version: "0.1.0",
|
|
1059
|
-
private: true,
|
|
1060
|
-
files: ["base.json"]
|
|
1061
|
-
},
|
|
1062
|
-
null,
|
|
1063
|
-
2
|
|
1064
|
-
)
|
|
1065
|
-
};
|
|
1066
|
-
files[`${basePath}/README.md`] = {
|
|
1067
|
-
type: "text",
|
|
1068
|
-
content: `# \`@config/oxfmt\`
|
|
1069
|
-
|
|
1070
|
-
Shared oxfmt (formatter) configuration for the monorepo.
|
|
1071
|
-
|
|
1072
|
-
## Usage
|
|
1073
|
-
|
|
1074
|
-
Run oxfmt with the config:
|
|
1075
|
-
|
|
1076
|
-
\`\`\`bash
|
|
1077
|
-
oxfmt -c node_modules/@config/oxfmt/base.json --write .
|
|
1078
|
-
\`\`\`
|
|
1079
|
-
|
|
1080
|
-
## Available Configs
|
|
1081
|
-
|
|
1082
|
-
- \`base.json\` - Base formatter settings (Prettier-compatible)
|
|
1083
|
-
`
|
|
1084
|
-
};
|
|
1085
|
-
files[`${basePath}/base.json`] = {
|
|
1086
|
-
type: "text",
|
|
1087
|
-
content: JSON.stringify(
|
|
1088
|
-
{
|
|
1089
|
-
printWidth: defaultFormatterConfig.printWidth,
|
|
1090
|
-
tabWidth: defaultFormatterConfig.tabWidth,
|
|
1091
|
-
useTabs: defaultFormatterConfig.useTabs,
|
|
1092
|
-
semi: defaultFormatterConfig.semi,
|
|
1093
|
-
singleQuote: defaultFormatterConfig.singleQuote,
|
|
1094
|
-
trailingComma: defaultFormatterConfig.trailingComma,
|
|
1095
|
-
bracketSpacing: defaultFormatterConfig.bracketSpacing,
|
|
1096
|
-
arrowParens: defaultFormatterConfig.arrowParens
|
|
1097
|
-
},
|
|
1098
|
-
null,
|
|
1099
|
-
2
|
|
1100
|
-
)
|
|
1101
|
-
};
|
|
1102
|
-
}
|
|
1103
1403
|
|
|
1104
1404
|
const monorepo = {
|
|
1105
1405
|
__proto__: null,
|
|
1106
|
-
|
|
1406
|
+
generateEslintConfigPackage: generateEslintConfigPackage,
|
|
1407
|
+
generateMonorepo: generateMonorepo,
|
|
1408
|
+
generateOxfmtConfigPackage: generateOxfmtConfigPackage,
|
|
1409
|
+
generateOxlintConfigPackage: generateOxlintConfigPackage,
|
|
1410
|
+
generatePrettierConfigPackage: generatePrettierConfigPackage,
|
|
1411
|
+
generateTypescriptConfigPackage: generateTypescriptConfigPackage,
|
|
1412
|
+
generateVscodeFiles: generateVscodeFiles
|
|
1107
1413
|
};
|
|
1108
1414
|
|
|
1109
1415
|
function toBiomeLevel(level) {
|
|
@@ -1360,10 +1666,7 @@ jobs:
|
|
|
1360
1666
|
uses: actions/deploy-pages@v4
|
|
1361
1667
|
`
|
|
1362
1668
|
});
|
|
1363
|
-
generator.inject(
|
|
1364
|
-
"readme-start",
|
|
1365
|
-
`A github pages deployment action is configurd.`
|
|
1366
|
-
);
|
|
1669
|
+
generator.inject("readme-start", `A github pages deployment action is configurd.`);
|
|
1367
1670
|
if (generator.options.githubUserName != null && generator.options.githubRepoName != null) {
|
|
1368
1671
|
const address = `${generator.options.githubUserName}.github.io/${generator.options.githubRepoName}`;
|
|
1369
1672
|
generator.inject(
|
|
@@ -2035,7 +2338,9 @@ function merge(target, modification) {
|
|
|
2035
2338
|
|
|
2036
2339
|
async function getLatestNpmVersion(packageName, fallback) {
|
|
2037
2340
|
try {
|
|
2038
|
-
const response = await fetch(
|
|
2341
|
+
const response = await fetch(
|
|
2342
|
+
`https://registry.npmjs.org/${packageName}/latest`
|
|
2343
|
+
);
|
|
2039
2344
|
const data = await response.json();
|
|
2040
2345
|
return data.version;
|
|
2041
2346
|
} catch {
|
|
@@ -2045,6 +2350,12 @@ async function getLatestNpmVersion(packageName, fallback) {
|
|
|
2045
2350
|
async function getLatestPnpmVersion() {
|
|
2046
2351
|
return getLatestNpmVersion("pnpm", "10.11.0");
|
|
2047
2352
|
}
|
|
2353
|
+
async function getLatestYarnVersion() {
|
|
2354
|
+
return getLatestNpmVersion("yarn", "4.6.0");
|
|
2355
|
+
}
|
|
2356
|
+
async function getLatestNpmCliVersion() {
|
|
2357
|
+
return getLatestNpmVersion("npm", "11.0.0");
|
|
2358
|
+
}
|
|
2048
2359
|
async function getLatestNodeVersion() {
|
|
2049
2360
|
try {
|
|
2050
2361
|
const response = await fetch("https://nodejs.org/dist/index.json");
|
|
@@ -2058,6 +2369,70 @@ async function getLatestNodeVersion() {
|
|
|
2058
2369
|
return "22.0.0";
|
|
2059
2370
|
}
|
|
2060
2371
|
}
|
|
2372
|
+
function validateNameSegment(segment, label) {
|
|
2373
|
+
if (!segment.length) {
|
|
2374
|
+
return `${label} is required`;
|
|
2375
|
+
}
|
|
2376
|
+
if (!/^[a-z0-9-]+$/.test(segment)) {
|
|
2377
|
+
return `${label} must be lowercase and contain only letters, numbers, and hyphens`;
|
|
2378
|
+
}
|
|
2379
|
+
if (segment.startsWith("-") || segment.endsWith("-")) {
|
|
2380
|
+
return `${label} cannot start or end with a hyphen`;
|
|
2381
|
+
}
|
|
2382
|
+
if (segment.includes("--")) {
|
|
2383
|
+
return `${label} cannot contain consecutive hyphens`;
|
|
2384
|
+
}
|
|
2385
|
+
return void 0;
|
|
2386
|
+
}
|
|
2387
|
+
function validatePackageName(name) {
|
|
2388
|
+
if (!name.length) {
|
|
2389
|
+
return "Package name is required";
|
|
2390
|
+
}
|
|
2391
|
+
if (name.includes("..") || name.includes("\\")) {
|
|
2392
|
+
return "Package name cannot contain path traversal sequences";
|
|
2393
|
+
}
|
|
2394
|
+
if (name.startsWith("@")) {
|
|
2395
|
+
const slashIndex = name.indexOf("/");
|
|
2396
|
+
if (slashIndex === -1) {
|
|
2397
|
+
return "Scoped package name must include a package name after the scope (e.g., @scope/name)";
|
|
2398
|
+
}
|
|
2399
|
+
if (name.indexOf("/", slashIndex + 1) !== -1) {
|
|
2400
|
+
return "Package name can only have one slash for scoped packages";
|
|
2401
|
+
}
|
|
2402
|
+
const scope = name.slice(1, slashIndex);
|
|
2403
|
+
const packageName = name.slice(slashIndex + 1);
|
|
2404
|
+
const scopeError = validateNameSegment(scope, "Scope");
|
|
2405
|
+
if (scopeError) return scopeError;
|
|
2406
|
+
const nameError = validateNameSegment(packageName, "Package name");
|
|
2407
|
+
if (nameError) return nameError;
|
|
2408
|
+
return void 0;
|
|
2409
|
+
}
|
|
2410
|
+
if (name.includes("/")) {
|
|
2411
|
+
return "Unscoped package name cannot contain slashes. Use @scope/name format for scoped packages";
|
|
2412
|
+
}
|
|
2413
|
+
return validateNameSegment(name, "Package name");
|
|
2414
|
+
}
|
|
2415
|
+
function parseWorkspaceYamlContent(content) {
|
|
2416
|
+
const directories = [];
|
|
2417
|
+
let inPackagesSection = false;
|
|
2418
|
+
for (const line of content.split("\n")) {
|
|
2419
|
+
const trimmed = line.trim();
|
|
2420
|
+
if (trimmed === "packages:") {
|
|
2421
|
+
inPackagesSection = true;
|
|
2422
|
+
continue;
|
|
2423
|
+
}
|
|
2424
|
+
if (inPackagesSection && trimmed && !line.startsWith(" ") && !line.startsWith(" ") && !trimmed.startsWith("-")) {
|
|
2425
|
+
break;
|
|
2426
|
+
}
|
|
2427
|
+
if (inPackagesSection && trimmed.startsWith("-")) {
|
|
2428
|
+
const entry = trimmed.slice(1).trim().replace(/^["']|["']$/g, "").replace(/^\.\//, "").replace(/\/\*.*$/, "");
|
|
2429
|
+
if (entry && !entry.startsWith(".")) {
|
|
2430
|
+
directories.push(entry);
|
|
2431
|
+
}
|
|
2432
|
+
}
|
|
2433
|
+
}
|
|
2434
|
+
return directories;
|
|
2435
|
+
}
|
|
2061
2436
|
function generateRandomName() {
|
|
2062
2437
|
const adjectives = [
|
|
2063
2438
|
"red",
|
|
@@ -2346,7 +2721,8 @@ function generate(options) {
|
|
|
2346
2721
|
devDependencies,
|
|
2347
2722
|
peerDependencies,
|
|
2348
2723
|
scripts,
|
|
2349
|
-
options: clonedOptions
|
|
2724
|
+
options: clonedOptions,
|
|
2725
|
+
workspaceDependencies: clonedOptions.workspaceDependencies
|
|
2350
2726
|
}).files
|
|
2351
2727
|
);
|
|
2352
2728
|
if (!isMonorepoPackage) {
|
|
@@ -2362,4 +2738,4 @@ function generate(options) {
|
|
|
2362
2738
|
return files;
|
|
2363
2739
|
}
|
|
2364
2740
|
|
|
2365
|
-
export { getLanguageFromTemplate as a, generateRandomName as b,
|
|
2741
|
+
export { getLanguageFromTemplate as a, generateRandomName as b, generateTypescriptConfigPackage as c, generateOxlintConfigPackage as d, generateEslintConfigPackage as e, generateOxfmtConfigPackage as f, getBaseTemplate as g, generatePrettierConfigPackage as h, generateVscodeFiles as i, generateAiFiles as j, getLatestNpmVersion as k, generate as l, getLatestPnpmVersion as m, getLatestYarnVersion as n, getLatestNpmCliVersion as o, getLatestNodeVersion as p, parseWorkspaceYamlContent as q, generateMonorepo as r, monorepo as s, validatePackageName as v };
|