create-krispya 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -6
- package/dist/cli.cjs +1334 -1507
- package/dist/cli.d.cts +36 -0
- package/dist/cli.d.mts +36 -0
- package/dist/cli.d.ts +36 -0
- package/dist/cli.mjs +1334 -1507
- package/dist/index.cjs +52 -16
- package/dist/index.d.cts +81 -180
- package/dist/index.d.mts +81 -180
- package/dist/index.d.ts +81 -180
- package/dist/index.mjs +34 -1
- package/dist/{chunks/index.mjs → shared/create-krispya.DKKVmsqH.mjs} +1298 -750
- package/dist/{chunks/index.cjs → shared/create-krispya.DTHeUlq4.cjs} +1320 -763
- package/dist/shared/create-krispya.to8NBxeJ.d.cts +237 -0
- package/dist/shared/create-krispya.to8NBxeJ.d.mts +237 -0
- package/dist/shared/create-krispya.to8NBxeJ.d.ts +237 -0
- package/package.json +6 -3
|
@@ -3,62 +3,7 @@ import { constants } from 'fs';
|
|
|
3
3
|
import { join } from 'path';
|
|
4
4
|
import color from 'chalk';
|
|
5
5
|
|
|
6
|
-
const
|
|
7
|
-
<html lang="en">
|
|
8
|
-
<head>
|
|
9
|
-
<meta charset="UTF-8">
|
|
10
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
11
|
-
<title>$title</title>
|
|
12
|
-
</head>
|
|
13
|
-
<body style="margin: 0; overscroll-behavior: none; user-select: none; touch-action: none;">
|
|
14
|
-
<script type="module" src="$indexPath"><\/script>
|
|
15
|
-
<div style="width: 100dvw; height: 100dvh; overflow: hidden;" id="root"></div>
|
|
16
|
-
</body>
|
|
17
|
-
</html>`;
|
|
18
|
-
const ViteHtmlContent = `<!DOCTYPE html>
|
|
19
|
-
<html lang="en">
|
|
20
|
-
<head>
|
|
21
|
-
<meta charset="UTF-8">
|
|
22
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
23
|
-
<title>$title</title>
|
|
24
|
-
</head>
|
|
25
|
-
<body>
|
|
26
|
-
<div id="app"></div>
|
|
27
|
-
<script type="module" src="$indexPath"><\/script>
|
|
28
|
-
</body>
|
|
29
|
-
</html>`;
|
|
30
|
-
const IndexContent = `import { StrictMode } from 'react'
|
|
31
|
-
import { createRoot } from 'react-dom/client'
|
|
32
|
-
import { App } from './app.js'
|
|
33
|
-
|
|
34
|
-
createRoot(document.getElementById('root')!).render(
|
|
35
|
-
<StrictMode>
|
|
36
|
-
<App />
|
|
37
|
-
</StrictMode>,
|
|
38
|
-
)`;
|
|
39
|
-
const ViteIndexContent = `import './style.css'
|
|
40
|
-
|
|
41
|
-
document.querySelector('#app')!.innerHTML = \`
|
|
42
|
-
<h1>Hello Vite!</h1>
|
|
43
|
-
<p>Edit src/main.ts and save to see HMR in action.</p>
|
|
44
|
-
\``;
|
|
45
|
-
const ViteStyleContent = `body {
|
|
46
|
-
font-family: system-ui, -apple-system, sans-serif;
|
|
47
|
-
margin: 0;
|
|
48
|
-
padding: 2rem;
|
|
49
|
-
min-height: 100vh;
|
|
50
|
-
background: #1a1a1a;
|
|
51
|
-
color: #fff;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
h1 {
|
|
55
|
-
color: #646cff;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
a {
|
|
59
|
-
color: #646cff;
|
|
60
|
-
}`;
|
|
61
|
-
const GitAttributes = [
|
|
6
|
+
const gitAttributesContent = [
|
|
62
7
|
"* text eol=lf",
|
|
63
8
|
"*.png binary",
|
|
64
9
|
"*.jpg binary",
|
|
@@ -83,55 +28,6 @@ const GitAttributes = [
|
|
|
83
28
|
"*.glb binary",
|
|
84
29
|
"*.gltf binary"
|
|
85
30
|
].join("\n");
|
|
86
|
-
const defaultFormatterConfig = {
|
|
87
|
-
printWidth: 102,
|
|
88
|
-
tabWidth: 2,
|
|
89
|
-
useTabs: false,
|
|
90
|
-
semi: true,
|
|
91
|
-
singleQuote: true,
|
|
92
|
-
trailingComma: "es5",
|
|
93
|
-
bracketSpacing: true,
|
|
94
|
-
arrowParens: "always"
|
|
95
|
-
};
|
|
96
|
-
const defaultPrettierConfig = {
|
|
97
|
-
$schema: "https://json.schemastore.org/prettierrc",
|
|
98
|
-
...defaultFormatterConfig,
|
|
99
|
-
overrides: [
|
|
100
|
-
{
|
|
101
|
-
files: ["*.md", "**/*.md"],
|
|
102
|
-
options: { semi: false }
|
|
103
|
-
},
|
|
104
|
-
{
|
|
105
|
-
files: ["*.yml", "*.yaml", "**/*.yml", "**/*.yaml"],
|
|
106
|
-
options: { semi: false }
|
|
107
|
-
}
|
|
108
|
-
]
|
|
109
|
-
};
|
|
110
|
-
const defaultOxfmtConfig = {
|
|
111
|
-
printWidth: defaultFormatterConfig.printWidth,
|
|
112
|
-
tabWidth: defaultFormatterConfig.tabWidth,
|
|
113
|
-
useTabs: defaultFormatterConfig.useTabs,
|
|
114
|
-
semi: defaultFormatterConfig.semi,
|
|
115
|
-
singleQuote: defaultFormatterConfig.singleQuote,
|
|
116
|
-
trailingComma: defaultFormatterConfig.trailingComma,
|
|
117
|
-
bracketSpacing: defaultFormatterConfig.bracketSpacing,
|
|
118
|
-
arrowParens: defaultFormatterConfig.arrowParens
|
|
119
|
-
};
|
|
120
|
-
const defaultLinterConfig = {
|
|
121
|
-
ignorePatterns: ["dist"],
|
|
122
|
-
rules: {
|
|
123
|
-
noUnusedVars: {
|
|
124
|
-
level: "warn",
|
|
125
|
-
argsIgnorePattern: "^_",
|
|
126
|
-
varsIgnorePattern: "^_",
|
|
127
|
-
caughtErrorsIgnorePattern: "^_"
|
|
128
|
-
},
|
|
129
|
-
noUnusedExpressions: {
|
|
130
|
-
level: "warn",
|
|
131
|
-
allowShortCircuit: true
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
};
|
|
135
31
|
|
|
136
32
|
const ALL_AI_PLATFORMS = ["agents", "claude"];
|
|
137
33
|
const AI_PLATFORM_LABELS = {
|
|
@@ -142,12 +38,15 @@ const AI_PLATFORM_HINTS = {
|
|
|
142
38
|
agents: "OpenAI, Cursor, Windsurf, etc.",
|
|
143
39
|
claude: "Claude Code"
|
|
144
40
|
};
|
|
145
|
-
function
|
|
146
|
-
const { platforms, isMonorepo, configStrategy, ...rest } = params;
|
|
41
|
+
function renderAiFiles(files, params) {
|
|
42
|
+
const { platforms, isMonorepo, configStrategy, hasTypecheck, ...rest } = params;
|
|
147
43
|
if (platforms.length === 0) return;
|
|
148
44
|
const content = generateWorkspace({
|
|
149
45
|
...rest,
|
|
150
|
-
isMonorepo: !!isMonorepo
|
|
46
|
+
isMonorepo: !!isMonorepo,
|
|
47
|
+
configStrategy: configStrategy ?? "stealth",
|
|
48
|
+
hasTypecheck: hasTypecheck ?? false
|
|
49
|
+
});
|
|
151
50
|
const pointer = "See [`AGENTS.md`](./Agents.md) for agent context.\n";
|
|
152
51
|
const hasAgents = platforms.includes("agents");
|
|
153
52
|
const hasClaude = platforms.includes("claude");
|
|
@@ -162,31 +61,115 @@ function generateAiFiles(files, params) {
|
|
|
162
61
|
}
|
|
163
62
|
}
|
|
164
63
|
function generateWorkspace(ctx) {
|
|
165
|
-
const {
|
|
64
|
+
const { packageManager, linter, formatter, hasTypecheck } = ctx;
|
|
65
|
+
const exampleFiles = "src/App.tsx src/core/systems/move-entity.ts";
|
|
66
|
+
const commands = getAfterEditingCommands(ctx, exampleFiles);
|
|
166
67
|
const sections = [
|
|
167
|
-
|
|
68
|
+
"# Workspace Tools",
|
|
168
69
|
"",
|
|
169
|
-
`- **Type:** ${isMonorepo ? "pnpm monorepo" : "standalone project"}`,
|
|
170
70
|
`- **Package Manager:** ${packageManager}`,
|
|
171
71
|
`- **Linter:** ${linter}`,
|
|
172
72
|
`- **Formatter:** ${formatter}`,
|
|
173
73
|
"",
|
|
174
|
-
"##
|
|
175
|
-
""
|
|
176
|
-
`- \`${packageManager} test\` \u2014 run tests`,
|
|
177
|
-
`- \`${packageManager} build\` \u2014 build`,
|
|
178
|
-
`- \`${packageManager} lint\` and \`${packageManager} format\` \u2014 run before committing`
|
|
74
|
+
"## After Editing",
|
|
75
|
+
""
|
|
179
76
|
];
|
|
180
|
-
if (
|
|
77
|
+
if (hasTypecheck) {
|
|
181
78
|
sections.push(
|
|
182
|
-
""
|
|
183
|
-
|
|
184
|
-
|
|
79
|
+
"\u2705 After editing files, check the types for errors and then format and lint only the files changed for the current task."
|
|
80
|
+
);
|
|
81
|
+
} else {
|
|
82
|
+
sections.push(
|
|
83
|
+
"\u2705 After editing files, format and lint only the files changed for the current task."
|
|
185
84
|
);
|
|
186
85
|
}
|
|
187
|
-
sections.push("");
|
|
86
|
+
sections.push("", "```sh", "# Example");
|
|
87
|
+
if (hasTypecheck) {
|
|
88
|
+
sections.push(runScript(packageManager, "typecheck"));
|
|
89
|
+
}
|
|
90
|
+
sections.push(
|
|
91
|
+
"# Run format and lint for only files modified",
|
|
92
|
+
commands.format,
|
|
93
|
+
commands.lint,
|
|
94
|
+
"```",
|
|
95
|
+
"",
|
|
96
|
+
"\u274C Avoid unless explicitly approved:",
|
|
97
|
+
"",
|
|
98
|
+
"```sh",
|
|
99
|
+
runScript(packageManager, "format"),
|
|
100
|
+
runScript(packageManager, "lint"),
|
|
101
|
+
"```",
|
|
102
|
+
""
|
|
103
|
+
);
|
|
188
104
|
return sections.join("\n");
|
|
189
105
|
}
|
|
106
|
+
function getAfterEditingCommands(ctx, files) {
|
|
107
|
+
return {
|
|
108
|
+
format: getFormatChangedFilesCommand(ctx, files),
|
|
109
|
+
lint: getLintChangedFilesCommand(ctx, files)
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
function getFormatChangedFilesCommand(ctx, files) {
|
|
113
|
+
const exec = getExecCommand(ctx.packageManager);
|
|
114
|
+
if (ctx.formatter === "prettier") {
|
|
115
|
+
const configPath = getPrettierConfigPath(ctx);
|
|
116
|
+
const ignorePath = getPrettierIgnorePath(ctx);
|
|
117
|
+
const configFlag2 = configPath == null ? "" : ` --config ${configPath}`;
|
|
118
|
+
const ignoreFlag = ignorePath == null ? "" : ` --ignore-path ${ignorePath}`;
|
|
119
|
+
return `${exec} prettier${configFlag2}${ignoreFlag} --write ${files}`;
|
|
120
|
+
}
|
|
121
|
+
if (ctx.formatter === "oxfmt") {
|
|
122
|
+
const configPath = getOxfmtConfigPath(ctx);
|
|
123
|
+
return `${exec} oxfmt -c ${configPath} --write ${files}`;
|
|
124
|
+
}
|
|
125
|
+
const configFlag = ctx.isMonorepo || ctx.configStrategy === "root" ? "" : " --config-path .config";
|
|
126
|
+
return `${exec} biome format${configFlag} --write ${files}`;
|
|
127
|
+
}
|
|
128
|
+
function getLintChangedFilesCommand(ctx, files) {
|
|
129
|
+
const exec = getExecCommand(ctx.packageManager);
|
|
130
|
+
if (ctx.linter === "oxlint") {
|
|
131
|
+
if (!ctx.isMonorepo) {
|
|
132
|
+
return runScript(ctx.packageManager, "lint", files);
|
|
133
|
+
}
|
|
134
|
+
return `${exec} oxlint ${files}`;
|
|
135
|
+
}
|
|
136
|
+
if (ctx.linter === "eslint") {
|
|
137
|
+
const configFlag2 = ctx.configStrategy === "stealth" ? " --config .config/eslint.config.js" : "";
|
|
138
|
+
return `${exec} eslint${configFlag2} ${files}`;
|
|
139
|
+
}
|
|
140
|
+
const configFlag = ctx.isMonorepo || ctx.configStrategy === "root" ? "" : " --config-path .config";
|
|
141
|
+
return `${exec} biome lint${configFlag} ${files}`;
|
|
142
|
+
}
|
|
143
|
+
function getPrettierConfigPath(ctx) {
|
|
144
|
+
if (ctx.isMonorepo) return ".config/prettier/base.json";
|
|
145
|
+
if (ctx.configStrategy === "stealth") return ".config/prettier.json";
|
|
146
|
+
return void 0;
|
|
147
|
+
}
|
|
148
|
+
function getPrettierIgnorePath(ctx) {
|
|
149
|
+
if (ctx.isMonorepo) return ".config/prettier/prettierignore";
|
|
150
|
+
if (ctx.configStrategy === "stealth") return ".config/prettierignore";
|
|
151
|
+
return void 0;
|
|
152
|
+
}
|
|
153
|
+
function getOxfmtConfigPath(ctx) {
|
|
154
|
+
if (ctx.isMonorepo) return ".config/oxfmt/base.json";
|
|
155
|
+
if (ctx.configStrategy === "stealth") return ".config/oxfmt.json";
|
|
156
|
+
return "oxfmt.json";
|
|
157
|
+
}
|
|
158
|
+
function runScript(packageManager, script, args) {
|
|
159
|
+
const suffix = args == null ? "" : ` ${args}`;
|
|
160
|
+
if (packageManager === "npm") {
|
|
161
|
+
return `npm run ${script}${args == null ? "" : ` --${suffix}`}`;
|
|
162
|
+
}
|
|
163
|
+
if (packageManager === "yarn") {
|
|
164
|
+
return `yarn ${script}${suffix}`;
|
|
165
|
+
}
|
|
166
|
+
return `${packageManager} ${script}${args == null ? "" : ` --${suffix}`}`;
|
|
167
|
+
}
|
|
168
|
+
function getExecCommand(packageManager) {
|
|
169
|
+
if (packageManager === "npm") return "npm exec --";
|
|
170
|
+
if (packageManager === "yarn") return "yarn exec";
|
|
171
|
+
return `${packageManager} exec`;
|
|
172
|
+
}
|
|
190
173
|
|
|
191
174
|
function getLanguageFromTemplate(template) {
|
|
192
175
|
return template.endsWith("-js") ? "javascript" : "typescript";
|
|
@@ -195,59 +178,51 @@ function getBaseTemplate(template) {
|
|
|
195
178
|
return template.replace("-js", "");
|
|
196
179
|
}
|
|
197
180
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
} catch {
|
|
204
|
-
return fallback;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
function compareNumericSemver(a, b) {
|
|
208
|
-
const aParts = a.split(".").map((part) => Number.parseInt(part, 10) || 0);
|
|
209
|
-
const bParts = b.split(".").map((part) => Number.parseInt(part, 10) || 0);
|
|
210
|
-
const maxLength = Math.max(aParts.length, bParts.length);
|
|
211
|
-
for (let index = 0; index < maxLength; index += 1) {
|
|
212
|
-
const difference = (aParts[index] ?? 0) - (bParts[index] ?? 0);
|
|
213
|
-
if (difference !== 0) {
|
|
214
|
-
return difference;
|
|
181
|
+
function unique(...array) {
|
|
182
|
+
const set = /* @__PURE__ */ new Set();
|
|
183
|
+
for (const arr of array) {
|
|
184
|
+
for (const item of arr) {
|
|
185
|
+
set.add(item);
|
|
215
186
|
}
|
|
216
187
|
}
|
|
217
|
-
return
|
|
188
|
+
return Array.from(set);
|
|
218
189
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
190
|
+
|
|
191
|
+
function merge(target, modification) {
|
|
192
|
+
const targetLabel = JSON.stringify(target);
|
|
193
|
+
const modificationLabel = JSON.stringify(modification);
|
|
194
|
+
if (modification == null) {
|
|
195
|
+
throw new Error(
|
|
196
|
+
`Cannot merge "${modificationLabel}" modification into target "${targetLabel}"`
|
|
197
|
+
);
|
|
227
198
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
return getLatestNpmVersion("npm", "11.0.0");
|
|
237
|
-
}
|
|
238
|
-
async function getLatestNodeVersion() {
|
|
239
|
-
try {
|
|
240
|
-
const response = await fetch("https://nodejs.org/dist/index.json");
|
|
241
|
-
const data = await response.json();
|
|
242
|
-
const latestVersion = data[0];
|
|
243
|
-
if (latestVersion) {
|
|
244
|
-
return latestVersion.version.replace(/^v/, "");
|
|
199
|
+
if (target == null) {
|
|
200
|
+
return modification;
|
|
201
|
+
}
|
|
202
|
+
if (Array.isArray(target)) {
|
|
203
|
+
if (!Array.isArray(modification)) {
|
|
204
|
+
throw new Error(
|
|
205
|
+
`Cannot merge non-array modification "${modificationLabel}" into array target "${targetLabel}"`
|
|
206
|
+
);
|
|
245
207
|
}
|
|
246
|
-
return
|
|
247
|
-
}
|
|
248
|
-
|
|
208
|
+
return [...target, ...modification];
|
|
209
|
+
}
|
|
210
|
+
if (typeof target === "object") {
|
|
211
|
+
if (typeof modification !== "object") {
|
|
212
|
+
throw new Error(
|
|
213
|
+
`Cannot merge non-object modification "${modificationLabel}" into object target "${targetLabel}"`
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
const result = { ...target };
|
|
217
|
+
for (const modificationKey in modification) {
|
|
218
|
+
result[modificationKey] = merge(target[modificationKey], modification[modificationKey]);
|
|
219
|
+
}
|
|
220
|
+
return result;
|
|
249
221
|
}
|
|
222
|
+
console.warn(`target "${targetLabel}" is overwritten with modification "${modificationLabel}"`);
|
|
223
|
+
return modification;
|
|
250
224
|
}
|
|
225
|
+
|
|
251
226
|
function validateNameSegment(segment, label) {
|
|
252
227
|
if (!segment.length) {
|
|
253
228
|
return `${label} is required`;
|
|
@@ -291,27 +266,83 @@ function validatePackageName(name) {
|
|
|
291
266
|
}
|
|
292
267
|
return validateNameSegment(name, "Package name");
|
|
293
268
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
269
|
+
|
|
270
|
+
function generateRandomName() {
|
|
271
|
+
const adjectives = [
|
|
272
|
+
"red",
|
|
273
|
+
"blue",
|
|
274
|
+
"green",
|
|
275
|
+
"yellow",
|
|
276
|
+
"purple",
|
|
277
|
+
"orange",
|
|
278
|
+
"pink",
|
|
279
|
+
"black",
|
|
280
|
+
"white",
|
|
281
|
+
"tiny",
|
|
282
|
+
"big",
|
|
283
|
+
"small",
|
|
284
|
+
"large",
|
|
285
|
+
"huge",
|
|
286
|
+
"giant",
|
|
287
|
+
"mini",
|
|
288
|
+
"mega",
|
|
289
|
+
"super",
|
|
290
|
+
"happy",
|
|
291
|
+
"sad",
|
|
292
|
+
"angry",
|
|
293
|
+
"calm",
|
|
294
|
+
"quiet",
|
|
295
|
+
"loud",
|
|
296
|
+
"silent",
|
|
297
|
+
"noisy",
|
|
298
|
+
"shiny",
|
|
299
|
+
"dull",
|
|
300
|
+
"bright",
|
|
301
|
+
"dark",
|
|
302
|
+
"fuzzy",
|
|
303
|
+
"smooth",
|
|
304
|
+
"rough",
|
|
305
|
+
"soft"
|
|
306
|
+
];
|
|
307
|
+
const nouns = [
|
|
308
|
+
"apple",
|
|
309
|
+
"banana",
|
|
310
|
+
"cherry",
|
|
311
|
+
"date",
|
|
312
|
+
"elderberry",
|
|
313
|
+
"fig",
|
|
314
|
+
"grape",
|
|
315
|
+
"honeydew",
|
|
316
|
+
"cat",
|
|
317
|
+
"dog",
|
|
318
|
+
"elephant",
|
|
319
|
+
"fox",
|
|
320
|
+
"giraffe",
|
|
321
|
+
"horse",
|
|
322
|
+
"iguana",
|
|
323
|
+
"jaguar",
|
|
324
|
+
"mountain",
|
|
325
|
+
"river",
|
|
326
|
+
"ocean",
|
|
327
|
+
"desert",
|
|
328
|
+
"forest",
|
|
329
|
+
"jungle",
|
|
330
|
+
"meadow",
|
|
331
|
+
"valley",
|
|
332
|
+
"star",
|
|
333
|
+
"moon",
|
|
334
|
+
"sun",
|
|
335
|
+
"planet",
|
|
336
|
+
"comet",
|
|
337
|
+
"asteroid",
|
|
338
|
+
"galaxy",
|
|
339
|
+
"universe"
|
|
340
|
+
];
|
|
341
|
+
const randomAdjective = adjectives[Math.floor(Math.random() * adjectives.length)];
|
|
342
|
+
const randomNoun = nouns[Math.floor(Math.random() * nouns.length)];
|
|
343
|
+
return `${randomAdjective}-${randomNoun}`;
|
|
314
344
|
}
|
|
345
|
+
|
|
315
346
|
async function pathExists(path) {
|
|
316
347
|
try {
|
|
317
348
|
await access(path, constants.F_OK);
|
|
@@ -387,81 +418,82 @@ async function detectTooling(root) {
|
|
|
387
418
|
} catch {
|
|
388
419
|
return { linter: void 0, formatter: void 0 };
|
|
389
420
|
}
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
"
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
"
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
"
|
|
441
|
-
|
|
442
|
-
"
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
"
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
"
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
"
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
async function getLatestNpmVersion(packageName, fallback) {
|
|
424
|
+
try {
|
|
425
|
+
const response = await fetch(`https://registry.npmjs.org/${packageName}/latest`);
|
|
426
|
+
const data = await response.json();
|
|
427
|
+
return data.version;
|
|
428
|
+
} catch {
|
|
429
|
+
return fallback;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
function compareNumericSemver(a, b) {
|
|
433
|
+
const aParts = a.split(".").map((part) => Number.parseInt(part, 10) || 0);
|
|
434
|
+
const bParts = b.split(".").map((part) => Number.parseInt(part, 10) || 0);
|
|
435
|
+
const maxLength = Math.max(aParts.length, bParts.length);
|
|
436
|
+
for (let index = 0; index < maxLength; index += 1) {
|
|
437
|
+
const difference = (aParts[index] ?? 0) - (bParts[index] ?? 0);
|
|
438
|
+
if (difference !== 0) {
|
|
439
|
+
return difference;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
return 0;
|
|
443
|
+
}
|
|
444
|
+
async function getLatestNpmMajorVersion(packageName, majorVersion, fallback) {
|
|
445
|
+
try {
|
|
446
|
+
const response = await fetch(`https://registry.npmjs.org/${packageName}`);
|
|
447
|
+
const data = await response.json();
|
|
448
|
+
const latestMatchingVersion = Object.keys(data.versions ?? {}).filter((version) => version.split(".")[0] === majorVersion).sort((a, b) => compareNumericSemver(b, a))[0];
|
|
449
|
+
return latestMatchingVersion ?? fallback;
|
|
450
|
+
} catch {
|
|
451
|
+
return fallback;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
async function getLatestPnpmVersion() {
|
|
455
|
+
return getLatestNpmVersion("pnpm", "10.11.0");
|
|
456
|
+
}
|
|
457
|
+
async function getLatestYarnVersion() {
|
|
458
|
+
return getLatestNpmVersion("yarn", "4.6.0");
|
|
459
|
+
}
|
|
460
|
+
async function getLatestNpmCliVersion() {
|
|
461
|
+
return getLatestNpmVersion("npm", "11.0.0");
|
|
462
|
+
}
|
|
463
|
+
async function getLatestNodeVersion() {
|
|
464
|
+
try {
|
|
465
|
+
const response = await fetch("https://nodejs.org/dist/index.json");
|
|
466
|
+
const data = await response.json();
|
|
467
|
+
const latestVersion = data[0];
|
|
468
|
+
if (latestVersion) {
|
|
469
|
+
return latestVersion.version.replace(/^v/, "");
|
|
470
|
+
}
|
|
471
|
+
return "25.0.0";
|
|
472
|
+
} catch {
|
|
473
|
+
return "25.0.0";
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
function parseWorkspaceYamlContent(content) {
|
|
478
|
+
const directories = [];
|
|
479
|
+
let inPackagesSection = false;
|
|
480
|
+
for (const line of content.split("\n")) {
|
|
481
|
+
const trimmed = line.trim();
|
|
482
|
+
if (trimmed === "packages:") {
|
|
483
|
+
inPackagesSection = true;
|
|
484
|
+
continue;
|
|
485
|
+
}
|
|
486
|
+
if (inPackagesSection && trimmed && !line.startsWith(" ") && !line.startsWith(" ") && !trimmed.startsWith("-")) {
|
|
487
|
+
break;
|
|
488
|
+
}
|
|
489
|
+
if (inPackagesSection && trimmed.startsWith("-")) {
|
|
490
|
+
const entry = trimmed.slice(1).trim().replace(/^["']|["']$/g, "").replace(/^\.\//, "").replace(/\/\*.*$/, "");
|
|
491
|
+
if (entry && !entry.startsWith(".")) {
|
|
492
|
+
directories.push(entry);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
return directories;
|
|
465
497
|
}
|
|
466
498
|
|
|
467
499
|
const PACKAGE_VERSION_DEFINITIONS = {
|
|
@@ -489,6 +521,7 @@ const PACKAGE_VERSION_DEFINITIONS = {
|
|
|
489
521
|
leva: { fallbackVersion: "0.10.0" },
|
|
490
522
|
oxfmt: { fallbackVersion: "0.21.0" },
|
|
491
523
|
oxlint: { fallbackVersion: "1.36.0" },
|
|
524
|
+
"oxlint-tsgolint": { fallbackVersion: "0.22.1" },
|
|
492
525
|
prettier: { fallbackVersion: "3.4.2" },
|
|
493
526
|
react: { fallbackVersion: "19.0.0" },
|
|
494
527
|
"react-dom": { fallbackVersion: "19.0.0" },
|
|
@@ -645,6 +678,9 @@ async function resolveMonorepoRootPackageVersions(params) {
|
|
|
645
678
|
const packageNames = /* @__PURE__ */ new Set();
|
|
646
679
|
const explicitVersions = new Set(Object.keys(params.versions ?? {}));
|
|
647
680
|
addPackageName(packageNames, explicitVersions, getLinterPackage(params.linter));
|
|
681
|
+
if (params.linter === "oxlint") {
|
|
682
|
+
addPackageName(packageNames, explicitVersions, "oxlint-tsgolint");
|
|
683
|
+
}
|
|
648
684
|
if (params.formatter !== "biome" || params.linter !== "biome") {
|
|
649
685
|
addPackageName(packageNames, explicitVersions, getFormatterPackage(params.formatter));
|
|
650
686
|
}
|
|
@@ -754,6 +790,9 @@ function collectProjectPackageNames(options) {
|
|
|
754
790
|
} else if (linter === "oxlint") {
|
|
755
791
|
if (!inWorkspace) {
|
|
756
792
|
addPackageName(packageNames, explicitVersions, "oxlint");
|
|
793
|
+
if (isTypescript) {
|
|
794
|
+
addPackageName(packageNames, explicitVersions, "oxlint-tsgolint");
|
|
795
|
+
}
|
|
757
796
|
}
|
|
758
797
|
} else if (linter === "biome") {
|
|
759
798
|
addPackageName(packageNames, explicitVersions, "@biomejs/biome");
|
|
@@ -788,7 +827,7 @@ function isEnabledOption(option) {
|
|
|
788
827
|
return option != null && option !== false;
|
|
789
828
|
}
|
|
790
829
|
|
|
791
|
-
function
|
|
830
|
+
function renderTypescriptConfig(baseTemplateOrParams) {
|
|
792
831
|
const params = typeof baseTemplateOrParams === "string" ? { baseTemplate: baseTemplateOrParams } : baseTemplateOrParams;
|
|
793
832
|
const {
|
|
794
833
|
baseTemplate,
|
|
@@ -858,6 +897,7 @@ function generateTypescriptConfig(baseTemplateOrParams) {
|
|
|
858
897
|
composite: true,
|
|
859
898
|
rewriteRelativeImportExtensions: true,
|
|
860
899
|
erasableSyntaxOnly: true,
|
|
900
|
+
noEmit: true,
|
|
861
901
|
...isReact || isR3f ? { jsx: "react-jsx" } : {}
|
|
862
902
|
},
|
|
863
903
|
include: ["../src", "../tests"]
|
|
@@ -879,7 +919,8 @@ function generateTypescriptConfig(baseTemplateOrParams) {
|
|
|
879
919
|
skipLibCheck: true,
|
|
880
920
|
composite: true,
|
|
881
921
|
rewriteRelativeImportExtensions: true,
|
|
882
|
-
erasableSyntaxOnly: true
|
|
922
|
+
erasableSyntaxOnly: true,
|
|
923
|
+
noEmit: true
|
|
883
924
|
},
|
|
884
925
|
include: ["../*.config.ts", "./*.ts"]
|
|
885
926
|
};
|
|
@@ -911,6 +952,7 @@ function generateTypescriptConfig(baseTemplateOrParams) {
|
|
|
911
952
|
composite: true,
|
|
912
953
|
rewriteRelativeImportExtensions: true,
|
|
913
954
|
erasableSyntaxOnly: true,
|
|
955
|
+
noEmit: true,
|
|
914
956
|
...isReact || isR3f ? { jsx: "react-jsx" } : {}
|
|
915
957
|
},
|
|
916
958
|
include: ["src", "tests"]
|
|
@@ -932,7 +974,8 @@ function generateTypescriptConfig(baseTemplateOrParams) {
|
|
|
932
974
|
skipLibCheck: true,
|
|
933
975
|
composite: true,
|
|
934
976
|
rewriteRelativeImportExtensions: true,
|
|
935
|
-
erasableSyntaxOnly: true
|
|
977
|
+
erasableSyntaxOnly: true,
|
|
978
|
+
noEmit: true
|
|
936
979
|
},
|
|
937
980
|
include: ["*.config.ts"]
|
|
938
981
|
};
|
|
@@ -944,8 +987,108 @@ function generateTypescriptConfig(baseTemplateOrParams) {
|
|
|
944
987
|
return { files, devDependencies };
|
|
945
988
|
}
|
|
946
989
|
|
|
990
|
+
const packageJsonScripts = {
|
|
991
|
+
appBase: {
|
|
992
|
+
dev: "vite",
|
|
993
|
+
build: "vite build"
|
|
994
|
+
},
|
|
995
|
+
typescript: {
|
|
996
|
+
typecheck: "tsc --build --noEmit",
|
|
997
|
+
"typecheck:watch": "tsc --build --watch"
|
|
998
|
+
},
|
|
999
|
+
test: {
|
|
1000
|
+
vitest: {
|
|
1001
|
+
test: "vitest"
|
|
1002
|
+
}
|
|
1003
|
+
},
|
|
1004
|
+
build: {
|
|
1005
|
+
unbuild(configPath) {
|
|
1006
|
+
return {
|
|
1007
|
+
build: configPath == null ? "unbuild" : `unbuild --config ${configPath}`
|
|
1008
|
+
};
|
|
1009
|
+
},
|
|
1010
|
+
tsdown: {
|
|
1011
|
+
build: "tsdown"
|
|
1012
|
+
}
|
|
1013
|
+
},
|
|
1014
|
+
lint: {
|
|
1015
|
+
oxlint(configPath) {
|
|
1016
|
+
return {
|
|
1017
|
+
lint: configPath == null ? "oxlint" : `oxlint -c ${configPath}`
|
|
1018
|
+
};
|
|
1019
|
+
},
|
|
1020
|
+
eslint(configPath) {
|
|
1021
|
+
return {
|
|
1022
|
+
lint: configPath == null ? "eslint ." : `eslint --config ${configPath} .`
|
|
1023
|
+
};
|
|
1024
|
+
},
|
|
1025
|
+
biome(configPath) {
|
|
1026
|
+
return {
|
|
1027
|
+
lint: configPath == null ? "biome lint ." : `biome lint --config-path ${configPath} .`
|
|
1028
|
+
};
|
|
1029
|
+
}
|
|
1030
|
+
},
|
|
1031
|
+
format: {
|
|
1032
|
+
prettier(configPath, ignorePath) {
|
|
1033
|
+
const configFlag = configPath == null ? "" : ` --config ${configPath}`;
|
|
1034
|
+
const ignoreFlag = ignorePath == null ? "" : ` --ignore-path ${ignorePath}`;
|
|
1035
|
+
return {
|
|
1036
|
+
format: `prettier${configFlag}${ignoreFlag} --write .`
|
|
1037
|
+
};
|
|
1038
|
+
},
|
|
1039
|
+
oxfmt(configPath) {
|
|
1040
|
+
return {
|
|
1041
|
+
format: `oxfmt -c ${configPath} --write .`
|
|
1042
|
+
};
|
|
1043
|
+
},
|
|
1044
|
+
biome(configPath) {
|
|
1045
|
+
return {
|
|
1046
|
+
format: configPath == null ? "biome format --write ." : `biome format --config-path ${configPath} --write .`
|
|
1047
|
+
};
|
|
1048
|
+
}
|
|
1049
|
+
},
|
|
1050
|
+
release(packageManagerName) {
|
|
1051
|
+
return {
|
|
1052
|
+
release: `${packageManagerName} run build && ${packageManagerName} publish`
|
|
1053
|
+
};
|
|
1054
|
+
},
|
|
1055
|
+
monorepoRoot(linter, formatter) {
|
|
1056
|
+
return mergePackageJsonScripts(
|
|
1057
|
+
{
|
|
1058
|
+
dev: "pnpm --filter './apps/*' run dev",
|
|
1059
|
+
build: "pnpm --filter './packages/*' run build && pnpm --filter './apps/*' run build",
|
|
1060
|
+
test: "pnpm -r run test"
|
|
1061
|
+
},
|
|
1062
|
+
linter === "oxlint" ? {
|
|
1063
|
+
lint: "oxlint ."
|
|
1064
|
+
} : linter === "biome" ? {
|
|
1065
|
+
lint: "biome check ."
|
|
1066
|
+
} : {
|
|
1067
|
+
lint: "eslint ."
|
|
1068
|
+
},
|
|
1069
|
+
formatter === "oxfmt" ? {
|
|
1070
|
+
format: "oxfmt -c .config/oxfmt/base.json ."
|
|
1071
|
+
} : formatter === "biome" ? {
|
|
1072
|
+
format: "biome format . --write"
|
|
1073
|
+
} : {
|
|
1074
|
+
format: "prettier --config .config/prettier/base.json --ignore-path .config/prettier/prettierignore --write ."
|
|
1075
|
+
}
|
|
1076
|
+
);
|
|
1077
|
+
}
|
|
1078
|
+
};
|
|
1079
|
+
function mergePackageJsonScripts(...scriptSets) {
|
|
1080
|
+
return Object.assign({}, ...scriptSets.filter((scriptSet) => scriptSet != null));
|
|
1081
|
+
}
|
|
1082
|
+
function resolveDefaultPackageJsonScripts(params) {
|
|
1083
|
+
return mergePackageJsonScripts(
|
|
1084
|
+
params.isLibrary ? void 0 : packageJsonScripts.appBase,
|
|
1085
|
+
params.language === "typescript" ? packageJsonScripts.typescript : void 0,
|
|
1086
|
+
params.isLibrary ? packageJsonScripts.release(params.packageManagerName) : void 0
|
|
1087
|
+
);
|
|
1088
|
+
}
|
|
1089
|
+
|
|
947
1090
|
const DEFAULT_LIBRARY_VERSION = "0.1.0";
|
|
948
|
-
function
|
|
1091
|
+
function renderPackageJson(params) {
|
|
949
1092
|
const {
|
|
950
1093
|
name,
|
|
951
1094
|
language,
|
|
@@ -953,13 +1096,20 @@ function generatePackageJson(params) {
|
|
|
953
1096
|
dependencies,
|
|
954
1097
|
devDependencies,
|
|
955
1098
|
peerDependencies,
|
|
956
|
-
scripts,
|
|
957
1099
|
options,
|
|
958
1100
|
workspaceDependencies
|
|
959
1101
|
} = params;
|
|
960
1102
|
const files = {};
|
|
961
1103
|
const packageManager = getPackageManagerSpec(options.packageManager);
|
|
962
1104
|
const isPnpm = packageManager.name === "pnpm";
|
|
1105
|
+
const resolvedScripts = mergePackageJsonScripts(
|
|
1106
|
+
resolveDefaultPackageJsonScripts({
|
|
1107
|
+
language,
|
|
1108
|
+
isLibrary,
|
|
1109
|
+
packageManagerName: packageManager.name
|
|
1110
|
+
}),
|
|
1111
|
+
params.scripts
|
|
1112
|
+
);
|
|
963
1113
|
const packageJson = {
|
|
964
1114
|
name,
|
|
965
1115
|
description: "Built with \u{1F339} create-krispya",
|
|
@@ -996,7 +1146,7 @@ function generatePackageJson(params) {
|
|
|
996
1146
|
options.engine
|
|
997
1147
|
);
|
|
998
1148
|
}
|
|
999
|
-
packageJson.scripts =
|
|
1149
|
+
packageJson.scripts = resolvedScripts;
|
|
1000
1150
|
packageJson.dependencies = sortKeys(allDependencies);
|
|
1001
1151
|
if (Object.keys(allDevDependencies).length > 0) {
|
|
1002
1152
|
packageJson.devDependencies = sortKeys(allDevDependencies);
|
|
@@ -1039,7 +1189,7 @@ function generatePackageJson(params) {
|
|
|
1039
1189
|
return { files };
|
|
1040
1190
|
}
|
|
1041
1191
|
|
|
1042
|
-
function
|
|
1192
|
+
function renderReadme(params) {
|
|
1043
1193
|
const { name, baseTemplate, isLibrary, libraryBundler, packageManager, codeSnippets } = params;
|
|
1044
1194
|
const isVanilla = baseTemplate === "vanilla";
|
|
1045
1195
|
const isReact = baseTemplate === "react";
|
|
@@ -1132,7 +1282,63 @@ function generateReadme(params) {
|
|
|
1132
1282
|
return { type: "text", content };
|
|
1133
1283
|
}
|
|
1134
1284
|
|
|
1135
|
-
|
|
1285
|
+
const htmlContent = `<!DOCTYPE html>
|
|
1286
|
+
<html lang="en">
|
|
1287
|
+
<head>
|
|
1288
|
+
<meta charset="UTF-8">
|
|
1289
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
1290
|
+
<title>$title</title>
|
|
1291
|
+
</head>
|
|
1292
|
+
<body style="margin: 0; overscroll-behavior: none; user-select: none; touch-action: none;">
|
|
1293
|
+
<script type="module" src="$indexPath"><\/script>
|
|
1294
|
+
<div style="width: 100dvw; height: 100dvh; overflow: hidden;" id="root"></div>
|
|
1295
|
+
</body>
|
|
1296
|
+
</html>`;
|
|
1297
|
+
const viteHtmlContent = `<!DOCTYPE html>
|
|
1298
|
+
<html lang="en">
|
|
1299
|
+
<head>
|
|
1300
|
+
<meta charset="UTF-8">
|
|
1301
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
1302
|
+
<title>$title</title>
|
|
1303
|
+
</head>
|
|
1304
|
+
<body>
|
|
1305
|
+
<div id="app"></div>
|
|
1306
|
+
<script type="module" src="$indexPath"><\/script>
|
|
1307
|
+
</body>
|
|
1308
|
+
</html>`;
|
|
1309
|
+
const indexContent = `import { StrictMode } from 'react'
|
|
1310
|
+
import { createRoot } from 'react-dom/client'
|
|
1311
|
+
import { App } from './app.js'
|
|
1312
|
+
|
|
1313
|
+
createRoot(document.getElementById('root')!).render(
|
|
1314
|
+
<StrictMode>
|
|
1315
|
+
<App />
|
|
1316
|
+
</StrictMode>,
|
|
1317
|
+
)`;
|
|
1318
|
+
const viteIndexContent = `import './style.css'
|
|
1319
|
+
|
|
1320
|
+
document.querySelector('#app')!.innerHTML = \`
|
|
1321
|
+
<h1>Hello Vite!</h1>
|
|
1322
|
+
<p>Edit src/main.ts and save to see HMR in action.</p>
|
|
1323
|
+
\``;
|
|
1324
|
+
const viteStyleContent = `body {
|
|
1325
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
1326
|
+
margin: 0;
|
|
1327
|
+
padding: 2rem;
|
|
1328
|
+
min-height: 100vh;
|
|
1329
|
+
background: #1a1a1a;
|
|
1330
|
+
color: #fff;
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
h1 {
|
|
1334
|
+
color: #646cff;
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1337
|
+
a {
|
|
1338
|
+
color: #646cff;
|
|
1339
|
+
}`;
|
|
1340
|
+
|
|
1341
|
+
function renderSourceFiles(params) {
|
|
1136
1342
|
const { name, baseTemplate, language, isLibrary, codeSnippets, replacements } = params;
|
|
1137
1343
|
const files = {};
|
|
1138
1344
|
const ext = language === "typescript" ? "ts" : "js";
|
|
@@ -1172,19 +1378,13 @@ function generateSourceFiles(params) {
|
|
|
1172
1378
|
}
|
|
1173
1379
|
files[`src/index.${libExt}`] = { type: "text", content: libContent };
|
|
1174
1380
|
} else if (isVanilla) {
|
|
1175
|
-
files[`src/main.${ext}`] = { type: "text", content:
|
|
1176
|
-
files["src/style.css"] = { type: "text", content:
|
|
1177
|
-
const indexHtml =
|
|
1178
|
-
"$title",
|
|
1179
|
-
name
|
|
1180
|
-
);
|
|
1381
|
+
files[`src/main.${ext}`] = { type: "text", content: viteIndexContent };
|
|
1382
|
+
files["src/style.css"] = { type: "text", content: viteStyleContent };
|
|
1383
|
+
const indexHtml = viteHtmlContent.replace("$indexPath", `./src/main.${ext}`).replace("$title", name);
|
|
1181
1384
|
files["index.html"] = { type: "text", content: indexHtml };
|
|
1182
1385
|
} else {
|
|
1183
|
-
files[`src/index.tsx`] = { type: "text", content:
|
|
1184
|
-
const indexHtml =
|
|
1185
|
-
"$indexPath",
|
|
1186
|
-
language === "javascript" ? "./src/index.jsx" : "./src/index.tsx"
|
|
1187
|
-
).replace("$title", name);
|
|
1386
|
+
files[`src/index.tsx`] = { type: "text", content: indexContent };
|
|
1387
|
+
const indexHtml = htmlContent.replace("$indexPath", language === "javascript" ? "./src/index.jsx" : "./src/index.tsx").replace("$title", name);
|
|
1188
1388
|
files["index.html"] = { type: "text", content: indexHtml };
|
|
1189
1389
|
codeSnippets["dom-end"]?.reverse();
|
|
1190
1390
|
codeSnippets["global-end"]?.reverse();
|
|
@@ -1231,7 +1431,7 @@ function generateSourceFiles(params) {
|
|
|
1231
1431
|
return files;
|
|
1232
1432
|
}
|
|
1233
1433
|
|
|
1234
|
-
function
|
|
1434
|
+
function renderTestFiles(params) {
|
|
1235
1435
|
const { baseTemplate, language, isLibrary } = params;
|
|
1236
1436
|
const files = {};
|
|
1237
1437
|
const ext = language === "typescript" ? "ts" : "js";
|
|
@@ -1338,21 +1538,184 @@ const COMMON_GITIGNORE_LINES = [
|
|
|
1338
1538
|
"*.tsbuildinfo",
|
|
1339
1539
|
".env",
|
|
1340
1540
|
".env.*",
|
|
1341
|
-
"!.env.example"
|
|
1541
|
+
"!.env.example",
|
|
1542
|
+
".pnpm-store"
|
|
1342
1543
|
];
|
|
1343
|
-
function
|
|
1544
|
+
function renderGitignore(variant) {
|
|
1344
1545
|
const lines = variant === "workspace-root" ? [...COMMON_GITIGNORE_LINES, ".DS_Store"] : COMMON_GITIGNORE_LINES;
|
|
1345
1546
|
return {
|
|
1346
1547
|
type: "text",
|
|
1347
1548
|
content: lines.join("\n")
|
|
1348
1549
|
};
|
|
1349
1550
|
}
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1551
|
+
|
|
1552
|
+
const defaultFormatterMetaConfig = {
|
|
1553
|
+
printWidth: 102,
|
|
1554
|
+
tabWidth: 2,
|
|
1555
|
+
useTabs: false,
|
|
1556
|
+
semi: true,
|
|
1557
|
+
singleQuote: true,
|
|
1558
|
+
trailingComma: "es5",
|
|
1559
|
+
bracketSpacing: true,
|
|
1560
|
+
arrowParens: "always",
|
|
1561
|
+
ignorePatterns: [
|
|
1562
|
+
"package-lock.json",
|
|
1563
|
+
"npm-shrinkwrap.json",
|
|
1564
|
+
"pnpm-lock.yaml",
|
|
1565
|
+
"pnpm-lock.json",
|
|
1566
|
+
"yarn.lock",
|
|
1567
|
+
"bun.lock",
|
|
1568
|
+
"bun.lockb"
|
|
1569
|
+
]
|
|
1570
|
+
};
|
|
1571
|
+
|
|
1572
|
+
function renderEditorConfig(config = defaultFormatterMetaConfig) {
|
|
1573
|
+
const indentStyle = config.useTabs ? "tab" : "space";
|
|
1574
|
+
const indentSize = config.useTabs ? "tab" : String(config.tabWidth);
|
|
1575
|
+
return {
|
|
1576
|
+
type: "text",
|
|
1577
|
+
content: [
|
|
1578
|
+
"root = true",
|
|
1579
|
+
"",
|
|
1580
|
+
"[*]",
|
|
1581
|
+
"charset = utf-8",
|
|
1582
|
+
"end_of_line = lf",
|
|
1583
|
+
"insert_final_newline = true",
|
|
1584
|
+
`indent_style = ${indentStyle}`,
|
|
1585
|
+
`indent_size = ${indentSize}`,
|
|
1586
|
+
`tab_width = ${config.tabWidth}`,
|
|
1587
|
+
`max_line_length = ${config.printWidth}`
|
|
1588
|
+
].join("\n")
|
|
1589
|
+
};
|
|
1590
|
+
}
|
|
1591
|
+
function renderVscodeEditorSettings(config = defaultFormatterMetaConfig) {
|
|
1592
|
+
return {
|
|
1593
|
+
"editor.detectIndentation": false,
|
|
1594
|
+
"editor.insertSpaces": !config.useTabs,
|
|
1595
|
+
"editor.tabSize": config.tabWidth,
|
|
1596
|
+
"files.eol": "\n",
|
|
1597
|
+
"files.insertFinalNewline": true
|
|
1598
|
+
};
|
|
1599
|
+
}
|
|
1600
|
+
|
|
1601
|
+
const DEFAULT_VSCODE_SETTINGS = {
|
|
1602
|
+
...renderVscodeEditorSettings(),
|
|
1603
|
+
"explorer.fileNesting.enabled": true,
|
|
1604
|
+
"explorer.fileNesting.expand": false,
|
|
1605
|
+
"explorer.fileNesting.patterns": {
|
|
1606
|
+
".gitignore": ".gitattributes",
|
|
1607
|
+
"AGENTS.md": "CLAUDE.md"
|
|
1608
|
+
}
|
|
1609
|
+
};
|
|
1610
|
+
const OXFMT_LANGUAGE_SETTINGS = {
|
|
1611
|
+
"[json]": {
|
|
1612
|
+
"editor.defaultFormatter": "vscode.json-language-features"
|
|
1613
|
+
},
|
|
1614
|
+
"[jsonc]": {
|
|
1615
|
+
"editor.defaultFormatter": "vscode.json-language-features"
|
|
1616
|
+
},
|
|
1617
|
+
"[markdown]": {
|
|
1618
|
+
"editor.defaultFormatter": "vscode.markdown-language-features"
|
|
1619
|
+
},
|
|
1620
|
+
"[yaml]": {
|
|
1621
|
+
"editor.defaultFormatter": "redhat.vscode-yaml"
|
|
1622
|
+
}
|
|
1623
|
+
};
|
|
1624
|
+
function resolvePackageJsonNestedFiles(packageManager) {
|
|
1625
|
+
if (packageManager === "pnpm") {
|
|
1626
|
+
return ["pnpm-lock.yaml", "pnpm-workspace.yaml"];
|
|
1627
|
+
}
|
|
1628
|
+
if (packageManager === "npm") {
|
|
1629
|
+
return ["package-lock.json", "npm-shrinkwrap.json"];
|
|
1630
|
+
}
|
|
1631
|
+
if (packageManager === "yarn") {
|
|
1632
|
+
return ["yarn.lock"];
|
|
1633
|
+
}
|
|
1634
|
+
return [];
|
|
1635
|
+
}
|
|
1636
|
+
function resolveVscodeRecommendations(linter, formatter) {
|
|
1637
|
+
const recommendations = [];
|
|
1638
|
+
if (linter === "oxlint" || formatter === "oxfmt") {
|
|
1639
|
+
recommendations.push("oxc.oxc-vscode");
|
|
1640
|
+
}
|
|
1641
|
+
if (linter === "eslint") {
|
|
1642
|
+
recommendations.push("dbaeumer.vscode-eslint");
|
|
1643
|
+
}
|
|
1644
|
+
if (linter === "biome" || formatter === "biome") {
|
|
1645
|
+
recommendations.push("biomejs.biome");
|
|
1646
|
+
}
|
|
1647
|
+
if (formatter === "prettier") {
|
|
1648
|
+
recommendations.push("esbenp.prettier-vscode");
|
|
1649
|
+
}
|
|
1650
|
+
return recommendations;
|
|
1651
|
+
}
|
|
1652
|
+
function resolveVscodeSettings(params) {
|
|
1653
|
+
const { linter, formatter, configStrategy, isMonorepo, packageManager } = params;
|
|
1654
|
+
const settings = { ...DEFAULT_VSCODE_SETTINGS };
|
|
1655
|
+
const isStealth = !isMonorepo && (configStrategy ?? "stealth") === "stealth";
|
|
1656
|
+
const packageJsonNestedFiles = resolvePackageJsonNestedFiles(packageManager);
|
|
1657
|
+
if (packageJsonNestedFiles.length > 0) {
|
|
1658
|
+
settings["explorer.fileNesting.patterns"] = {
|
|
1659
|
+
...settings["explorer.fileNesting.patterns"],
|
|
1660
|
+
"package.json": packageJsonNestedFiles.join(", ")
|
|
1661
|
+
};
|
|
1662
|
+
}
|
|
1663
|
+
if (linter === "eslint") {
|
|
1664
|
+
settings["eslint.enable"] = true;
|
|
1665
|
+
settings["oxc.enable"] = false;
|
|
1666
|
+
settings["biome.enabled"] = false;
|
|
1667
|
+
if (isStealth) {
|
|
1668
|
+
settings["eslint.options"] = {
|
|
1669
|
+
overrideConfigFile: ".config/eslint.config.js"
|
|
1670
|
+
};
|
|
1671
|
+
}
|
|
1672
|
+
} else if (linter === "oxlint") {
|
|
1673
|
+
settings["oxc.enable"] = true;
|
|
1674
|
+
settings["eslint.enable"] = false;
|
|
1675
|
+
settings["biome.enabled"] = false;
|
|
1676
|
+
if (isStealth) {
|
|
1677
|
+
settings["oxc.configPath"] = ".config/oxlint.json";
|
|
1678
|
+
}
|
|
1679
|
+
} else if (linter === "biome") {
|
|
1680
|
+
settings["biome.enabled"] = true;
|
|
1681
|
+
settings["eslint.enable"] = false;
|
|
1682
|
+
settings["oxc.enable"] = false;
|
|
1683
|
+
if (isStealth) {
|
|
1684
|
+
settings["biome.linter.configPath"] = ".config/biome.json";
|
|
1685
|
+
}
|
|
1686
|
+
}
|
|
1687
|
+
if (formatter === "prettier") {
|
|
1688
|
+
settings["editor.defaultFormatter"] = "esbenp.prettier-vscode";
|
|
1689
|
+
if (isStealth) {
|
|
1690
|
+
settings["prettier.configPath"] = ".config/prettier.json";
|
|
1691
|
+
settings["prettier.ignorePath"] = ".config/prettierignore";
|
|
1692
|
+
}
|
|
1693
|
+
} else if (formatter === "oxfmt") {
|
|
1694
|
+
settings["editor.defaultFormatter"] = "oxc.oxc-vscode";
|
|
1695
|
+
Object.assign(settings, OXFMT_LANGUAGE_SETTINGS);
|
|
1696
|
+
if (isStealth) {
|
|
1697
|
+
settings["oxc.fmt.configPath"] = ".config/oxfmt.json";
|
|
1698
|
+
}
|
|
1699
|
+
} else if (formatter === "biome") {
|
|
1700
|
+
settings["biome.enabled"] = true;
|
|
1701
|
+
settings["eslint.enable"] = false;
|
|
1702
|
+
settings["oxc.enable"] = false;
|
|
1703
|
+
settings["editor.defaultFormatter"] = "biomejs.biome";
|
|
1704
|
+
if (isStealth) {
|
|
1705
|
+
settings["biome.linter.configPath"] = ".config/biome.json";
|
|
1706
|
+
}
|
|
1707
|
+
}
|
|
1708
|
+
return settings;
|
|
1709
|
+
}
|
|
1710
|
+
function renderVscodeFiles$1(params) {
|
|
1711
|
+
const { codeSnippets = {}, vscodeSettings = {} } = params;
|
|
1353
1712
|
const files = {};
|
|
1354
|
-
|
|
1355
|
-
|
|
1713
|
+
const recommendations = [
|
|
1714
|
+
...codeSnippets["vscode-extension-suggestion"] ?? [],
|
|
1715
|
+
...resolveVscodeRecommendations(params.linter, params.formatter)
|
|
1716
|
+
];
|
|
1717
|
+
if (recommendations.length > 0) {
|
|
1718
|
+
const uniqueRecommendations = [...new Set(recommendations)];
|
|
1356
1719
|
files[".vscode/extensions.json"] = {
|
|
1357
1720
|
type: "text",
|
|
1358
1721
|
content: JSON.stringify(
|
|
@@ -1364,9 +1727,13 @@ function generateVscodeFiles$1(params) {
|
|
|
1364
1727
|
)
|
|
1365
1728
|
};
|
|
1366
1729
|
}
|
|
1367
|
-
|
|
1730
|
+
const resolvedSettings = {
|
|
1731
|
+
...resolveVscodeSettings(params),
|
|
1732
|
+
...vscodeSettings
|
|
1733
|
+
};
|
|
1734
|
+
if (Object.keys(resolvedSettings).length > 0) {
|
|
1368
1735
|
const sortedSettings = Object.fromEntries(
|
|
1369
|
-
Object.entries(
|
|
1736
|
+
Object.entries(resolvedSettings).sort(([a], [b]) => a.localeCompare(b))
|
|
1370
1737
|
);
|
|
1371
1738
|
files[".vscode/settings.json"] = {
|
|
1372
1739
|
type: "text",
|
|
@@ -1410,7 +1777,7 @@ ${spaces}}`;
|
|
|
1410
1777
|
}
|
|
1411
1778
|
return String(value);
|
|
1412
1779
|
}
|
|
1413
|
-
function
|
|
1780
|
+
function renderViteConfig(params) {
|
|
1414
1781
|
const { viteConfig, codeSnippets } = params;
|
|
1415
1782
|
const configBody = formatValue(viteConfig, 0);
|
|
1416
1783
|
const viteConfigContent = [
|
|
@@ -1423,7 +1790,93 @@ function generateViteConfig(params) {
|
|
|
1423
1790
|
return { type: "text", content: viteConfigContent };
|
|
1424
1791
|
}
|
|
1425
1792
|
|
|
1426
|
-
function
|
|
1793
|
+
function toPrettierConfig(config = defaultFormatterMetaConfig) {
|
|
1794
|
+
return {
|
|
1795
|
+
$schema: "https://json.schemastore.org/prettierrc",
|
|
1796
|
+
printWidth: config.printWidth,
|
|
1797
|
+
tabWidth: config.tabWidth,
|
|
1798
|
+
useTabs: config.useTabs,
|
|
1799
|
+
semi: config.semi,
|
|
1800
|
+
singleQuote: config.singleQuote,
|
|
1801
|
+
trailingComma: config.trailingComma,
|
|
1802
|
+
bracketSpacing: config.bracketSpacing,
|
|
1803
|
+
arrowParens: config.arrowParens,
|
|
1804
|
+
overrides: [
|
|
1805
|
+
{
|
|
1806
|
+
files: ["*.md", "**/*.md"],
|
|
1807
|
+
options: { semi: false }
|
|
1808
|
+
},
|
|
1809
|
+
{
|
|
1810
|
+
files: ["*.yml", "*.yaml", "**/*.yml", "**/*.yaml"],
|
|
1811
|
+
options: { semi: false }
|
|
1812
|
+
}
|
|
1813
|
+
]
|
|
1814
|
+
};
|
|
1815
|
+
}
|
|
1816
|
+
function toPrettierIgnoreContent(config = defaultFormatterMetaConfig) {
|
|
1817
|
+
return config.ignorePatterns.join("\n");
|
|
1818
|
+
}
|
|
1819
|
+
function toOxfmtConfig(config = defaultFormatterMetaConfig) {
|
|
1820
|
+
return {
|
|
1821
|
+
printWidth: config.printWidth,
|
|
1822
|
+
tabWidth: config.tabWidth,
|
|
1823
|
+
useTabs: config.useTabs,
|
|
1824
|
+
semi: config.semi,
|
|
1825
|
+
singleQuote: config.singleQuote,
|
|
1826
|
+
trailingComma: config.trailingComma,
|
|
1827
|
+
bracketSpacing: config.bracketSpacing,
|
|
1828
|
+
arrowParens: config.arrowParens,
|
|
1829
|
+
ignorePatterns: config.ignorePatterns
|
|
1830
|
+
};
|
|
1831
|
+
}
|
|
1832
|
+
|
|
1833
|
+
const defaultLinterMetaConfig = {
|
|
1834
|
+
ignorePatterns: ["dist"],
|
|
1835
|
+
rules: {
|
|
1836
|
+
noUnusedVars: {
|
|
1837
|
+
level: "warn",
|
|
1838
|
+
argsIgnorePattern: "^_",
|
|
1839
|
+
varsIgnorePattern: "^_",
|
|
1840
|
+
caughtErrorsIgnorePattern: "^_"
|
|
1841
|
+
},
|
|
1842
|
+
noUnusedExpressions: {
|
|
1843
|
+
level: "warn",
|
|
1844
|
+
allowShortCircuit: true
|
|
1845
|
+
}
|
|
1846
|
+
}
|
|
1847
|
+
};
|
|
1848
|
+
|
|
1849
|
+
function renderOxlintConfig(params) {
|
|
1850
|
+
const config = params.config ?? defaultLinterMetaConfig;
|
|
1851
|
+
const { rules } = config;
|
|
1852
|
+
const plugins = ["unicorn", "typescript", "oxc"];
|
|
1853
|
+
if (params.react === true) {
|
|
1854
|
+
plugins.push("react");
|
|
1855
|
+
}
|
|
1856
|
+
return {
|
|
1857
|
+
$schema: params.schemaPath,
|
|
1858
|
+
plugins,
|
|
1859
|
+
...params.typescript === true ? { options: { typeAware: true } } : {},
|
|
1860
|
+
rules: {
|
|
1861
|
+
"no-unused-vars": [
|
|
1862
|
+
rules.noUnusedVars.level,
|
|
1863
|
+
{
|
|
1864
|
+
argsIgnorePattern: rules.noUnusedVars.argsIgnorePattern,
|
|
1865
|
+
varsIgnorePattern: rules.noUnusedVars.varsIgnorePattern,
|
|
1866
|
+
caughtErrorsIgnorePattern: rules.noUnusedVars.caughtErrorsIgnorePattern
|
|
1867
|
+
}
|
|
1868
|
+
],
|
|
1869
|
+
"no-useless-escape": "off",
|
|
1870
|
+
"no-unused-expressions": [
|
|
1871
|
+
rules.noUnusedExpressions.level,
|
|
1872
|
+
{ allowShortCircuit: rules.noUnusedExpressions.allowShortCircuit }
|
|
1873
|
+
]
|
|
1874
|
+
},
|
|
1875
|
+
ignorePatterns: config.ignorePatterns
|
|
1876
|
+
};
|
|
1877
|
+
}
|
|
1878
|
+
|
|
1879
|
+
function renderTypescriptConfigPackage(files) {
|
|
1427
1880
|
const basePath = ".config/typescript";
|
|
1428
1881
|
files[`${basePath}/package.json`] = {
|
|
1429
1882
|
type: "text",
|
|
@@ -1528,9 +1981,8 @@ In your package's \`tsconfig.json\`:
|
|
|
1528
1981
|
)
|
|
1529
1982
|
};
|
|
1530
1983
|
}
|
|
1531
|
-
function
|
|
1984
|
+
function renderOxlintConfigPackage(files) {
|
|
1532
1985
|
const basePath = ".config/oxlint";
|
|
1533
|
-
const { rules } = defaultLinterConfig;
|
|
1534
1986
|
files[`${basePath}/package.json`] = {
|
|
1535
1987
|
type: "text",
|
|
1536
1988
|
content: JSON.stringify(
|
|
@@ -1567,26 +2019,10 @@ oxlint -c node_modules/@config/oxlint/base.json
|
|
|
1567
2019
|
files[`${basePath}/base.json`] = {
|
|
1568
2020
|
type: "text",
|
|
1569
2021
|
content: JSON.stringify(
|
|
1570
|
-
{
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
"no-unused-vars": [
|
|
1575
|
-
rules.noUnusedVars.level,
|
|
1576
|
-
{
|
|
1577
|
-
argsIgnorePattern: rules.noUnusedVars.argsIgnorePattern,
|
|
1578
|
-
varsIgnorePattern: rules.noUnusedVars.varsIgnorePattern,
|
|
1579
|
-
caughtErrorsIgnorePattern: rules.noUnusedVars.caughtErrorsIgnorePattern
|
|
1580
|
-
}
|
|
1581
|
-
],
|
|
1582
|
-
"no-useless-escape": "off",
|
|
1583
|
-
"no-unused-expressions": [
|
|
1584
|
-
rules.noUnusedExpressions.level,
|
|
1585
|
-
{ allowShortCircuit: rules.noUnusedExpressions.allowShortCircuit }
|
|
1586
|
-
]
|
|
1587
|
-
},
|
|
1588
|
-
ignorePatterns: defaultLinterConfig.ignorePatterns
|
|
1589
|
-
},
|
|
2022
|
+
renderOxlintConfig({
|
|
2023
|
+
schemaPath: "./node_modules/oxlint/configuration_schema.json",
|
|
2024
|
+
typescript: true
|
|
2025
|
+
}),
|
|
1590
2026
|
null,
|
|
1591
2027
|
2
|
|
1592
2028
|
)
|
|
@@ -1594,32 +2030,17 @@ oxlint -c node_modules/@config/oxlint/base.json
|
|
|
1594
2030
|
files[`${basePath}/react.json`] = {
|
|
1595
2031
|
type: "text",
|
|
1596
2032
|
content: JSON.stringify(
|
|
1597
|
-
{
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
rules.noUnusedVars.level,
|
|
1603
|
-
{
|
|
1604
|
-
argsIgnorePattern: rules.noUnusedVars.argsIgnorePattern,
|
|
1605
|
-
varsIgnorePattern: rules.noUnusedVars.varsIgnorePattern,
|
|
1606
|
-
caughtErrorsIgnorePattern: rules.noUnusedVars.caughtErrorsIgnorePattern
|
|
1607
|
-
}
|
|
1608
|
-
],
|
|
1609
|
-
"no-useless-escape": "off",
|
|
1610
|
-
"no-unused-expressions": [
|
|
1611
|
-
rules.noUnusedExpressions.level,
|
|
1612
|
-
{ allowShortCircuit: rules.noUnusedExpressions.allowShortCircuit }
|
|
1613
|
-
]
|
|
1614
|
-
},
|
|
1615
|
-
ignorePatterns: defaultLinterConfig.ignorePatterns
|
|
1616
|
-
},
|
|
2033
|
+
renderOxlintConfig({
|
|
2034
|
+
schemaPath: "./node_modules/oxlint/configuration_schema.json",
|
|
2035
|
+
react: true,
|
|
2036
|
+
typescript: true
|
|
2037
|
+
}),
|
|
1617
2038
|
null,
|
|
1618
2039
|
2
|
|
1619
2040
|
)
|
|
1620
2041
|
};
|
|
1621
2042
|
}
|
|
1622
|
-
function
|
|
2043
|
+
function renderEslintConfigPackage(files) {
|
|
1623
2044
|
const basePath = ".config/eslint";
|
|
1624
2045
|
files[`${basePath}/package.json`] = {
|
|
1625
2046
|
type: "text",
|
|
@@ -1726,7 +2147,7 @@ export default tseslint.config(
|
|
|
1726
2147
|
`
|
|
1727
2148
|
};
|
|
1728
2149
|
}
|
|
1729
|
-
function
|
|
2150
|
+
function renderPrettierConfigPackage(files) {
|
|
1730
2151
|
const basePath = ".config/prettier";
|
|
1731
2152
|
files[`${basePath}/package.json`] = {
|
|
1732
2153
|
type: "text",
|
|
@@ -1739,7 +2160,7 @@ function generatePrettierConfigPackage(files) {
|
|
|
1739
2160
|
exports: {
|
|
1740
2161
|
".": "./base.json"
|
|
1741
2162
|
},
|
|
1742
|
-
files: ["base.json"]
|
|
2163
|
+
files: ["base.json", "prettierignore"]
|
|
1743
2164
|
},
|
|
1744
2165
|
null,
|
|
1745
2166
|
2
|
|
@@ -1774,10 +2195,14 @@ Or in \`.prettierrc.json\`:
|
|
|
1774
2195
|
};
|
|
1775
2196
|
files[`${basePath}/base.json`] = {
|
|
1776
2197
|
type: "text",
|
|
1777
|
-
content: JSON.stringify(
|
|
2198
|
+
content: JSON.stringify(toPrettierConfig(), null, 2)
|
|
2199
|
+
};
|
|
2200
|
+
files[`${basePath}/prettierignore`] = {
|
|
2201
|
+
type: "text",
|
|
2202
|
+
content: toPrettierIgnoreContent()
|
|
1778
2203
|
};
|
|
1779
2204
|
}
|
|
1780
|
-
function
|
|
2205
|
+
function renderOxfmtConfigPackage(files) {
|
|
1781
2206
|
const basePath = ".config/oxfmt";
|
|
1782
2207
|
files[`${basePath}/package.json`] = {
|
|
1783
2208
|
type: "text",
|
|
@@ -1813,11 +2238,11 @@ oxfmt -c node_modules/@config/oxfmt/base.json --write .
|
|
|
1813
2238
|
};
|
|
1814
2239
|
files[`${basePath}/base.json`] = {
|
|
1815
2240
|
type: "text",
|
|
1816
|
-
content: JSON.stringify(
|
|
2241
|
+
content: JSON.stringify(toOxfmtConfig(), null, 2)
|
|
1817
2242
|
};
|
|
1818
2243
|
}
|
|
1819
2244
|
|
|
1820
|
-
function
|
|
2245
|
+
function renderMonorepo(params) {
|
|
1821
2246
|
const {
|
|
1822
2247
|
name,
|
|
1823
2248
|
linter,
|
|
@@ -1826,6 +2251,7 @@ function generateMonorepo(params) {
|
|
|
1826
2251
|
pnpmManageVersions,
|
|
1827
2252
|
engine,
|
|
1828
2253
|
versions = {},
|
|
2254
|
+
ide = "vscode",
|
|
1829
2255
|
aiPlatforms
|
|
1830
2256
|
} = params;
|
|
1831
2257
|
const files = {};
|
|
@@ -1838,6 +2264,7 @@ function generateMonorepo(params) {
|
|
|
1838
2264
|
}
|
|
1839
2265
|
if (linter === "oxlint") {
|
|
1840
2266
|
assignResolvedPackageVersion(devDependencies, versions, "oxlint");
|
|
2267
|
+
assignResolvedPackageVersion(devDependencies, versions, "oxlint-tsgolint");
|
|
1841
2268
|
} else if (linter === "eslint") {
|
|
1842
2269
|
assignResolvedPackageVersion(devDependencies, versions, "eslint");
|
|
1843
2270
|
} else if (linter === "biome") {
|
|
@@ -1853,13 +2280,7 @@ function generateMonorepo(params) {
|
|
|
1853
2280
|
version: "0.0.0",
|
|
1854
2281
|
private: true,
|
|
1855
2282
|
type: "module",
|
|
1856
|
-
scripts:
|
|
1857
|
-
dev: "pnpm --filter './apps/*' run dev",
|
|
1858
|
-
build: "pnpm --filter './packages/*' run build && pnpm --filter './apps/*' run build",
|
|
1859
|
-
test: "pnpm -r run test",
|
|
1860
|
-
lint: linter === "oxlint" ? "oxlint ." : linter === "biome" ? "biome check ." : "eslint .",
|
|
1861
|
-
format: formatter === "oxfmt" ? "oxfmt -c .config/oxfmt/base.json ." : formatter === "biome" ? "biome format . --write" : "prettier --config .config/prettier/base.json --write ."
|
|
1862
|
-
},
|
|
2283
|
+
scripts: packageJsonScripts.monorepoRoot(linter, formatter),
|
|
1863
2284
|
devDependencies
|
|
1864
2285
|
};
|
|
1865
2286
|
const engines = {};
|
|
@@ -1905,9 +2326,9 @@ function generateMonorepo(params) {
|
|
|
1905
2326
|
2
|
|
1906
2327
|
)
|
|
1907
2328
|
};
|
|
1908
|
-
|
|
2329
|
+
renderTypescriptConfigPackage(files);
|
|
1909
2330
|
if (linter === "oxlint") {
|
|
1910
|
-
|
|
2331
|
+
renderOxlintConfigPackage(files);
|
|
1911
2332
|
files["oxlint.json"] = {
|
|
1912
2333
|
type: "text",
|
|
1913
2334
|
content: JSON.stringify(
|
|
@@ -1920,7 +2341,7 @@ function generateMonorepo(params) {
|
|
|
1920
2341
|
)
|
|
1921
2342
|
};
|
|
1922
2343
|
} else if (linter === "eslint") {
|
|
1923
|
-
|
|
2344
|
+
renderEslintConfigPackage(files);
|
|
1924
2345
|
files["eslint.config.js"] = {
|
|
1925
2346
|
type: "text",
|
|
1926
2347
|
content: `import base from "@config/eslint/base";
|
|
@@ -1953,11 +2374,12 @@ export default [...base];
|
|
|
1953
2374
|
};
|
|
1954
2375
|
}
|
|
1955
2376
|
if (formatter === "oxfmt") {
|
|
1956
|
-
|
|
2377
|
+
renderOxfmtConfigPackage(files);
|
|
1957
2378
|
} else if (formatter === "prettier") {
|
|
1958
|
-
|
|
2379
|
+
renderPrettierConfigPackage(files);
|
|
1959
2380
|
}
|
|
1960
|
-
files[".
|
|
2381
|
+
files[".editorconfig"] = renderEditorConfig();
|
|
2382
|
+
files[".gitignore"] = renderGitignore("workspace-root");
|
|
1961
2383
|
files[".gitattributes"] = {
|
|
1962
2384
|
type: "text",
|
|
1963
2385
|
content: `* text=auto eol=lf
|
|
@@ -1965,7 +2387,9 @@ export default [...base];
|
|
|
1965
2387
|
*.{bat,[bB][aA][tT]} text eol=crlf
|
|
1966
2388
|
`
|
|
1967
2389
|
};
|
|
1968
|
-
|
|
2390
|
+
if (ide === "vscode") {
|
|
2391
|
+
renderVscodeFiles(files, linter, formatter, packageManager.name);
|
|
2392
|
+
}
|
|
1969
2393
|
files["README.md"] = {
|
|
1970
2394
|
type: "text",
|
|
1971
2395
|
content: `# ${name}
|
|
@@ -1993,104 +2417,50 @@ To add a new package to this workspace, run create-krispya from this directory a
|
|
|
1993
2417
|
`
|
|
1994
2418
|
};
|
|
1995
2419
|
if (aiPlatforms && aiPlatforms.length > 0) {
|
|
1996
|
-
|
|
2420
|
+
renderAiFiles(files, {
|
|
1997
2421
|
name,
|
|
1998
2422
|
packageManager: packageManager.name,
|
|
1999
2423
|
linter,
|
|
2000
2424
|
formatter,
|
|
2001
2425
|
isMonorepo: true,
|
|
2426
|
+
hasTypecheck: false,
|
|
2002
2427
|
platforms: aiPlatforms
|
|
2003
2428
|
});
|
|
2004
2429
|
}
|
|
2005
2430
|
return { files };
|
|
2006
2431
|
}
|
|
2007
|
-
function
|
|
2008
|
-
const recommendations = [];
|
|
2009
|
-
const settings = {};
|
|
2010
|
-
if (linter === "oxlint") {
|
|
2011
|
-
recommendations.push("oxc.oxc-vscode");
|
|
2012
|
-
settings["oxc.enable"] = true;
|
|
2013
|
-
settings["eslint.enable"] = false;
|
|
2014
|
-
settings["biome.enabled"] = false;
|
|
2015
|
-
} else if (linter === "eslint") {
|
|
2016
|
-
recommendations.push("dbaeumer.vscode-eslint");
|
|
2017
|
-
settings["eslint.enable"] = true;
|
|
2018
|
-
settings["oxc.enable"] = false;
|
|
2019
|
-
settings["biome.enabled"] = false;
|
|
2020
|
-
} else if (linter === "biome") {
|
|
2021
|
-
recommendations.push("biomejs.biome");
|
|
2022
|
-
settings["biome.enabled"] = true;
|
|
2023
|
-
settings["eslint.enable"] = false;
|
|
2024
|
-
settings["oxc.enable"] = false;
|
|
2025
|
-
}
|
|
2026
|
-
if (formatter === "oxfmt") {
|
|
2027
|
-
if (!recommendations.includes("oxc.oxc-vscode")) {
|
|
2028
|
-
recommendations.push("oxc.oxc-vscode");
|
|
2029
|
-
}
|
|
2030
|
-
settings["editor.defaultFormatter"] = "oxc.oxc-vscode";
|
|
2031
|
-
settings["[json]"] = {
|
|
2032
|
-
"editor.defaultFormatter": "vscode.json-language-features"
|
|
2033
|
-
};
|
|
2034
|
-
settings["[jsonc]"] = {
|
|
2035
|
-
"editor.defaultFormatter": "vscode.json-language-features"
|
|
2036
|
-
};
|
|
2037
|
-
} else if (formatter === "prettier") {
|
|
2038
|
-
recommendations.push("esbenp.prettier-vscode");
|
|
2039
|
-
settings["editor.defaultFormatter"] = "esbenp.prettier-vscode";
|
|
2040
|
-
} else if (formatter === "biome") {
|
|
2041
|
-
if (!recommendations.includes("biomejs.biome")) {
|
|
2042
|
-
recommendations.push("biomejs.biome");
|
|
2043
|
-
}
|
|
2044
|
-
settings["editor.defaultFormatter"] = "biomejs.biome";
|
|
2045
|
-
}
|
|
2046
|
-
files[".vscode/extensions.json"] = {
|
|
2047
|
-
type: "text",
|
|
2048
|
-
content: JSON.stringify({ recommendations }, null, 2)
|
|
2049
|
-
};
|
|
2050
|
-
const codeSnippets = {};
|
|
2051
|
-
if (recommendations.length > 0) {
|
|
2052
|
-
codeSnippets["vscode-extension-suggestion"] = recommendations;
|
|
2053
|
-
}
|
|
2432
|
+
function renderVscodeFiles(files, linter, formatter, packageManager = "pnpm") {
|
|
2054
2433
|
Object.assign(
|
|
2055
2434
|
files,
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2435
|
+
renderVscodeFiles$1({
|
|
2436
|
+
linter,
|
|
2437
|
+
formatter,
|
|
2438
|
+
isMonorepo: true,
|
|
2439
|
+
packageManager
|
|
2059
2440
|
})
|
|
2060
2441
|
);
|
|
2061
2442
|
}
|
|
2062
2443
|
|
|
2063
|
-
const monorepo = {
|
|
2064
|
-
__proto__: null,
|
|
2065
|
-
generateEslintConfigPackage: generateEslintConfigPackage,
|
|
2066
|
-
generateMonorepo: generateMonorepo,
|
|
2067
|
-
generateOxfmtConfigPackage: generateOxfmtConfigPackage,
|
|
2068
|
-
generateOxlintConfigPackage: generateOxlintConfigPackage,
|
|
2069
|
-
generatePrettierConfigPackage: generatePrettierConfigPackage,
|
|
2070
|
-
generateTypescriptConfigPackage: generateTypescriptConfigPackage,
|
|
2071
|
-
generateVscodeFiles: generateVscodeFiles
|
|
2072
|
-
};
|
|
2073
|
-
|
|
2074
2444
|
function toBiomeLevel(level) {
|
|
2075
2445
|
return level;
|
|
2076
2446
|
}
|
|
2077
|
-
function
|
|
2447
|
+
function planBiome(builder, options) {
|
|
2078
2448
|
if (options == null || !options.linter && !options.formatter) {
|
|
2079
2449
|
return;
|
|
2080
2450
|
}
|
|
2081
|
-
const version =
|
|
2082
|
-
|
|
2083
|
-
const { rules } = defaultLinterConfig;
|
|
2451
|
+
const version = builder.getVersion("@biomejs/biome");
|
|
2452
|
+
builder.addDevDependency("@biomejs/biome");
|
|
2084
2453
|
const biomeConfig = {
|
|
2085
2454
|
$schema: `https://biomejs.dev/schemas/${version}/schema.json`
|
|
2086
2455
|
};
|
|
2087
2456
|
if (options.linter) {
|
|
2457
|
+
const linterConfig = options.linter.config;
|
|
2088
2458
|
biomeConfig.linter = {
|
|
2089
2459
|
enabled: true,
|
|
2090
2460
|
rules: {
|
|
2091
2461
|
recommended: true,
|
|
2092
2462
|
correctness: {
|
|
2093
|
-
noUnusedVariables: toBiomeLevel(rules.noUnusedVars.level)
|
|
2463
|
+
noUnusedVariables: toBiomeLevel(linterConfig.rules.noUnusedVars.level)
|
|
2094
2464
|
}
|
|
2095
2465
|
}
|
|
2096
2466
|
};
|
|
@@ -2100,19 +2470,20 @@ function generateBiome(generator, options) {
|
|
|
2100
2470
|
};
|
|
2101
2471
|
}
|
|
2102
2472
|
if (options.formatter) {
|
|
2473
|
+
const formatterConfig = options.formatter.config;
|
|
2103
2474
|
biomeConfig.formatter = {
|
|
2104
2475
|
enabled: true,
|
|
2105
|
-
lineWidth:
|
|
2106
|
-
indentWidth:
|
|
2107
|
-
indentStyle: "space"
|
|
2476
|
+
lineWidth: formatterConfig.printWidth,
|
|
2477
|
+
indentWidth: formatterConfig.tabWidth,
|
|
2478
|
+
indentStyle: formatterConfig.useTabs ? "tab" : "space"
|
|
2108
2479
|
};
|
|
2109
2480
|
biomeConfig.javascript = {
|
|
2110
2481
|
formatter: {
|
|
2111
|
-
semicolons: "always" ,
|
|
2112
|
-
quoteStyle: "single" ,
|
|
2113
|
-
trailingCommas:
|
|
2114
|
-
bracketSpacing:
|
|
2115
|
-
arrowParentheses: "always"
|
|
2482
|
+
semicolons: formatterConfig.semi ? "always" : "asNeeded",
|
|
2483
|
+
quoteStyle: formatterConfig.singleQuote ? "single" : "double",
|
|
2484
|
+
trailingCommas: formatterConfig.trailingComma,
|
|
2485
|
+
bracketSpacing: formatterConfig.bracketSpacing,
|
|
2486
|
+
arrowParentheses: formatterConfig.arrowParens === "always" ? "always" : "asNeeded"
|
|
2116
2487
|
}
|
|
2117
2488
|
};
|
|
2118
2489
|
biomeConfig.json = {
|
|
@@ -2125,53 +2496,48 @@ function generateBiome(generator, options) {
|
|
|
2125
2496
|
enabled: false
|
|
2126
2497
|
};
|
|
2127
2498
|
}
|
|
2128
|
-
const isStealth =
|
|
2499
|
+
const isStealth = builder.isStealthConfig();
|
|
2129
2500
|
if (isStealth) {
|
|
2130
|
-
|
|
2501
|
+
builder.addFile(".config/biome.json", {
|
|
2131
2502
|
type: "text",
|
|
2132
2503
|
content: JSON.stringify(biomeConfig, null, 2)
|
|
2133
2504
|
});
|
|
2134
2505
|
if (options.linter) {
|
|
2135
|
-
|
|
2506
|
+
builder.addScripts(packageJsonScripts.lint.biome(".config"));
|
|
2136
2507
|
}
|
|
2137
2508
|
if (options.formatter) {
|
|
2138
|
-
|
|
2509
|
+
builder.addScripts(packageJsonScripts.format.biome(".config"));
|
|
2139
2510
|
}
|
|
2140
|
-
generator.addVscodeSetting("biome.linter.configPath", ".config/biome.json");
|
|
2141
2511
|
} else {
|
|
2142
|
-
|
|
2512
|
+
builder.addFile("biome.json", {
|
|
2143
2513
|
type: "text",
|
|
2144
2514
|
content: JSON.stringify(biomeConfig, null, 2)
|
|
2145
2515
|
});
|
|
2146
2516
|
if (options.linter) {
|
|
2147
|
-
|
|
2517
|
+
builder.addScripts(packageJsonScripts.lint.biome());
|
|
2148
2518
|
}
|
|
2149
2519
|
if (options.formatter) {
|
|
2150
|
-
|
|
2520
|
+
builder.addScripts(packageJsonScripts.format.biome());
|
|
2151
2521
|
}
|
|
2152
2522
|
}
|
|
2153
2523
|
const roles = [];
|
|
2154
2524
|
if (options.linter) roles.push("linter");
|
|
2155
2525
|
if (options.formatter) roles.push("formatter");
|
|
2156
|
-
|
|
2526
|
+
builder.inject(
|
|
2157
2527
|
"readme-tools",
|
|
2158
2528
|
`[Biome](https://biomejs.dev/) - Fast ${roles.join(" and ")} for JavaScript and TypeScript`
|
|
2159
2529
|
);
|
|
2160
|
-
|
|
2161
|
-
generator.addVscodeSetting("biome.enabled", true);
|
|
2162
|
-
if (options.formatter) {
|
|
2163
|
-
generator.addVscodeSetting("editor.defaultFormatter", "biomejs.biome");
|
|
2164
|
-
}
|
|
2530
|
+
builder.inject("vscode-extension-suggestion", "biomejs.biome");
|
|
2165
2531
|
}
|
|
2166
2532
|
|
|
2167
|
-
function
|
|
2533
|
+
function planDrei(builder, options) {
|
|
2168
2534
|
if (options == null) {
|
|
2169
2535
|
return;
|
|
2170
2536
|
}
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2537
|
+
builder.addDependency("@react-three/drei");
|
|
2538
|
+
builder.inject("import", `import { Environment } from "@react-three/drei"`);
|
|
2539
|
+
builder.inject("scene", '<Environment background preset="city" />');
|
|
2540
|
+
builder.inject(
|
|
2175
2541
|
"readme-libraries",
|
|
2176
2542
|
`[@react-three/drei](https://drei.docs.pmnd.rs/) - Useful helpers for @react-three/fiber`
|
|
2177
2543
|
);
|
|
@@ -2180,25 +2546,28 @@ function generateDrei(generator, options) {
|
|
|
2180
2546
|
function toEslintLevel(level) {
|
|
2181
2547
|
return level;
|
|
2182
2548
|
}
|
|
2183
|
-
function
|
|
2184
|
-
|
|
2185
|
-
|
|
2549
|
+
function planEslint(builder, options) {
|
|
2550
|
+
if (options == null) {
|
|
2551
|
+
return;
|
|
2552
|
+
}
|
|
2553
|
+
builder.addDevDependency("eslint");
|
|
2554
|
+
const template = builder.options.template ?? "vanilla";
|
|
2186
2555
|
const baseTemplate = getBaseTemplate(template);
|
|
2187
2556
|
const isTypescript = getLanguageFromTemplate(template) === "typescript";
|
|
2188
2557
|
const isReact = baseTemplate === "react" || baseTemplate === "r3f";
|
|
2189
|
-
const { rules } =
|
|
2558
|
+
const { rules } = options.config;
|
|
2190
2559
|
const imports = ['import js from "@eslint/js"'];
|
|
2191
2560
|
const configs = ["js.configs.recommended"];
|
|
2192
2561
|
if (isTypescript) {
|
|
2193
|
-
|
|
2562
|
+
builder.addDevDependency("typescript-eslint");
|
|
2194
2563
|
imports.push('import tseslint from "typescript-eslint"');
|
|
2195
2564
|
configs.push("...tseslint.configs.recommended");
|
|
2196
2565
|
}
|
|
2197
2566
|
if (isReact) {
|
|
2198
|
-
|
|
2567
|
+
builder.addDevDependency("eslint-plugin-react-hooks");
|
|
2199
2568
|
imports.push('import reactHooks from "eslint-plugin-react-hooks"');
|
|
2200
2569
|
}
|
|
2201
|
-
const ignoresArray = JSON.stringify(
|
|
2570
|
+
const ignoresArray = JSON.stringify(options.config.ignorePatterns);
|
|
2202
2571
|
const unusedVarsRule = isTypescript ? "@typescript-eslint/no-unused-vars" : "no-unused-vars";
|
|
2203
2572
|
const rulesConfig = {
|
|
2204
2573
|
[unusedVarsRule]: [
|
|
@@ -2232,34 +2601,30 @@ function generateEslint(generator, options) {
|
|
|
2232
2601
|
},`,
|
|
2233
2602
|
"]"
|
|
2234
2603
|
].filter(Boolean).join("\n");
|
|
2235
|
-
const isStealth =
|
|
2604
|
+
const isStealth = builder.isStealthConfig();
|
|
2236
2605
|
if (isStealth) {
|
|
2237
|
-
|
|
2606
|
+
builder.addFile(".config/eslint.config.js", {
|
|
2238
2607
|
type: "text",
|
|
2239
2608
|
content: configContent
|
|
2240
2609
|
});
|
|
2241
|
-
|
|
2242
|
-
generator.addVscodeSetting("eslint.options", {
|
|
2243
|
-
overrideConfigFile: ".config/eslint.config.js"
|
|
2244
|
-
});
|
|
2610
|
+
builder.addScripts(packageJsonScripts.lint.eslint(".config/eslint.config.js"));
|
|
2245
2611
|
} else {
|
|
2246
|
-
|
|
2612
|
+
builder.addFile("eslint.config.js", {
|
|
2247
2613
|
type: "text",
|
|
2248
2614
|
content: configContent
|
|
2249
2615
|
});
|
|
2250
|
-
|
|
2616
|
+
builder.addScripts(packageJsonScripts.lint.eslint());
|
|
2251
2617
|
}
|
|
2252
|
-
|
|
2618
|
+
builder.inject(
|
|
2253
2619
|
"readme-tools",
|
|
2254
2620
|
"[ESLint](https://eslint.org/) - Linter for JavaScript and TypeScript"
|
|
2255
2621
|
);
|
|
2256
|
-
|
|
2257
|
-
generator.addVscodeSetting("eslint.enable", true);
|
|
2622
|
+
builder.inject("vscode-extension-suggestion", "dbaeumer.vscode-eslint");
|
|
2258
2623
|
}
|
|
2259
2624
|
|
|
2260
|
-
function
|
|
2261
|
-
|
|
2262
|
-
|
|
2625
|
+
function planFiber(builder, _options) {
|
|
2626
|
+
builder.inject("import", `import { Box } from "./box.js"`);
|
|
2627
|
+
builder.inject(
|
|
2263
2628
|
"scene",
|
|
2264
2629
|
[
|
|
2265
2630
|
`<ambientLight intensity={Math.PI / 2} />`,
|
|
@@ -2269,7 +2634,7 @@ function generateFiber(generator, _options) {
|
|
|
2269
2634
|
`<Box position={[1.2, 0, 0]} />`
|
|
2270
2635
|
].join("\n")
|
|
2271
2636
|
);
|
|
2272
|
-
|
|
2637
|
+
builder.addFile("src/box.tsx", {
|
|
2273
2638
|
type: "text",
|
|
2274
2639
|
content: `import type { Mesh } from 'three'
|
|
2275
2640
|
import { useRef, useState } from 'react'
|
|
@@ -2296,11 +2661,11 @@ export function Box(props: ThreeElements['mesh']) {
|
|
|
2296
2661
|
});
|
|
2297
2662
|
}
|
|
2298
2663
|
|
|
2299
|
-
function
|
|
2300
|
-
if (options === false || getPackageManagerName(
|
|
2664
|
+
function planGithubPages(builder, options) {
|
|
2665
|
+
if (options === false || getPackageManagerName(builder.options.packageManager) !== "npm") {
|
|
2301
2666
|
return;
|
|
2302
2667
|
}
|
|
2303
|
-
|
|
2668
|
+
builder.addFile(".github/workflows/gh-pages.yml", {
|
|
2304
2669
|
type: "text",
|
|
2305
2670
|
content: `name: Deploy to Github Pages
|
|
2306
2671
|
|
|
@@ -2346,10 +2711,10 @@ jobs:
|
|
|
2346
2711
|
uses: actions/deploy-pages@v4
|
|
2347
2712
|
`
|
|
2348
2713
|
});
|
|
2349
|
-
|
|
2350
|
-
if (
|
|
2351
|
-
const address = `${
|
|
2352
|
-
|
|
2714
|
+
builder.inject("readme-start", `A github pages deployment action is configurd.`);
|
|
2715
|
+
if (builder.options.githubUserName != null && builder.options.githubRepoName != null) {
|
|
2716
|
+
const address = `${builder.options.githubUserName}.github.io/${builder.options.githubRepoName}`;
|
|
2717
|
+
builder.inject(
|
|
2353
2718
|
"readme-start",
|
|
2354
2719
|
`Your app will be publish at [${address}](https://${address}) once the github action is finished.
|
|
2355
2720
|
`
|
|
@@ -2357,228 +2722,199 @@ jobs:
|
|
|
2357
2722
|
}
|
|
2358
2723
|
}
|
|
2359
2724
|
|
|
2360
|
-
function
|
|
2725
|
+
function planHandle(builder, options) {
|
|
2361
2726
|
if (options == null) {
|
|
2362
2727
|
return;
|
|
2363
2728
|
}
|
|
2364
|
-
|
|
2365
|
-
|
|
2729
|
+
builder.addDependency("@react-three/handle");
|
|
2730
|
+
builder.inject(
|
|
2366
2731
|
"readme-libraries",
|
|
2367
2732
|
`[@react-three/handle](https://pmndrs.github.io/xr/docs/handles/introduction) - interactive controls and handles for your 3D objects`
|
|
2368
2733
|
);
|
|
2369
2734
|
}
|
|
2370
2735
|
|
|
2371
|
-
function
|
|
2736
|
+
function planKoota(builder, options) {
|
|
2372
2737
|
if (options == null) {
|
|
2373
2738
|
return;
|
|
2374
2739
|
}
|
|
2375
|
-
|
|
2376
|
-
|
|
2740
|
+
builder.addDependency("koota");
|
|
2741
|
+
builder.inject(
|
|
2377
2742
|
"readme-libraries",
|
|
2378
2743
|
`[koota](https://github.com/pmndrs/koota) - ECS-based state management library optimized for real-time apps, games, and XR experiences`
|
|
2379
2744
|
);
|
|
2380
2745
|
}
|
|
2381
2746
|
|
|
2382
|
-
function
|
|
2747
|
+
function planLeva(builder, options) {
|
|
2383
2748
|
if (options == null) {
|
|
2384
2749
|
return;
|
|
2385
2750
|
}
|
|
2386
|
-
|
|
2387
|
-
|
|
2751
|
+
builder.addDependency("leva");
|
|
2752
|
+
builder.inject(
|
|
2388
2753
|
"readme-libraries",
|
|
2389
2754
|
`[leva](https://github.com/pmndrs/leva) - HTML GUI panel for React with lightweight, beautiful and extensible controls`
|
|
2390
2755
|
);
|
|
2391
2756
|
}
|
|
2392
2757
|
|
|
2393
|
-
function
|
|
2758
|
+
function planOffscreen(builder, options) {
|
|
2394
2759
|
if (options == null) {
|
|
2395
2760
|
return;
|
|
2396
2761
|
}
|
|
2397
|
-
if (
|
|
2762
|
+
if (builder.options.xr != null) {
|
|
2398
2763
|
console.info(
|
|
2399
2764
|
color.blue("Info:"),
|
|
2400
2765
|
"@react-three/offscreen is disabled because it is not supported with XR"
|
|
2401
2766
|
);
|
|
2402
2767
|
return;
|
|
2403
2768
|
}
|
|
2404
|
-
|
|
2405
|
-
|
|
2769
|
+
builder.addDependency("@react-three/offscreen");
|
|
2770
|
+
builder.inject(
|
|
2406
2771
|
"readme-libraries",
|
|
2407
2772
|
`[@react-three/offscreen](https://github.com/pmndrs/offscreen) - Offload your scene to a worker thread for better performance`
|
|
2408
2773
|
);
|
|
2409
2774
|
}
|
|
2410
2775
|
|
|
2411
|
-
function
|
|
2412
|
-
|
|
2776
|
+
function planOxfmt(builder, options) {
|
|
2777
|
+
if (options == null) {
|
|
2778
|
+
return;
|
|
2779
|
+
}
|
|
2780
|
+
const isMonorepo = builder.options.workspaceRoot != null;
|
|
2413
2781
|
if (isMonorepo) {
|
|
2414
|
-
|
|
2782
|
+
builder.addDevDependency("@config/oxfmt", { version: "workspace:*" });
|
|
2415
2783
|
const configPath = "node_modules/@config/oxfmt/base.json";
|
|
2416
|
-
|
|
2417
|
-
generator.addVscodeSetting("oxc.fmt.configPath", configPath);
|
|
2784
|
+
builder.addScripts(packageJsonScripts.format.oxfmt(configPath));
|
|
2418
2785
|
} else {
|
|
2419
|
-
|
|
2420
|
-
const isStealth =
|
|
2786
|
+
builder.addDevDependency("oxfmt");
|
|
2787
|
+
const isStealth = builder.isStealthConfig();
|
|
2421
2788
|
if (isStealth) {
|
|
2422
|
-
|
|
2789
|
+
builder.addFile(".config/oxfmt.json", {
|
|
2423
2790
|
type: "text",
|
|
2424
|
-
content: JSON.stringify(
|
|
2791
|
+
content: JSON.stringify(toOxfmtConfig(options.config), null, 2)
|
|
2425
2792
|
});
|
|
2426
|
-
|
|
2427
|
-
generator.addVscodeSetting("oxc.fmt.configPath", ".config/oxfmt.json");
|
|
2793
|
+
builder.addScripts(packageJsonScripts.format.oxfmt(".config/oxfmt.json"));
|
|
2428
2794
|
} else {
|
|
2429
|
-
|
|
2795
|
+
builder.addFile("oxfmt.json", {
|
|
2430
2796
|
type: "text",
|
|
2431
|
-
content: JSON.stringify(
|
|
2797
|
+
content: JSON.stringify(toOxfmtConfig(options.config), null, 2)
|
|
2432
2798
|
});
|
|
2433
|
-
|
|
2799
|
+
builder.addScripts(packageJsonScripts.format.oxfmt("oxfmt.json"));
|
|
2434
2800
|
}
|
|
2435
2801
|
}
|
|
2436
|
-
|
|
2802
|
+
builder.inject(
|
|
2437
2803
|
"readme-tools",
|
|
2438
2804
|
"[Oxfmt](https://oxc.rs/docs/guide/usage/formatter) - Fast Prettier-compatible code formatter"
|
|
2439
2805
|
);
|
|
2440
|
-
|
|
2441
|
-
generator.addVscodeSetting("editor.defaultFormatter", "oxc.oxc-vscode");
|
|
2442
|
-
generator.addVscodeSetting("[json]", {
|
|
2443
|
-
"editor.defaultFormatter": "vscode.json-language-features"
|
|
2444
|
-
});
|
|
2445
|
-
generator.addVscodeSetting("[jsonc]", {
|
|
2446
|
-
"editor.defaultFormatter": "vscode.json-language-features"
|
|
2447
|
-
});
|
|
2448
|
-
generator.addVscodeSetting("[markdown]", {
|
|
2449
|
-
"editor.defaultFormatter": "vscode.markdown-language-features"
|
|
2450
|
-
});
|
|
2451
|
-
generator.addVscodeSetting("[yaml]", {
|
|
2452
|
-
"editor.defaultFormatter": "redhat.vscode-yaml"
|
|
2453
|
-
});
|
|
2806
|
+
builder.inject("vscode-extension-suggestion", "oxc.oxc-vscode");
|
|
2454
2807
|
}
|
|
2455
2808
|
|
|
2456
|
-
function
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
const template =
|
|
2809
|
+
function planOxlint(builder, options) {
|
|
2810
|
+
if (options == null) {
|
|
2811
|
+
return;
|
|
2812
|
+
}
|
|
2813
|
+
const template = builder.options.template ?? "vanilla";
|
|
2461
2814
|
const baseTemplate = getBaseTemplate(template);
|
|
2815
|
+
const isTypescript = getLanguageFromTemplate(template) === "typescript";
|
|
2462
2816
|
const isReact = baseTemplate === "react" || baseTemplate === "r3f";
|
|
2463
|
-
const isMonorepo =
|
|
2817
|
+
const isMonorepo = builder.options.workspaceRoot != null;
|
|
2464
2818
|
if (isMonorepo) {
|
|
2465
|
-
|
|
2819
|
+
builder.addDevDependency("@config/oxlint", { version: "workspace:*" });
|
|
2466
2820
|
const configPath = isReact ? "node_modules/@config/oxlint/react.json" : "node_modules/@config/oxlint/base.json";
|
|
2467
|
-
|
|
2468
|
-
generator.addVscodeSetting("oxc.configPath", configPath);
|
|
2821
|
+
builder.addScripts(packageJsonScripts.lint.oxlint(configPath));
|
|
2469
2822
|
} else {
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
"no-unused-vars": [
|
|
2482
|
-
toOxlintLevel(rules.noUnusedVars.level),
|
|
2483
|
-
{
|
|
2484
|
-
argsIgnorePattern: rules.noUnusedVars.argsIgnorePattern,
|
|
2485
|
-
varsIgnorePattern: rules.noUnusedVars.varsIgnorePattern,
|
|
2486
|
-
caughtErrorsIgnorePattern: rules.noUnusedVars.caughtErrorsIgnorePattern
|
|
2487
|
-
}
|
|
2488
|
-
],
|
|
2489
|
-
"no-useless-escape": "off",
|
|
2490
|
-
"no-unused-expressions": [
|
|
2491
|
-
toOxlintLevel(rules.noUnusedExpressions.level),
|
|
2492
|
-
{ allowShortCircuit: rules.noUnusedExpressions.allowShortCircuit }
|
|
2493
|
-
]
|
|
2494
|
-
},
|
|
2495
|
-
ignorePatterns: defaultLinterConfig.ignorePatterns
|
|
2496
|
-
};
|
|
2823
|
+
builder.addDevDependency("oxlint");
|
|
2824
|
+
if (isTypescript) {
|
|
2825
|
+
builder.addDevDependency("oxlint-tsgolint");
|
|
2826
|
+
}
|
|
2827
|
+
const isStealth = builder.isStealthConfig();
|
|
2828
|
+
const oxlintConfig = renderOxlintConfig({
|
|
2829
|
+
schemaPath: isStealth ? "../node_modules/oxlint/configuration_schema.json" : "./node_modules/oxlint/configuration_schema.json",
|
|
2830
|
+
react: isReact,
|
|
2831
|
+
typescript: isTypescript,
|
|
2832
|
+
config: options.config
|
|
2833
|
+
});
|
|
2497
2834
|
if (isStealth) {
|
|
2498
|
-
|
|
2835
|
+
builder.addFile(".config/oxlint.json", {
|
|
2499
2836
|
type: "text",
|
|
2500
2837
|
content: JSON.stringify(oxlintConfig, null, 2)
|
|
2501
2838
|
});
|
|
2502
|
-
|
|
2503
|
-
generator.addVscodeSetting("oxc.configPath", ".config/oxlint.json");
|
|
2839
|
+
builder.addScripts(packageJsonScripts.lint.oxlint(".config/oxlint.json"));
|
|
2504
2840
|
} else {
|
|
2505
|
-
|
|
2841
|
+
builder.addFile("oxlint.json", {
|
|
2506
2842
|
type: "text",
|
|
2507
2843
|
content: JSON.stringify(oxlintConfig, null, 2)
|
|
2508
2844
|
});
|
|
2509
|
-
|
|
2845
|
+
builder.addScripts(packageJsonScripts.lint.oxlint());
|
|
2510
2846
|
}
|
|
2511
2847
|
}
|
|
2512
|
-
|
|
2848
|
+
builder.inject(
|
|
2513
2849
|
"readme-tools",
|
|
2514
2850
|
"[Oxlint](https://oxc.rs/docs/guide/usage/linter) - A fast linter for JavaScript and TypeScript"
|
|
2515
2851
|
);
|
|
2516
|
-
|
|
2517
|
-
generator.addVscodeSetting("oxc.enable", true);
|
|
2852
|
+
builder.inject("vscode-extension-suggestion", "oxc.oxc-vscode");
|
|
2518
2853
|
}
|
|
2519
2854
|
|
|
2520
|
-
function
|
|
2855
|
+
function planPostprocessing(builder, options) {
|
|
2521
2856
|
if (options == null) {
|
|
2522
2857
|
return;
|
|
2523
2858
|
}
|
|
2524
|
-
if (
|
|
2859
|
+
if (builder.options.xr != null) {
|
|
2525
2860
|
console.info(
|
|
2526
2861
|
color.blue("Info:"),
|
|
2527
2862
|
"@react-three/postprocessing is disabled because it is not supported with XR"
|
|
2528
2863
|
);
|
|
2529
2864
|
return;
|
|
2530
2865
|
}
|
|
2531
|
-
|
|
2532
|
-
|
|
2866
|
+
builder.addDependency("@react-three/postprocessing");
|
|
2867
|
+
builder.inject(
|
|
2533
2868
|
"readme-libraries",
|
|
2534
2869
|
`[@react-three/postprocessing](https://react-postprocessing.docs.pmnd.rs/) - Post-processing effects for @react-three/fiber`
|
|
2535
2870
|
);
|
|
2536
2871
|
}
|
|
2537
2872
|
|
|
2538
|
-
function
|
|
2539
|
-
|
|
2540
|
-
|
|
2873
|
+
function planPrettier(builder, options) {
|
|
2874
|
+
if (options == null) {
|
|
2875
|
+
return;
|
|
2876
|
+
}
|
|
2877
|
+
builder.addDevDependency("prettier");
|
|
2878
|
+
const isStealth = builder.isStealthConfig();
|
|
2541
2879
|
if (isStealth) {
|
|
2542
|
-
|
|
2880
|
+
builder.addFile(".config/prettier.json", {
|
|
2881
|
+
type: "text",
|
|
2882
|
+
content: JSON.stringify(toPrettierConfig(options.config), null, 2)
|
|
2883
|
+
});
|
|
2884
|
+
builder.addFile(".config/prettierignore", {
|
|
2543
2885
|
type: "text",
|
|
2544
|
-
content:
|
|
2886
|
+
content: toPrettierIgnoreContent(options.config)
|
|
2545
2887
|
});
|
|
2546
|
-
|
|
2547
|
-
|
|
2888
|
+
builder.addScripts(
|
|
2889
|
+
packageJsonScripts.format.prettier(".config/prettier.json", ".config/prettierignore")
|
|
2890
|
+
);
|
|
2548
2891
|
} else {
|
|
2549
|
-
|
|
2892
|
+
builder.addFile(".prettierrc", {
|
|
2550
2893
|
type: "text",
|
|
2551
|
-
content: JSON.stringify(
|
|
2894
|
+
content: JSON.stringify(toPrettierConfig(options.config), null, 2)
|
|
2552
2895
|
});
|
|
2553
|
-
|
|
2896
|
+
builder.addFile(".prettierignore", {
|
|
2897
|
+
type: "text",
|
|
2898
|
+
content: toPrettierIgnoreContent(options.config)
|
|
2899
|
+
});
|
|
2900
|
+
builder.addScripts(packageJsonScripts.format.prettier());
|
|
2554
2901
|
}
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
generator.addVscodeSetting("editor.defaultFormatter", "esbenp.prettier-vscode");
|
|
2902
|
+
builder.inject("readme-tools", "[Prettier](https://prettier.io/) - Opinionated code formatter");
|
|
2903
|
+
builder.inject("vscode-extension-suggestion", "esbenp.prettier-vscode");
|
|
2558
2904
|
}
|
|
2559
2905
|
|
|
2560
|
-
function
|
|
2906
|
+
function planRapier(builder, options) {
|
|
2561
2907
|
if (options == null) {
|
|
2562
2908
|
return;
|
|
2563
2909
|
}
|
|
2564
|
-
|
|
2565
|
-
|
|
2910
|
+
builder.addDependency("@react-three/rapier");
|
|
2911
|
+
builder.inject(
|
|
2566
2912
|
"readme-libraries",
|
|
2567
2913
|
`[@react-three/rapier](https://github.com/pmndrs/react-three-rapier) - Physics based on Rapier for your @react-three/fiber scene`
|
|
2568
2914
|
);
|
|
2569
2915
|
}
|
|
2570
2916
|
|
|
2571
|
-
function
|
|
2572
|
-
const set = /* @__PURE__ */ new Set();
|
|
2573
|
-
for (const arr of array) {
|
|
2574
|
-
for (const item of arr) {
|
|
2575
|
-
set.add(item);
|
|
2576
|
-
}
|
|
2577
|
-
}
|
|
2578
|
-
return Array.from(set);
|
|
2579
|
-
}
|
|
2580
|
-
|
|
2581
|
-
function generateProvidersModule(generator) {
|
|
2917
|
+
function generateProvidersModule(builder) {
|
|
2582
2918
|
const canvasProviders = [];
|
|
2583
2919
|
const globalProviders = [];
|
|
2584
2920
|
const providerDefs = {
|
|
@@ -2644,13 +2980,13 @@ function generateProvidersModule(generator) {
|
|
|
2644
2980
|
]
|
|
2645
2981
|
}
|
|
2646
2982
|
};
|
|
2647
|
-
if (
|
|
2983
|
+
if (builder.options.rapier) {
|
|
2648
2984
|
canvasProviders.push("rapier");
|
|
2649
2985
|
}
|
|
2650
|
-
if (!!
|
|
2986
|
+
if (!!builder.options.postprocessing && !builder.options.xr) {
|
|
2651
2987
|
canvasProviders.push("postprocessing");
|
|
2652
2988
|
}
|
|
2653
|
-
if (
|
|
2989
|
+
if (builder.options.uikit) {
|
|
2654
2990
|
globalProviders.push("uikit");
|
|
2655
2991
|
}
|
|
2656
2992
|
function generateProviderFunction(name, { jsdoc, providers }) {
|
|
@@ -2713,20 +3049,20 @@ ${jsdoc.split("\n").map((line) => ` * ${line}`).join("\n")}
|
|
|
2713
3049
|
${canvas.code}
|
|
2714
3050
|
`;
|
|
2715
3051
|
}
|
|
2716
|
-
function
|
|
3052
|
+
function planTriplex(builder, options) {
|
|
2717
3053
|
if (options == null) {
|
|
2718
3054
|
return;
|
|
2719
3055
|
}
|
|
2720
|
-
|
|
2721
|
-
|
|
3056
|
+
builder.inject("vscode-extension-suggestion", "trytriplex.triplex-vsce");
|
|
3057
|
+
builder.inject(
|
|
2722
3058
|
"readme-tools",
|
|
2723
3059
|
`[Triplex](https://triplex.dev) - Your visual workspace for React / Three Fiber. Get started by installing [Triplex for VS Code](https://triplex.dev/docs/get-started/vscode). Don't use Visual Studio Code? Download [Triplex Standalone](https://triplex.dev/docs/get-started/standalone).`
|
|
2724
3060
|
);
|
|
2725
|
-
|
|
2726
|
-
content: generateProvidersModule(
|
|
3061
|
+
builder.addFile(".triplex/providers.tsx", {
|
|
3062
|
+
content: generateProvidersModule(builder),
|
|
2727
3063
|
type: "text"
|
|
2728
3064
|
});
|
|
2729
|
-
|
|
3065
|
+
builder.addFile(".triplex/config.json", {
|
|
2730
3066
|
content: JSON.stringify(
|
|
2731
3067
|
{
|
|
2732
3068
|
$schema: "https://triplex.dev/config.schema.json",
|
|
@@ -2739,9 +3075,9 @@ function generateTriplex(generator, options) {
|
|
|
2739
3075
|
});
|
|
2740
3076
|
}
|
|
2741
3077
|
|
|
2742
|
-
function
|
|
2743
|
-
|
|
2744
|
-
const template =
|
|
3078
|
+
function planTsdown(builder) {
|
|
3079
|
+
builder.addDevDependency("tsdown");
|
|
3080
|
+
const template = builder.options.template ?? "vanilla";
|
|
2745
3081
|
const baseTemplate = getBaseTemplate(template);
|
|
2746
3082
|
const language = getLanguageFromTemplate(template);
|
|
2747
3083
|
const isReact = baseTemplate === "react" || baseTemplate === "r3f";
|
|
@@ -2761,36 +3097,36 @@ function generateTsdown(generator) {
|
|
|
2761
3097
|
configLines.push(` },`);
|
|
2762
3098
|
}
|
|
2763
3099
|
configLines.push(`})`);
|
|
2764
|
-
|
|
3100
|
+
builder.addFile(`tsdown.config.${ext}`, {
|
|
2765
3101
|
type: "text",
|
|
2766
3102
|
content: configLines.join("\n")
|
|
2767
3103
|
});
|
|
2768
|
-
|
|
2769
|
-
|
|
3104
|
+
builder.addScripts(packageJsonScripts.build.tsdown);
|
|
3105
|
+
builder.inject(
|
|
2770
3106
|
"readme-libraries",
|
|
2771
3107
|
"[tsdown](https://github.com/nicepkg/tsdown) - Fast TypeScript bundler powered by esbuild"
|
|
2772
3108
|
);
|
|
2773
3109
|
}
|
|
2774
3110
|
|
|
2775
|
-
function
|
|
3111
|
+
function planUikit(builder, options) {
|
|
2776
3112
|
if (options == null) {
|
|
2777
3113
|
return;
|
|
2778
3114
|
}
|
|
2779
|
-
|
|
2780
|
-
|
|
3115
|
+
builder.addDependency("@react-three/uikit");
|
|
3116
|
+
builder.inject(
|
|
2781
3117
|
"readme-libraries",
|
|
2782
3118
|
`[@react-three/uikit](https://pmndrs.github.io/uikit/docs/) - UI primitives for React Three Fiber`
|
|
2783
3119
|
);
|
|
2784
3120
|
}
|
|
2785
3121
|
|
|
2786
|
-
function
|
|
2787
|
-
|
|
2788
|
-
const template =
|
|
3122
|
+
function planUnbuild(builder) {
|
|
3123
|
+
builder.addDevDependency("unbuild");
|
|
3124
|
+
const template = builder.options.template ?? "vanilla";
|
|
2789
3125
|
const baseTemplate = getBaseTemplate(template);
|
|
2790
3126
|
const language = getLanguageFromTemplate(template);
|
|
2791
3127
|
const isReact = baseTemplate === "react" || baseTemplate === "r3f";
|
|
2792
3128
|
const ext = language === "typescript" ? "ts" : "js";
|
|
2793
|
-
const isMonorepo =
|
|
3129
|
+
const isMonorepo = builder.options.workspaceRoot != null;
|
|
2794
3130
|
const buildConfigLines = [
|
|
2795
3131
|
`import { defineBuildConfig } from "unbuild"`,
|
|
2796
3132
|
``,
|
|
@@ -2808,51 +3144,54 @@ function generateUnbuild(generator) {
|
|
|
2808
3144
|
}
|
|
2809
3145
|
buildConfigLines.push(` },`);
|
|
2810
3146
|
buildConfigLines.push(`})`);
|
|
2811
|
-
const isStealth =
|
|
3147
|
+
const isStealth = builder.isStealthConfig() && !isMonorepo;
|
|
2812
3148
|
if (isStealth) {
|
|
2813
|
-
|
|
3149
|
+
builder.addFile(`.config/build.config.${ext}`, {
|
|
2814
3150
|
type: "text",
|
|
2815
3151
|
content: buildConfigLines.join("\n")
|
|
2816
3152
|
});
|
|
2817
|
-
|
|
3153
|
+
builder.addScripts(packageJsonScripts.build.unbuild(`.config/build.config.${ext}`));
|
|
2818
3154
|
} else {
|
|
2819
|
-
|
|
3155
|
+
builder.addFile(`build.config.${ext}`, {
|
|
2820
3156
|
type: "text",
|
|
2821
3157
|
content: buildConfigLines.join("\n")
|
|
2822
3158
|
});
|
|
2823
|
-
|
|
3159
|
+
builder.addScripts(packageJsonScripts.build.unbuild());
|
|
2824
3160
|
}
|
|
2825
|
-
|
|
3161
|
+
builder.inject(
|
|
2826
3162
|
"readme-libraries",
|
|
2827
3163
|
"[unbuild](https://github.com/unjs/unbuild) - Unified JavaScript build system"
|
|
2828
3164
|
);
|
|
2829
3165
|
}
|
|
2830
3166
|
|
|
2831
|
-
function
|
|
2832
|
-
|
|
2833
|
-
|
|
3167
|
+
function planVitest(builder, options) {
|
|
3168
|
+
if (options == null) {
|
|
3169
|
+
return;
|
|
3170
|
+
}
|
|
3171
|
+
builder.addDevDependency("vitest");
|
|
3172
|
+
const template = builder.options.template ?? "vanilla";
|
|
2834
3173
|
const baseTemplate = getBaseTemplate(template);
|
|
2835
3174
|
const isReact = baseTemplate === "react" || baseTemplate === "r3f";
|
|
2836
3175
|
if (isReact) {
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
3176
|
+
builder.addDevDependency("@testing-library/react");
|
|
3177
|
+
builder.addDevDependency("@testing-library/dom");
|
|
3178
|
+
builder.addDevDependency("jsdom");
|
|
2840
3179
|
}
|
|
2841
3180
|
if (isReact) {
|
|
2842
|
-
|
|
3181
|
+
builder.configureVite({ test: { environment: "jsdom" } });
|
|
2843
3182
|
}
|
|
2844
|
-
|
|
2845
|
-
|
|
3183
|
+
builder.addScripts(packageJsonScripts.test.vitest);
|
|
3184
|
+
builder.inject(
|
|
2846
3185
|
"readme-tools",
|
|
2847
3186
|
"[Vitest](https://vitest.dev/) - Fast unit test framework powered by Vite"
|
|
2848
3187
|
);
|
|
2849
3188
|
}
|
|
2850
3189
|
|
|
2851
|
-
function
|
|
2852
|
-
if (options == null || getPackageManagerName(
|
|
3190
|
+
function planViverse(builder, options) {
|
|
3191
|
+
if (options == null || getPackageManagerName(builder.options.packageManager) !== "npm") {
|
|
2853
3192
|
return;
|
|
2854
3193
|
}
|
|
2855
|
-
|
|
3194
|
+
builder.addFile(".github/workflows/viverse.yml", {
|
|
2856
3195
|
type: "text",
|
|
2857
3196
|
content: `name: Deploy to Viverse
|
|
2858
3197
|
|
|
@@ -2903,12 +3242,12 @@ jobs:
|
|
|
2903
3242
|
run: npx viverse-cli auth login -e \${{ secrets.VIVERSE_EMAIL }} -p \${{ secrets.VIVERSE_PASSWORD }}
|
|
2904
3243
|
|
|
2905
3244
|
- name: Deploy to Viverse
|
|
2906
|
-
run: npx viverse-cli app publish ./dist --auto-create-app --name ${
|
|
3245
|
+
run: npx viverse-cli app publish ./dist --auto-create-app --name ${builder.options.name}
|
|
2907
3246
|
|
|
2908
3247
|
`
|
|
2909
3248
|
});
|
|
2910
|
-
|
|
2911
|
-
|
|
3249
|
+
builder.addDependency("@viverse/cli");
|
|
3250
|
+
builder.inject(
|
|
2912
3251
|
"readme-start",
|
|
2913
3252
|
`A GitHub CI/CD workflow for publishing to Viverse is configured.
|
|
2914
3253
|
|
|
@@ -2921,36 +3260,36 @@ You can also upload your project manually using the Viverse CLI:
|
|
|
2921
3260
|
\`\`\`bash
|
|
2922
3261
|
viverse-cli auth login -e <email> -p <password>
|
|
2923
3262
|
npm run build
|
|
2924
|
-
viverse-cli app publish ./dist --auto-create-app --name ${
|
|
3263
|
+
viverse-cli app publish ./dist --auto-create-app --name ${builder.options.name}
|
|
2925
3264
|
\`\`\`
|
|
2926
3265
|
`
|
|
2927
3266
|
);
|
|
2928
3267
|
}
|
|
2929
3268
|
|
|
2930
|
-
function
|
|
3269
|
+
function planXr(builder, options) {
|
|
2931
3270
|
if (options == null || options === false) {
|
|
2932
3271
|
return;
|
|
2933
3272
|
}
|
|
2934
3273
|
if (options === true) {
|
|
2935
3274
|
options = {};
|
|
2936
3275
|
}
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
3276
|
+
builder.addDependency("@react-three/xr");
|
|
3277
|
+
builder.addDependency("@vitejs/plugin-basic-ssl");
|
|
3278
|
+
builder.inject("import", "import { XR, createXRStore } from '@react-three/xr'");
|
|
3279
|
+
builder.inject(
|
|
2941
3280
|
`global-start`,
|
|
2942
3281
|
`const store = createXRStore(${JSON.stringify(options.storeOptions ?? {})})`
|
|
2943
3282
|
);
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
3283
|
+
builder.inject("scene-start", "<XR store={store}>");
|
|
3284
|
+
builder.inject("scene-end", "</XR>");
|
|
3285
|
+
builder.inject("vite-config-import", "import basicSsl from '@vitejs/plugin-basic-ssl'");
|
|
3286
|
+
builder.configureVite({
|
|
2948
3287
|
server: {
|
|
2949
3288
|
host: true
|
|
2950
3289
|
},
|
|
2951
3290
|
plugins: ["$raw:basicSsl()"]
|
|
2952
3291
|
});
|
|
2953
|
-
|
|
3292
|
+
builder.inject(
|
|
2954
3293
|
"dom-start",
|
|
2955
3294
|
`<div style={{
|
|
2956
3295
|
display: "flex",
|
|
@@ -2982,55 +3321,226 @@ function generateXr(generator, options) {
|
|
|
2982
3321
|
Enter VR
|
|
2983
3322
|
</button></div>`
|
|
2984
3323
|
);
|
|
2985
|
-
|
|
3324
|
+
builder.inject(
|
|
2986
3325
|
"readme-libraries",
|
|
2987
3326
|
`[@react-three/xr](https://pmndrs.github.io/xr/docs/) - VR/AR support for @react-three/fiber`
|
|
2988
3327
|
);
|
|
2989
3328
|
}
|
|
2990
3329
|
|
|
2991
|
-
function
|
|
3330
|
+
function planZustand(builder, options) {
|
|
2992
3331
|
if (options == null) {
|
|
2993
3332
|
return;
|
|
2994
3333
|
}
|
|
2995
|
-
|
|
2996
|
-
|
|
3334
|
+
builder.addDependency("zustand");
|
|
3335
|
+
builder.inject(
|
|
2997
3336
|
"readme-libraries",
|
|
2998
3337
|
`[zustand](https://zustand.docs.pmnd.rs/) - small, fast and scalable state-management solution`
|
|
2999
3338
|
);
|
|
3000
3339
|
}
|
|
3001
3340
|
|
|
3002
|
-
function
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3341
|
+
function resolveProjectPlanInput(options) {
|
|
3342
|
+
const packageManager = options.packageManager ?? { name: "pnpm" };
|
|
3343
|
+
return {
|
|
3344
|
+
project: {
|
|
3345
|
+
githubUserName: options.githubUserName,
|
|
3346
|
+
githubRepoName: options.githubRepoName,
|
|
3347
|
+
name: options.name,
|
|
3348
|
+
projectType: options.projectType,
|
|
3349
|
+
template: options.template
|
|
3350
|
+
},
|
|
3351
|
+
aiAgents: {
|
|
3352
|
+
tool: "ai-agents",
|
|
3353
|
+
config: {
|
|
3354
|
+
platforms: options.aiPlatforms ?? []
|
|
3355
|
+
}
|
|
3356
|
+
},
|
|
3357
|
+
formatter: {
|
|
3358
|
+
tool: options.formatter ?? "prettier",
|
|
3359
|
+
config: structuredClone(defaultFormatterMetaConfig)
|
|
3360
|
+
},
|
|
3361
|
+
linter: {
|
|
3362
|
+
tool: options.linter ?? "oxlint",
|
|
3363
|
+
config: structuredClone(defaultLinterMetaConfig)
|
|
3364
|
+
},
|
|
3365
|
+
testing: {
|
|
3366
|
+
tool: options.testing ?? (options.projectType === "library" ? "vitest" : "none"),
|
|
3367
|
+
config: {}
|
|
3368
|
+
},
|
|
3369
|
+
typescript: {
|
|
3370
|
+
tool: "typescript",
|
|
3371
|
+
config: {
|
|
3372
|
+
configStrategy: options.configStrategy
|
|
3373
|
+
}
|
|
3374
|
+
},
|
|
3375
|
+
ide: {
|
|
3376
|
+
tool: options.ide ?? "vscode",
|
|
3377
|
+
config: {}
|
|
3378
|
+
},
|
|
3379
|
+
packageManager: {
|
|
3380
|
+
tool: packageManager.name,
|
|
3381
|
+
config: {
|
|
3382
|
+
version: packageManager.version,
|
|
3383
|
+
pnpmManageVersions: options.pnpmManageVersions
|
|
3384
|
+
}
|
|
3385
|
+
},
|
|
3386
|
+
libraryBundler: {
|
|
3387
|
+
tool: options.libraryBundler ?? "unbuild",
|
|
3388
|
+
config: {}
|
|
3389
|
+
},
|
|
3390
|
+
features: {
|
|
3391
|
+
fiber: options.fiber,
|
|
3392
|
+
handle: options.handle,
|
|
3393
|
+
drei: options.drei,
|
|
3394
|
+
koota: options.koota,
|
|
3395
|
+
leva: options.leva,
|
|
3396
|
+
offscreen: options.offscreen,
|
|
3397
|
+
postprocessing: options.postprocessing,
|
|
3398
|
+
rapier: options.rapier,
|
|
3399
|
+
triplex: options.triplex,
|
|
3400
|
+
viverse: options.viverse,
|
|
3401
|
+
uikit: options.uikit,
|
|
3402
|
+
xr: options.xr,
|
|
3403
|
+
zustand: options.zustand,
|
|
3404
|
+
githubPages: options.githubPages
|
|
3405
|
+
},
|
|
3406
|
+
context: {
|
|
3407
|
+
dependencies: options.dependencies,
|
|
3408
|
+
engine: options.engine,
|
|
3409
|
+
files: options.files,
|
|
3410
|
+
injections: options.injections,
|
|
3411
|
+
replacements: options.replacements,
|
|
3412
|
+
versions: options.versions,
|
|
3413
|
+
workspaceRoot: options.workspaceRoot,
|
|
3414
|
+
workspaceDependencies: options.workspaceDependencies
|
|
3022
3415
|
}
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3416
|
+
};
|
|
3417
|
+
}
|
|
3418
|
+
function projectPlanInputToOptions(input) {
|
|
3419
|
+
return {
|
|
3420
|
+
...input.project,
|
|
3421
|
+
aiPlatforms: input.aiAgents.config.platforms.length > 0 ? input.aiAgents.config.platforms : void 0,
|
|
3422
|
+
formatter: input.formatter.tool,
|
|
3423
|
+
linter: input.linter.tool,
|
|
3424
|
+
testing: input.testing.tool,
|
|
3425
|
+
configStrategy: input.typescript.config.configStrategy,
|
|
3426
|
+
ide: input.ide.tool,
|
|
3427
|
+
packageManager: packageManagerSpecFromInput(input.packageManager),
|
|
3428
|
+
pnpmManageVersions: input.packageManager.config.pnpmManageVersions,
|
|
3429
|
+
libraryBundler: input.libraryBundler.tool,
|
|
3430
|
+
...input.features,
|
|
3431
|
+
dependencies: input.context.dependencies,
|
|
3432
|
+
engine: input.context.engine,
|
|
3433
|
+
files: input.context.files,
|
|
3434
|
+
injections: input.context.injections,
|
|
3435
|
+
replacements: input.context.replacements,
|
|
3436
|
+
versions: input.context.versions,
|
|
3437
|
+
workspaceRoot: input.context.workspaceRoot,
|
|
3438
|
+
workspaceDependencies: input.context.workspaceDependencies
|
|
3439
|
+
};
|
|
3440
|
+
}
|
|
3441
|
+
function resolveWorkspacePlanInput(params) {
|
|
3442
|
+
return {
|
|
3443
|
+
project: {
|
|
3444
|
+
name: params.name
|
|
3445
|
+
},
|
|
3446
|
+
aiAgents: {
|
|
3447
|
+
tool: "ai-agents",
|
|
3448
|
+
config: {
|
|
3449
|
+
platforms: params.aiPlatforms ?? []
|
|
3450
|
+
}
|
|
3451
|
+
},
|
|
3452
|
+
formatter: {
|
|
3453
|
+
tool: params.formatter,
|
|
3454
|
+
config: structuredClone(defaultFormatterMetaConfig)
|
|
3455
|
+
},
|
|
3456
|
+
linter: {
|
|
3457
|
+
tool: params.linter,
|
|
3458
|
+
config: structuredClone(defaultLinterMetaConfig)
|
|
3459
|
+
},
|
|
3460
|
+
ide: {
|
|
3461
|
+
tool: params.ide ?? "vscode",
|
|
3462
|
+
config: {}
|
|
3463
|
+
},
|
|
3464
|
+
packageManager: {
|
|
3465
|
+
tool: params.packageManager.name,
|
|
3466
|
+
config: {
|
|
3467
|
+
version: params.packageManager.version,
|
|
3468
|
+
pnpmManageVersions: params.pnpmManageVersions
|
|
3469
|
+
}
|
|
3470
|
+
},
|
|
3471
|
+
context: {
|
|
3472
|
+
engine: params.engine,
|
|
3473
|
+
pnpmManageVersions: params.pnpmManageVersions,
|
|
3474
|
+
versions: params.versions
|
|
3026
3475
|
}
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
return
|
|
3476
|
+
};
|
|
3477
|
+
}
|
|
3478
|
+
function workspacePlanInputToMonorepoParams(input) {
|
|
3479
|
+
return {
|
|
3480
|
+
name: input.project.name,
|
|
3481
|
+
linter: input.linter.tool,
|
|
3482
|
+
formatter: input.formatter.tool,
|
|
3483
|
+
packageManager: packageManagerSpecFromInput(input.packageManager),
|
|
3484
|
+
pnpmManageVersions: input.context.pnpmManageVersions,
|
|
3485
|
+
engine: input.context.engine,
|
|
3486
|
+
versions: input.context.versions,
|
|
3487
|
+
aiPlatforms: input.aiAgents.config.platforms.length > 0 ? input.aiAgents.config.platforms : void 0,
|
|
3488
|
+
ide: input.ide.tool
|
|
3489
|
+
};
|
|
3490
|
+
}
|
|
3491
|
+
function isProjectPlanInput(input) {
|
|
3492
|
+
return "project" in input && "formatter" in input && typeof input.formatter === "object";
|
|
3493
|
+
}
|
|
3494
|
+
function isWorkspacePlanInput(input) {
|
|
3495
|
+
return "project" in input && "formatter" in input && typeof input.formatter === "object";
|
|
3496
|
+
}
|
|
3497
|
+
function packageManagerSpecFromInput(packageManager) {
|
|
3498
|
+
return {
|
|
3499
|
+
name: packageManager.tool,
|
|
3500
|
+
version: packageManager.config.version
|
|
3501
|
+
};
|
|
3502
|
+
}
|
|
3503
|
+
|
|
3504
|
+
async function resolveProjectFacts(input) {
|
|
3505
|
+
const options = projectPlanInputToOptions(input);
|
|
3506
|
+
options.packageManager = await resolvePackageManager(options);
|
|
3507
|
+
options.engine = await resolveEngine(options);
|
|
3508
|
+
options.versions = await resolveProjectPackageVersions(options);
|
|
3509
|
+
return resolveProjectPlanInput(options);
|
|
3510
|
+
}
|
|
3511
|
+
async function resolveWorkspaceFacts(input) {
|
|
3512
|
+
const params = workspacePlanInputToMonorepoParams(input);
|
|
3513
|
+
const options = {
|
|
3514
|
+
name: params.name,
|
|
3515
|
+
linter: params.linter,
|
|
3516
|
+
formatter: params.formatter,
|
|
3517
|
+
packageManager: params.packageManager,
|
|
3518
|
+
engine: params.engine,
|
|
3519
|
+
pnpmManageVersions: params.pnpmManageVersions,
|
|
3520
|
+
versions: params.versions
|
|
3521
|
+
};
|
|
3522
|
+
const packageManager = await resolvePackageManager(options);
|
|
3523
|
+
const engine = await resolveEngine(options);
|
|
3524
|
+
const versions = await resolveMonorepoRootPackageVersions({
|
|
3525
|
+
linter: params.linter,
|
|
3526
|
+
formatter: params.formatter,
|
|
3527
|
+
engine,
|
|
3528
|
+
versions: params.versions
|
|
3529
|
+
});
|
|
3530
|
+
return resolveWorkspacePlanInput({
|
|
3531
|
+
...params,
|
|
3532
|
+
packageManager,
|
|
3533
|
+
engine,
|
|
3534
|
+
versions
|
|
3535
|
+
});
|
|
3031
3536
|
}
|
|
3032
3537
|
|
|
3033
|
-
function
|
|
3538
|
+
async function planProject(input) {
|
|
3539
|
+
const planInput = isProjectPlanInput(input) ? input : resolveProjectPlanInput(input);
|
|
3540
|
+
return createProjectPlan(await resolveProjectFacts(planInput));
|
|
3541
|
+
}
|
|
3542
|
+
function createProjectPlan(planInput) {
|
|
3543
|
+
const options = projectPlanInputToOptions(planInput);
|
|
3034
3544
|
const clonedOptions = structuredClone(options);
|
|
3035
3545
|
const template = clonedOptions.template ?? "vanilla";
|
|
3036
3546
|
const baseTemplate = getBaseTemplate(template);
|
|
@@ -3039,7 +3549,8 @@ function generate(options) {
|
|
|
3039
3549
|
const isReact = baseTemplate === "react";
|
|
3040
3550
|
const isR3f = baseTemplate === "r3f";
|
|
3041
3551
|
const isLibrary = clonedOptions.projectType === "library";
|
|
3042
|
-
const libraryBundler =
|
|
3552
|
+
const libraryBundler = planInput.libraryBundler.tool;
|
|
3553
|
+
const ide = planInput.ide.tool;
|
|
3043
3554
|
const files = {
|
|
3044
3555
|
...clonedOptions.files
|
|
3045
3556
|
};
|
|
@@ -3073,7 +3584,7 @@ function generate(options) {
|
|
|
3073
3584
|
}
|
|
3074
3585
|
}
|
|
3075
3586
|
if (language === "typescript") {
|
|
3076
|
-
const tsResult =
|
|
3587
|
+
const tsResult = renderTypescriptConfig({
|
|
3077
3588
|
baseTemplate,
|
|
3078
3589
|
useConfigPackage: clonedOptions.workspaceRoot != null,
|
|
3079
3590
|
configStrategy: clonedOptions.configStrategy,
|
|
@@ -3085,10 +3596,7 @@ function generate(options) {
|
|
|
3085
3596
|
}
|
|
3086
3597
|
const codeSnippets = {};
|
|
3087
3598
|
const vscodeSettings = {};
|
|
3088
|
-
const scripts =
|
|
3089
|
-
dev: "vite",
|
|
3090
|
-
build: "vite build"
|
|
3091
|
-
};
|
|
3599
|
+
const scripts = {};
|
|
3092
3600
|
if (!isLibrary && (isReact || isR3f)) {
|
|
3093
3601
|
codeSnippets["vite-config-import"] = ["import react from '@vitejs/plugin-react'"];
|
|
3094
3602
|
}
|
|
@@ -3107,7 +3615,7 @@ function generate(options) {
|
|
|
3107
3615
|
viteConfig.resolve = { dedupe: ["three"] };
|
|
3108
3616
|
}
|
|
3109
3617
|
const isMonorepoPackage = clonedOptions.workspaceRoot != null;
|
|
3110
|
-
const
|
|
3618
|
+
const builder = {
|
|
3111
3619
|
options: clonedOptions,
|
|
3112
3620
|
versions,
|
|
3113
3621
|
getVersion(name2) {
|
|
@@ -3137,8 +3645,11 @@ function generate(options) {
|
|
|
3137
3645
|
addFile(path, content) {
|
|
3138
3646
|
files[path] = content;
|
|
3139
3647
|
},
|
|
3648
|
+
addScripts(nextScripts) {
|
|
3649
|
+
Object.assign(scripts, nextScripts);
|
|
3650
|
+
},
|
|
3140
3651
|
addScript(name2, command) {
|
|
3141
|
-
|
|
3652
|
+
this.addScripts({ [name2]: command });
|
|
3142
3653
|
},
|
|
3143
3654
|
inject(location, code) {
|
|
3144
3655
|
let entries = codeSnippets[location];
|
|
@@ -3158,71 +3669,61 @@ function generate(options) {
|
|
|
3158
3669
|
}
|
|
3159
3670
|
};
|
|
3160
3671
|
if (isR3f) {
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3672
|
+
planDrei(builder, planInput.features.drei);
|
|
3673
|
+
planHandle(builder, planInput.features.handle);
|
|
3674
|
+
planKoota(builder, planInput.features.koota);
|
|
3675
|
+
planLeva(builder, planInput.features.leva);
|
|
3676
|
+
planOffscreen(builder, planInput.features.offscreen);
|
|
3677
|
+
planPostprocessing(builder, planInput.features.postprocessing);
|
|
3678
|
+
planRapier(builder, planInput.features.rapier);
|
|
3679
|
+
planUikit(builder, planInput.features.uikit);
|
|
3680
|
+
planXr(builder, planInput.features.xr);
|
|
3681
|
+
planZustand(builder, planInput.features.zustand);
|
|
3682
|
+
planFiber(builder, planInput.features.fiber);
|
|
3683
|
+
planTriplex(builder, planInput.features.triplex);
|
|
3684
|
+
planViverse(builder, planInput.features.viverse);
|
|
3174
3685
|
}
|
|
3175
3686
|
if (!isLibrary) {
|
|
3176
|
-
|
|
3687
|
+
planGithubPages(builder, planInput.features.githubPages);
|
|
3177
3688
|
}
|
|
3178
3689
|
if (isLibrary) {
|
|
3179
3690
|
if (libraryBundler === "unbuild") {
|
|
3180
|
-
|
|
3691
|
+
planUnbuild(builder);
|
|
3181
3692
|
} else if (libraryBundler === "tsdown") {
|
|
3182
|
-
|
|
3693
|
+
planTsdown(builder);
|
|
3183
3694
|
}
|
|
3184
|
-
const packageManager2 = getPackageManagerName(clonedOptions.packageManager);
|
|
3185
|
-
generator.addScript("release", `${packageManager2} run build && ${packageManager2} publish`);
|
|
3186
3695
|
}
|
|
3187
|
-
const testing =
|
|
3696
|
+
const testing = planInput.testing.tool;
|
|
3188
3697
|
if (testing === "vitest") {
|
|
3189
|
-
|
|
3190
|
-
}
|
|
3191
|
-
const linter =
|
|
3192
|
-
const formatter =
|
|
3193
|
-
if (linter === "eslint") {
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
} else if (linter === "
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
} else if (linter === "biome") {
|
|
3202
|
-
generateBiome(generator, {
|
|
3203
|
-
linter: true,
|
|
3204
|
-
formatter: formatter === "biome"
|
|
3698
|
+
planVitest(builder, planInput.testing);
|
|
3699
|
+
}
|
|
3700
|
+
const linter = planInput.linter.tool;
|
|
3701
|
+
const formatter = planInput.formatter.tool;
|
|
3702
|
+
if (planInput.linter.tool === "eslint") {
|
|
3703
|
+
planEslint(builder, planInput.linter);
|
|
3704
|
+
} else if (planInput.linter.tool === "oxlint") {
|
|
3705
|
+
planOxlint(builder, planInput.linter);
|
|
3706
|
+
} else if (planInput.linter.tool === "biome") {
|
|
3707
|
+
planBiome(builder, {
|
|
3708
|
+
linter: planInput.linter,
|
|
3709
|
+
formatter: planInput.formatter.tool === "biome" ? planInput.formatter : void 0
|
|
3205
3710
|
});
|
|
3206
|
-
generator.addVscodeSetting("eslint.enable", false);
|
|
3207
|
-
generator.addVscodeSetting("oxc.enable", false);
|
|
3208
3711
|
}
|
|
3209
|
-
if (formatter === "prettier") {
|
|
3210
|
-
|
|
3211
|
-
} else if (formatter === "oxfmt") {
|
|
3212
|
-
|
|
3213
|
-
} else if (formatter === "biome" && linter !== "biome") {
|
|
3214
|
-
|
|
3215
|
-
generator.addVscodeSetting("eslint.enable", false);
|
|
3216
|
-
generator.addVscodeSetting("oxc.enable", false);
|
|
3712
|
+
if (planInput.formatter.tool === "prettier") {
|
|
3713
|
+
planPrettier(builder, planInput.formatter);
|
|
3714
|
+
} else if (planInput.formatter.tool === "oxfmt") {
|
|
3715
|
+
planOxfmt(builder, planInput.formatter);
|
|
3716
|
+
} else if (planInput.formatter.tool === "biome" && planInput.linter.tool !== "biome") {
|
|
3717
|
+
planBiome(builder, { formatter: planInput.formatter });
|
|
3217
3718
|
}
|
|
3218
3719
|
for (const { code, location } of clonedOptions.injections ?? []) {
|
|
3219
|
-
|
|
3720
|
+
builder.inject(location, code);
|
|
3220
3721
|
}
|
|
3221
3722
|
if (!isLibrary) {
|
|
3222
|
-
files["vite.config.ts"] =
|
|
3723
|
+
files["vite.config.ts"] = renderViteConfig({ viteConfig, codeSnippets });
|
|
3223
3724
|
}
|
|
3224
3725
|
const packageManager = getPackageManagerName(options.packageManager);
|
|
3225
|
-
files["README.md"] =
|
|
3726
|
+
files["README.md"] = renderReadme({
|
|
3226
3727
|
name,
|
|
3227
3728
|
baseTemplate,
|
|
3228
3729
|
isLibrary,
|
|
@@ -3232,7 +3733,7 @@ function generate(options) {
|
|
|
3232
3733
|
});
|
|
3233
3734
|
Object.assign(
|
|
3234
3735
|
files,
|
|
3235
|
-
|
|
3736
|
+
renderSourceFiles({
|
|
3236
3737
|
name,
|
|
3237
3738
|
baseTemplate,
|
|
3238
3739
|
language,
|
|
@@ -3244,7 +3745,7 @@ function generate(options) {
|
|
|
3244
3745
|
if (testing === "vitest") {
|
|
3245
3746
|
Object.assign(
|
|
3246
3747
|
files,
|
|
3247
|
-
|
|
3748
|
+
renderTestFiles({
|
|
3248
3749
|
baseTemplate,
|
|
3249
3750
|
language,
|
|
3250
3751
|
isLibrary
|
|
@@ -3253,7 +3754,7 @@ function generate(options) {
|
|
|
3253
3754
|
}
|
|
3254
3755
|
Object.assign(
|
|
3255
3756
|
files,
|
|
3256
|
-
|
|
3757
|
+
renderPackageJson({
|
|
3257
3758
|
name,
|
|
3258
3759
|
language,
|
|
3259
3760
|
isLibrary,
|
|
@@ -3265,25 +3766,54 @@ function generate(options) {
|
|
|
3265
3766
|
workspaceDependencies: clonedOptions.workspaceDependencies
|
|
3266
3767
|
}).files
|
|
3267
3768
|
);
|
|
3268
|
-
if (!isMonorepoPackage) {
|
|
3269
|
-
Object.assign(
|
|
3769
|
+
if (!isMonorepoPackage && ide === "vscode") {
|
|
3770
|
+
Object.assign(
|
|
3771
|
+
files,
|
|
3772
|
+
renderVscodeFiles$1({
|
|
3773
|
+
codeSnippets,
|
|
3774
|
+
vscodeSettings,
|
|
3775
|
+
linter,
|
|
3776
|
+
formatter,
|
|
3777
|
+
configStrategy: clonedOptions.configStrategy,
|
|
3778
|
+
isMonorepo: false,
|
|
3779
|
+
packageManager
|
|
3780
|
+
})
|
|
3781
|
+
);
|
|
3270
3782
|
}
|
|
3271
3783
|
if (!isMonorepoPackage) {
|
|
3272
|
-
files[".
|
|
3273
|
-
files[".
|
|
3784
|
+
files[".editorconfig"] = renderEditorConfig();
|
|
3785
|
+
files[".gitignore"] = renderGitignore("standalone");
|
|
3786
|
+
files[".gitattributes"] = { type: "text", content: gitAttributesContent };
|
|
3274
3787
|
}
|
|
3275
|
-
if (!isMonorepoPackage &&
|
|
3276
|
-
|
|
3788
|
+
if (!isMonorepoPackage && planInput.aiAgents.config.platforms.length > 0) {
|
|
3789
|
+
renderAiFiles(files, {
|
|
3277
3790
|
name,
|
|
3278
3791
|
packageManager: getPackageManagerName(clonedOptions.packageManager),
|
|
3279
3792
|
linter: clonedOptions.linter ?? "oxlint",
|
|
3280
3793
|
formatter: clonedOptions.formatter ?? "prettier",
|
|
3281
3794
|
isMonorepo: false,
|
|
3282
3795
|
configStrategy: clonedOptions.configStrategy,
|
|
3283
|
-
|
|
3796
|
+
hasTypecheck: language === "typescript",
|
|
3797
|
+
platforms: planInput.aiAgents.config.platforms
|
|
3284
3798
|
});
|
|
3285
3799
|
}
|
|
3286
|
-
return
|
|
3800
|
+
return {
|
|
3801
|
+
files,
|
|
3802
|
+
dependencies,
|
|
3803
|
+
devDependencies,
|
|
3804
|
+
peerDependencies,
|
|
3805
|
+
scripts,
|
|
3806
|
+
vscodeSettings,
|
|
3807
|
+
vscodeExtensions: [...new Set(codeSnippets["vscode-extension-suggestion"] ?? [])],
|
|
3808
|
+
injections: Object.entries(codeSnippets).flatMap(
|
|
3809
|
+
([location, entries]) => (entries ?? []).map((code) => ({
|
|
3810
|
+
location,
|
|
3811
|
+
code
|
|
3812
|
+
}))
|
|
3813
|
+
),
|
|
3814
|
+
replacements,
|
|
3815
|
+
warnings: []
|
|
3816
|
+
};
|
|
3287
3817
|
}
|
|
3288
3818
|
function resolveDependencySemver(name, versions, options = {}) {
|
|
3289
3819
|
if (options.version != null) {
|
|
@@ -3292,4 +3822,22 @@ function resolveDependencySemver(name, versions, options = {}) {
|
|
|
3292
3822
|
return formatResolvedPackageVersion(versions, name, options.prefix);
|
|
3293
3823
|
}
|
|
3294
3824
|
|
|
3295
|
-
|
|
3825
|
+
async function planWorkspace(input) {
|
|
3826
|
+
const planInput = isWorkspacePlanInput(input) ? input : resolveWorkspacePlanInput(input);
|
|
3827
|
+
const resolvedInput = await resolveWorkspaceFacts(planInput);
|
|
3828
|
+
const { files } = renderMonorepo(workspacePlanInputToMonorepoParams(resolvedInput));
|
|
3829
|
+
return {
|
|
3830
|
+
files,
|
|
3831
|
+
dependencies: {},
|
|
3832
|
+
devDependencies: {},
|
|
3833
|
+
peerDependencies: {},
|
|
3834
|
+
scripts: {},
|
|
3835
|
+
vscodeSettings: {},
|
|
3836
|
+
vscodeExtensions: [],
|
|
3837
|
+
injections: [],
|
|
3838
|
+
replacements: [],
|
|
3839
|
+
warnings: []
|
|
3840
|
+
};
|
|
3841
|
+
}
|
|
3842
|
+
|
|
3843
|
+
export { ALL_AI_PLATFORMS as A, renderTypescriptConfigPackage as B, renderOxlintConfigPackage as C, renderEslintConfigPackage as D, renderOxfmtConfigPackage as E, renderPrettierConfigPackage as F, resolveMonorepoRootPackageVersions as G, getResolvedPackageVersion as H, renderVscodeFiles as I, renderAiFiles as J, renderVscodeFiles$1 as K, renderEditorConfig as L, renderGitignore as M, toPrettierIgnoreContent as N, mergePackageJsonScripts as O, packageJsonScripts as P, resolveDefaultPackageJsonScripts as Q, formatResolvedPackageVersion as R, renderOxlintConfig as S, getBaseTemplate as a, getLanguageFromTemplate as b, getLatestNodeVersion as c, detectTooling as d, getLatestNpmCliVersion as e, getLatestNpmMajorVersion as f, generateRandomName as g, getLatestNpmVersion as h, getLatestPnpmVersion as i, getLatestYarnVersion as j, planProject as k, planWorkspace as l, merge as m, projectPlanInputToOptions as n, resolveWorkspacePlanInput as o, parseWorkspaceYamlContent as p, getEngineName as q, resolveProjectPlanInput as r, getPackageManagerName as s, AI_PLATFORM_LABELS as t, unique as u, validatePackageName as v, workspacePlanInputToMonorepoParams as w, AI_PLATFORM_HINTS as x, parsePackageManager as y, parseEngine as z };
|