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