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
|
@@ -9,62 +9,7 @@ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'defau
|
|
|
9
9
|
|
|
10
10
|
const color__default = /*#__PURE__*/_interopDefaultCompat(color);
|
|
11
11
|
|
|
12
|
-
const
|
|
13
|
-
<html lang="en">
|
|
14
|
-
<head>
|
|
15
|
-
<meta charset="UTF-8">
|
|
16
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
17
|
-
<title>$title</title>
|
|
18
|
-
</head>
|
|
19
|
-
<body style="margin: 0; overscroll-behavior: none; user-select: none; touch-action: none;">
|
|
20
|
-
<script type="module" src="$indexPath"><\/script>
|
|
21
|
-
<div style="width: 100dvw; height: 100dvh; overflow: hidden;" id="root"></div>
|
|
22
|
-
</body>
|
|
23
|
-
</html>`;
|
|
24
|
-
const ViteHtmlContent = `<!DOCTYPE html>
|
|
25
|
-
<html lang="en">
|
|
26
|
-
<head>
|
|
27
|
-
<meta charset="UTF-8">
|
|
28
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
29
|
-
<title>$title</title>
|
|
30
|
-
</head>
|
|
31
|
-
<body>
|
|
32
|
-
<div id="app"></div>
|
|
33
|
-
<script type="module" src="$indexPath"><\/script>
|
|
34
|
-
</body>
|
|
35
|
-
</html>`;
|
|
36
|
-
const IndexContent = `import { StrictMode } from 'react'
|
|
37
|
-
import { createRoot } from 'react-dom/client'
|
|
38
|
-
import { App } from './app.js'
|
|
39
|
-
|
|
40
|
-
createRoot(document.getElementById('root')!).render(
|
|
41
|
-
<StrictMode>
|
|
42
|
-
<App />
|
|
43
|
-
</StrictMode>,
|
|
44
|
-
)`;
|
|
45
|
-
const ViteIndexContent = `import './style.css'
|
|
46
|
-
|
|
47
|
-
document.querySelector('#app')!.innerHTML = \`
|
|
48
|
-
<h1>Hello Vite!</h1>
|
|
49
|
-
<p>Edit src/main.ts and save to see HMR in action.</p>
|
|
50
|
-
\``;
|
|
51
|
-
const ViteStyleContent = `body {
|
|
52
|
-
font-family: system-ui, -apple-system, sans-serif;
|
|
53
|
-
margin: 0;
|
|
54
|
-
padding: 2rem;
|
|
55
|
-
min-height: 100vh;
|
|
56
|
-
background: #1a1a1a;
|
|
57
|
-
color: #fff;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
h1 {
|
|
61
|
-
color: #646cff;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
a {
|
|
65
|
-
color: #646cff;
|
|
66
|
-
}`;
|
|
67
|
-
const GitAttributes = [
|
|
12
|
+
const gitAttributesContent = [
|
|
68
13
|
"* text eol=lf",
|
|
69
14
|
"*.png binary",
|
|
70
15
|
"*.jpg binary",
|
|
@@ -89,55 +34,6 @@ const GitAttributes = [
|
|
|
89
34
|
"*.glb binary",
|
|
90
35
|
"*.gltf binary"
|
|
91
36
|
].join("\n");
|
|
92
|
-
const defaultFormatterConfig = {
|
|
93
|
-
printWidth: 102,
|
|
94
|
-
tabWidth: 2,
|
|
95
|
-
useTabs: false,
|
|
96
|
-
semi: true,
|
|
97
|
-
singleQuote: true,
|
|
98
|
-
trailingComma: "es5",
|
|
99
|
-
bracketSpacing: true,
|
|
100
|
-
arrowParens: "always"
|
|
101
|
-
};
|
|
102
|
-
const defaultPrettierConfig = {
|
|
103
|
-
$schema: "https://json.schemastore.org/prettierrc",
|
|
104
|
-
...defaultFormatterConfig,
|
|
105
|
-
overrides: [
|
|
106
|
-
{
|
|
107
|
-
files: ["*.md", "**/*.md"],
|
|
108
|
-
options: { semi: false }
|
|
109
|
-
},
|
|
110
|
-
{
|
|
111
|
-
files: ["*.yml", "*.yaml", "**/*.yml", "**/*.yaml"],
|
|
112
|
-
options: { semi: false }
|
|
113
|
-
}
|
|
114
|
-
]
|
|
115
|
-
};
|
|
116
|
-
const defaultOxfmtConfig = {
|
|
117
|
-
printWidth: defaultFormatterConfig.printWidth,
|
|
118
|
-
tabWidth: defaultFormatterConfig.tabWidth,
|
|
119
|
-
useTabs: defaultFormatterConfig.useTabs,
|
|
120
|
-
semi: defaultFormatterConfig.semi,
|
|
121
|
-
singleQuote: defaultFormatterConfig.singleQuote,
|
|
122
|
-
trailingComma: defaultFormatterConfig.trailingComma,
|
|
123
|
-
bracketSpacing: defaultFormatterConfig.bracketSpacing,
|
|
124
|
-
arrowParens: defaultFormatterConfig.arrowParens
|
|
125
|
-
};
|
|
126
|
-
const defaultLinterConfig = {
|
|
127
|
-
ignorePatterns: ["dist"],
|
|
128
|
-
rules: {
|
|
129
|
-
noUnusedVars: {
|
|
130
|
-
level: "warn",
|
|
131
|
-
argsIgnorePattern: "^_",
|
|
132
|
-
varsIgnorePattern: "^_",
|
|
133
|
-
caughtErrorsIgnorePattern: "^_"
|
|
134
|
-
},
|
|
135
|
-
noUnusedExpressions: {
|
|
136
|
-
level: "warn",
|
|
137
|
-
allowShortCircuit: true
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
};
|
|
141
37
|
|
|
142
38
|
const ALL_AI_PLATFORMS = ["agents", "claude"];
|
|
143
39
|
const AI_PLATFORM_LABELS = {
|
|
@@ -148,12 +44,15 @@ const AI_PLATFORM_HINTS = {
|
|
|
148
44
|
agents: "OpenAI, Cursor, Windsurf, etc.",
|
|
149
45
|
claude: "Claude Code"
|
|
150
46
|
};
|
|
151
|
-
function
|
|
152
|
-
const { platforms, isMonorepo, configStrategy, ...rest } = params;
|
|
47
|
+
function renderAiFiles(files, params) {
|
|
48
|
+
const { platforms, isMonorepo, configStrategy, hasTypecheck, ...rest } = params;
|
|
153
49
|
if (platforms.length === 0) return;
|
|
154
50
|
const content = generateWorkspace({
|
|
155
51
|
...rest,
|
|
156
|
-
isMonorepo: !!isMonorepo
|
|
52
|
+
isMonorepo: !!isMonorepo,
|
|
53
|
+
configStrategy: configStrategy ?? "stealth",
|
|
54
|
+
hasTypecheck: hasTypecheck ?? false
|
|
55
|
+
});
|
|
157
56
|
const pointer = "See [`AGENTS.md`](./Agents.md) for agent context.\n";
|
|
158
57
|
const hasAgents = platforms.includes("agents");
|
|
159
58
|
const hasClaude = platforms.includes("claude");
|
|
@@ -168,31 +67,115 @@ function generateAiFiles(files, params) {
|
|
|
168
67
|
}
|
|
169
68
|
}
|
|
170
69
|
function generateWorkspace(ctx) {
|
|
171
|
-
const {
|
|
70
|
+
const { packageManager, linter, formatter, hasTypecheck } = ctx;
|
|
71
|
+
const exampleFiles = "src/App.tsx src/core/systems/move-entity.ts";
|
|
72
|
+
const commands = getAfterEditingCommands(ctx, exampleFiles);
|
|
172
73
|
const sections = [
|
|
173
|
-
|
|
74
|
+
"# Workspace Tools",
|
|
174
75
|
"",
|
|
175
|
-
`- **Type:** ${isMonorepo ? "pnpm monorepo" : "standalone project"}`,
|
|
176
76
|
`- **Package Manager:** ${packageManager}`,
|
|
177
77
|
`- **Linter:** ${linter}`,
|
|
178
78
|
`- **Formatter:** ${formatter}`,
|
|
179
79
|
"",
|
|
180
|
-
"##
|
|
181
|
-
""
|
|
182
|
-
`- \`${packageManager} test\` \u2014 run tests`,
|
|
183
|
-
`- \`${packageManager} build\` \u2014 build`,
|
|
184
|
-
`- \`${packageManager} lint\` and \`${packageManager} format\` \u2014 run before committing`
|
|
80
|
+
"## After Editing",
|
|
81
|
+
""
|
|
185
82
|
];
|
|
186
|
-
if (
|
|
83
|
+
if (hasTypecheck) {
|
|
187
84
|
sections.push(
|
|
188
|
-
""
|
|
189
|
-
|
|
190
|
-
|
|
85
|
+
"\u2705 After editing files, check the types for errors and then format and lint only the files changed for the current task."
|
|
86
|
+
);
|
|
87
|
+
} else {
|
|
88
|
+
sections.push(
|
|
89
|
+
"\u2705 After editing files, format and lint only the files changed for the current task."
|
|
191
90
|
);
|
|
192
91
|
}
|
|
193
|
-
sections.push("");
|
|
92
|
+
sections.push("", "```sh", "# Example");
|
|
93
|
+
if (hasTypecheck) {
|
|
94
|
+
sections.push(runScript(packageManager, "typecheck"));
|
|
95
|
+
}
|
|
96
|
+
sections.push(
|
|
97
|
+
"# Run format and lint for only files modified",
|
|
98
|
+
commands.format,
|
|
99
|
+
commands.lint,
|
|
100
|
+
"```",
|
|
101
|
+
"",
|
|
102
|
+
"\u274C Avoid unless explicitly approved:",
|
|
103
|
+
"",
|
|
104
|
+
"```sh",
|
|
105
|
+
runScript(packageManager, "format"),
|
|
106
|
+
runScript(packageManager, "lint"),
|
|
107
|
+
"```",
|
|
108
|
+
""
|
|
109
|
+
);
|
|
194
110
|
return sections.join("\n");
|
|
195
111
|
}
|
|
112
|
+
function getAfterEditingCommands(ctx, files) {
|
|
113
|
+
return {
|
|
114
|
+
format: getFormatChangedFilesCommand(ctx, files),
|
|
115
|
+
lint: getLintChangedFilesCommand(ctx, files)
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
function getFormatChangedFilesCommand(ctx, files) {
|
|
119
|
+
const exec = getExecCommand(ctx.packageManager);
|
|
120
|
+
if (ctx.formatter === "prettier") {
|
|
121
|
+
const configPath = getPrettierConfigPath(ctx);
|
|
122
|
+
const ignorePath = getPrettierIgnorePath(ctx);
|
|
123
|
+
const configFlag2 = configPath == null ? "" : ` --config ${configPath}`;
|
|
124
|
+
const ignoreFlag = ignorePath == null ? "" : ` --ignore-path ${ignorePath}`;
|
|
125
|
+
return `${exec} prettier${configFlag2}${ignoreFlag} --write ${files}`;
|
|
126
|
+
}
|
|
127
|
+
if (ctx.formatter === "oxfmt") {
|
|
128
|
+
const configPath = getOxfmtConfigPath(ctx);
|
|
129
|
+
return `${exec} oxfmt -c ${configPath} --write ${files}`;
|
|
130
|
+
}
|
|
131
|
+
const configFlag = ctx.isMonorepo || ctx.configStrategy === "root" ? "" : " --config-path .config";
|
|
132
|
+
return `${exec} biome format${configFlag} --write ${files}`;
|
|
133
|
+
}
|
|
134
|
+
function getLintChangedFilesCommand(ctx, files) {
|
|
135
|
+
const exec = getExecCommand(ctx.packageManager);
|
|
136
|
+
if (ctx.linter === "oxlint") {
|
|
137
|
+
if (!ctx.isMonorepo) {
|
|
138
|
+
return runScript(ctx.packageManager, "lint", files);
|
|
139
|
+
}
|
|
140
|
+
return `${exec} oxlint ${files}`;
|
|
141
|
+
}
|
|
142
|
+
if (ctx.linter === "eslint") {
|
|
143
|
+
const configFlag2 = ctx.configStrategy === "stealth" ? " --config .config/eslint.config.js" : "";
|
|
144
|
+
return `${exec} eslint${configFlag2} ${files}`;
|
|
145
|
+
}
|
|
146
|
+
const configFlag = ctx.isMonorepo || ctx.configStrategy === "root" ? "" : " --config-path .config";
|
|
147
|
+
return `${exec} biome lint${configFlag} ${files}`;
|
|
148
|
+
}
|
|
149
|
+
function getPrettierConfigPath(ctx) {
|
|
150
|
+
if (ctx.isMonorepo) return ".config/prettier/base.json";
|
|
151
|
+
if (ctx.configStrategy === "stealth") return ".config/prettier.json";
|
|
152
|
+
return void 0;
|
|
153
|
+
}
|
|
154
|
+
function getPrettierIgnorePath(ctx) {
|
|
155
|
+
if (ctx.isMonorepo) return ".config/prettier/prettierignore";
|
|
156
|
+
if (ctx.configStrategy === "stealth") return ".config/prettierignore";
|
|
157
|
+
return void 0;
|
|
158
|
+
}
|
|
159
|
+
function getOxfmtConfigPath(ctx) {
|
|
160
|
+
if (ctx.isMonorepo) return ".config/oxfmt/base.json";
|
|
161
|
+
if (ctx.configStrategy === "stealth") return ".config/oxfmt.json";
|
|
162
|
+
return "oxfmt.json";
|
|
163
|
+
}
|
|
164
|
+
function runScript(packageManager, script, args) {
|
|
165
|
+
const suffix = args == null ? "" : ` ${args}`;
|
|
166
|
+
if (packageManager === "npm") {
|
|
167
|
+
return `npm run ${script}${args == null ? "" : ` --${suffix}`}`;
|
|
168
|
+
}
|
|
169
|
+
if (packageManager === "yarn") {
|
|
170
|
+
return `yarn ${script}${suffix}`;
|
|
171
|
+
}
|
|
172
|
+
return `${packageManager} ${script}${args == null ? "" : ` --${suffix}`}`;
|
|
173
|
+
}
|
|
174
|
+
function getExecCommand(packageManager) {
|
|
175
|
+
if (packageManager === "npm") return "npm exec --";
|
|
176
|
+
if (packageManager === "yarn") return "yarn exec";
|
|
177
|
+
return `${packageManager} exec`;
|
|
178
|
+
}
|
|
196
179
|
|
|
197
180
|
function getLanguageFromTemplate(template) {
|
|
198
181
|
return template.endsWith("-js") ? "javascript" : "typescript";
|
|
@@ -201,59 +184,51 @@ function getBaseTemplate(template) {
|
|
|
201
184
|
return template.replace("-js", "");
|
|
202
185
|
}
|
|
203
186
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
const
|
|
208
|
-
|
|
209
|
-
} catch {
|
|
210
|
-
return fallback;
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
function compareNumericSemver(a, b) {
|
|
214
|
-
const aParts = a.split(".").map((part) => Number.parseInt(part, 10) || 0);
|
|
215
|
-
const bParts = b.split(".").map((part) => Number.parseInt(part, 10) || 0);
|
|
216
|
-
const maxLength = Math.max(aParts.length, bParts.length);
|
|
217
|
-
for (let index = 0; index < maxLength; index += 1) {
|
|
218
|
-
const difference = (aParts[index] ?? 0) - (bParts[index] ?? 0);
|
|
219
|
-
if (difference !== 0) {
|
|
220
|
-
return difference;
|
|
187
|
+
function unique(...array) {
|
|
188
|
+
const set = /* @__PURE__ */ new Set();
|
|
189
|
+
for (const arr of array) {
|
|
190
|
+
for (const item of arr) {
|
|
191
|
+
set.add(item);
|
|
221
192
|
}
|
|
222
193
|
}
|
|
223
|
-
return
|
|
194
|
+
return Array.from(set);
|
|
224
195
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
196
|
+
|
|
197
|
+
function merge(target, modification) {
|
|
198
|
+
const targetLabel = JSON.stringify(target);
|
|
199
|
+
const modificationLabel = JSON.stringify(modification);
|
|
200
|
+
if (modification == null) {
|
|
201
|
+
throw new Error(
|
|
202
|
+
`Cannot merge "${modificationLabel}" modification into target "${targetLabel}"`
|
|
203
|
+
);
|
|
233
204
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
return getLatestNpmVersion("npm", "11.0.0");
|
|
243
|
-
}
|
|
244
|
-
async function getLatestNodeVersion() {
|
|
245
|
-
try {
|
|
246
|
-
const response = await fetch("https://nodejs.org/dist/index.json");
|
|
247
|
-
const data = await response.json();
|
|
248
|
-
const latestVersion = data[0];
|
|
249
|
-
if (latestVersion) {
|
|
250
|
-
return latestVersion.version.replace(/^v/, "");
|
|
205
|
+
if (target == null) {
|
|
206
|
+
return modification;
|
|
207
|
+
}
|
|
208
|
+
if (Array.isArray(target)) {
|
|
209
|
+
if (!Array.isArray(modification)) {
|
|
210
|
+
throw new Error(
|
|
211
|
+
`Cannot merge non-array modification "${modificationLabel}" into array target "${targetLabel}"`
|
|
212
|
+
);
|
|
251
213
|
}
|
|
252
|
-
return
|
|
253
|
-
}
|
|
254
|
-
|
|
214
|
+
return [...target, ...modification];
|
|
215
|
+
}
|
|
216
|
+
if (typeof target === "object") {
|
|
217
|
+
if (typeof modification !== "object") {
|
|
218
|
+
throw new Error(
|
|
219
|
+
`Cannot merge non-object modification "${modificationLabel}" into object target "${targetLabel}"`
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
const result = { ...target };
|
|
223
|
+
for (const modificationKey in modification) {
|
|
224
|
+
result[modificationKey] = merge(target[modificationKey], modification[modificationKey]);
|
|
225
|
+
}
|
|
226
|
+
return result;
|
|
255
227
|
}
|
|
228
|
+
console.warn(`target "${targetLabel}" is overwritten with modification "${modificationLabel}"`);
|
|
229
|
+
return modification;
|
|
256
230
|
}
|
|
231
|
+
|
|
257
232
|
function validateNameSegment(segment, label) {
|
|
258
233
|
if (!segment.length) {
|
|
259
234
|
return `${label} is required`;
|
|
@@ -297,27 +272,83 @@ function validatePackageName(name) {
|
|
|
297
272
|
}
|
|
298
273
|
return validateNameSegment(name, "Package name");
|
|
299
274
|
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
275
|
+
|
|
276
|
+
function generateRandomName() {
|
|
277
|
+
const adjectives = [
|
|
278
|
+
"red",
|
|
279
|
+
"blue",
|
|
280
|
+
"green",
|
|
281
|
+
"yellow",
|
|
282
|
+
"purple",
|
|
283
|
+
"orange",
|
|
284
|
+
"pink",
|
|
285
|
+
"black",
|
|
286
|
+
"white",
|
|
287
|
+
"tiny",
|
|
288
|
+
"big",
|
|
289
|
+
"small",
|
|
290
|
+
"large",
|
|
291
|
+
"huge",
|
|
292
|
+
"giant",
|
|
293
|
+
"mini",
|
|
294
|
+
"mega",
|
|
295
|
+
"super",
|
|
296
|
+
"happy",
|
|
297
|
+
"sad",
|
|
298
|
+
"angry",
|
|
299
|
+
"calm",
|
|
300
|
+
"quiet",
|
|
301
|
+
"loud",
|
|
302
|
+
"silent",
|
|
303
|
+
"noisy",
|
|
304
|
+
"shiny",
|
|
305
|
+
"dull",
|
|
306
|
+
"bright",
|
|
307
|
+
"dark",
|
|
308
|
+
"fuzzy",
|
|
309
|
+
"smooth",
|
|
310
|
+
"rough",
|
|
311
|
+
"soft"
|
|
312
|
+
];
|
|
313
|
+
const nouns = [
|
|
314
|
+
"apple",
|
|
315
|
+
"banana",
|
|
316
|
+
"cherry",
|
|
317
|
+
"date",
|
|
318
|
+
"elderberry",
|
|
319
|
+
"fig",
|
|
320
|
+
"grape",
|
|
321
|
+
"honeydew",
|
|
322
|
+
"cat",
|
|
323
|
+
"dog",
|
|
324
|
+
"elephant",
|
|
325
|
+
"fox",
|
|
326
|
+
"giraffe",
|
|
327
|
+
"horse",
|
|
328
|
+
"iguana",
|
|
329
|
+
"jaguar",
|
|
330
|
+
"mountain",
|
|
331
|
+
"river",
|
|
332
|
+
"ocean",
|
|
333
|
+
"desert",
|
|
334
|
+
"forest",
|
|
335
|
+
"jungle",
|
|
336
|
+
"meadow",
|
|
337
|
+
"valley",
|
|
338
|
+
"star",
|
|
339
|
+
"moon",
|
|
340
|
+
"sun",
|
|
341
|
+
"planet",
|
|
342
|
+
"comet",
|
|
343
|
+
"asteroid",
|
|
344
|
+
"galaxy",
|
|
345
|
+
"universe"
|
|
346
|
+
];
|
|
347
|
+
const randomAdjective = adjectives[Math.floor(Math.random() * adjectives.length)];
|
|
348
|
+
const randomNoun = nouns[Math.floor(Math.random() * nouns.length)];
|
|
349
|
+
return `${randomAdjective}-${randomNoun}`;
|
|
320
350
|
}
|
|
351
|
+
|
|
321
352
|
async function pathExists(path) {
|
|
322
353
|
try {
|
|
323
354
|
await promises.access(path, fs.constants.F_OK);
|
|
@@ -393,81 +424,82 @@ async function detectTooling(root) {
|
|
|
393
424
|
} catch {
|
|
394
425
|
return { linter: void 0, formatter: void 0 };
|
|
395
426
|
}
|
|
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
|
-
"
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
async function getLatestNpmVersion(packageName, fallback) {
|
|
430
|
+
try {
|
|
431
|
+
const response = await fetch(`https://registry.npmjs.org/${packageName}/latest`);
|
|
432
|
+
const data = await response.json();
|
|
433
|
+
return data.version;
|
|
434
|
+
} catch {
|
|
435
|
+
return fallback;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
function compareNumericSemver(a, b) {
|
|
439
|
+
const aParts = a.split(".").map((part) => Number.parseInt(part, 10) || 0);
|
|
440
|
+
const bParts = b.split(".").map((part) => Number.parseInt(part, 10) || 0);
|
|
441
|
+
const maxLength = Math.max(aParts.length, bParts.length);
|
|
442
|
+
for (let index = 0; index < maxLength; index += 1) {
|
|
443
|
+
const difference = (aParts[index] ?? 0) - (bParts[index] ?? 0);
|
|
444
|
+
if (difference !== 0) {
|
|
445
|
+
return difference;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
return 0;
|
|
449
|
+
}
|
|
450
|
+
async function getLatestNpmMajorVersion(packageName, majorVersion, fallback) {
|
|
451
|
+
try {
|
|
452
|
+
const response = await fetch(`https://registry.npmjs.org/${packageName}`);
|
|
453
|
+
const data = await response.json();
|
|
454
|
+
const latestMatchingVersion = Object.keys(data.versions ?? {}).filter((version) => version.split(".")[0] === majorVersion).sort((a, b) => compareNumericSemver(b, a))[0];
|
|
455
|
+
return latestMatchingVersion ?? fallback;
|
|
456
|
+
} catch {
|
|
457
|
+
return fallback;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
async function getLatestPnpmVersion() {
|
|
461
|
+
return getLatestNpmVersion("pnpm", "10.11.0");
|
|
462
|
+
}
|
|
463
|
+
async function getLatestYarnVersion() {
|
|
464
|
+
return getLatestNpmVersion("yarn", "4.6.0");
|
|
465
|
+
}
|
|
466
|
+
async function getLatestNpmCliVersion() {
|
|
467
|
+
return getLatestNpmVersion("npm", "11.0.0");
|
|
468
|
+
}
|
|
469
|
+
async function getLatestNodeVersion() {
|
|
470
|
+
try {
|
|
471
|
+
const response = await fetch("https://nodejs.org/dist/index.json");
|
|
472
|
+
const data = await response.json();
|
|
473
|
+
const latestVersion = data[0];
|
|
474
|
+
if (latestVersion) {
|
|
475
|
+
return latestVersion.version.replace(/^v/, "");
|
|
476
|
+
}
|
|
477
|
+
return "25.0.0";
|
|
478
|
+
} catch {
|
|
479
|
+
return "25.0.0";
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
function parseWorkspaceYamlContent(content) {
|
|
484
|
+
const directories = [];
|
|
485
|
+
let inPackagesSection = false;
|
|
486
|
+
for (const line of content.split("\n")) {
|
|
487
|
+
const trimmed = line.trim();
|
|
488
|
+
if (trimmed === "packages:") {
|
|
489
|
+
inPackagesSection = true;
|
|
490
|
+
continue;
|
|
491
|
+
}
|
|
492
|
+
if (inPackagesSection && trimmed && !line.startsWith(" ") && !line.startsWith(" ") && !trimmed.startsWith("-")) {
|
|
493
|
+
break;
|
|
494
|
+
}
|
|
495
|
+
if (inPackagesSection && trimmed.startsWith("-")) {
|
|
496
|
+
const entry = trimmed.slice(1).trim().replace(/^["']|["']$/g, "").replace(/^\.\//, "").replace(/\/\*.*$/, "");
|
|
497
|
+
if (entry && !entry.startsWith(".")) {
|
|
498
|
+
directories.push(entry);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
return directories;
|
|
471
503
|
}
|
|
472
504
|
|
|
473
505
|
const PACKAGE_VERSION_DEFINITIONS = {
|
|
@@ -495,6 +527,7 @@ const PACKAGE_VERSION_DEFINITIONS = {
|
|
|
495
527
|
leva: { fallbackVersion: "0.10.0" },
|
|
496
528
|
oxfmt: { fallbackVersion: "0.21.0" },
|
|
497
529
|
oxlint: { fallbackVersion: "1.36.0" },
|
|
530
|
+
"oxlint-tsgolint": { fallbackVersion: "0.22.1" },
|
|
498
531
|
prettier: { fallbackVersion: "3.4.2" },
|
|
499
532
|
react: { fallbackVersion: "19.0.0" },
|
|
500
533
|
"react-dom": { fallbackVersion: "19.0.0" },
|
|
@@ -651,6 +684,9 @@ async function resolveMonorepoRootPackageVersions(params) {
|
|
|
651
684
|
const packageNames = /* @__PURE__ */ new Set();
|
|
652
685
|
const explicitVersions = new Set(Object.keys(params.versions ?? {}));
|
|
653
686
|
addPackageName(packageNames, explicitVersions, getLinterPackage(params.linter));
|
|
687
|
+
if (params.linter === "oxlint") {
|
|
688
|
+
addPackageName(packageNames, explicitVersions, "oxlint-tsgolint");
|
|
689
|
+
}
|
|
654
690
|
if (params.formatter !== "biome" || params.linter !== "biome") {
|
|
655
691
|
addPackageName(packageNames, explicitVersions, getFormatterPackage(params.formatter));
|
|
656
692
|
}
|
|
@@ -760,6 +796,9 @@ function collectProjectPackageNames(options) {
|
|
|
760
796
|
} else if (linter === "oxlint") {
|
|
761
797
|
if (!inWorkspace) {
|
|
762
798
|
addPackageName(packageNames, explicitVersions, "oxlint");
|
|
799
|
+
if (isTypescript) {
|
|
800
|
+
addPackageName(packageNames, explicitVersions, "oxlint-tsgolint");
|
|
801
|
+
}
|
|
763
802
|
}
|
|
764
803
|
} else if (linter === "biome") {
|
|
765
804
|
addPackageName(packageNames, explicitVersions, "@biomejs/biome");
|
|
@@ -794,7 +833,7 @@ function isEnabledOption(option) {
|
|
|
794
833
|
return option != null && option !== false;
|
|
795
834
|
}
|
|
796
835
|
|
|
797
|
-
function
|
|
836
|
+
function renderTypescriptConfig(baseTemplateOrParams) {
|
|
798
837
|
const params = typeof baseTemplateOrParams === "string" ? { baseTemplate: baseTemplateOrParams } : baseTemplateOrParams;
|
|
799
838
|
const {
|
|
800
839
|
baseTemplate,
|
|
@@ -864,6 +903,7 @@ function generateTypescriptConfig(baseTemplateOrParams) {
|
|
|
864
903
|
composite: true,
|
|
865
904
|
rewriteRelativeImportExtensions: true,
|
|
866
905
|
erasableSyntaxOnly: true,
|
|
906
|
+
noEmit: true,
|
|
867
907
|
...isReact || isR3f ? { jsx: "react-jsx" } : {}
|
|
868
908
|
},
|
|
869
909
|
include: ["../src", "../tests"]
|
|
@@ -885,7 +925,8 @@ function generateTypescriptConfig(baseTemplateOrParams) {
|
|
|
885
925
|
skipLibCheck: true,
|
|
886
926
|
composite: true,
|
|
887
927
|
rewriteRelativeImportExtensions: true,
|
|
888
|
-
erasableSyntaxOnly: true
|
|
928
|
+
erasableSyntaxOnly: true,
|
|
929
|
+
noEmit: true
|
|
889
930
|
},
|
|
890
931
|
include: ["../*.config.ts", "./*.ts"]
|
|
891
932
|
};
|
|
@@ -917,6 +958,7 @@ function generateTypescriptConfig(baseTemplateOrParams) {
|
|
|
917
958
|
composite: true,
|
|
918
959
|
rewriteRelativeImportExtensions: true,
|
|
919
960
|
erasableSyntaxOnly: true,
|
|
961
|
+
noEmit: true,
|
|
920
962
|
...isReact || isR3f ? { jsx: "react-jsx" } : {}
|
|
921
963
|
},
|
|
922
964
|
include: ["src", "tests"]
|
|
@@ -938,7 +980,8 @@ function generateTypescriptConfig(baseTemplateOrParams) {
|
|
|
938
980
|
skipLibCheck: true,
|
|
939
981
|
composite: true,
|
|
940
982
|
rewriteRelativeImportExtensions: true,
|
|
941
|
-
erasableSyntaxOnly: true
|
|
983
|
+
erasableSyntaxOnly: true,
|
|
984
|
+
noEmit: true
|
|
942
985
|
},
|
|
943
986
|
include: ["*.config.ts"]
|
|
944
987
|
};
|
|
@@ -950,8 +993,108 @@ function generateTypescriptConfig(baseTemplateOrParams) {
|
|
|
950
993
|
return { files, devDependencies };
|
|
951
994
|
}
|
|
952
995
|
|
|
996
|
+
const packageJsonScripts = {
|
|
997
|
+
appBase: {
|
|
998
|
+
dev: "vite",
|
|
999
|
+
build: "vite build"
|
|
1000
|
+
},
|
|
1001
|
+
typescript: {
|
|
1002
|
+
typecheck: "tsc --build --noEmit",
|
|
1003
|
+
"typecheck:watch": "tsc --build --watch"
|
|
1004
|
+
},
|
|
1005
|
+
test: {
|
|
1006
|
+
vitest: {
|
|
1007
|
+
test: "vitest"
|
|
1008
|
+
}
|
|
1009
|
+
},
|
|
1010
|
+
build: {
|
|
1011
|
+
unbuild(configPath) {
|
|
1012
|
+
return {
|
|
1013
|
+
build: configPath == null ? "unbuild" : `unbuild --config ${configPath}`
|
|
1014
|
+
};
|
|
1015
|
+
},
|
|
1016
|
+
tsdown: {
|
|
1017
|
+
build: "tsdown"
|
|
1018
|
+
}
|
|
1019
|
+
},
|
|
1020
|
+
lint: {
|
|
1021
|
+
oxlint(configPath) {
|
|
1022
|
+
return {
|
|
1023
|
+
lint: configPath == null ? "oxlint" : `oxlint -c ${configPath}`
|
|
1024
|
+
};
|
|
1025
|
+
},
|
|
1026
|
+
eslint(configPath) {
|
|
1027
|
+
return {
|
|
1028
|
+
lint: configPath == null ? "eslint ." : `eslint --config ${configPath} .`
|
|
1029
|
+
};
|
|
1030
|
+
},
|
|
1031
|
+
biome(configPath) {
|
|
1032
|
+
return {
|
|
1033
|
+
lint: configPath == null ? "biome lint ." : `biome lint --config-path ${configPath} .`
|
|
1034
|
+
};
|
|
1035
|
+
}
|
|
1036
|
+
},
|
|
1037
|
+
format: {
|
|
1038
|
+
prettier(configPath, ignorePath) {
|
|
1039
|
+
const configFlag = configPath == null ? "" : ` --config ${configPath}`;
|
|
1040
|
+
const ignoreFlag = ignorePath == null ? "" : ` --ignore-path ${ignorePath}`;
|
|
1041
|
+
return {
|
|
1042
|
+
format: `prettier${configFlag}${ignoreFlag} --write .`
|
|
1043
|
+
};
|
|
1044
|
+
},
|
|
1045
|
+
oxfmt(configPath) {
|
|
1046
|
+
return {
|
|
1047
|
+
format: `oxfmt -c ${configPath} --write .`
|
|
1048
|
+
};
|
|
1049
|
+
},
|
|
1050
|
+
biome(configPath) {
|
|
1051
|
+
return {
|
|
1052
|
+
format: configPath == null ? "biome format --write ." : `biome format --config-path ${configPath} --write .`
|
|
1053
|
+
};
|
|
1054
|
+
}
|
|
1055
|
+
},
|
|
1056
|
+
release(packageManagerName) {
|
|
1057
|
+
return {
|
|
1058
|
+
release: `${packageManagerName} run build && ${packageManagerName} publish`
|
|
1059
|
+
};
|
|
1060
|
+
},
|
|
1061
|
+
monorepoRoot(linter, formatter) {
|
|
1062
|
+
return mergePackageJsonScripts(
|
|
1063
|
+
{
|
|
1064
|
+
dev: "pnpm --filter './apps/*' run dev",
|
|
1065
|
+
build: "pnpm --filter './packages/*' run build && pnpm --filter './apps/*' run build",
|
|
1066
|
+
test: "pnpm -r run test"
|
|
1067
|
+
},
|
|
1068
|
+
linter === "oxlint" ? {
|
|
1069
|
+
lint: "oxlint ."
|
|
1070
|
+
} : linter === "biome" ? {
|
|
1071
|
+
lint: "biome check ."
|
|
1072
|
+
} : {
|
|
1073
|
+
lint: "eslint ."
|
|
1074
|
+
},
|
|
1075
|
+
formatter === "oxfmt" ? {
|
|
1076
|
+
format: "oxfmt -c .config/oxfmt/base.json ."
|
|
1077
|
+
} : formatter === "biome" ? {
|
|
1078
|
+
format: "biome format . --write"
|
|
1079
|
+
} : {
|
|
1080
|
+
format: "prettier --config .config/prettier/base.json --ignore-path .config/prettier/prettierignore --write ."
|
|
1081
|
+
}
|
|
1082
|
+
);
|
|
1083
|
+
}
|
|
1084
|
+
};
|
|
1085
|
+
function mergePackageJsonScripts(...scriptSets) {
|
|
1086
|
+
return Object.assign({}, ...scriptSets.filter((scriptSet) => scriptSet != null));
|
|
1087
|
+
}
|
|
1088
|
+
function resolveDefaultPackageJsonScripts(params) {
|
|
1089
|
+
return mergePackageJsonScripts(
|
|
1090
|
+
params.isLibrary ? void 0 : packageJsonScripts.appBase,
|
|
1091
|
+
params.language === "typescript" ? packageJsonScripts.typescript : void 0,
|
|
1092
|
+
params.isLibrary ? packageJsonScripts.release(params.packageManagerName) : void 0
|
|
1093
|
+
);
|
|
1094
|
+
}
|
|
1095
|
+
|
|
953
1096
|
const DEFAULT_LIBRARY_VERSION = "0.1.0";
|
|
954
|
-
function
|
|
1097
|
+
function renderPackageJson(params) {
|
|
955
1098
|
const {
|
|
956
1099
|
name,
|
|
957
1100
|
language,
|
|
@@ -959,13 +1102,20 @@ function generatePackageJson(params) {
|
|
|
959
1102
|
dependencies,
|
|
960
1103
|
devDependencies,
|
|
961
1104
|
peerDependencies,
|
|
962
|
-
scripts,
|
|
963
1105
|
options,
|
|
964
1106
|
workspaceDependencies
|
|
965
1107
|
} = params;
|
|
966
1108
|
const files = {};
|
|
967
1109
|
const packageManager = getPackageManagerSpec(options.packageManager);
|
|
968
1110
|
const isPnpm = packageManager.name === "pnpm";
|
|
1111
|
+
const resolvedScripts = mergePackageJsonScripts(
|
|
1112
|
+
resolveDefaultPackageJsonScripts({
|
|
1113
|
+
language,
|
|
1114
|
+
isLibrary,
|
|
1115
|
+
packageManagerName: packageManager.name
|
|
1116
|
+
}),
|
|
1117
|
+
params.scripts
|
|
1118
|
+
);
|
|
969
1119
|
const packageJson = {
|
|
970
1120
|
name,
|
|
971
1121
|
description: "Built with \u{1F339} create-krispya",
|
|
@@ -1002,7 +1152,7 @@ function generatePackageJson(params) {
|
|
|
1002
1152
|
options.engine
|
|
1003
1153
|
);
|
|
1004
1154
|
}
|
|
1005
|
-
packageJson.scripts =
|
|
1155
|
+
packageJson.scripts = resolvedScripts;
|
|
1006
1156
|
packageJson.dependencies = sortKeys(allDependencies);
|
|
1007
1157
|
if (Object.keys(allDevDependencies).length > 0) {
|
|
1008
1158
|
packageJson.devDependencies = sortKeys(allDevDependencies);
|
|
@@ -1045,7 +1195,7 @@ function generatePackageJson(params) {
|
|
|
1045
1195
|
return { files };
|
|
1046
1196
|
}
|
|
1047
1197
|
|
|
1048
|
-
function
|
|
1198
|
+
function renderReadme(params) {
|
|
1049
1199
|
const { name, baseTemplate, isLibrary, libraryBundler, packageManager, codeSnippets } = params;
|
|
1050
1200
|
const isVanilla = baseTemplate === "vanilla";
|
|
1051
1201
|
const isReact = baseTemplate === "react";
|
|
@@ -1138,7 +1288,63 @@ function generateReadme(params) {
|
|
|
1138
1288
|
return { type: "text", content };
|
|
1139
1289
|
}
|
|
1140
1290
|
|
|
1141
|
-
|
|
1291
|
+
const htmlContent = `<!DOCTYPE html>
|
|
1292
|
+
<html lang="en">
|
|
1293
|
+
<head>
|
|
1294
|
+
<meta charset="UTF-8">
|
|
1295
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
1296
|
+
<title>$title</title>
|
|
1297
|
+
</head>
|
|
1298
|
+
<body style="margin: 0; overscroll-behavior: none; user-select: none; touch-action: none;">
|
|
1299
|
+
<script type="module" src="$indexPath"><\/script>
|
|
1300
|
+
<div style="width: 100dvw; height: 100dvh; overflow: hidden;" id="root"></div>
|
|
1301
|
+
</body>
|
|
1302
|
+
</html>`;
|
|
1303
|
+
const viteHtmlContent = `<!DOCTYPE html>
|
|
1304
|
+
<html lang="en">
|
|
1305
|
+
<head>
|
|
1306
|
+
<meta charset="UTF-8">
|
|
1307
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
1308
|
+
<title>$title</title>
|
|
1309
|
+
</head>
|
|
1310
|
+
<body>
|
|
1311
|
+
<div id="app"></div>
|
|
1312
|
+
<script type="module" src="$indexPath"><\/script>
|
|
1313
|
+
</body>
|
|
1314
|
+
</html>`;
|
|
1315
|
+
const indexContent = `import { StrictMode } from 'react'
|
|
1316
|
+
import { createRoot } from 'react-dom/client'
|
|
1317
|
+
import { App } from './app.js'
|
|
1318
|
+
|
|
1319
|
+
createRoot(document.getElementById('root')!).render(
|
|
1320
|
+
<StrictMode>
|
|
1321
|
+
<App />
|
|
1322
|
+
</StrictMode>,
|
|
1323
|
+
)`;
|
|
1324
|
+
const viteIndexContent = `import './style.css'
|
|
1325
|
+
|
|
1326
|
+
document.querySelector('#app')!.innerHTML = \`
|
|
1327
|
+
<h1>Hello Vite!</h1>
|
|
1328
|
+
<p>Edit src/main.ts and save to see HMR in action.</p>
|
|
1329
|
+
\``;
|
|
1330
|
+
const viteStyleContent = `body {
|
|
1331
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
1332
|
+
margin: 0;
|
|
1333
|
+
padding: 2rem;
|
|
1334
|
+
min-height: 100vh;
|
|
1335
|
+
background: #1a1a1a;
|
|
1336
|
+
color: #fff;
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1339
|
+
h1 {
|
|
1340
|
+
color: #646cff;
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
a {
|
|
1344
|
+
color: #646cff;
|
|
1345
|
+
}`;
|
|
1346
|
+
|
|
1347
|
+
function renderSourceFiles(params) {
|
|
1142
1348
|
const { name, baseTemplate, language, isLibrary, codeSnippets, replacements } = params;
|
|
1143
1349
|
const files = {};
|
|
1144
1350
|
const ext = language === "typescript" ? "ts" : "js";
|
|
@@ -1178,19 +1384,13 @@ function generateSourceFiles(params) {
|
|
|
1178
1384
|
}
|
|
1179
1385
|
files[`src/index.${libExt}`] = { type: "text", content: libContent };
|
|
1180
1386
|
} else if (isVanilla) {
|
|
1181
|
-
files[`src/main.${ext}`] = { type: "text", content:
|
|
1182
|
-
files["src/style.css"] = { type: "text", content:
|
|
1183
|
-
const indexHtml =
|
|
1184
|
-
"$title",
|
|
1185
|
-
name
|
|
1186
|
-
);
|
|
1387
|
+
files[`src/main.${ext}`] = { type: "text", content: viteIndexContent };
|
|
1388
|
+
files["src/style.css"] = { type: "text", content: viteStyleContent };
|
|
1389
|
+
const indexHtml = viteHtmlContent.replace("$indexPath", `./src/main.${ext}`).replace("$title", name);
|
|
1187
1390
|
files["index.html"] = { type: "text", content: indexHtml };
|
|
1188
1391
|
} else {
|
|
1189
|
-
files[`src/index.tsx`] = { type: "text", content:
|
|
1190
|
-
const indexHtml =
|
|
1191
|
-
"$indexPath",
|
|
1192
|
-
language === "javascript" ? "./src/index.jsx" : "./src/index.tsx"
|
|
1193
|
-
).replace("$title", name);
|
|
1392
|
+
files[`src/index.tsx`] = { type: "text", content: indexContent };
|
|
1393
|
+
const indexHtml = htmlContent.replace("$indexPath", language === "javascript" ? "./src/index.jsx" : "./src/index.tsx").replace("$title", name);
|
|
1194
1394
|
files["index.html"] = { type: "text", content: indexHtml };
|
|
1195
1395
|
codeSnippets["dom-end"]?.reverse();
|
|
1196
1396
|
codeSnippets["global-end"]?.reverse();
|
|
@@ -1237,7 +1437,7 @@ function generateSourceFiles(params) {
|
|
|
1237
1437
|
return files;
|
|
1238
1438
|
}
|
|
1239
1439
|
|
|
1240
|
-
function
|
|
1440
|
+
function renderTestFiles(params) {
|
|
1241
1441
|
const { baseTemplate, language, isLibrary } = params;
|
|
1242
1442
|
const files = {};
|
|
1243
1443
|
const ext = language === "typescript" ? "ts" : "js";
|
|
@@ -1344,21 +1544,184 @@ const COMMON_GITIGNORE_LINES = [
|
|
|
1344
1544
|
"*.tsbuildinfo",
|
|
1345
1545
|
".env",
|
|
1346
1546
|
".env.*",
|
|
1347
|
-
"!.env.example"
|
|
1547
|
+
"!.env.example",
|
|
1548
|
+
".pnpm-store"
|
|
1348
1549
|
];
|
|
1349
|
-
function
|
|
1550
|
+
function renderGitignore(variant) {
|
|
1350
1551
|
const lines = variant === "workspace-root" ? [...COMMON_GITIGNORE_LINES, ".DS_Store"] : COMMON_GITIGNORE_LINES;
|
|
1351
1552
|
return {
|
|
1352
1553
|
type: "text",
|
|
1353
1554
|
content: lines.join("\n")
|
|
1354
1555
|
};
|
|
1355
1556
|
}
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1557
|
+
|
|
1558
|
+
const defaultFormatterMetaConfig = {
|
|
1559
|
+
printWidth: 102,
|
|
1560
|
+
tabWidth: 2,
|
|
1561
|
+
useTabs: false,
|
|
1562
|
+
semi: true,
|
|
1563
|
+
singleQuote: true,
|
|
1564
|
+
trailingComma: "es5",
|
|
1565
|
+
bracketSpacing: true,
|
|
1566
|
+
arrowParens: "always",
|
|
1567
|
+
ignorePatterns: [
|
|
1568
|
+
"package-lock.json",
|
|
1569
|
+
"npm-shrinkwrap.json",
|
|
1570
|
+
"pnpm-lock.yaml",
|
|
1571
|
+
"pnpm-lock.json",
|
|
1572
|
+
"yarn.lock",
|
|
1573
|
+
"bun.lock",
|
|
1574
|
+
"bun.lockb"
|
|
1575
|
+
]
|
|
1576
|
+
};
|
|
1577
|
+
|
|
1578
|
+
function renderEditorConfig(config = defaultFormatterMetaConfig) {
|
|
1579
|
+
const indentStyle = config.useTabs ? "tab" : "space";
|
|
1580
|
+
const indentSize = config.useTabs ? "tab" : String(config.tabWidth);
|
|
1581
|
+
return {
|
|
1582
|
+
type: "text",
|
|
1583
|
+
content: [
|
|
1584
|
+
"root = true",
|
|
1585
|
+
"",
|
|
1586
|
+
"[*]",
|
|
1587
|
+
"charset = utf-8",
|
|
1588
|
+
"end_of_line = lf",
|
|
1589
|
+
"insert_final_newline = true",
|
|
1590
|
+
`indent_style = ${indentStyle}`,
|
|
1591
|
+
`indent_size = ${indentSize}`,
|
|
1592
|
+
`tab_width = ${config.tabWidth}`,
|
|
1593
|
+
`max_line_length = ${config.printWidth}`
|
|
1594
|
+
].join("\n")
|
|
1595
|
+
};
|
|
1596
|
+
}
|
|
1597
|
+
function renderVscodeEditorSettings(config = defaultFormatterMetaConfig) {
|
|
1598
|
+
return {
|
|
1599
|
+
"editor.detectIndentation": false,
|
|
1600
|
+
"editor.insertSpaces": !config.useTabs,
|
|
1601
|
+
"editor.tabSize": config.tabWidth,
|
|
1602
|
+
"files.eol": "\n",
|
|
1603
|
+
"files.insertFinalNewline": true
|
|
1604
|
+
};
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1607
|
+
const DEFAULT_VSCODE_SETTINGS = {
|
|
1608
|
+
...renderVscodeEditorSettings(),
|
|
1609
|
+
"explorer.fileNesting.enabled": true,
|
|
1610
|
+
"explorer.fileNesting.expand": false,
|
|
1611
|
+
"explorer.fileNesting.patterns": {
|
|
1612
|
+
".gitignore": ".gitattributes",
|
|
1613
|
+
"AGENTS.md": "CLAUDE.md"
|
|
1614
|
+
}
|
|
1615
|
+
};
|
|
1616
|
+
const OXFMT_LANGUAGE_SETTINGS = {
|
|
1617
|
+
"[json]": {
|
|
1618
|
+
"editor.defaultFormatter": "vscode.json-language-features"
|
|
1619
|
+
},
|
|
1620
|
+
"[jsonc]": {
|
|
1621
|
+
"editor.defaultFormatter": "vscode.json-language-features"
|
|
1622
|
+
},
|
|
1623
|
+
"[markdown]": {
|
|
1624
|
+
"editor.defaultFormatter": "vscode.markdown-language-features"
|
|
1625
|
+
},
|
|
1626
|
+
"[yaml]": {
|
|
1627
|
+
"editor.defaultFormatter": "redhat.vscode-yaml"
|
|
1628
|
+
}
|
|
1629
|
+
};
|
|
1630
|
+
function resolvePackageJsonNestedFiles(packageManager) {
|
|
1631
|
+
if (packageManager === "pnpm") {
|
|
1632
|
+
return ["pnpm-lock.yaml", "pnpm-workspace.yaml"];
|
|
1633
|
+
}
|
|
1634
|
+
if (packageManager === "npm") {
|
|
1635
|
+
return ["package-lock.json", "npm-shrinkwrap.json"];
|
|
1636
|
+
}
|
|
1637
|
+
if (packageManager === "yarn") {
|
|
1638
|
+
return ["yarn.lock"];
|
|
1639
|
+
}
|
|
1640
|
+
return [];
|
|
1641
|
+
}
|
|
1642
|
+
function resolveVscodeRecommendations(linter, formatter) {
|
|
1643
|
+
const recommendations = [];
|
|
1644
|
+
if (linter === "oxlint" || formatter === "oxfmt") {
|
|
1645
|
+
recommendations.push("oxc.oxc-vscode");
|
|
1646
|
+
}
|
|
1647
|
+
if (linter === "eslint") {
|
|
1648
|
+
recommendations.push("dbaeumer.vscode-eslint");
|
|
1649
|
+
}
|
|
1650
|
+
if (linter === "biome" || formatter === "biome") {
|
|
1651
|
+
recommendations.push("biomejs.biome");
|
|
1652
|
+
}
|
|
1653
|
+
if (formatter === "prettier") {
|
|
1654
|
+
recommendations.push("esbenp.prettier-vscode");
|
|
1655
|
+
}
|
|
1656
|
+
return recommendations;
|
|
1657
|
+
}
|
|
1658
|
+
function resolveVscodeSettings(params) {
|
|
1659
|
+
const { linter, formatter, configStrategy, isMonorepo, packageManager } = params;
|
|
1660
|
+
const settings = { ...DEFAULT_VSCODE_SETTINGS };
|
|
1661
|
+
const isStealth = !isMonorepo && (configStrategy ?? "stealth") === "stealth";
|
|
1662
|
+
const packageJsonNestedFiles = resolvePackageJsonNestedFiles(packageManager);
|
|
1663
|
+
if (packageJsonNestedFiles.length > 0) {
|
|
1664
|
+
settings["explorer.fileNesting.patterns"] = {
|
|
1665
|
+
...settings["explorer.fileNesting.patterns"],
|
|
1666
|
+
"package.json": packageJsonNestedFiles.join(", ")
|
|
1667
|
+
};
|
|
1668
|
+
}
|
|
1669
|
+
if (linter === "eslint") {
|
|
1670
|
+
settings["eslint.enable"] = true;
|
|
1671
|
+
settings["oxc.enable"] = false;
|
|
1672
|
+
settings["biome.enabled"] = false;
|
|
1673
|
+
if (isStealth) {
|
|
1674
|
+
settings["eslint.options"] = {
|
|
1675
|
+
overrideConfigFile: ".config/eslint.config.js"
|
|
1676
|
+
};
|
|
1677
|
+
}
|
|
1678
|
+
} else if (linter === "oxlint") {
|
|
1679
|
+
settings["oxc.enable"] = true;
|
|
1680
|
+
settings["eslint.enable"] = false;
|
|
1681
|
+
settings["biome.enabled"] = false;
|
|
1682
|
+
if (isStealth) {
|
|
1683
|
+
settings["oxc.configPath"] = ".config/oxlint.json";
|
|
1684
|
+
}
|
|
1685
|
+
} else if (linter === "biome") {
|
|
1686
|
+
settings["biome.enabled"] = true;
|
|
1687
|
+
settings["eslint.enable"] = false;
|
|
1688
|
+
settings["oxc.enable"] = false;
|
|
1689
|
+
if (isStealth) {
|
|
1690
|
+
settings["biome.linter.configPath"] = ".config/biome.json";
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
if (formatter === "prettier") {
|
|
1694
|
+
settings["editor.defaultFormatter"] = "esbenp.prettier-vscode";
|
|
1695
|
+
if (isStealth) {
|
|
1696
|
+
settings["prettier.configPath"] = ".config/prettier.json";
|
|
1697
|
+
settings["prettier.ignorePath"] = ".config/prettierignore";
|
|
1698
|
+
}
|
|
1699
|
+
} else if (formatter === "oxfmt") {
|
|
1700
|
+
settings["editor.defaultFormatter"] = "oxc.oxc-vscode";
|
|
1701
|
+
Object.assign(settings, OXFMT_LANGUAGE_SETTINGS);
|
|
1702
|
+
if (isStealth) {
|
|
1703
|
+
settings["oxc.fmt.configPath"] = ".config/oxfmt.json";
|
|
1704
|
+
}
|
|
1705
|
+
} else if (formatter === "biome") {
|
|
1706
|
+
settings["biome.enabled"] = true;
|
|
1707
|
+
settings["eslint.enable"] = false;
|
|
1708
|
+
settings["oxc.enable"] = false;
|
|
1709
|
+
settings["editor.defaultFormatter"] = "biomejs.biome";
|
|
1710
|
+
if (isStealth) {
|
|
1711
|
+
settings["biome.linter.configPath"] = ".config/biome.json";
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1714
|
+
return settings;
|
|
1715
|
+
}
|
|
1716
|
+
function renderVscodeFiles$1(params) {
|
|
1717
|
+
const { codeSnippets = {}, vscodeSettings = {} } = params;
|
|
1359
1718
|
const files = {};
|
|
1360
|
-
|
|
1361
|
-
|
|
1719
|
+
const recommendations = [
|
|
1720
|
+
...codeSnippets["vscode-extension-suggestion"] ?? [],
|
|
1721
|
+
...resolveVscodeRecommendations(params.linter, params.formatter)
|
|
1722
|
+
];
|
|
1723
|
+
if (recommendations.length > 0) {
|
|
1724
|
+
const uniqueRecommendations = [...new Set(recommendations)];
|
|
1362
1725
|
files[".vscode/extensions.json"] = {
|
|
1363
1726
|
type: "text",
|
|
1364
1727
|
content: JSON.stringify(
|
|
@@ -1370,9 +1733,13 @@ function generateVscodeFiles$1(params) {
|
|
|
1370
1733
|
)
|
|
1371
1734
|
};
|
|
1372
1735
|
}
|
|
1373
|
-
|
|
1736
|
+
const resolvedSettings = {
|
|
1737
|
+
...resolveVscodeSettings(params),
|
|
1738
|
+
...vscodeSettings
|
|
1739
|
+
};
|
|
1740
|
+
if (Object.keys(resolvedSettings).length > 0) {
|
|
1374
1741
|
const sortedSettings = Object.fromEntries(
|
|
1375
|
-
Object.entries(
|
|
1742
|
+
Object.entries(resolvedSettings).sort(([a], [b]) => a.localeCompare(b))
|
|
1376
1743
|
);
|
|
1377
1744
|
files[".vscode/settings.json"] = {
|
|
1378
1745
|
type: "text",
|
|
@@ -1416,7 +1783,7 @@ ${spaces}}`;
|
|
|
1416
1783
|
}
|
|
1417
1784
|
return String(value);
|
|
1418
1785
|
}
|
|
1419
|
-
function
|
|
1786
|
+
function renderViteConfig(params) {
|
|
1420
1787
|
const { viteConfig, codeSnippets } = params;
|
|
1421
1788
|
const configBody = formatValue(viteConfig, 0);
|
|
1422
1789
|
const viteConfigContent = [
|
|
@@ -1429,7 +1796,93 @@ function generateViteConfig(params) {
|
|
|
1429
1796
|
return { type: "text", content: viteConfigContent };
|
|
1430
1797
|
}
|
|
1431
1798
|
|
|
1432
|
-
function
|
|
1799
|
+
function toPrettierConfig(config = defaultFormatterMetaConfig) {
|
|
1800
|
+
return {
|
|
1801
|
+
$schema: "https://json.schemastore.org/prettierrc",
|
|
1802
|
+
printWidth: config.printWidth,
|
|
1803
|
+
tabWidth: config.tabWidth,
|
|
1804
|
+
useTabs: config.useTabs,
|
|
1805
|
+
semi: config.semi,
|
|
1806
|
+
singleQuote: config.singleQuote,
|
|
1807
|
+
trailingComma: config.trailingComma,
|
|
1808
|
+
bracketSpacing: config.bracketSpacing,
|
|
1809
|
+
arrowParens: config.arrowParens,
|
|
1810
|
+
overrides: [
|
|
1811
|
+
{
|
|
1812
|
+
files: ["*.md", "**/*.md"],
|
|
1813
|
+
options: { semi: false }
|
|
1814
|
+
},
|
|
1815
|
+
{
|
|
1816
|
+
files: ["*.yml", "*.yaml", "**/*.yml", "**/*.yaml"],
|
|
1817
|
+
options: { semi: false }
|
|
1818
|
+
}
|
|
1819
|
+
]
|
|
1820
|
+
};
|
|
1821
|
+
}
|
|
1822
|
+
function toPrettierIgnoreContent(config = defaultFormatterMetaConfig) {
|
|
1823
|
+
return config.ignorePatterns.join("\n");
|
|
1824
|
+
}
|
|
1825
|
+
function toOxfmtConfig(config = defaultFormatterMetaConfig) {
|
|
1826
|
+
return {
|
|
1827
|
+
printWidth: config.printWidth,
|
|
1828
|
+
tabWidth: config.tabWidth,
|
|
1829
|
+
useTabs: config.useTabs,
|
|
1830
|
+
semi: config.semi,
|
|
1831
|
+
singleQuote: config.singleQuote,
|
|
1832
|
+
trailingComma: config.trailingComma,
|
|
1833
|
+
bracketSpacing: config.bracketSpacing,
|
|
1834
|
+
arrowParens: config.arrowParens,
|
|
1835
|
+
ignorePatterns: config.ignorePatterns
|
|
1836
|
+
};
|
|
1837
|
+
}
|
|
1838
|
+
|
|
1839
|
+
const defaultLinterMetaConfig = {
|
|
1840
|
+
ignorePatterns: ["dist"],
|
|
1841
|
+
rules: {
|
|
1842
|
+
noUnusedVars: {
|
|
1843
|
+
level: "warn",
|
|
1844
|
+
argsIgnorePattern: "^_",
|
|
1845
|
+
varsIgnorePattern: "^_",
|
|
1846
|
+
caughtErrorsIgnorePattern: "^_"
|
|
1847
|
+
},
|
|
1848
|
+
noUnusedExpressions: {
|
|
1849
|
+
level: "warn",
|
|
1850
|
+
allowShortCircuit: true
|
|
1851
|
+
}
|
|
1852
|
+
}
|
|
1853
|
+
};
|
|
1854
|
+
|
|
1855
|
+
function renderOxlintConfig(params) {
|
|
1856
|
+
const config = params.config ?? defaultLinterMetaConfig;
|
|
1857
|
+
const { rules } = config;
|
|
1858
|
+
const plugins = ["unicorn", "typescript", "oxc"];
|
|
1859
|
+
if (params.react === true) {
|
|
1860
|
+
plugins.push("react");
|
|
1861
|
+
}
|
|
1862
|
+
return {
|
|
1863
|
+
$schema: params.schemaPath,
|
|
1864
|
+
plugins,
|
|
1865
|
+
...params.typescript === true ? { options: { typeAware: true } } : {},
|
|
1866
|
+
rules: {
|
|
1867
|
+
"no-unused-vars": [
|
|
1868
|
+
rules.noUnusedVars.level,
|
|
1869
|
+
{
|
|
1870
|
+
argsIgnorePattern: rules.noUnusedVars.argsIgnorePattern,
|
|
1871
|
+
varsIgnorePattern: rules.noUnusedVars.varsIgnorePattern,
|
|
1872
|
+
caughtErrorsIgnorePattern: rules.noUnusedVars.caughtErrorsIgnorePattern
|
|
1873
|
+
}
|
|
1874
|
+
],
|
|
1875
|
+
"no-useless-escape": "off",
|
|
1876
|
+
"no-unused-expressions": [
|
|
1877
|
+
rules.noUnusedExpressions.level,
|
|
1878
|
+
{ allowShortCircuit: rules.noUnusedExpressions.allowShortCircuit }
|
|
1879
|
+
]
|
|
1880
|
+
},
|
|
1881
|
+
ignorePatterns: config.ignorePatterns
|
|
1882
|
+
};
|
|
1883
|
+
}
|
|
1884
|
+
|
|
1885
|
+
function renderTypescriptConfigPackage(files) {
|
|
1433
1886
|
const basePath = ".config/typescript";
|
|
1434
1887
|
files[`${basePath}/package.json`] = {
|
|
1435
1888
|
type: "text",
|
|
@@ -1534,9 +1987,8 @@ In your package's \`tsconfig.json\`:
|
|
|
1534
1987
|
)
|
|
1535
1988
|
};
|
|
1536
1989
|
}
|
|
1537
|
-
function
|
|
1990
|
+
function renderOxlintConfigPackage(files) {
|
|
1538
1991
|
const basePath = ".config/oxlint";
|
|
1539
|
-
const { rules } = defaultLinterConfig;
|
|
1540
1992
|
files[`${basePath}/package.json`] = {
|
|
1541
1993
|
type: "text",
|
|
1542
1994
|
content: JSON.stringify(
|
|
@@ -1573,26 +2025,10 @@ oxlint -c node_modules/@config/oxlint/base.json
|
|
|
1573
2025
|
files[`${basePath}/base.json`] = {
|
|
1574
2026
|
type: "text",
|
|
1575
2027
|
content: JSON.stringify(
|
|
1576
|
-
{
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
"no-unused-vars": [
|
|
1581
|
-
rules.noUnusedVars.level,
|
|
1582
|
-
{
|
|
1583
|
-
argsIgnorePattern: rules.noUnusedVars.argsIgnorePattern,
|
|
1584
|
-
varsIgnorePattern: rules.noUnusedVars.varsIgnorePattern,
|
|
1585
|
-
caughtErrorsIgnorePattern: rules.noUnusedVars.caughtErrorsIgnorePattern
|
|
1586
|
-
}
|
|
1587
|
-
],
|
|
1588
|
-
"no-useless-escape": "off",
|
|
1589
|
-
"no-unused-expressions": [
|
|
1590
|
-
rules.noUnusedExpressions.level,
|
|
1591
|
-
{ allowShortCircuit: rules.noUnusedExpressions.allowShortCircuit }
|
|
1592
|
-
]
|
|
1593
|
-
},
|
|
1594
|
-
ignorePatterns: defaultLinterConfig.ignorePatterns
|
|
1595
|
-
},
|
|
2028
|
+
renderOxlintConfig({
|
|
2029
|
+
schemaPath: "./node_modules/oxlint/configuration_schema.json",
|
|
2030
|
+
typescript: true
|
|
2031
|
+
}),
|
|
1596
2032
|
null,
|
|
1597
2033
|
2
|
|
1598
2034
|
)
|
|
@@ -1600,32 +2036,17 @@ oxlint -c node_modules/@config/oxlint/base.json
|
|
|
1600
2036
|
files[`${basePath}/react.json`] = {
|
|
1601
2037
|
type: "text",
|
|
1602
2038
|
content: JSON.stringify(
|
|
1603
|
-
{
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
rules.noUnusedVars.level,
|
|
1609
|
-
{
|
|
1610
|
-
argsIgnorePattern: rules.noUnusedVars.argsIgnorePattern,
|
|
1611
|
-
varsIgnorePattern: rules.noUnusedVars.varsIgnorePattern,
|
|
1612
|
-
caughtErrorsIgnorePattern: rules.noUnusedVars.caughtErrorsIgnorePattern
|
|
1613
|
-
}
|
|
1614
|
-
],
|
|
1615
|
-
"no-useless-escape": "off",
|
|
1616
|
-
"no-unused-expressions": [
|
|
1617
|
-
rules.noUnusedExpressions.level,
|
|
1618
|
-
{ allowShortCircuit: rules.noUnusedExpressions.allowShortCircuit }
|
|
1619
|
-
]
|
|
1620
|
-
},
|
|
1621
|
-
ignorePatterns: defaultLinterConfig.ignorePatterns
|
|
1622
|
-
},
|
|
2039
|
+
renderOxlintConfig({
|
|
2040
|
+
schemaPath: "./node_modules/oxlint/configuration_schema.json",
|
|
2041
|
+
react: true,
|
|
2042
|
+
typescript: true
|
|
2043
|
+
}),
|
|
1623
2044
|
null,
|
|
1624
2045
|
2
|
|
1625
2046
|
)
|
|
1626
2047
|
};
|
|
1627
2048
|
}
|
|
1628
|
-
function
|
|
2049
|
+
function renderEslintConfigPackage(files) {
|
|
1629
2050
|
const basePath = ".config/eslint";
|
|
1630
2051
|
files[`${basePath}/package.json`] = {
|
|
1631
2052
|
type: "text",
|
|
@@ -1732,7 +2153,7 @@ export default tseslint.config(
|
|
|
1732
2153
|
`
|
|
1733
2154
|
};
|
|
1734
2155
|
}
|
|
1735
|
-
function
|
|
2156
|
+
function renderPrettierConfigPackage(files) {
|
|
1736
2157
|
const basePath = ".config/prettier";
|
|
1737
2158
|
files[`${basePath}/package.json`] = {
|
|
1738
2159
|
type: "text",
|
|
@@ -1745,7 +2166,7 @@ function generatePrettierConfigPackage(files) {
|
|
|
1745
2166
|
exports: {
|
|
1746
2167
|
".": "./base.json"
|
|
1747
2168
|
},
|
|
1748
|
-
files: ["base.json"]
|
|
2169
|
+
files: ["base.json", "prettierignore"]
|
|
1749
2170
|
},
|
|
1750
2171
|
null,
|
|
1751
2172
|
2
|
|
@@ -1780,10 +2201,14 @@ Or in \`.prettierrc.json\`:
|
|
|
1780
2201
|
};
|
|
1781
2202
|
files[`${basePath}/base.json`] = {
|
|
1782
2203
|
type: "text",
|
|
1783
|
-
content: JSON.stringify(
|
|
2204
|
+
content: JSON.stringify(toPrettierConfig(), null, 2)
|
|
2205
|
+
};
|
|
2206
|
+
files[`${basePath}/prettierignore`] = {
|
|
2207
|
+
type: "text",
|
|
2208
|
+
content: toPrettierIgnoreContent()
|
|
1784
2209
|
};
|
|
1785
2210
|
}
|
|
1786
|
-
function
|
|
2211
|
+
function renderOxfmtConfigPackage(files) {
|
|
1787
2212
|
const basePath = ".config/oxfmt";
|
|
1788
2213
|
files[`${basePath}/package.json`] = {
|
|
1789
2214
|
type: "text",
|
|
@@ -1819,11 +2244,11 @@ oxfmt -c node_modules/@config/oxfmt/base.json --write .
|
|
|
1819
2244
|
};
|
|
1820
2245
|
files[`${basePath}/base.json`] = {
|
|
1821
2246
|
type: "text",
|
|
1822
|
-
content: JSON.stringify(
|
|
2247
|
+
content: JSON.stringify(toOxfmtConfig(), null, 2)
|
|
1823
2248
|
};
|
|
1824
2249
|
}
|
|
1825
2250
|
|
|
1826
|
-
function
|
|
2251
|
+
function renderMonorepo(params) {
|
|
1827
2252
|
const {
|
|
1828
2253
|
name,
|
|
1829
2254
|
linter,
|
|
@@ -1832,6 +2257,7 @@ function generateMonorepo(params) {
|
|
|
1832
2257
|
pnpmManageVersions,
|
|
1833
2258
|
engine,
|
|
1834
2259
|
versions = {},
|
|
2260
|
+
ide = "vscode",
|
|
1835
2261
|
aiPlatforms
|
|
1836
2262
|
} = params;
|
|
1837
2263
|
const files = {};
|
|
@@ -1844,6 +2270,7 @@ function generateMonorepo(params) {
|
|
|
1844
2270
|
}
|
|
1845
2271
|
if (linter === "oxlint") {
|
|
1846
2272
|
assignResolvedPackageVersion(devDependencies, versions, "oxlint");
|
|
2273
|
+
assignResolvedPackageVersion(devDependencies, versions, "oxlint-tsgolint");
|
|
1847
2274
|
} else if (linter === "eslint") {
|
|
1848
2275
|
assignResolvedPackageVersion(devDependencies, versions, "eslint");
|
|
1849
2276
|
} else if (linter === "biome") {
|
|
@@ -1859,13 +2286,7 @@ function generateMonorepo(params) {
|
|
|
1859
2286
|
version: "0.0.0",
|
|
1860
2287
|
private: true,
|
|
1861
2288
|
type: "module",
|
|
1862
|
-
scripts:
|
|
1863
|
-
dev: "pnpm --filter './apps/*' run dev",
|
|
1864
|
-
build: "pnpm --filter './packages/*' run build && pnpm --filter './apps/*' run build",
|
|
1865
|
-
test: "pnpm -r run test",
|
|
1866
|
-
lint: linter === "oxlint" ? "oxlint ." : linter === "biome" ? "biome check ." : "eslint .",
|
|
1867
|
-
format: formatter === "oxfmt" ? "oxfmt -c .config/oxfmt/base.json ." : formatter === "biome" ? "biome format . --write" : "prettier --config .config/prettier/base.json --write ."
|
|
1868
|
-
},
|
|
2289
|
+
scripts: packageJsonScripts.monorepoRoot(linter, formatter),
|
|
1869
2290
|
devDependencies
|
|
1870
2291
|
};
|
|
1871
2292
|
const engines = {};
|
|
@@ -1911,9 +2332,9 @@ function generateMonorepo(params) {
|
|
|
1911
2332
|
2
|
|
1912
2333
|
)
|
|
1913
2334
|
};
|
|
1914
|
-
|
|
2335
|
+
renderTypescriptConfigPackage(files);
|
|
1915
2336
|
if (linter === "oxlint") {
|
|
1916
|
-
|
|
2337
|
+
renderOxlintConfigPackage(files);
|
|
1917
2338
|
files["oxlint.json"] = {
|
|
1918
2339
|
type: "text",
|
|
1919
2340
|
content: JSON.stringify(
|
|
@@ -1926,7 +2347,7 @@ function generateMonorepo(params) {
|
|
|
1926
2347
|
)
|
|
1927
2348
|
};
|
|
1928
2349
|
} else if (linter === "eslint") {
|
|
1929
|
-
|
|
2350
|
+
renderEslintConfigPackage(files);
|
|
1930
2351
|
files["eslint.config.js"] = {
|
|
1931
2352
|
type: "text",
|
|
1932
2353
|
content: `import base from "@config/eslint/base";
|
|
@@ -1959,11 +2380,12 @@ export default [...base];
|
|
|
1959
2380
|
};
|
|
1960
2381
|
}
|
|
1961
2382
|
if (formatter === "oxfmt") {
|
|
1962
|
-
|
|
2383
|
+
renderOxfmtConfigPackage(files);
|
|
1963
2384
|
} else if (formatter === "prettier") {
|
|
1964
|
-
|
|
2385
|
+
renderPrettierConfigPackage(files);
|
|
1965
2386
|
}
|
|
1966
|
-
files[".
|
|
2387
|
+
files[".editorconfig"] = renderEditorConfig();
|
|
2388
|
+
files[".gitignore"] = renderGitignore("workspace-root");
|
|
1967
2389
|
files[".gitattributes"] = {
|
|
1968
2390
|
type: "text",
|
|
1969
2391
|
content: `* text=auto eol=lf
|
|
@@ -1971,7 +2393,9 @@ export default [...base];
|
|
|
1971
2393
|
*.{bat,[bB][aA][tT]} text eol=crlf
|
|
1972
2394
|
`
|
|
1973
2395
|
};
|
|
1974
|
-
|
|
2396
|
+
if (ide === "vscode") {
|
|
2397
|
+
renderVscodeFiles(files, linter, formatter, packageManager.name);
|
|
2398
|
+
}
|
|
1975
2399
|
files["README.md"] = {
|
|
1976
2400
|
type: "text",
|
|
1977
2401
|
content: `# ${name}
|
|
@@ -1999,104 +2423,50 @@ To add a new package to this workspace, run create-krispya from this directory a
|
|
|
1999
2423
|
`
|
|
2000
2424
|
};
|
|
2001
2425
|
if (aiPlatforms && aiPlatforms.length > 0) {
|
|
2002
|
-
|
|
2426
|
+
renderAiFiles(files, {
|
|
2003
2427
|
name,
|
|
2004
2428
|
packageManager: packageManager.name,
|
|
2005
2429
|
linter,
|
|
2006
2430
|
formatter,
|
|
2007
2431
|
isMonorepo: true,
|
|
2432
|
+
hasTypecheck: false,
|
|
2008
2433
|
platforms: aiPlatforms
|
|
2009
2434
|
});
|
|
2010
2435
|
}
|
|
2011
2436
|
return { files };
|
|
2012
2437
|
}
|
|
2013
|
-
function
|
|
2014
|
-
const recommendations = [];
|
|
2015
|
-
const settings = {};
|
|
2016
|
-
if (linter === "oxlint") {
|
|
2017
|
-
recommendations.push("oxc.oxc-vscode");
|
|
2018
|
-
settings["oxc.enable"] = true;
|
|
2019
|
-
settings["eslint.enable"] = false;
|
|
2020
|
-
settings["biome.enabled"] = false;
|
|
2021
|
-
} else if (linter === "eslint") {
|
|
2022
|
-
recommendations.push("dbaeumer.vscode-eslint");
|
|
2023
|
-
settings["eslint.enable"] = true;
|
|
2024
|
-
settings["oxc.enable"] = false;
|
|
2025
|
-
settings["biome.enabled"] = false;
|
|
2026
|
-
} else if (linter === "biome") {
|
|
2027
|
-
recommendations.push("biomejs.biome");
|
|
2028
|
-
settings["biome.enabled"] = true;
|
|
2029
|
-
settings["eslint.enable"] = false;
|
|
2030
|
-
settings["oxc.enable"] = false;
|
|
2031
|
-
}
|
|
2032
|
-
if (formatter === "oxfmt") {
|
|
2033
|
-
if (!recommendations.includes("oxc.oxc-vscode")) {
|
|
2034
|
-
recommendations.push("oxc.oxc-vscode");
|
|
2035
|
-
}
|
|
2036
|
-
settings["editor.defaultFormatter"] = "oxc.oxc-vscode";
|
|
2037
|
-
settings["[json]"] = {
|
|
2038
|
-
"editor.defaultFormatter": "vscode.json-language-features"
|
|
2039
|
-
};
|
|
2040
|
-
settings["[jsonc]"] = {
|
|
2041
|
-
"editor.defaultFormatter": "vscode.json-language-features"
|
|
2042
|
-
};
|
|
2043
|
-
} else if (formatter === "prettier") {
|
|
2044
|
-
recommendations.push("esbenp.prettier-vscode");
|
|
2045
|
-
settings["editor.defaultFormatter"] = "esbenp.prettier-vscode";
|
|
2046
|
-
} else if (formatter === "biome") {
|
|
2047
|
-
if (!recommendations.includes("biomejs.biome")) {
|
|
2048
|
-
recommendations.push("biomejs.biome");
|
|
2049
|
-
}
|
|
2050
|
-
settings["editor.defaultFormatter"] = "biomejs.biome";
|
|
2051
|
-
}
|
|
2052
|
-
files[".vscode/extensions.json"] = {
|
|
2053
|
-
type: "text",
|
|
2054
|
-
content: JSON.stringify({ recommendations }, null, 2)
|
|
2055
|
-
};
|
|
2056
|
-
const codeSnippets = {};
|
|
2057
|
-
if (recommendations.length > 0) {
|
|
2058
|
-
codeSnippets["vscode-extension-suggestion"] = recommendations;
|
|
2059
|
-
}
|
|
2438
|
+
function renderVscodeFiles(files, linter, formatter, packageManager = "pnpm") {
|
|
2060
2439
|
Object.assign(
|
|
2061
2440
|
files,
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2441
|
+
renderVscodeFiles$1({
|
|
2442
|
+
linter,
|
|
2443
|
+
formatter,
|
|
2444
|
+
isMonorepo: true,
|
|
2445
|
+
packageManager
|
|
2065
2446
|
})
|
|
2066
2447
|
);
|
|
2067
2448
|
}
|
|
2068
2449
|
|
|
2069
|
-
const monorepo = {
|
|
2070
|
-
__proto__: null,
|
|
2071
|
-
generateEslintConfigPackage: generateEslintConfigPackage,
|
|
2072
|
-
generateMonorepo: generateMonorepo,
|
|
2073
|
-
generateOxfmtConfigPackage: generateOxfmtConfigPackage,
|
|
2074
|
-
generateOxlintConfigPackage: generateOxlintConfigPackage,
|
|
2075
|
-
generatePrettierConfigPackage: generatePrettierConfigPackage,
|
|
2076
|
-
generateTypescriptConfigPackage: generateTypescriptConfigPackage,
|
|
2077
|
-
generateVscodeFiles: generateVscodeFiles
|
|
2078
|
-
};
|
|
2079
|
-
|
|
2080
2450
|
function toBiomeLevel(level) {
|
|
2081
2451
|
return level;
|
|
2082
2452
|
}
|
|
2083
|
-
function
|
|
2453
|
+
function planBiome(builder, options) {
|
|
2084
2454
|
if (options == null || !options.linter && !options.formatter) {
|
|
2085
2455
|
return;
|
|
2086
2456
|
}
|
|
2087
|
-
const version =
|
|
2088
|
-
|
|
2089
|
-
const { rules } = defaultLinterConfig;
|
|
2457
|
+
const version = builder.getVersion("@biomejs/biome");
|
|
2458
|
+
builder.addDevDependency("@biomejs/biome");
|
|
2090
2459
|
const biomeConfig = {
|
|
2091
2460
|
$schema: `https://biomejs.dev/schemas/${version}/schema.json`
|
|
2092
2461
|
};
|
|
2093
2462
|
if (options.linter) {
|
|
2463
|
+
const linterConfig = options.linter.config;
|
|
2094
2464
|
biomeConfig.linter = {
|
|
2095
2465
|
enabled: true,
|
|
2096
2466
|
rules: {
|
|
2097
2467
|
recommended: true,
|
|
2098
2468
|
correctness: {
|
|
2099
|
-
noUnusedVariables: toBiomeLevel(rules.noUnusedVars.level)
|
|
2469
|
+
noUnusedVariables: toBiomeLevel(linterConfig.rules.noUnusedVars.level)
|
|
2100
2470
|
}
|
|
2101
2471
|
}
|
|
2102
2472
|
};
|
|
@@ -2106,19 +2476,20 @@ function generateBiome(generator, options) {
|
|
|
2106
2476
|
};
|
|
2107
2477
|
}
|
|
2108
2478
|
if (options.formatter) {
|
|
2479
|
+
const formatterConfig = options.formatter.config;
|
|
2109
2480
|
biomeConfig.formatter = {
|
|
2110
2481
|
enabled: true,
|
|
2111
|
-
lineWidth:
|
|
2112
|
-
indentWidth:
|
|
2113
|
-
indentStyle: "space"
|
|
2482
|
+
lineWidth: formatterConfig.printWidth,
|
|
2483
|
+
indentWidth: formatterConfig.tabWidth,
|
|
2484
|
+
indentStyle: formatterConfig.useTabs ? "tab" : "space"
|
|
2114
2485
|
};
|
|
2115
2486
|
biomeConfig.javascript = {
|
|
2116
2487
|
formatter: {
|
|
2117
|
-
semicolons: "always" ,
|
|
2118
|
-
quoteStyle: "single" ,
|
|
2119
|
-
trailingCommas:
|
|
2120
|
-
bracketSpacing:
|
|
2121
|
-
arrowParentheses: "always"
|
|
2488
|
+
semicolons: formatterConfig.semi ? "always" : "asNeeded",
|
|
2489
|
+
quoteStyle: formatterConfig.singleQuote ? "single" : "double",
|
|
2490
|
+
trailingCommas: formatterConfig.trailingComma,
|
|
2491
|
+
bracketSpacing: formatterConfig.bracketSpacing,
|
|
2492
|
+
arrowParentheses: formatterConfig.arrowParens === "always" ? "always" : "asNeeded"
|
|
2122
2493
|
}
|
|
2123
2494
|
};
|
|
2124
2495
|
biomeConfig.json = {
|
|
@@ -2131,53 +2502,48 @@ function generateBiome(generator, options) {
|
|
|
2131
2502
|
enabled: false
|
|
2132
2503
|
};
|
|
2133
2504
|
}
|
|
2134
|
-
const isStealth =
|
|
2505
|
+
const isStealth = builder.isStealthConfig();
|
|
2135
2506
|
if (isStealth) {
|
|
2136
|
-
|
|
2507
|
+
builder.addFile(".config/biome.json", {
|
|
2137
2508
|
type: "text",
|
|
2138
2509
|
content: JSON.stringify(biomeConfig, null, 2)
|
|
2139
2510
|
});
|
|
2140
2511
|
if (options.linter) {
|
|
2141
|
-
|
|
2512
|
+
builder.addScripts(packageJsonScripts.lint.biome(".config"));
|
|
2142
2513
|
}
|
|
2143
2514
|
if (options.formatter) {
|
|
2144
|
-
|
|
2515
|
+
builder.addScripts(packageJsonScripts.format.biome(".config"));
|
|
2145
2516
|
}
|
|
2146
|
-
generator.addVscodeSetting("biome.linter.configPath", ".config/biome.json");
|
|
2147
2517
|
} else {
|
|
2148
|
-
|
|
2518
|
+
builder.addFile("biome.json", {
|
|
2149
2519
|
type: "text",
|
|
2150
2520
|
content: JSON.stringify(biomeConfig, null, 2)
|
|
2151
2521
|
});
|
|
2152
2522
|
if (options.linter) {
|
|
2153
|
-
|
|
2523
|
+
builder.addScripts(packageJsonScripts.lint.biome());
|
|
2154
2524
|
}
|
|
2155
2525
|
if (options.formatter) {
|
|
2156
|
-
|
|
2526
|
+
builder.addScripts(packageJsonScripts.format.biome());
|
|
2157
2527
|
}
|
|
2158
2528
|
}
|
|
2159
2529
|
const roles = [];
|
|
2160
2530
|
if (options.linter) roles.push("linter");
|
|
2161
2531
|
if (options.formatter) roles.push("formatter");
|
|
2162
|
-
|
|
2532
|
+
builder.inject(
|
|
2163
2533
|
"readme-tools",
|
|
2164
2534
|
`[Biome](https://biomejs.dev/) - Fast ${roles.join(" and ")} for JavaScript and TypeScript`
|
|
2165
2535
|
);
|
|
2166
|
-
|
|
2167
|
-
generator.addVscodeSetting("biome.enabled", true);
|
|
2168
|
-
if (options.formatter) {
|
|
2169
|
-
generator.addVscodeSetting("editor.defaultFormatter", "biomejs.biome");
|
|
2170
|
-
}
|
|
2536
|
+
builder.inject("vscode-extension-suggestion", "biomejs.biome");
|
|
2171
2537
|
}
|
|
2172
2538
|
|
|
2173
|
-
function
|
|
2539
|
+
function planDrei(builder, options) {
|
|
2174
2540
|
if (options == null) {
|
|
2175
2541
|
return;
|
|
2176
2542
|
}
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2543
|
+
builder.addDependency("@react-three/drei");
|
|
2544
|
+
builder.inject("import", `import { Environment } from "@react-three/drei"`);
|
|
2545
|
+
builder.inject("scene", '<Environment background preset="city" />');
|
|
2546
|
+
builder.inject(
|
|
2181
2547
|
"readme-libraries",
|
|
2182
2548
|
`[@react-three/drei](https://drei.docs.pmnd.rs/) - Useful helpers for @react-three/fiber`
|
|
2183
2549
|
);
|
|
@@ -2186,25 +2552,28 @@ function generateDrei(generator, options) {
|
|
|
2186
2552
|
function toEslintLevel(level) {
|
|
2187
2553
|
return level;
|
|
2188
2554
|
}
|
|
2189
|
-
function
|
|
2190
|
-
|
|
2191
|
-
|
|
2555
|
+
function planEslint(builder, options) {
|
|
2556
|
+
if (options == null) {
|
|
2557
|
+
return;
|
|
2558
|
+
}
|
|
2559
|
+
builder.addDevDependency("eslint");
|
|
2560
|
+
const template = builder.options.template ?? "vanilla";
|
|
2192
2561
|
const baseTemplate = getBaseTemplate(template);
|
|
2193
2562
|
const isTypescript = getLanguageFromTemplate(template) === "typescript";
|
|
2194
2563
|
const isReact = baseTemplate === "react" || baseTemplate === "r3f";
|
|
2195
|
-
const { rules } =
|
|
2564
|
+
const { rules } = options.config;
|
|
2196
2565
|
const imports = ['import js from "@eslint/js"'];
|
|
2197
2566
|
const configs = ["js.configs.recommended"];
|
|
2198
2567
|
if (isTypescript) {
|
|
2199
|
-
|
|
2568
|
+
builder.addDevDependency("typescript-eslint");
|
|
2200
2569
|
imports.push('import tseslint from "typescript-eslint"');
|
|
2201
2570
|
configs.push("...tseslint.configs.recommended");
|
|
2202
2571
|
}
|
|
2203
2572
|
if (isReact) {
|
|
2204
|
-
|
|
2573
|
+
builder.addDevDependency("eslint-plugin-react-hooks");
|
|
2205
2574
|
imports.push('import reactHooks from "eslint-plugin-react-hooks"');
|
|
2206
2575
|
}
|
|
2207
|
-
const ignoresArray = JSON.stringify(
|
|
2576
|
+
const ignoresArray = JSON.stringify(options.config.ignorePatterns);
|
|
2208
2577
|
const unusedVarsRule = isTypescript ? "@typescript-eslint/no-unused-vars" : "no-unused-vars";
|
|
2209
2578
|
const rulesConfig = {
|
|
2210
2579
|
[unusedVarsRule]: [
|
|
@@ -2238,34 +2607,30 @@ function generateEslint(generator, options) {
|
|
|
2238
2607
|
},`,
|
|
2239
2608
|
"]"
|
|
2240
2609
|
].filter(Boolean).join("\n");
|
|
2241
|
-
const isStealth =
|
|
2610
|
+
const isStealth = builder.isStealthConfig();
|
|
2242
2611
|
if (isStealth) {
|
|
2243
|
-
|
|
2612
|
+
builder.addFile(".config/eslint.config.js", {
|
|
2244
2613
|
type: "text",
|
|
2245
2614
|
content: configContent
|
|
2246
2615
|
});
|
|
2247
|
-
|
|
2248
|
-
generator.addVscodeSetting("eslint.options", {
|
|
2249
|
-
overrideConfigFile: ".config/eslint.config.js"
|
|
2250
|
-
});
|
|
2616
|
+
builder.addScripts(packageJsonScripts.lint.eslint(".config/eslint.config.js"));
|
|
2251
2617
|
} else {
|
|
2252
|
-
|
|
2618
|
+
builder.addFile("eslint.config.js", {
|
|
2253
2619
|
type: "text",
|
|
2254
2620
|
content: configContent
|
|
2255
2621
|
});
|
|
2256
|
-
|
|
2622
|
+
builder.addScripts(packageJsonScripts.lint.eslint());
|
|
2257
2623
|
}
|
|
2258
|
-
|
|
2624
|
+
builder.inject(
|
|
2259
2625
|
"readme-tools",
|
|
2260
2626
|
"[ESLint](https://eslint.org/) - Linter for JavaScript and TypeScript"
|
|
2261
2627
|
);
|
|
2262
|
-
|
|
2263
|
-
generator.addVscodeSetting("eslint.enable", true);
|
|
2628
|
+
builder.inject("vscode-extension-suggestion", "dbaeumer.vscode-eslint");
|
|
2264
2629
|
}
|
|
2265
2630
|
|
|
2266
|
-
function
|
|
2267
|
-
|
|
2268
|
-
|
|
2631
|
+
function planFiber(builder, _options) {
|
|
2632
|
+
builder.inject("import", `import { Box } from "./box.js"`);
|
|
2633
|
+
builder.inject(
|
|
2269
2634
|
"scene",
|
|
2270
2635
|
[
|
|
2271
2636
|
`<ambientLight intensity={Math.PI / 2} />`,
|
|
@@ -2275,7 +2640,7 @@ function generateFiber(generator, _options) {
|
|
|
2275
2640
|
`<Box position={[1.2, 0, 0]} />`
|
|
2276
2641
|
].join("\n")
|
|
2277
2642
|
);
|
|
2278
|
-
|
|
2643
|
+
builder.addFile("src/box.tsx", {
|
|
2279
2644
|
type: "text",
|
|
2280
2645
|
content: `import type { Mesh } from 'three'
|
|
2281
2646
|
import { useRef, useState } from 'react'
|
|
@@ -2302,11 +2667,11 @@ export function Box(props: ThreeElements['mesh']) {
|
|
|
2302
2667
|
});
|
|
2303
2668
|
}
|
|
2304
2669
|
|
|
2305
|
-
function
|
|
2306
|
-
if (options === false || getPackageManagerName(
|
|
2670
|
+
function planGithubPages(builder, options) {
|
|
2671
|
+
if (options === false || getPackageManagerName(builder.options.packageManager) !== "npm") {
|
|
2307
2672
|
return;
|
|
2308
2673
|
}
|
|
2309
|
-
|
|
2674
|
+
builder.addFile(".github/workflows/gh-pages.yml", {
|
|
2310
2675
|
type: "text",
|
|
2311
2676
|
content: `name: Deploy to Github Pages
|
|
2312
2677
|
|
|
@@ -2352,10 +2717,10 @@ jobs:
|
|
|
2352
2717
|
uses: actions/deploy-pages@v4
|
|
2353
2718
|
`
|
|
2354
2719
|
});
|
|
2355
|
-
|
|
2356
|
-
if (
|
|
2357
|
-
const address = `${
|
|
2358
|
-
|
|
2720
|
+
builder.inject("readme-start", `A github pages deployment action is configurd.`);
|
|
2721
|
+
if (builder.options.githubUserName != null && builder.options.githubRepoName != null) {
|
|
2722
|
+
const address = `${builder.options.githubUserName}.github.io/${builder.options.githubRepoName}`;
|
|
2723
|
+
builder.inject(
|
|
2359
2724
|
"readme-start",
|
|
2360
2725
|
`Your app will be publish at [${address}](https://${address}) once the github action is finished.
|
|
2361
2726
|
`
|
|
@@ -2363,228 +2728,199 @@ jobs:
|
|
|
2363
2728
|
}
|
|
2364
2729
|
}
|
|
2365
2730
|
|
|
2366
|
-
function
|
|
2731
|
+
function planHandle(builder, options) {
|
|
2367
2732
|
if (options == null) {
|
|
2368
2733
|
return;
|
|
2369
2734
|
}
|
|
2370
|
-
|
|
2371
|
-
|
|
2735
|
+
builder.addDependency("@react-three/handle");
|
|
2736
|
+
builder.inject(
|
|
2372
2737
|
"readme-libraries",
|
|
2373
2738
|
`[@react-three/handle](https://pmndrs.github.io/xr/docs/handles/introduction) - interactive controls and handles for your 3D objects`
|
|
2374
2739
|
);
|
|
2375
2740
|
}
|
|
2376
2741
|
|
|
2377
|
-
function
|
|
2742
|
+
function planKoota(builder, options) {
|
|
2378
2743
|
if (options == null) {
|
|
2379
2744
|
return;
|
|
2380
2745
|
}
|
|
2381
|
-
|
|
2382
|
-
|
|
2746
|
+
builder.addDependency("koota");
|
|
2747
|
+
builder.inject(
|
|
2383
2748
|
"readme-libraries",
|
|
2384
2749
|
`[koota](https://github.com/pmndrs/koota) - ECS-based state management library optimized for real-time apps, games, and XR experiences`
|
|
2385
2750
|
);
|
|
2386
2751
|
}
|
|
2387
2752
|
|
|
2388
|
-
function
|
|
2753
|
+
function planLeva(builder, options) {
|
|
2389
2754
|
if (options == null) {
|
|
2390
2755
|
return;
|
|
2391
2756
|
}
|
|
2392
|
-
|
|
2393
|
-
|
|
2757
|
+
builder.addDependency("leva");
|
|
2758
|
+
builder.inject(
|
|
2394
2759
|
"readme-libraries",
|
|
2395
2760
|
`[leva](https://github.com/pmndrs/leva) - HTML GUI panel for React with lightweight, beautiful and extensible controls`
|
|
2396
2761
|
);
|
|
2397
2762
|
}
|
|
2398
2763
|
|
|
2399
|
-
function
|
|
2764
|
+
function planOffscreen(builder, options) {
|
|
2400
2765
|
if (options == null) {
|
|
2401
2766
|
return;
|
|
2402
2767
|
}
|
|
2403
|
-
if (
|
|
2768
|
+
if (builder.options.xr != null) {
|
|
2404
2769
|
console.info(
|
|
2405
2770
|
color__default.blue("Info:"),
|
|
2406
2771
|
"@react-three/offscreen is disabled because it is not supported with XR"
|
|
2407
2772
|
);
|
|
2408
2773
|
return;
|
|
2409
2774
|
}
|
|
2410
|
-
|
|
2411
|
-
|
|
2775
|
+
builder.addDependency("@react-three/offscreen");
|
|
2776
|
+
builder.inject(
|
|
2412
2777
|
"readme-libraries",
|
|
2413
2778
|
`[@react-three/offscreen](https://github.com/pmndrs/offscreen) - Offload your scene to a worker thread for better performance`
|
|
2414
2779
|
);
|
|
2415
2780
|
}
|
|
2416
2781
|
|
|
2417
|
-
function
|
|
2418
|
-
|
|
2782
|
+
function planOxfmt(builder, options) {
|
|
2783
|
+
if (options == null) {
|
|
2784
|
+
return;
|
|
2785
|
+
}
|
|
2786
|
+
const isMonorepo = builder.options.workspaceRoot != null;
|
|
2419
2787
|
if (isMonorepo) {
|
|
2420
|
-
|
|
2788
|
+
builder.addDevDependency("@config/oxfmt", { version: "workspace:*" });
|
|
2421
2789
|
const configPath = "node_modules/@config/oxfmt/base.json";
|
|
2422
|
-
|
|
2423
|
-
generator.addVscodeSetting("oxc.fmt.configPath", configPath);
|
|
2790
|
+
builder.addScripts(packageJsonScripts.format.oxfmt(configPath));
|
|
2424
2791
|
} else {
|
|
2425
|
-
|
|
2426
|
-
const isStealth =
|
|
2792
|
+
builder.addDevDependency("oxfmt");
|
|
2793
|
+
const isStealth = builder.isStealthConfig();
|
|
2427
2794
|
if (isStealth) {
|
|
2428
|
-
|
|
2795
|
+
builder.addFile(".config/oxfmt.json", {
|
|
2429
2796
|
type: "text",
|
|
2430
|
-
content: JSON.stringify(
|
|
2797
|
+
content: JSON.stringify(toOxfmtConfig(options.config), null, 2)
|
|
2431
2798
|
});
|
|
2432
|
-
|
|
2433
|
-
generator.addVscodeSetting("oxc.fmt.configPath", ".config/oxfmt.json");
|
|
2799
|
+
builder.addScripts(packageJsonScripts.format.oxfmt(".config/oxfmt.json"));
|
|
2434
2800
|
} else {
|
|
2435
|
-
|
|
2801
|
+
builder.addFile("oxfmt.json", {
|
|
2436
2802
|
type: "text",
|
|
2437
|
-
content: JSON.stringify(
|
|
2803
|
+
content: JSON.stringify(toOxfmtConfig(options.config), null, 2)
|
|
2438
2804
|
});
|
|
2439
|
-
|
|
2805
|
+
builder.addScripts(packageJsonScripts.format.oxfmt("oxfmt.json"));
|
|
2440
2806
|
}
|
|
2441
2807
|
}
|
|
2442
|
-
|
|
2808
|
+
builder.inject(
|
|
2443
2809
|
"readme-tools",
|
|
2444
2810
|
"[Oxfmt](https://oxc.rs/docs/guide/usage/formatter) - Fast Prettier-compatible code formatter"
|
|
2445
2811
|
);
|
|
2446
|
-
|
|
2447
|
-
generator.addVscodeSetting("editor.defaultFormatter", "oxc.oxc-vscode");
|
|
2448
|
-
generator.addVscodeSetting("[json]", {
|
|
2449
|
-
"editor.defaultFormatter": "vscode.json-language-features"
|
|
2450
|
-
});
|
|
2451
|
-
generator.addVscodeSetting("[jsonc]", {
|
|
2452
|
-
"editor.defaultFormatter": "vscode.json-language-features"
|
|
2453
|
-
});
|
|
2454
|
-
generator.addVscodeSetting("[markdown]", {
|
|
2455
|
-
"editor.defaultFormatter": "vscode.markdown-language-features"
|
|
2456
|
-
});
|
|
2457
|
-
generator.addVscodeSetting("[yaml]", {
|
|
2458
|
-
"editor.defaultFormatter": "redhat.vscode-yaml"
|
|
2459
|
-
});
|
|
2812
|
+
builder.inject("vscode-extension-suggestion", "oxc.oxc-vscode");
|
|
2460
2813
|
}
|
|
2461
2814
|
|
|
2462
|
-
function
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
const template =
|
|
2815
|
+
function planOxlint(builder, options) {
|
|
2816
|
+
if (options == null) {
|
|
2817
|
+
return;
|
|
2818
|
+
}
|
|
2819
|
+
const template = builder.options.template ?? "vanilla";
|
|
2467
2820
|
const baseTemplate = getBaseTemplate(template);
|
|
2821
|
+
const isTypescript = getLanguageFromTemplate(template) === "typescript";
|
|
2468
2822
|
const isReact = baseTemplate === "react" || baseTemplate === "r3f";
|
|
2469
|
-
const isMonorepo =
|
|
2823
|
+
const isMonorepo = builder.options.workspaceRoot != null;
|
|
2470
2824
|
if (isMonorepo) {
|
|
2471
|
-
|
|
2825
|
+
builder.addDevDependency("@config/oxlint", { version: "workspace:*" });
|
|
2472
2826
|
const configPath = isReact ? "node_modules/@config/oxlint/react.json" : "node_modules/@config/oxlint/base.json";
|
|
2473
|
-
|
|
2474
|
-
generator.addVscodeSetting("oxc.configPath", configPath);
|
|
2827
|
+
builder.addScripts(packageJsonScripts.lint.oxlint(configPath));
|
|
2475
2828
|
} else {
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
"no-unused-vars": [
|
|
2488
|
-
toOxlintLevel(rules.noUnusedVars.level),
|
|
2489
|
-
{
|
|
2490
|
-
argsIgnorePattern: rules.noUnusedVars.argsIgnorePattern,
|
|
2491
|
-
varsIgnorePattern: rules.noUnusedVars.varsIgnorePattern,
|
|
2492
|
-
caughtErrorsIgnorePattern: rules.noUnusedVars.caughtErrorsIgnorePattern
|
|
2493
|
-
}
|
|
2494
|
-
],
|
|
2495
|
-
"no-useless-escape": "off",
|
|
2496
|
-
"no-unused-expressions": [
|
|
2497
|
-
toOxlintLevel(rules.noUnusedExpressions.level),
|
|
2498
|
-
{ allowShortCircuit: rules.noUnusedExpressions.allowShortCircuit }
|
|
2499
|
-
]
|
|
2500
|
-
},
|
|
2501
|
-
ignorePatterns: defaultLinterConfig.ignorePatterns
|
|
2502
|
-
};
|
|
2829
|
+
builder.addDevDependency("oxlint");
|
|
2830
|
+
if (isTypescript) {
|
|
2831
|
+
builder.addDevDependency("oxlint-tsgolint");
|
|
2832
|
+
}
|
|
2833
|
+
const isStealth = builder.isStealthConfig();
|
|
2834
|
+
const oxlintConfig = renderOxlintConfig({
|
|
2835
|
+
schemaPath: isStealth ? "../node_modules/oxlint/configuration_schema.json" : "./node_modules/oxlint/configuration_schema.json",
|
|
2836
|
+
react: isReact,
|
|
2837
|
+
typescript: isTypescript,
|
|
2838
|
+
config: options.config
|
|
2839
|
+
});
|
|
2503
2840
|
if (isStealth) {
|
|
2504
|
-
|
|
2841
|
+
builder.addFile(".config/oxlint.json", {
|
|
2505
2842
|
type: "text",
|
|
2506
2843
|
content: JSON.stringify(oxlintConfig, null, 2)
|
|
2507
2844
|
});
|
|
2508
|
-
|
|
2509
|
-
generator.addVscodeSetting("oxc.configPath", ".config/oxlint.json");
|
|
2845
|
+
builder.addScripts(packageJsonScripts.lint.oxlint(".config/oxlint.json"));
|
|
2510
2846
|
} else {
|
|
2511
|
-
|
|
2847
|
+
builder.addFile("oxlint.json", {
|
|
2512
2848
|
type: "text",
|
|
2513
2849
|
content: JSON.stringify(oxlintConfig, null, 2)
|
|
2514
2850
|
});
|
|
2515
|
-
|
|
2851
|
+
builder.addScripts(packageJsonScripts.lint.oxlint());
|
|
2516
2852
|
}
|
|
2517
2853
|
}
|
|
2518
|
-
|
|
2854
|
+
builder.inject(
|
|
2519
2855
|
"readme-tools",
|
|
2520
2856
|
"[Oxlint](https://oxc.rs/docs/guide/usage/linter) - A fast linter for JavaScript and TypeScript"
|
|
2521
2857
|
);
|
|
2522
|
-
|
|
2523
|
-
generator.addVscodeSetting("oxc.enable", true);
|
|
2858
|
+
builder.inject("vscode-extension-suggestion", "oxc.oxc-vscode");
|
|
2524
2859
|
}
|
|
2525
2860
|
|
|
2526
|
-
function
|
|
2861
|
+
function planPostprocessing(builder, options) {
|
|
2527
2862
|
if (options == null) {
|
|
2528
2863
|
return;
|
|
2529
2864
|
}
|
|
2530
|
-
if (
|
|
2865
|
+
if (builder.options.xr != null) {
|
|
2531
2866
|
console.info(
|
|
2532
2867
|
color__default.blue("Info:"),
|
|
2533
2868
|
"@react-three/postprocessing is disabled because it is not supported with XR"
|
|
2534
2869
|
);
|
|
2535
2870
|
return;
|
|
2536
2871
|
}
|
|
2537
|
-
|
|
2538
|
-
|
|
2872
|
+
builder.addDependency("@react-three/postprocessing");
|
|
2873
|
+
builder.inject(
|
|
2539
2874
|
"readme-libraries",
|
|
2540
2875
|
`[@react-three/postprocessing](https://react-postprocessing.docs.pmnd.rs/) - Post-processing effects for @react-three/fiber`
|
|
2541
2876
|
);
|
|
2542
2877
|
}
|
|
2543
2878
|
|
|
2544
|
-
function
|
|
2545
|
-
|
|
2546
|
-
|
|
2879
|
+
function planPrettier(builder, options) {
|
|
2880
|
+
if (options == null) {
|
|
2881
|
+
return;
|
|
2882
|
+
}
|
|
2883
|
+
builder.addDevDependency("prettier");
|
|
2884
|
+
const isStealth = builder.isStealthConfig();
|
|
2547
2885
|
if (isStealth) {
|
|
2548
|
-
|
|
2886
|
+
builder.addFile(".config/prettier.json", {
|
|
2887
|
+
type: "text",
|
|
2888
|
+
content: JSON.stringify(toPrettierConfig(options.config), null, 2)
|
|
2889
|
+
});
|
|
2890
|
+
builder.addFile(".config/prettierignore", {
|
|
2549
2891
|
type: "text",
|
|
2550
|
-
content:
|
|
2892
|
+
content: toPrettierIgnoreContent(options.config)
|
|
2551
2893
|
});
|
|
2552
|
-
|
|
2553
|
-
|
|
2894
|
+
builder.addScripts(
|
|
2895
|
+
packageJsonScripts.format.prettier(".config/prettier.json", ".config/prettierignore")
|
|
2896
|
+
);
|
|
2554
2897
|
} else {
|
|
2555
|
-
|
|
2898
|
+
builder.addFile(".prettierrc", {
|
|
2556
2899
|
type: "text",
|
|
2557
|
-
content: JSON.stringify(
|
|
2900
|
+
content: JSON.stringify(toPrettierConfig(options.config), null, 2)
|
|
2558
2901
|
});
|
|
2559
|
-
|
|
2902
|
+
builder.addFile(".prettierignore", {
|
|
2903
|
+
type: "text",
|
|
2904
|
+
content: toPrettierIgnoreContent(options.config)
|
|
2905
|
+
});
|
|
2906
|
+
builder.addScripts(packageJsonScripts.format.prettier());
|
|
2560
2907
|
}
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
generator.addVscodeSetting("editor.defaultFormatter", "esbenp.prettier-vscode");
|
|
2908
|
+
builder.inject("readme-tools", "[Prettier](https://prettier.io/) - Opinionated code formatter");
|
|
2909
|
+
builder.inject("vscode-extension-suggestion", "esbenp.prettier-vscode");
|
|
2564
2910
|
}
|
|
2565
2911
|
|
|
2566
|
-
function
|
|
2912
|
+
function planRapier(builder, options) {
|
|
2567
2913
|
if (options == null) {
|
|
2568
2914
|
return;
|
|
2569
2915
|
}
|
|
2570
|
-
|
|
2571
|
-
|
|
2916
|
+
builder.addDependency("@react-three/rapier");
|
|
2917
|
+
builder.inject(
|
|
2572
2918
|
"readme-libraries",
|
|
2573
2919
|
`[@react-three/rapier](https://github.com/pmndrs/react-three-rapier) - Physics based on Rapier for your @react-three/fiber scene`
|
|
2574
2920
|
);
|
|
2575
2921
|
}
|
|
2576
2922
|
|
|
2577
|
-
function
|
|
2578
|
-
const set = /* @__PURE__ */ new Set();
|
|
2579
|
-
for (const arr of array) {
|
|
2580
|
-
for (const item of arr) {
|
|
2581
|
-
set.add(item);
|
|
2582
|
-
}
|
|
2583
|
-
}
|
|
2584
|
-
return Array.from(set);
|
|
2585
|
-
}
|
|
2586
|
-
|
|
2587
|
-
function generateProvidersModule(generator) {
|
|
2923
|
+
function generateProvidersModule(builder) {
|
|
2588
2924
|
const canvasProviders = [];
|
|
2589
2925
|
const globalProviders = [];
|
|
2590
2926
|
const providerDefs = {
|
|
@@ -2650,13 +2986,13 @@ function generateProvidersModule(generator) {
|
|
|
2650
2986
|
]
|
|
2651
2987
|
}
|
|
2652
2988
|
};
|
|
2653
|
-
if (
|
|
2989
|
+
if (builder.options.rapier) {
|
|
2654
2990
|
canvasProviders.push("rapier");
|
|
2655
2991
|
}
|
|
2656
|
-
if (!!
|
|
2992
|
+
if (!!builder.options.postprocessing && !builder.options.xr) {
|
|
2657
2993
|
canvasProviders.push("postprocessing");
|
|
2658
2994
|
}
|
|
2659
|
-
if (
|
|
2995
|
+
if (builder.options.uikit) {
|
|
2660
2996
|
globalProviders.push("uikit");
|
|
2661
2997
|
}
|
|
2662
2998
|
function generateProviderFunction(name, { jsdoc, providers }) {
|
|
@@ -2719,20 +3055,20 @@ ${jsdoc.split("\n").map((line) => ` * ${line}`).join("\n")}
|
|
|
2719
3055
|
${canvas.code}
|
|
2720
3056
|
`;
|
|
2721
3057
|
}
|
|
2722
|
-
function
|
|
3058
|
+
function planTriplex(builder, options) {
|
|
2723
3059
|
if (options == null) {
|
|
2724
3060
|
return;
|
|
2725
3061
|
}
|
|
2726
|
-
|
|
2727
|
-
|
|
3062
|
+
builder.inject("vscode-extension-suggestion", "trytriplex.triplex-vsce");
|
|
3063
|
+
builder.inject(
|
|
2728
3064
|
"readme-tools",
|
|
2729
3065
|
`[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).`
|
|
2730
3066
|
);
|
|
2731
|
-
|
|
2732
|
-
content: generateProvidersModule(
|
|
3067
|
+
builder.addFile(".triplex/providers.tsx", {
|
|
3068
|
+
content: generateProvidersModule(builder),
|
|
2733
3069
|
type: "text"
|
|
2734
3070
|
});
|
|
2735
|
-
|
|
3071
|
+
builder.addFile(".triplex/config.json", {
|
|
2736
3072
|
content: JSON.stringify(
|
|
2737
3073
|
{
|
|
2738
3074
|
$schema: "https://triplex.dev/config.schema.json",
|
|
@@ -2745,9 +3081,9 @@ function generateTriplex(generator, options) {
|
|
|
2745
3081
|
});
|
|
2746
3082
|
}
|
|
2747
3083
|
|
|
2748
|
-
function
|
|
2749
|
-
|
|
2750
|
-
const template =
|
|
3084
|
+
function planTsdown(builder) {
|
|
3085
|
+
builder.addDevDependency("tsdown");
|
|
3086
|
+
const template = builder.options.template ?? "vanilla";
|
|
2751
3087
|
const baseTemplate = getBaseTemplate(template);
|
|
2752
3088
|
const language = getLanguageFromTemplate(template);
|
|
2753
3089
|
const isReact = baseTemplate === "react" || baseTemplate === "r3f";
|
|
@@ -2767,36 +3103,36 @@ function generateTsdown(generator) {
|
|
|
2767
3103
|
configLines.push(` },`);
|
|
2768
3104
|
}
|
|
2769
3105
|
configLines.push(`})`);
|
|
2770
|
-
|
|
3106
|
+
builder.addFile(`tsdown.config.${ext}`, {
|
|
2771
3107
|
type: "text",
|
|
2772
3108
|
content: configLines.join("\n")
|
|
2773
3109
|
});
|
|
2774
|
-
|
|
2775
|
-
|
|
3110
|
+
builder.addScripts(packageJsonScripts.build.tsdown);
|
|
3111
|
+
builder.inject(
|
|
2776
3112
|
"readme-libraries",
|
|
2777
3113
|
"[tsdown](https://github.com/nicepkg/tsdown) - Fast TypeScript bundler powered by esbuild"
|
|
2778
3114
|
);
|
|
2779
3115
|
}
|
|
2780
3116
|
|
|
2781
|
-
function
|
|
3117
|
+
function planUikit(builder, options) {
|
|
2782
3118
|
if (options == null) {
|
|
2783
3119
|
return;
|
|
2784
3120
|
}
|
|
2785
|
-
|
|
2786
|
-
|
|
3121
|
+
builder.addDependency("@react-three/uikit");
|
|
3122
|
+
builder.inject(
|
|
2787
3123
|
"readme-libraries",
|
|
2788
3124
|
`[@react-three/uikit](https://pmndrs.github.io/uikit/docs/) - UI primitives for React Three Fiber`
|
|
2789
3125
|
);
|
|
2790
3126
|
}
|
|
2791
3127
|
|
|
2792
|
-
function
|
|
2793
|
-
|
|
2794
|
-
const template =
|
|
3128
|
+
function planUnbuild(builder) {
|
|
3129
|
+
builder.addDevDependency("unbuild");
|
|
3130
|
+
const template = builder.options.template ?? "vanilla";
|
|
2795
3131
|
const baseTemplate = getBaseTemplate(template);
|
|
2796
3132
|
const language = getLanguageFromTemplate(template);
|
|
2797
3133
|
const isReact = baseTemplate === "react" || baseTemplate === "r3f";
|
|
2798
3134
|
const ext = language === "typescript" ? "ts" : "js";
|
|
2799
|
-
const isMonorepo =
|
|
3135
|
+
const isMonorepo = builder.options.workspaceRoot != null;
|
|
2800
3136
|
const buildConfigLines = [
|
|
2801
3137
|
`import { defineBuildConfig } from "unbuild"`,
|
|
2802
3138
|
``,
|
|
@@ -2814,51 +3150,54 @@ function generateUnbuild(generator) {
|
|
|
2814
3150
|
}
|
|
2815
3151
|
buildConfigLines.push(` },`);
|
|
2816
3152
|
buildConfigLines.push(`})`);
|
|
2817
|
-
const isStealth =
|
|
3153
|
+
const isStealth = builder.isStealthConfig() && !isMonorepo;
|
|
2818
3154
|
if (isStealth) {
|
|
2819
|
-
|
|
3155
|
+
builder.addFile(`.config/build.config.${ext}`, {
|
|
2820
3156
|
type: "text",
|
|
2821
3157
|
content: buildConfigLines.join("\n")
|
|
2822
3158
|
});
|
|
2823
|
-
|
|
3159
|
+
builder.addScripts(packageJsonScripts.build.unbuild(`.config/build.config.${ext}`));
|
|
2824
3160
|
} else {
|
|
2825
|
-
|
|
3161
|
+
builder.addFile(`build.config.${ext}`, {
|
|
2826
3162
|
type: "text",
|
|
2827
3163
|
content: buildConfigLines.join("\n")
|
|
2828
3164
|
});
|
|
2829
|
-
|
|
3165
|
+
builder.addScripts(packageJsonScripts.build.unbuild());
|
|
2830
3166
|
}
|
|
2831
|
-
|
|
3167
|
+
builder.inject(
|
|
2832
3168
|
"readme-libraries",
|
|
2833
3169
|
"[unbuild](https://github.com/unjs/unbuild) - Unified JavaScript build system"
|
|
2834
3170
|
);
|
|
2835
3171
|
}
|
|
2836
3172
|
|
|
2837
|
-
function
|
|
2838
|
-
|
|
2839
|
-
|
|
3173
|
+
function planVitest(builder, options) {
|
|
3174
|
+
if (options == null) {
|
|
3175
|
+
return;
|
|
3176
|
+
}
|
|
3177
|
+
builder.addDevDependency("vitest");
|
|
3178
|
+
const template = builder.options.template ?? "vanilla";
|
|
2840
3179
|
const baseTemplate = getBaseTemplate(template);
|
|
2841
3180
|
const isReact = baseTemplate === "react" || baseTemplate === "r3f";
|
|
2842
3181
|
if (isReact) {
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
3182
|
+
builder.addDevDependency("@testing-library/react");
|
|
3183
|
+
builder.addDevDependency("@testing-library/dom");
|
|
3184
|
+
builder.addDevDependency("jsdom");
|
|
2846
3185
|
}
|
|
2847
3186
|
if (isReact) {
|
|
2848
|
-
|
|
3187
|
+
builder.configureVite({ test: { environment: "jsdom" } });
|
|
2849
3188
|
}
|
|
2850
|
-
|
|
2851
|
-
|
|
3189
|
+
builder.addScripts(packageJsonScripts.test.vitest);
|
|
3190
|
+
builder.inject(
|
|
2852
3191
|
"readme-tools",
|
|
2853
3192
|
"[Vitest](https://vitest.dev/) - Fast unit test framework powered by Vite"
|
|
2854
3193
|
);
|
|
2855
3194
|
}
|
|
2856
3195
|
|
|
2857
|
-
function
|
|
2858
|
-
if (options == null || getPackageManagerName(
|
|
3196
|
+
function planViverse(builder, options) {
|
|
3197
|
+
if (options == null || getPackageManagerName(builder.options.packageManager) !== "npm") {
|
|
2859
3198
|
return;
|
|
2860
3199
|
}
|
|
2861
|
-
|
|
3200
|
+
builder.addFile(".github/workflows/viverse.yml", {
|
|
2862
3201
|
type: "text",
|
|
2863
3202
|
content: `name: Deploy to Viverse
|
|
2864
3203
|
|
|
@@ -2909,12 +3248,12 @@ jobs:
|
|
|
2909
3248
|
run: npx viverse-cli auth login -e \${{ secrets.VIVERSE_EMAIL }} -p \${{ secrets.VIVERSE_PASSWORD }}
|
|
2910
3249
|
|
|
2911
3250
|
- name: Deploy to Viverse
|
|
2912
|
-
run: npx viverse-cli app publish ./dist --auto-create-app --name ${
|
|
3251
|
+
run: npx viverse-cli app publish ./dist --auto-create-app --name ${builder.options.name}
|
|
2913
3252
|
|
|
2914
3253
|
`
|
|
2915
3254
|
});
|
|
2916
|
-
|
|
2917
|
-
|
|
3255
|
+
builder.addDependency("@viverse/cli");
|
|
3256
|
+
builder.inject(
|
|
2918
3257
|
"readme-start",
|
|
2919
3258
|
`A GitHub CI/CD workflow for publishing to Viverse is configured.
|
|
2920
3259
|
|
|
@@ -2927,36 +3266,36 @@ You can also upload your project manually using the Viverse CLI:
|
|
|
2927
3266
|
\`\`\`bash
|
|
2928
3267
|
viverse-cli auth login -e <email> -p <password>
|
|
2929
3268
|
npm run build
|
|
2930
|
-
viverse-cli app publish ./dist --auto-create-app --name ${
|
|
3269
|
+
viverse-cli app publish ./dist --auto-create-app --name ${builder.options.name}
|
|
2931
3270
|
\`\`\`
|
|
2932
3271
|
`
|
|
2933
3272
|
);
|
|
2934
3273
|
}
|
|
2935
3274
|
|
|
2936
|
-
function
|
|
3275
|
+
function planXr(builder, options) {
|
|
2937
3276
|
if (options == null || options === false) {
|
|
2938
3277
|
return;
|
|
2939
3278
|
}
|
|
2940
3279
|
if (options === true) {
|
|
2941
3280
|
options = {};
|
|
2942
3281
|
}
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
3282
|
+
builder.addDependency("@react-three/xr");
|
|
3283
|
+
builder.addDependency("@vitejs/plugin-basic-ssl");
|
|
3284
|
+
builder.inject("import", "import { XR, createXRStore } from '@react-three/xr'");
|
|
3285
|
+
builder.inject(
|
|
2947
3286
|
`global-start`,
|
|
2948
3287
|
`const store = createXRStore(${JSON.stringify(options.storeOptions ?? {})})`
|
|
2949
3288
|
);
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
3289
|
+
builder.inject("scene-start", "<XR store={store}>");
|
|
3290
|
+
builder.inject("scene-end", "</XR>");
|
|
3291
|
+
builder.inject("vite-config-import", "import basicSsl from '@vitejs/plugin-basic-ssl'");
|
|
3292
|
+
builder.configureVite({
|
|
2954
3293
|
server: {
|
|
2955
3294
|
host: true
|
|
2956
3295
|
},
|
|
2957
3296
|
plugins: ["$raw:basicSsl()"]
|
|
2958
3297
|
});
|
|
2959
|
-
|
|
3298
|
+
builder.inject(
|
|
2960
3299
|
"dom-start",
|
|
2961
3300
|
`<div style={{
|
|
2962
3301
|
display: "flex",
|
|
@@ -2988,55 +3327,226 @@ function generateXr(generator, options) {
|
|
|
2988
3327
|
Enter VR
|
|
2989
3328
|
</button></div>`
|
|
2990
3329
|
);
|
|
2991
|
-
|
|
3330
|
+
builder.inject(
|
|
2992
3331
|
"readme-libraries",
|
|
2993
3332
|
`[@react-three/xr](https://pmndrs.github.io/xr/docs/) - VR/AR support for @react-three/fiber`
|
|
2994
3333
|
);
|
|
2995
3334
|
}
|
|
2996
3335
|
|
|
2997
|
-
function
|
|
3336
|
+
function planZustand(builder, options) {
|
|
2998
3337
|
if (options == null) {
|
|
2999
3338
|
return;
|
|
3000
3339
|
}
|
|
3001
|
-
|
|
3002
|
-
|
|
3340
|
+
builder.addDependency("zustand");
|
|
3341
|
+
builder.inject(
|
|
3003
3342
|
"readme-libraries",
|
|
3004
3343
|
`[zustand](https://zustand.docs.pmnd.rs/) - small, fast and scalable state-management solution`
|
|
3005
3344
|
);
|
|
3006
3345
|
}
|
|
3007
3346
|
|
|
3008
|
-
function
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3347
|
+
function resolveProjectPlanInput(options) {
|
|
3348
|
+
const packageManager = options.packageManager ?? { name: "pnpm" };
|
|
3349
|
+
return {
|
|
3350
|
+
project: {
|
|
3351
|
+
githubUserName: options.githubUserName,
|
|
3352
|
+
githubRepoName: options.githubRepoName,
|
|
3353
|
+
name: options.name,
|
|
3354
|
+
projectType: options.projectType,
|
|
3355
|
+
template: options.template
|
|
3356
|
+
},
|
|
3357
|
+
aiAgents: {
|
|
3358
|
+
tool: "ai-agents",
|
|
3359
|
+
config: {
|
|
3360
|
+
platforms: options.aiPlatforms ?? []
|
|
3361
|
+
}
|
|
3362
|
+
},
|
|
3363
|
+
formatter: {
|
|
3364
|
+
tool: options.formatter ?? "prettier",
|
|
3365
|
+
config: structuredClone(defaultFormatterMetaConfig)
|
|
3366
|
+
},
|
|
3367
|
+
linter: {
|
|
3368
|
+
tool: options.linter ?? "oxlint",
|
|
3369
|
+
config: structuredClone(defaultLinterMetaConfig)
|
|
3370
|
+
},
|
|
3371
|
+
testing: {
|
|
3372
|
+
tool: options.testing ?? (options.projectType === "library" ? "vitest" : "none"),
|
|
3373
|
+
config: {}
|
|
3374
|
+
},
|
|
3375
|
+
typescript: {
|
|
3376
|
+
tool: "typescript",
|
|
3377
|
+
config: {
|
|
3378
|
+
configStrategy: options.configStrategy
|
|
3379
|
+
}
|
|
3380
|
+
},
|
|
3381
|
+
ide: {
|
|
3382
|
+
tool: options.ide ?? "vscode",
|
|
3383
|
+
config: {}
|
|
3384
|
+
},
|
|
3385
|
+
packageManager: {
|
|
3386
|
+
tool: packageManager.name,
|
|
3387
|
+
config: {
|
|
3388
|
+
version: packageManager.version,
|
|
3389
|
+
pnpmManageVersions: options.pnpmManageVersions
|
|
3390
|
+
}
|
|
3391
|
+
},
|
|
3392
|
+
libraryBundler: {
|
|
3393
|
+
tool: options.libraryBundler ?? "unbuild",
|
|
3394
|
+
config: {}
|
|
3395
|
+
},
|
|
3396
|
+
features: {
|
|
3397
|
+
fiber: options.fiber,
|
|
3398
|
+
handle: options.handle,
|
|
3399
|
+
drei: options.drei,
|
|
3400
|
+
koota: options.koota,
|
|
3401
|
+
leva: options.leva,
|
|
3402
|
+
offscreen: options.offscreen,
|
|
3403
|
+
postprocessing: options.postprocessing,
|
|
3404
|
+
rapier: options.rapier,
|
|
3405
|
+
triplex: options.triplex,
|
|
3406
|
+
viverse: options.viverse,
|
|
3407
|
+
uikit: options.uikit,
|
|
3408
|
+
xr: options.xr,
|
|
3409
|
+
zustand: options.zustand,
|
|
3410
|
+
githubPages: options.githubPages
|
|
3411
|
+
},
|
|
3412
|
+
context: {
|
|
3413
|
+
dependencies: options.dependencies,
|
|
3414
|
+
engine: options.engine,
|
|
3415
|
+
files: options.files,
|
|
3416
|
+
injections: options.injections,
|
|
3417
|
+
replacements: options.replacements,
|
|
3418
|
+
versions: options.versions,
|
|
3419
|
+
workspaceRoot: options.workspaceRoot,
|
|
3420
|
+
workspaceDependencies: options.workspaceDependencies
|
|
3028
3421
|
}
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3422
|
+
};
|
|
3423
|
+
}
|
|
3424
|
+
function projectPlanInputToOptions(input) {
|
|
3425
|
+
return {
|
|
3426
|
+
...input.project,
|
|
3427
|
+
aiPlatforms: input.aiAgents.config.platforms.length > 0 ? input.aiAgents.config.platforms : void 0,
|
|
3428
|
+
formatter: input.formatter.tool,
|
|
3429
|
+
linter: input.linter.tool,
|
|
3430
|
+
testing: input.testing.tool,
|
|
3431
|
+
configStrategy: input.typescript.config.configStrategy,
|
|
3432
|
+
ide: input.ide.tool,
|
|
3433
|
+
packageManager: packageManagerSpecFromInput(input.packageManager),
|
|
3434
|
+
pnpmManageVersions: input.packageManager.config.pnpmManageVersions,
|
|
3435
|
+
libraryBundler: input.libraryBundler.tool,
|
|
3436
|
+
...input.features,
|
|
3437
|
+
dependencies: input.context.dependencies,
|
|
3438
|
+
engine: input.context.engine,
|
|
3439
|
+
files: input.context.files,
|
|
3440
|
+
injections: input.context.injections,
|
|
3441
|
+
replacements: input.context.replacements,
|
|
3442
|
+
versions: input.context.versions,
|
|
3443
|
+
workspaceRoot: input.context.workspaceRoot,
|
|
3444
|
+
workspaceDependencies: input.context.workspaceDependencies
|
|
3445
|
+
};
|
|
3446
|
+
}
|
|
3447
|
+
function resolveWorkspacePlanInput(params) {
|
|
3448
|
+
return {
|
|
3449
|
+
project: {
|
|
3450
|
+
name: params.name
|
|
3451
|
+
},
|
|
3452
|
+
aiAgents: {
|
|
3453
|
+
tool: "ai-agents",
|
|
3454
|
+
config: {
|
|
3455
|
+
platforms: params.aiPlatforms ?? []
|
|
3456
|
+
}
|
|
3457
|
+
},
|
|
3458
|
+
formatter: {
|
|
3459
|
+
tool: params.formatter,
|
|
3460
|
+
config: structuredClone(defaultFormatterMetaConfig)
|
|
3461
|
+
},
|
|
3462
|
+
linter: {
|
|
3463
|
+
tool: params.linter,
|
|
3464
|
+
config: structuredClone(defaultLinterMetaConfig)
|
|
3465
|
+
},
|
|
3466
|
+
ide: {
|
|
3467
|
+
tool: params.ide ?? "vscode",
|
|
3468
|
+
config: {}
|
|
3469
|
+
},
|
|
3470
|
+
packageManager: {
|
|
3471
|
+
tool: params.packageManager.name,
|
|
3472
|
+
config: {
|
|
3473
|
+
version: params.packageManager.version,
|
|
3474
|
+
pnpmManageVersions: params.pnpmManageVersions
|
|
3475
|
+
}
|
|
3476
|
+
},
|
|
3477
|
+
context: {
|
|
3478
|
+
engine: params.engine,
|
|
3479
|
+
pnpmManageVersions: params.pnpmManageVersions,
|
|
3480
|
+
versions: params.versions
|
|
3032
3481
|
}
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
return
|
|
3482
|
+
};
|
|
3483
|
+
}
|
|
3484
|
+
function workspacePlanInputToMonorepoParams(input) {
|
|
3485
|
+
return {
|
|
3486
|
+
name: input.project.name,
|
|
3487
|
+
linter: input.linter.tool,
|
|
3488
|
+
formatter: input.formatter.tool,
|
|
3489
|
+
packageManager: packageManagerSpecFromInput(input.packageManager),
|
|
3490
|
+
pnpmManageVersions: input.context.pnpmManageVersions,
|
|
3491
|
+
engine: input.context.engine,
|
|
3492
|
+
versions: input.context.versions,
|
|
3493
|
+
aiPlatforms: input.aiAgents.config.platforms.length > 0 ? input.aiAgents.config.platforms : void 0,
|
|
3494
|
+
ide: input.ide.tool
|
|
3495
|
+
};
|
|
3496
|
+
}
|
|
3497
|
+
function isProjectPlanInput(input) {
|
|
3498
|
+
return "project" in input && "formatter" in input && typeof input.formatter === "object";
|
|
3499
|
+
}
|
|
3500
|
+
function isWorkspacePlanInput(input) {
|
|
3501
|
+
return "project" in input && "formatter" in input && typeof input.formatter === "object";
|
|
3502
|
+
}
|
|
3503
|
+
function packageManagerSpecFromInput(packageManager) {
|
|
3504
|
+
return {
|
|
3505
|
+
name: packageManager.tool,
|
|
3506
|
+
version: packageManager.config.version
|
|
3507
|
+
};
|
|
3508
|
+
}
|
|
3509
|
+
|
|
3510
|
+
async function resolveProjectFacts(input) {
|
|
3511
|
+
const options = projectPlanInputToOptions(input);
|
|
3512
|
+
options.packageManager = await resolvePackageManager(options);
|
|
3513
|
+
options.engine = await resolveEngine(options);
|
|
3514
|
+
options.versions = await resolveProjectPackageVersions(options);
|
|
3515
|
+
return resolveProjectPlanInput(options);
|
|
3516
|
+
}
|
|
3517
|
+
async function resolveWorkspaceFacts(input) {
|
|
3518
|
+
const params = workspacePlanInputToMonorepoParams(input);
|
|
3519
|
+
const options = {
|
|
3520
|
+
name: params.name,
|
|
3521
|
+
linter: params.linter,
|
|
3522
|
+
formatter: params.formatter,
|
|
3523
|
+
packageManager: params.packageManager,
|
|
3524
|
+
engine: params.engine,
|
|
3525
|
+
pnpmManageVersions: params.pnpmManageVersions,
|
|
3526
|
+
versions: params.versions
|
|
3527
|
+
};
|
|
3528
|
+
const packageManager = await resolvePackageManager(options);
|
|
3529
|
+
const engine = await resolveEngine(options);
|
|
3530
|
+
const versions = await resolveMonorepoRootPackageVersions({
|
|
3531
|
+
linter: params.linter,
|
|
3532
|
+
formatter: params.formatter,
|
|
3533
|
+
engine,
|
|
3534
|
+
versions: params.versions
|
|
3535
|
+
});
|
|
3536
|
+
return resolveWorkspacePlanInput({
|
|
3537
|
+
...params,
|
|
3538
|
+
packageManager,
|
|
3539
|
+
engine,
|
|
3540
|
+
versions
|
|
3541
|
+
});
|
|
3037
3542
|
}
|
|
3038
3543
|
|
|
3039
|
-
function
|
|
3544
|
+
async function planProject(input) {
|
|
3545
|
+
const planInput = isProjectPlanInput(input) ? input : resolveProjectPlanInput(input);
|
|
3546
|
+
return createProjectPlan(await resolveProjectFacts(planInput));
|
|
3547
|
+
}
|
|
3548
|
+
function createProjectPlan(planInput) {
|
|
3549
|
+
const options = projectPlanInputToOptions(planInput);
|
|
3040
3550
|
const clonedOptions = structuredClone(options);
|
|
3041
3551
|
const template = clonedOptions.template ?? "vanilla";
|
|
3042
3552
|
const baseTemplate = getBaseTemplate(template);
|
|
@@ -3045,7 +3555,8 @@ function generate(options) {
|
|
|
3045
3555
|
const isReact = baseTemplate === "react";
|
|
3046
3556
|
const isR3f = baseTemplate === "r3f";
|
|
3047
3557
|
const isLibrary = clonedOptions.projectType === "library";
|
|
3048
|
-
const libraryBundler =
|
|
3558
|
+
const libraryBundler = planInput.libraryBundler.tool;
|
|
3559
|
+
const ide = planInput.ide.tool;
|
|
3049
3560
|
const files = {
|
|
3050
3561
|
...clonedOptions.files
|
|
3051
3562
|
};
|
|
@@ -3079,7 +3590,7 @@ function generate(options) {
|
|
|
3079
3590
|
}
|
|
3080
3591
|
}
|
|
3081
3592
|
if (language === "typescript") {
|
|
3082
|
-
const tsResult =
|
|
3593
|
+
const tsResult = renderTypescriptConfig({
|
|
3083
3594
|
baseTemplate,
|
|
3084
3595
|
useConfigPackage: clonedOptions.workspaceRoot != null,
|
|
3085
3596
|
configStrategy: clonedOptions.configStrategy,
|
|
@@ -3091,10 +3602,7 @@ function generate(options) {
|
|
|
3091
3602
|
}
|
|
3092
3603
|
const codeSnippets = {};
|
|
3093
3604
|
const vscodeSettings = {};
|
|
3094
|
-
const scripts =
|
|
3095
|
-
dev: "vite",
|
|
3096
|
-
build: "vite build"
|
|
3097
|
-
};
|
|
3605
|
+
const scripts = {};
|
|
3098
3606
|
if (!isLibrary && (isReact || isR3f)) {
|
|
3099
3607
|
codeSnippets["vite-config-import"] = ["import react from '@vitejs/plugin-react'"];
|
|
3100
3608
|
}
|
|
@@ -3113,7 +3621,7 @@ function generate(options) {
|
|
|
3113
3621
|
viteConfig.resolve = { dedupe: ["three"] };
|
|
3114
3622
|
}
|
|
3115
3623
|
const isMonorepoPackage = clonedOptions.workspaceRoot != null;
|
|
3116
|
-
const
|
|
3624
|
+
const builder = {
|
|
3117
3625
|
options: clonedOptions,
|
|
3118
3626
|
versions,
|
|
3119
3627
|
getVersion(name2) {
|
|
@@ -3143,8 +3651,11 @@ function generate(options) {
|
|
|
3143
3651
|
addFile(path, content) {
|
|
3144
3652
|
files[path] = content;
|
|
3145
3653
|
},
|
|
3654
|
+
addScripts(nextScripts) {
|
|
3655
|
+
Object.assign(scripts, nextScripts);
|
|
3656
|
+
},
|
|
3146
3657
|
addScript(name2, command) {
|
|
3147
|
-
|
|
3658
|
+
this.addScripts({ [name2]: command });
|
|
3148
3659
|
},
|
|
3149
3660
|
inject(location, code) {
|
|
3150
3661
|
let entries = codeSnippets[location];
|
|
@@ -3164,71 +3675,61 @@ function generate(options) {
|
|
|
3164
3675
|
}
|
|
3165
3676
|
};
|
|
3166
3677
|
if (isR3f) {
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3678
|
+
planDrei(builder, planInput.features.drei);
|
|
3679
|
+
planHandle(builder, planInput.features.handle);
|
|
3680
|
+
planKoota(builder, planInput.features.koota);
|
|
3681
|
+
planLeva(builder, planInput.features.leva);
|
|
3682
|
+
planOffscreen(builder, planInput.features.offscreen);
|
|
3683
|
+
planPostprocessing(builder, planInput.features.postprocessing);
|
|
3684
|
+
planRapier(builder, planInput.features.rapier);
|
|
3685
|
+
planUikit(builder, planInput.features.uikit);
|
|
3686
|
+
planXr(builder, planInput.features.xr);
|
|
3687
|
+
planZustand(builder, planInput.features.zustand);
|
|
3688
|
+
planFiber(builder, planInput.features.fiber);
|
|
3689
|
+
planTriplex(builder, planInput.features.triplex);
|
|
3690
|
+
planViverse(builder, planInput.features.viverse);
|
|
3180
3691
|
}
|
|
3181
3692
|
if (!isLibrary) {
|
|
3182
|
-
|
|
3693
|
+
planGithubPages(builder, planInput.features.githubPages);
|
|
3183
3694
|
}
|
|
3184
3695
|
if (isLibrary) {
|
|
3185
3696
|
if (libraryBundler === "unbuild") {
|
|
3186
|
-
|
|
3697
|
+
planUnbuild(builder);
|
|
3187
3698
|
} else if (libraryBundler === "tsdown") {
|
|
3188
|
-
|
|
3699
|
+
planTsdown(builder);
|
|
3189
3700
|
}
|
|
3190
|
-
const packageManager2 = getPackageManagerName(clonedOptions.packageManager);
|
|
3191
|
-
generator.addScript("release", `${packageManager2} run build && ${packageManager2} publish`);
|
|
3192
3701
|
}
|
|
3193
|
-
const testing =
|
|
3702
|
+
const testing = planInput.testing.tool;
|
|
3194
3703
|
if (testing === "vitest") {
|
|
3195
|
-
|
|
3196
|
-
}
|
|
3197
|
-
const linter =
|
|
3198
|
-
const formatter =
|
|
3199
|
-
if (linter === "eslint") {
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
} else if (linter === "
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
} else if (linter === "biome") {
|
|
3208
|
-
generateBiome(generator, {
|
|
3209
|
-
linter: true,
|
|
3210
|
-
formatter: formatter === "biome"
|
|
3704
|
+
planVitest(builder, planInput.testing);
|
|
3705
|
+
}
|
|
3706
|
+
const linter = planInput.linter.tool;
|
|
3707
|
+
const formatter = planInput.formatter.tool;
|
|
3708
|
+
if (planInput.linter.tool === "eslint") {
|
|
3709
|
+
planEslint(builder, planInput.linter);
|
|
3710
|
+
} else if (planInput.linter.tool === "oxlint") {
|
|
3711
|
+
planOxlint(builder, planInput.linter);
|
|
3712
|
+
} else if (planInput.linter.tool === "biome") {
|
|
3713
|
+
planBiome(builder, {
|
|
3714
|
+
linter: planInput.linter,
|
|
3715
|
+
formatter: planInput.formatter.tool === "biome" ? planInput.formatter : void 0
|
|
3211
3716
|
});
|
|
3212
|
-
generator.addVscodeSetting("eslint.enable", false);
|
|
3213
|
-
generator.addVscodeSetting("oxc.enable", false);
|
|
3214
3717
|
}
|
|
3215
|
-
if (formatter === "prettier") {
|
|
3216
|
-
|
|
3217
|
-
} else if (formatter === "oxfmt") {
|
|
3218
|
-
|
|
3219
|
-
} else if (formatter === "biome" && linter !== "biome") {
|
|
3220
|
-
|
|
3221
|
-
generator.addVscodeSetting("eslint.enable", false);
|
|
3222
|
-
generator.addVscodeSetting("oxc.enable", false);
|
|
3718
|
+
if (planInput.formatter.tool === "prettier") {
|
|
3719
|
+
planPrettier(builder, planInput.formatter);
|
|
3720
|
+
} else if (planInput.formatter.tool === "oxfmt") {
|
|
3721
|
+
planOxfmt(builder, planInput.formatter);
|
|
3722
|
+
} else if (planInput.formatter.tool === "biome" && planInput.linter.tool !== "biome") {
|
|
3723
|
+
planBiome(builder, { formatter: planInput.formatter });
|
|
3223
3724
|
}
|
|
3224
3725
|
for (const { code, location } of clonedOptions.injections ?? []) {
|
|
3225
|
-
|
|
3726
|
+
builder.inject(location, code);
|
|
3226
3727
|
}
|
|
3227
3728
|
if (!isLibrary) {
|
|
3228
|
-
files["vite.config.ts"] =
|
|
3729
|
+
files["vite.config.ts"] = renderViteConfig({ viteConfig, codeSnippets });
|
|
3229
3730
|
}
|
|
3230
3731
|
const packageManager = getPackageManagerName(options.packageManager);
|
|
3231
|
-
files["README.md"] =
|
|
3732
|
+
files["README.md"] = renderReadme({
|
|
3232
3733
|
name,
|
|
3233
3734
|
baseTemplate,
|
|
3234
3735
|
isLibrary,
|
|
@@ -3238,7 +3739,7 @@ function generate(options) {
|
|
|
3238
3739
|
});
|
|
3239
3740
|
Object.assign(
|
|
3240
3741
|
files,
|
|
3241
|
-
|
|
3742
|
+
renderSourceFiles({
|
|
3242
3743
|
name,
|
|
3243
3744
|
baseTemplate,
|
|
3244
3745
|
language,
|
|
@@ -3250,7 +3751,7 @@ function generate(options) {
|
|
|
3250
3751
|
if (testing === "vitest") {
|
|
3251
3752
|
Object.assign(
|
|
3252
3753
|
files,
|
|
3253
|
-
|
|
3754
|
+
renderTestFiles({
|
|
3254
3755
|
baseTemplate,
|
|
3255
3756
|
language,
|
|
3256
3757
|
isLibrary
|
|
@@ -3259,7 +3760,7 @@ function generate(options) {
|
|
|
3259
3760
|
}
|
|
3260
3761
|
Object.assign(
|
|
3261
3762
|
files,
|
|
3262
|
-
|
|
3763
|
+
renderPackageJson({
|
|
3263
3764
|
name,
|
|
3264
3765
|
language,
|
|
3265
3766
|
isLibrary,
|
|
@@ -3271,25 +3772,54 @@ function generate(options) {
|
|
|
3271
3772
|
workspaceDependencies: clonedOptions.workspaceDependencies
|
|
3272
3773
|
}).files
|
|
3273
3774
|
);
|
|
3274
|
-
if (!isMonorepoPackage) {
|
|
3275
|
-
Object.assign(
|
|
3775
|
+
if (!isMonorepoPackage && ide === "vscode") {
|
|
3776
|
+
Object.assign(
|
|
3777
|
+
files,
|
|
3778
|
+
renderVscodeFiles$1({
|
|
3779
|
+
codeSnippets,
|
|
3780
|
+
vscodeSettings,
|
|
3781
|
+
linter,
|
|
3782
|
+
formatter,
|
|
3783
|
+
configStrategy: clonedOptions.configStrategy,
|
|
3784
|
+
isMonorepo: false,
|
|
3785
|
+
packageManager
|
|
3786
|
+
})
|
|
3787
|
+
);
|
|
3276
3788
|
}
|
|
3277
3789
|
if (!isMonorepoPackage) {
|
|
3278
|
-
files[".
|
|
3279
|
-
files[".
|
|
3790
|
+
files[".editorconfig"] = renderEditorConfig();
|
|
3791
|
+
files[".gitignore"] = renderGitignore("standalone");
|
|
3792
|
+
files[".gitattributes"] = { type: "text", content: gitAttributesContent };
|
|
3280
3793
|
}
|
|
3281
|
-
if (!isMonorepoPackage &&
|
|
3282
|
-
|
|
3794
|
+
if (!isMonorepoPackage && planInput.aiAgents.config.platforms.length > 0) {
|
|
3795
|
+
renderAiFiles(files, {
|
|
3283
3796
|
name,
|
|
3284
3797
|
packageManager: getPackageManagerName(clonedOptions.packageManager),
|
|
3285
3798
|
linter: clonedOptions.linter ?? "oxlint",
|
|
3286
3799
|
formatter: clonedOptions.formatter ?? "prettier",
|
|
3287
3800
|
isMonorepo: false,
|
|
3288
3801
|
configStrategy: clonedOptions.configStrategy,
|
|
3289
|
-
|
|
3802
|
+
hasTypecheck: language === "typescript",
|
|
3803
|
+
platforms: planInput.aiAgents.config.platforms
|
|
3290
3804
|
});
|
|
3291
3805
|
}
|
|
3292
|
-
return
|
|
3806
|
+
return {
|
|
3807
|
+
files,
|
|
3808
|
+
dependencies,
|
|
3809
|
+
devDependencies,
|
|
3810
|
+
peerDependencies,
|
|
3811
|
+
scripts,
|
|
3812
|
+
vscodeSettings,
|
|
3813
|
+
vscodeExtensions: [...new Set(codeSnippets["vscode-extension-suggestion"] ?? [])],
|
|
3814
|
+
injections: Object.entries(codeSnippets).flatMap(
|
|
3815
|
+
([location, entries]) => (entries ?? []).map((code) => ({
|
|
3816
|
+
location,
|
|
3817
|
+
code
|
|
3818
|
+
}))
|
|
3819
|
+
),
|
|
3820
|
+
replacements,
|
|
3821
|
+
warnings: []
|
|
3822
|
+
};
|
|
3293
3823
|
}
|
|
3294
3824
|
function resolveDependencySemver(name, versions, options = {}) {
|
|
3295
3825
|
if (options.version != null) {
|
|
@@ -3298,22 +3828,30 @@ function resolveDependencySemver(name, versions, options = {}) {
|
|
|
3298
3828
|
return formatResolvedPackageVersion(versions, name, options.prefix);
|
|
3299
3829
|
}
|
|
3300
3830
|
|
|
3831
|
+
async function planWorkspace(input) {
|
|
3832
|
+
const planInput = isWorkspacePlanInput(input) ? input : resolveWorkspacePlanInput(input);
|
|
3833
|
+
const resolvedInput = await resolveWorkspaceFacts(planInput);
|
|
3834
|
+
const { files } = renderMonorepo(workspacePlanInputToMonorepoParams(resolvedInput));
|
|
3835
|
+
return {
|
|
3836
|
+
files,
|
|
3837
|
+
dependencies: {},
|
|
3838
|
+
devDependencies: {},
|
|
3839
|
+
peerDependencies: {},
|
|
3840
|
+
scripts: {},
|
|
3841
|
+
vscodeSettings: {},
|
|
3842
|
+
vscodeExtensions: [],
|
|
3843
|
+
injections: [],
|
|
3844
|
+
replacements: [],
|
|
3845
|
+
warnings: []
|
|
3846
|
+
};
|
|
3847
|
+
}
|
|
3848
|
+
|
|
3301
3849
|
exports.AI_PLATFORM_HINTS = AI_PLATFORM_HINTS;
|
|
3302
3850
|
exports.AI_PLATFORM_LABELS = AI_PLATFORM_LABELS;
|
|
3303
3851
|
exports.ALL_AI_PLATFORMS = ALL_AI_PLATFORMS;
|
|
3304
3852
|
exports.detectTooling = detectTooling;
|
|
3305
3853
|
exports.formatResolvedPackageVersion = formatResolvedPackageVersion;
|
|
3306
|
-
exports.generate = generate;
|
|
3307
|
-
exports.generateAiFiles = generateAiFiles;
|
|
3308
|
-
exports.generateEslintConfigPackage = generateEslintConfigPackage;
|
|
3309
|
-
exports.generateGitignore = generateGitignore;
|
|
3310
|
-
exports.generateMonorepo = generateMonorepo;
|
|
3311
|
-
exports.generateOxfmtConfigPackage = generateOxfmtConfigPackage;
|
|
3312
|
-
exports.generateOxlintConfigPackage = generateOxlintConfigPackage;
|
|
3313
|
-
exports.generatePrettierConfigPackage = generatePrettierConfigPackage;
|
|
3314
3854
|
exports.generateRandomName = generateRandomName;
|
|
3315
|
-
exports.generateTypescriptConfigPackage = generateTypescriptConfigPackage;
|
|
3316
|
-
exports.generateVscodeFiles = generateVscodeFiles;
|
|
3317
3855
|
exports.getBaseTemplate = getBaseTemplate;
|
|
3318
3856
|
exports.getEngineName = getEngineName;
|
|
3319
3857
|
exports.getLanguageFromTemplate = getLanguageFromTemplate;
|
|
@@ -3325,12 +3863,31 @@ exports.getLatestPnpmVersion = getLatestPnpmVersion;
|
|
|
3325
3863
|
exports.getLatestYarnVersion = getLatestYarnVersion;
|
|
3326
3864
|
exports.getPackageManagerName = getPackageManagerName;
|
|
3327
3865
|
exports.getResolvedPackageVersion = getResolvedPackageVersion;
|
|
3328
|
-
exports.
|
|
3866
|
+
exports.merge = merge;
|
|
3867
|
+
exports.mergePackageJsonScripts = mergePackageJsonScripts;
|
|
3868
|
+
exports.packageJsonScripts = packageJsonScripts;
|
|
3329
3869
|
exports.parseEngine = parseEngine;
|
|
3330
3870
|
exports.parsePackageManager = parsePackageManager;
|
|
3331
3871
|
exports.parseWorkspaceYamlContent = parseWorkspaceYamlContent;
|
|
3332
|
-
exports.
|
|
3872
|
+
exports.planProject = planProject;
|
|
3873
|
+
exports.planWorkspace = planWorkspace;
|
|
3874
|
+
exports.projectPlanInputToOptions = projectPlanInputToOptions;
|
|
3875
|
+
exports.renderAiFiles = renderAiFiles;
|
|
3876
|
+
exports.renderEditorConfig = renderEditorConfig;
|
|
3877
|
+
exports.renderEslintConfigPackage = renderEslintConfigPackage;
|
|
3878
|
+
exports.renderGitignore = renderGitignore;
|
|
3879
|
+
exports.renderOxfmtConfigPackage = renderOxfmtConfigPackage;
|
|
3880
|
+
exports.renderOxlintConfig = renderOxlintConfig;
|
|
3881
|
+
exports.renderOxlintConfigPackage = renderOxlintConfigPackage;
|
|
3882
|
+
exports.renderPrettierConfigPackage = renderPrettierConfigPackage;
|
|
3883
|
+
exports.renderTypescriptConfigPackage = renderTypescriptConfigPackage;
|
|
3884
|
+
exports.renderVscodeFiles = renderVscodeFiles;
|
|
3885
|
+
exports.renderVscodeFiles$1 = renderVscodeFiles$1;
|
|
3886
|
+
exports.resolveDefaultPackageJsonScripts = resolveDefaultPackageJsonScripts;
|
|
3333
3887
|
exports.resolveMonorepoRootPackageVersions = resolveMonorepoRootPackageVersions;
|
|
3334
|
-
exports.
|
|
3335
|
-
exports.
|
|
3888
|
+
exports.resolveProjectPlanInput = resolveProjectPlanInput;
|
|
3889
|
+
exports.resolveWorkspacePlanInput = resolveWorkspacePlanInput;
|
|
3890
|
+
exports.toPrettierIgnoreContent = toPrettierIgnoreContent;
|
|
3891
|
+
exports.unique = unique;
|
|
3336
3892
|
exports.validatePackageName = validatePackageName;
|
|
3893
|
+
exports.workspacePlanInputToMonorepoParams = workspacePlanInputToMonorepoParams;
|