create-krispya 0.6.0 → 0.8.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 +13 -341
- package/dist/chunks/index.cjs +741 -451
- package/dist/chunks/index.mjs +731 -452
- package/dist/cli.cjs +374 -573
- package/dist/cli.mjs +364 -563
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +40 -34
- package/dist/index.d.mts +40 -34
- package/dist/index.d.ts +40 -34
- package/dist/index.mjs +2 -2
- package/package.json +32 -15
- package/LICENSE +0 -15
package/dist/chunks/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import color from 'chalk';
|
|
2
1
|
import { readFile, access } from 'fs/promises';
|
|
3
2
|
import { constants } from 'fs';
|
|
4
3
|
import { join } from 'path';
|
|
4
|
+
import color from 'chalk';
|
|
5
5
|
|
|
6
6
|
const HtmlContent = `<!DOCTYPE html>
|
|
7
7
|
<html lang="en">
|
|
@@ -85,7 +85,7 @@ const GitAttributes = [
|
|
|
85
85
|
].join("\n");
|
|
86
86
|
const defaultFormatterConfig = {
|
|
87
87
|
printWidth: 102,
|
|
88
|
-
tabWidth:
|
|
88
|
+
tabWidth: 2,
|
|
89
89
|
useTabs: false,
|
|
90
90
|
semi: true,
|
|
91
91
|
singleQuote: true,
|
|
@@ -97,17 +97,13 @@ const defaultPrettierConfig = {
|
|
|
97
97
|
$schema: "https://json.schemastore.org/prettierrc",
|
|
98
98
|
...defaultFormatterConfig,
|
|
99
99
|
overrides: [
|
|
100
|
-
{
|
|
101
|
-
files: ["*.json", "**/*.json"],
|
|
102
|
-
options: { tabWidth: 2 }
|
|
103
|
-
},
|
|
104
100
|
{
|
|
105
101
|
files: ["*.md", "**/*.md"],
|
|
106
|
-
options: {
|
|
102
|
+
options: { semi: false }
|
|
107
103
|
},
|
|
108
104
|
{
|
|
109
105
|
files: ["*.yml", "*.yaml", "**/*.yml", "**/*.yaml"],
|
|
110
|
-
options: {
|
|
106
|
+
options: { semi: false }
|
|
111
107
|
}
|
|
112
108
|
]
|
|
113
109
|
};
|
|
@@ -149,22 +145,24 @@ const AI_PLATFORM_HINTS = {
|
|
|
149
145
|
function generateAiFiles(files, params) {
|
|
150
146
|
const { platforms, isMonorepo, configStrategy, ...rest } = params;
|
|
151
147
|
if (platforms.length === 0) return;
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
148
|
+
const content = generateWorkspace({
|
|
149
|
+
...rest,
|
|
150
|
+
isMonorepo: !!isMonorepo});
|
|
151
|
+
const pointer = "See [`AGENTS.md`](./Agents.md) for agent context.\n";
|
|
152
|
+
const hasAgents = platforms.includes("agents");
|
|
153
|
+
const hasClaude = platforms.includes("claude");
|
|
154
|
+
const isSingleton = platforms.length === 1;
|
|
155
|
+
if (hasAgents) files["AGENTS.md"] = { type: "text", content };
|
|
156
|
+
if (hasClaude) {
|
|
157
|
+
if (isSingleton) {
|
|
158
|
+
files["CLAUDE.md"] = { type: "text", content };
|
|
159
|
+
} else {
|
|
160
|
+
files["CLAUDE.md"] = { type: "text", content: pointer };
|
|
161
|
+
}
|
|
164
162
|
}
|
|
165
163
|
}
|
|
166
164
|
function generateWorkspace(ctx) {
|
|
167
|
-
const { name, packageManager, linter, formatter, isMonorepo
|
|
165
|
+
const { name, packageManager, linter, formatter, isMonorepo} = ctx;
|
|
168
166
|
const sections = [
|
|
169
167
|
`# ${name}`,
|
|
170
168
|
"",
|
|
@@ -181,54 +179,572 @@ function generateWorkspace(ctx) {
|
|
|
181
179
|
];
|
|
182
180
|
if (isMonorepo) {
|
|
183
181
|
sections.push(
|
|
184
|
-
"",
|
|
185
|
-
"## Structure",
|
|
186
|
-
"",
|
|
187
|
-
"- `apps/` \u2014 applications",
|
|
188
|
-
"- `packages/` \u2014 shared libraries",
|
|
189
|
-
"- `.config/` \u2014 shared config packages",
|
|
190
|
-
"",
|
|
191
|
-
"## Monorepo",
|
|
192
182
|
"",
|
|
193
183
|
"- Use `workspace:*` for internal dependencies",
|
|
194
184
|
`- New packages: \`${packageManager} create krispya <name> --workspace\``
|
|
195
185
|
);
|
|
196
|
-
} else if (configStrategy === "root") {
|
|
197
|
-
sections.push(
|
|
198
|
-
"",
|
|
199
|
-
"## Structure",
|
|
200
|
-
"",
|
|
201
|
-
"- `src/` \u2014 source code",
|
|
202
|
-
"- `dist/` \u2014 generated, don't edit",
|
|
203
|
-
"- Config files (`tsconfig.json`, etc.) are at project root"
|
|
204
|
-
);
|
|
205
|
-
} else {
|
|
206
|
-
sections.push(
|
|
207
|
-
"",
|
|
208
|
-
"## Structure",
|
|
209
|
-
"",
|
|
210
|
-
"- `src/` \u2014 source code",
|
|
211
|
-
"- `.config/` \u2014 configs, don't move",
|
|
212
|
-
"- `dist/` \u2014 generated, don't edit"
|
|
213
|
-
);
|
|
214
186
|
}
|
|
215
187
|
sections.push("");
|
|
216
188
|
return sections.join("\n");
|
|
217
189
|
}
|
|
218
190
|
|
|
191
|
+
function getLanguageFromTemplate(template) {
|
|
192
|
+
return template.endsWith("-js") ? "javascript" : "typescript";
|
|
193
|
+
}
|
|
194
|
+
function getBaseTemplate(template) {
|
|
195
|
+
return template.replace("-js", "");
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
async function getLatestNpmVersion(packageName, fallback) {
|
|
199
|
+
try {
|
|
200
|
+
const response = await fetch(`https://registry.npmjs.org/${packageName}/latest`);
|
|
201
|
+
const data = await response.json();
|
|
202
|
+
return data.version;
|
|
203
|
+
} catch {
|
|
204
|
+
return fallback;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
async function getLatestPnpmVersion() {
|
|
208
|
+
return getLatestNpmVersion("pnpm", "10.11.0");
|
|
209
|
+
}
|
|
210
|
+
async function getLatestYarnVersion() {
|
|
211
|
+
return getLatestNpmVersion("yarn", "4.6.0");
|
|
212
|
+
}
|
|
213
|
+
async function getLatestNpmCliVersion() {
|
|
214
|
+
return getLatestNpmVersion("npm", "11.0.0");
|
|
215
|
+
}
|
|
216
|
+
async function getLatestNodeVersion() {
|
|
217
|
+
try {
|
|
218
|
+
const response = await fetch("https://nodejs.org/dist/index.json");
|
|
219
|
+
const data = await response.json();
|
|
220
|
+
const latestVersion = data[0];
|
|
221
|
+
if (latestVersion) {
|
|
222
|
+
return latestVersion.version.replace(/^v/, "");
|
|
223
|
+
}
|
|
224
|
+
return "25.0.0";
|
|
225
|
+
} catch {
|
|
226
|
+
return "25.0.0";
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
function validateNameSegment(segment, label) {
|
|
230
|
+
if (!segment.length) {
|
|
231
|
+
return `${label} is required`;
|
|
232
|
+
}
|
|
233
|
+
if (!/^[a-z0-9-]+$/.test(segment)) {
|
|
234
|
+
return `${label} must be lowercase and contain only letters, numbers, and hyphens`;
|
|
235
|
+
}
|
|
236
|
+
if (segment.startsWith("-") || segment.endsWith("-")) {
|
|
237
|
+
return `${label} cannot start or end with a hyphen`;
|
|
238
|
+
}
|
|
239
|
+
if (segment.includes("--")) {
|
|
240
|
+
return `${label} cannot contain consecutive hyphens`;
|
|
241
|
+
}
|
|
242
|
+
return void 0;
|
|
243
|
+
}
|
|
244
|
+
function validatePackageName(name) {
|
|
245
|
+
if (!name.length) {
|
|
246
|
+
return "Package name is required";
|
|
247
|
+
}
|
|
248
|
+
if (name.includes("..") || name.includes("\\")) {
|
|
249
|
+
return "Package name cannot contain path traversal sequences";
|
|
250
|
+
}
|
|
251
|
+
if (name.startsWith("@")) {
|
|
252
|
+
const slashIndex = name.indexOf("/");
|
|
253
|
+
if (slashIndex === -1) {
|
|
254
|
+
return "Scoped package name must include a package name after the scope (e.g., @scope/name)";
|
|
255
|
+
}
|
|
256
|
+
if (name.indexOf("/", slashIndex + 1) !== -1) {
|
|
257
|
+
return "Package name can only have one slash for scoped packages";
|
|
258
|
+
}
|
|
259
|
+
const scope = name.slice(1, slashIndex);
|
|
260
|
+
const packageName = name.slice(slashIndex + 1);
|
|
261
|
+
const scopeError = validateNameSegment(scope, "Scope");
|
|
262
|
+
if (scopeError) return scopeError;
|
|
263
|
+
const nameError = validateNameSegment(packageName, "Package name");
|
|
264
|
+
if (nameError) return nameError;
|
|
265
|
+
return void 0;
|
|
266
|
+
}
|
|
267
|
+
if (name.includes("/")) {
|
|
268
|
+
return "Unscoped package name cannot contain slashes. Use @scope/name format for scoped packages";
|
|
269
|
+
}
|
|
270
|
+
return validateNameSegment(name, "Package name");
|
|
271
|
+
}
|
|
272
|
+
function parseWorkspaceYamlContent(content) {
|
|
273
|
+
const directories = [];
|
|
274
|
+
let inPackagesSection = false;
|
|
275
|
+
for (const line of content.split("\n")) {
|
|
276
|
+
const trimmed = line.trim();
|
|
277
|
+
if (trimmed === "packages:") {
|
|
278
|
+
inPackagesSection = true;
|
|
279
|
+
continue;
|
|
280
|
+
}
|
|
281
|
+
if (inPackagesSection && trimmed && !line.startsWith(" ") && !line.startsWith(" ") && !trimmed.startsWith("-")) {
|
|
282
|
+
break;
|
|
283
|
+
}
|
|
284
|
+
if (inPackagesSection && trimmed.startsWith("-")) {
|
|
285
|
+
const entry = trimmed.slice(1).trim().replace(/^["']|["']$/g, "").replace(/^\.\//, "").replace(/\/\*.*$/, "");
|
|
286
|
+
if (entry && !entry.startsWith(".")) {
|
|
287
|
+
directories.push(entry);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return directories;
|
|
292
|
+
}
|
|
293
|
+
async function pathExists(path) {
|
|
294
|
+
try {
|
|
295
|
+
await access(path, constants.F_OK);
|
|
296
|
+
return true;
|
|
297
|
+
} catch {
|
|
298
|
+
return false;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
function detectLinterFromScript(script) {
|
|
302
|
+
if (!script) return void 0;
|
|
303
|
+
if (script.includes("oxlint")) return "oxlint";
|
|
304
|
+
if (script.includes("eslint")) return "eslint";
|
|
305
|
+
if (script.includes("biome check") || script.includes("biome lint")) return "biome";
|
|
306
|
+
return void 0;
|
|
307
|
+
}
|
|
308
|
+
function detectFormatterFromScript(script) {
|
|
309
|
+
if (!script) return void 0;
|
|
310
|
+
if (script.includes("prettier")) return "prettier";
|
|
311
|
+
if (script.includes("oxfmt")) return "oxfmt";
|
|
312
|
+
if (script.includes("biome format")) return "biome";
|
|
313
|
+
return void 0;
|
|
314
|
+
}
|
|
315
|
+
async function detectLinterFromConfig(root) {
|
|
316
|
+
if (await pathExists(join(root, ".config/oxlint"))) return "oxlint";
|
|
317
|
+
if (await pathExists(join(root, ".config/eslint"))) return "eslint";
|
|
318
|
+
if (await pathExists(join(root, "biome.json"))) {
|
|
319
|
+
try {
|
|
320
|
+
const content = await readFile(join(root, "biome.json"), "utf-8");
|
|
321
|
+
const config = JSON.parse(content);
|
|
322
|
+
if (config.linter?.enabled !== false) return "biome";
|
|
323
|
+
} catch {
|
|
324
|
+
return "biome";
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
return void 0;
|
|
328
|
+
}
|
|
329
|
+
async function detectFormatterFromConfig(root) {
|
|
330
|
+
if (await pathExists(join(root, ".config/prettier"))) return "prettier";
|
|
331
|
+
if (await pathExists(join(root, ".config/oxfmt"))) return "oxfmt";
|
|
332
|
+
if (await pathExists(join(root, "biome.json"))) {
|
|
333
|
+
try {
|
|
334
|
+
const content = await readFile(join(root, "biome.json"), "utf-8");
|
|
335
|
+
const config = JSON.parse(content);
|
|
336
|
+
if (config.formatter?.enabled !== false) return "biome";
|
|
337
|
+
} catch {
|
|
338
|
+
return "biome";
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
return void 0;
|
|
342
|
+
}
|
|
343
|
+
function detectLinterFromDeps(devDeps) {
|
|
344
|
+
if (!devDeps) return void 0;
|
|
345
|
+
if (devDeps["@biomejs/biome"]) return "biome";
|
|
346
|
+
if (devDeps.eslint) return "eslint";
|
|
347
|
+
if (devDeps.oxlint) return "oxlint";
|
|
348
|
+
return void 0;
|
|
349
|
+
}
|
|
350
|
+
function detectFormatterFromDeps(devDeps) {
|
|
351
|
+
if (!devDeps) return void 0;
|
|
352
|
+
if (devDeps["@biomejs/biome"]) return "biome";
|
|
353
|
+
if (devDeps.prettier) return "prettier";
|
|
354
|
+
if (devDeps.oxfmt) return "oxfmt";
|
|
355
|
+
return void 0;
|
|
356
|
+
}
|
|
357
|
+
async function detectTooling(root) {
|
|
358
|
+
try {
|
|
359
|
+
const pkgPath = join(root, "package.json");
|
|
360
|
+
const content = await readFile(pkgPath, "utf-8");
|
|
361
|
+
const pkg = JSON.parse(content);
|
|
362
|
+
const linter = detectLinterFromScript(pkg.scripts?.lint) ?? await detectLinterFromConfig(root) ?? detectLinterFromDeps(pkg.devDependencies);
|
|
363
|
+
const formatter = detectFormatterFromScript(pkg.scripts?.format) ?? await detectFormatterFromConfig(root) ?? detectFormatterFromDeps(pkg.devDependencies);
|
|
364
|
+
return { linter, formatter };
|
|
365
|
+
} catch {
|
|
366
|
+
return { linter: void 0, formatter: void 0 };
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
function generateRandomName() {
|
|
370
|
+
const adjectives = [
|
|
371
|
+
"red",
|
|
372
|
+
"blue",
|
|
373
|
+
"green",
|
|
374
|
+
"yellow",
|
|
375
|
+
"purple",
|
|
376
|
+
"orange",
|
|
377
|
+
"pink",
|
|
378
|
+
"black",
|
|
379
|
+
"white",
|
|
380
|
+
"tiny",
|
|
381
|
+
"big",
|
|
382
|
+
"small",
|
|
383
|
+
"large",
|
|
384
|
+
"huge",
|
|
385
|
+
"giant",
|
|
386
|
+
"mini",
|
|
387
|
+
"mega",
|
|
388
|
+
"super",
|
|
389
|
+
"happy",
|
|
390
|
+
"sad",
|
|
391
|
+
"angry",
|
|
392
|
+
"calm",
|
|
393
|
+
"quiet",
|
|
394
|
+
"loud",
|
|
395
|
+
"silent",
|
|
396
|
+
"noisy",
|
|
397
|
+
"shiny",
|
|
398
|
+
"dull",
|
|
399
|
+
"bright",
|
|
400
|
+
"dark",
|
|
401
|
+
"fuzzy",
|
|
402
|
+
"smooth",
|
|
403
|
+
"rough",
|
|
404
|
+
"soft"
|
|
405
|
+
];
|
|
406
|
+
const nouns = [
|
|
407
|
+
"apple",
|
|
408
|
+
"banana",
|
|
409
|
+
"cherry",
|
|
410
|
+
"date",
|
|
411
|
+
"elderberry",
|
|
412
|
+
"fig",
|
|
413
|
+
"grape",
|
|
414
|
+
"honeydew",
|
|
415
|
+
"cat",
|
|
416
|
+
"dog",
|
|
417
|
+
"elephant",
|
|
418
|
+
"fox",
|
|
419
|
+
"giraffe",
|
|
420
|
+
"horse",
|
|
421
|
+
"iguana",
|
|
422
|
+
"jaguar",
|
|
423
|
+
"mountain",
|
|
424
|
+
"river",
|
|
425
|
+
"ocean",
|
|
426
|
+
"desert",
|
|
427
|
+
"forest",
|
|
428
|
+
"jungle",
|
|
429
|
+
"meadow",
|
|
430
|
+
"valley",
|
|
431
|
+
"star",
|
|
432
|
+
"moon",
|
|
433
|
+
"sun",
|
|
434
|
+
"planet",
|
|
435
|
+
"comet",
|
|
436
|
+
"asteroid",
|
|
437
|
+
"galaxy",
|
|
438
|
+
"universe"
|
|
439
|
+
];
|
|
440
|
+
const randomAdjective = adjectives[Math.floor(Math.random() * adjectives.length)];
|
|
441
|
+
const randomNoun = nouns[Math.floor(Math.random() * nouns.length)];
|
|
442
|
+
return `${randomAdjective}-${randomNoun}`;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
const PACKAGE_VERSION_DEFINITIONS = {
|
|
446
|
+
"@biomejs/biome": { fallbackVersion: "2.0.0" },
|
|
447
|
+
"@react-three/drei": { fallbackVersion: "10.0.0" },
|
|
448
|
+
"@react-three/fiber": { fallbackVersion: "9.0.0" },
|
|
449
|
+
"@react-three/handle": { fallbackVersion: "6.6.16" },
|
|
450
|
+
"@react-three/offscreen": { fallbackVersion: "0.0.8" },
|
|
451
|
+
"@react-three/postprocessing": { fallbackVersion: "3.0.4" },
|
|
452
|
+
"@react-three/rapier": { fallbackVersion: "2.1.0" },
|
|
453
|
+
"@react-three/uikit": { fallbackVersion: "0.8.15" },
|
|
454
|
+
"@react-three/xr": { fallbackVersion: "6.6.16" },
|
|
455
|
+
"@testing-library/dom": { fallbackVersion: "10.4.0" },
|
|
456
|
+
"@testing-library/react": { fallbackVersion: "16.2.0" },
|
|
457
|
+
"@types/react": { fallbackVersion: "19.0.0" },
|
|
458
|
+
"@types/react-dom": { fallbackVersion: "19.0.0" },
|
|
459
|
+
"@types/three": { fallbackVersion: "0.175.0", prefix: "~" },
|
|
460
|
+
"@vitejs/plugin-basic-ssl": { fallbackVersion: "2.0.0" },
|
|
461
|
+
"@vitejs/plugin-react": { fallbackVersion: "4.4.1" },
|
|
462
|
+
"@viverse/cli": { fallbackVersion: "0.9.5-beta.8" },
|
|
463
|
+
eslint: { fallbackVersion: "9.17.0" },
|
|
464
|
+
"eslint-plugin-react-hooks": { fallbackVersion: "5.1.0" },
|
|
465
|
+
jsdom: { fallbackVersion: "26.0.0" },
|
|
466
|
+
koota: { fallbackVersion: "0.4.0" },
|
|
467
|
+
leva: { fallbackVersion: "0.10.0" },
|
|
468
|
+
oxfmt: { fallbackVersion: "0.21.0" },
|
|
469
|
+
oxlint: { fallbackVersion: "1.36.0" },
|
|
470
|
+
prettier: { fallbackVersion: "3.4.2" },
|
|
471
|
+
react: { fallbackVersion: "19.0.0" },
|
|
472
|
+
"react-dom": { fallbackVersion: "19.0.0" },
|
|
473
|
+
three: { fallbackVersion: "0.175.0", prefix: "~" },
|
|
474
|
+
tsdown: { fallbackVersion: "0.12.0" },
|
|
475
|
+
"typescript-eslint": { fallbackVersion: "8.18.0" },
|
|
476
|
+
unbuild: { fallbackVersion: "3.5.0" },
|
|
477
|
+
vite: { fallbackVersion: "6.3.4" },
|
|
478
|
+
vitest: { fallbackVersion: "4.0.0" },
|
|
479
|
+
zustand: { fallbackVersion: "5.0.3" }
|
|
480
|
+
};
|
|
481
|
+
function addPackageName(packageNames, explicitVersions, packageName) {
|
|
482
|
+
if (!explicitVersions.has(packageName)) {
|
|
483
|
+
packageNames.add(packageName);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
function getExplicitVersionPackages(options) {
|
|
487
|
+
return /* @__PURE__ */ new Set([
|
|
488
|
+
...Object.keys(options.dependencies ?? {}),
|
|
489
|
+
...Object.keys(options.versions ?? {})
|
|
490
|
+
]);
|
|
491
|
+
}
|
|
492
|
+
function getPackageFallbackVersion(packageName) {
|
|
493
|
+
const definition = PACKAGE_VERSION_DEFINITIONS[packageName];
|
|
494
|
+
if (definition == null) {
|
|
495
|
+
throw new Error(`Missing package version definition for ${packageName}`);
|
|
496
|
+
}
|
|
497
|
+
return definition.fallbackVersion;
|
|
498
|
+
}
|
|
499
|
+
function getResolvedPackageVersion(versions, packageName) {
|
|
500
|
+
return versions[packageName] ?? getPackageFallbackVersion(packageName);
|
|
501
|
+
}
|
|
502
|
+
function formatResolvedPackageVersion(versions, packageName, prefix) {
|
|
503
|
+
const resolvedPrefix = prefix ?? PACKAGE_VERSION_DEFINITIONS[packageName]?.prefix ?? "^";
|
|
504
|
+
return `${resolvedPrefix}${getResolvedPackageVersion(versions, packageName)}`;
|
|
505
|
+
}
|
|
506
|
+
function assignResolvedPackageVersion(target, versions, packageName, prefix) {
|
|
507
|
+
target[packageName] = formatResolvedPackageVersion(versions, packageName, prefix);
|
|
508
|
+
}
|
|
509
|
+
function getPackageManagerSpec(packageManager) {
|
|
510
|
+
return packageManager ?? { name: "pnpm" };
|
|
511
|
+
}
|
|
512
|
+
function getPackageManagerName(packageManager) {
|
|
513
|
+
return getPackageManagerSpec(packageManager).name;
|
|
514
|
+
}
|
|
515
|
+
function formatPackageManager(packageManager) {
|
|
516
|
+
const spec = getPackageManagerSpec(packageManager);
|
|
517
|
+
return spec.version ? `${spec.name}@${spec.version}` : spec.name;
|
|
518
|
+
}
|
|
519
|
+
function parsePackageManager(packageManager) {
|
|
520
|
+
if (packageManager == null || packageManager.length === 0) {
|
|
521
|
+
return void 0;
|
|
522
|
+
}
|
|
523
|
+
const atIndex = packageManager.indexOf("@");
|
|
524
|
+
if (atIndex === -1) {
|
|
525
|
+
return { name: packageManager };
|
|
526
|
+
}
|
|
527
|
+
return {
|
|
528
|
+
name: packageManager.slice(0, atIndex),
|
|
529
|
+
version: packageManager.slice(atIndex + 1)
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
function getEngineSpec(engine) {
|
|
533
|
+
return engine ?? { name: "node" };
|
|
534
|
+
}
|
|
535
|
+
function getEngineName(engine) {
|
|
536
|
+
return getEngineSpec(engine).name;
|
|
537
|
+
}
|
|
538
|
+
function parseEngine(engines) {
|
|
539
|
+
if (engines == null) {
|
|
540
|
+
return void 0;
|
|
541
|
+
}
|
|
542
|
+
const [name, range] = Object.entries(engines).find(
|
|
543
|
+
([engineName]) => engineName !== "npm" && engineName !== "pnpm" && engineName !== "yarn"
|
|
544
|
+
) ?? [];
|
|
545
|
+
if (name == null) {
|
|
546
|
+
return void 0;
|
|
547
|
+
}
|
|
548
|
+
const version = range?.match(/(\d+(?:\.\d+(?:\.\d+)?)?)/)?.[1];
|
|
549
|
+
return { name, version };
|
|
550
|
+
}
|
|
551
|
+
async function resolvePackageManager(options) {
|
|
552
|
+
const packageManager = getPackageManagerSpec(options.packageManager);
|
|
553
|
+
if (packageManager.version == null) {
|
|
554
|
+
if (packageManager.name === "pnpm") {
|
|
555
|
+
packageManager.version = await getLatestPnpmVersion();
|
|
556
|
+
} else if (packageManager.name === "yarn") {
|
|
557
|
+
packageManager.version = await getLatestYarnVersion();
|
|
558
|
+
} else if (packageManager.name === "npm") {
|
|
559
|
+
packageManager.version = await getLatestNpmCliVersion();
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
return packageManager;
|
|
563
|
+
}
|
|
564
|
+
async function resolveEngine(options) {
|
|
565
|
+
const engine = getEngineSpec(options.engine);
|
|
566
|
+
if (engine.version == null && engine.name === "node") {
|
|
567
|
+
engine.version = await getLatestNodeVersion();
|
|
568
|
+
}
|
|
569
|
+
return engine;
|
|
570
|
+
}
|
|
571
|
+
async function resolvePackageVersions(packageNames, existingVersions = {}) {
|
|
572
|
+
const versions = { ...existingVersions };
|
|
573
|
+
const uniquePackageNames = [...new Set(packageNames)];
|
|
574
|
+
await Promise.all(
|
|
575
|
+
uniquePackageNames.map(async (packageName) => {
|
|
576
|
+
if (versions[packageName] != null) return;
|
|
577
|
+
versions[packageName] = await getLatestNpmVersion(
|
|
578
|
+
packageName,
|
|
579
|
+
getPackageFallbackVersion(packageName)
|
|
580
|
+
);
|
|
581
|
+
})
|
|
582
|
+
);
|
|
583
|
+
return versions;
|
|
584
|
+
}
|
|
585
|
+
async function resolveProjectPackageVersions(options) {
|
|
586
|
+
return resolvePackageVersions(collectProjectPackageNames(options), options.versions);
|
|
587
|
+
}
|
|
588
|
+
async function resolveMonorepoRootPackageVersions(params) {
|
|
589
|
+
const packageNames = /* @__PURE__ */ new Set();
|
|
590
|
+
const explicitVersions = new Set(Object.keys(params.versions ?? {}));
|
|
591
|
+
addPackageName(packageNames, explicitVersions, getLinterPackage(params.linter));
|
|
592
|
+
if (params.formatter !== "biome" || params.linter !== "biome") {
|
|
593
|
+
addPackageName(packageNames, explicitVersions, getFormatterPackage(params.formatter));
|
|
594
|
+
}
|
|
595
|
+
return resolvePackageVersions(packageNames, params.versions);
|
|
596
|
+
}
|
|
597
|
+
function collectProjectPackageNames(options) {
|
|
598
|
+
const packageNames = /* @__PURE__ */ new Set();
|
|
599
|
+
const explicitVersions = getExplicitVersionPackages(options);
|
|
600
|
+
const template = options.template ?? "vanilla";
|
|
601
|
+
const baseTemplate = getBaseTemplate(template);
|
|
602
|
+
const language = getLanguageFromTemplate(template);
|
|
603
|
+
const isLibrary = options.projectType === "library";
|
|
604
|
+
const isReact = baseTemplate === "react" || baseTemplate === "r3f";
|
|
605
|
+
const isR3f = baseTemplate === "r3f";
|
|
606
|
+
const isTypescript = language === "typescript";
|
|
607
|
+
const inWorkspace = options.workspaceRoot != null;
|
|
608
|
+
const testing = options.testing ?? (isLibrary ? "vitest" : "none");
|
|
609
|
+
const linter = options.linter ?? "oxlint";
|
|
610
|
+
const formatter = options.formatter ?? "prettier";
|
|
611
|
+
const bundler = options.libraryBundler ?? "unbuild";
|
|
612
|
+
const packageManager = getPackageManagerName(options.packageManager);
|
|
613
|
+
if (!isLibrary) {
|
|
614
|
+
addPackageName(packageNames, explicitVersions, "vite");
|
|
615
|
+
}
|
|
616
|
+
if (isReact) {
|
|
617
|
+
if (!isLibrary) {
|
|
618
|
+
addPackageName(packageNames, explicitVersions, "react");
|
|
619
|
+
addPackageName(packageNames, explicitVersions, "react-dom");
|
|
620
|
+
addPackageName(packageNames, explicitVersions, "@vitejs/plugin-react");
|
|
621
|
+
}
|
|
622
|
+
if (isTypescript) {
|
|
623
|
+
addPackageName(packageNames, explicitVersions, "@types/react");
|
|
624
|
+
addPackageName(packageNames, explicitVersions, "@types/react-dom");
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
if (isR3f) {
|
|
628
|
+
if (!isLibrary) {
|
|
629
|
+
addPackageName(packageNames, explicitVersions, "three");
|
|
630
|
+
addPackageName(packageNames, explicitVersions, "@react-three/fiber");
|
|
631
|
+
}
|
|
632
|
+
if (isTypescript) {
|
|
633
|
+
addPackageName(packageNames, explicitVersions, "@types/three");
|
|
634
|
+
}
|
|
635
|
+
if (isEnabledOption(options.drei)) {
|
|
636
|
+
addPackageName(packageNames, explicitVersions, "@react-three/drei");
|
|
637
|
+
}
|
|
638
|
+
if (isEnabledOption(options.handle)) {
|
|
639
|
+
addPackageName(packageNames, explicitVersions, "@react-three/handle");
|
|
640
|
+
}
|
|
641
|
+
if (isEnabledOption(options.koota)) {
|
|
642
|
+
addPackageName(packageNames, explicitVersions, "koota");
|
|
643
|
+
}
|
|
644
|
+
if (isEnabledOption(options.leva)) {
|
|
645
|
+
addPackageName(packageNames, explicitVersions, "leva");
|
|
646
|
+
}
|
|
647
|
+
if (isEnabledOption(options.rapier)) {
|
|
648
|
+
addPackageName(packageNames, explicitVersions, "@react-three/rapier");
|
|
649
|
+
}
|
|
650
|
+
if (isEnabledOption(options.uikit)) {
|
|
651
|
+
addPackageName(packageNames, explicitVersions, "@react-three/uikit");
|
|
652
|
+
}
|
|
653
|
+
if (isEnabledOption(options.zustand)) {
|
|
654
|
+
addPackageName(packageNames, explicitVersions, "zustand");
|
|
655
|
+
}
|
|
656
|
+
if (isEnabledOption(options.xr)) {
|
|
657
|
+
addPackageName(packageNames, explicitVersions, "@react-three/xr");
|
|
658
|
+
addPackageName(packageNames, explicitVersions, "@vitejs/plugin-basic-ssl");
|
|
659
|
+
}
|
|
660
|
+
if (!isEnabledOption(options.xr) && isEnabledOption(options.offscreen)) {
|
|
661
|
+
addPackageName(packageNames, explicitVersions, "@react-three/offscreen");
|
|
662
|
+
}
|
|
663
|
+
if (!isEnabledOption(options.xr) && isEnabledOption(options.postprocessing)) {
|
|
664
|
+
addPackageName(packageNames, explicitVersions, "@react-three/postprocessing");
|
|
665
|
+
}
|
|
666
|
+
if (isEnabledOption(options.viverse) && packageManager === "npm") {
|
|
667
|
+
addPackageName(packageNames, explicitVersions, "@viverse/cli");
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
if (testing === "vitest") {
|
|
671
|
+
addPackageName(packageNames, explicitVersions, "vitest");
|
|
672
|
+
if (isReact) {
|
|
673
|
+
addPackageName(packageNames, explicitVersions, "@testing-library/react");
|
|
674
|
+
addPackageName(packageNames, explicitVersions, "@testing-library/dom");
|
|
675
|
+
addPackageName(packageNames, explicitVersions, "jsdom");
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
if (linter === "eslint") {
|
|
679
|
+
addPackageName(packageNames, explicitVersions, "eslint");
|
|
680
|
+
if (isTypescript) {
|
|
681
|
+
addPackageName(packageNames, explicitVersions, "typescript-eslint");
|
|
682
|
+
}
|
|
683
|
+
if (isReact) {
|
|
684
|
+
addPackageName(packageNames, explicitVersions, "eslint-plugin-react-hooks");
|
|
685
|
+
}
|
|
686
|
+
} else if (linter === "oxlint") {
|
|
687
|
+
if (!inWorkspace) {
|
|
688
|
+
addPackageName(packageNames, explicitVersions, "oxlint");
|
|
689
|
+
}
|
|
690
|
+
} else if (linter === "biome") {
|
|
691
|
+
addPackageName(packageNames, explicitVersions, "@biomejs/biome");
|
|
692
|
+
}
|
|
693
|
+
if (formatter === "prettier") {
|
|
694
|
+
addPackageName(packageNames, explicitVersions, "prettier");
|
|
695
|
+
} else if (formatter === "oxfmt") {
|
|
696
|
+
if (!inWorkspace) {
|
|
697
|
+
addPackageName(packageNames, explicitVersions, "oxfmt");
|
|
698
|
+
}
|
|
699
|
+
} else if (formatter === "biome") {
|
|
700
|
+
addPackageName(packageNames, explicitVersions, "@biomejs/biome");
|
|
701
|
+
}
|
|
702
|
+
if (isLibrary) {
|
|
703
|
+
addPackageName(packageNames, explicitVersions, bundler === "unbuild" ? "unbuild" : "tsdown");
|
|
704
|
+
}
|
|
705
|
+
return [...packageNames];
|
|
706
|
+
}
|
|
707
|
+
function getLinterPackage(linter) {
|
|
708
|
+
if (linter === "biome") {
|
|
709
|
+
return "@biomejs/biome";
|
|
710
|
+
}
|
|
711
|
+
return linter;
|
|
712
|
+
}
|
|
713
|
+
function getFormatterPackage(formatter) {
|
|
714
|
+
if (formatter === "biome") {
|
|
715
|
+
return "@biomejs/biome";
|
|
716
|
+
}
|
|
717
|
+
return formatter;
|
|
718
|
+
}
|
|
719
|
+
function isEnabledOption(option) {
|
|
720
|
+
return option != null && option !== false;
|
|
721
|
+
}
|
|
722
|
+
|
|
219
723
|
function generateTypescriptConfig(baseTemplateOrParams) {
|
|
220
724
|
const params = typeof baseTemplateOrParams === "string" ? { baseTemplate: baseTemplateOrParams } : baseTemplateOrParams;
|
|
221
|
-
const {
|
|
725
|
+
const {
|
|
726
|
+
baseTemplate,
|
|
727
|
+
useConfigPackage,
|
|
728
|
+
configStrategy = "stealth",
|
|
729
|
+
engine,
|
|
730
|
+
versions = {}
|
|
731
|
+
} = params;
|
|
222
732
|
const isReact = baseTemplate === "react";
|
|
223
733
|
const isR3f = baseTemplate === "r3f";
|
|
224
734
|
const files = {};
|
|
225
735
|
const devDependencies = {};
|
|
736
|
+
if (getEngineName(engine) === "node" && getEngineSpec(engine).version) {
|
|
737
|
+
const majorVersion = getEngineSpec(engine).version.split(".")[0];
|
|
738
|
+
devDependencies["@types/node"] = `^${majorVersion}.0.0`;
|
|
739
|
+
} else {
|
|
740
|
+
devDependencies["@types/node"] = "^22.0.0";
|
|
741
|
+
}
|
|
226
742
|
if (isReact || isR3f) {
|
|
227
|
-
devDependencies
|
|
228
|
-
devDependencies
|
|
743
|
+
assignResolvedPackageVersion(devDependencies, versions, "@types/react");
|
|
744
|
+
assignResolvedPackageVersion(devDependencies, versions, "@types/react-dom");
|
|
229
745
|
}
|
|
230
746
|
if (isR3f) {
|
|
231
|
-
devDependencies
|
|
747
|
+
assignResolvedPackageVersion(devDependencies, versions, "@types/three", "~");
|
|
232
748
|
}
|
|
233
749
|
if (useConfigPackage) {
|
|
234
750
|
devDependencies["@config/typescript"] = "workspace:*";
|
|
@@ -251,7 +767,10 @@ function generateTypescriptConfig(baseTemplateOrParams) {
|
|
|
251
767
|
const tsConfig = {
|
|
252
768
|
$schema: "https://json.schemastore.org/tsconfig",
|
|
253
769
|
files: [],
|
|
254
|
-
references: [
|
|
770
|
+
references: [
|
|
771
|
+
{ path: "./.config/tsconfig.app.json" },
|
|
772
|
+
{ path: "./.config/tsconfig.node.json" }
|
|
773
|
+
]
|
|
255
774
|
};
|
|
256
775
|
files["tsconfig.json"] = {
|
|
257
776
|
type: "text",
|
|
@@ -357,6 +876,7 @@ function generateTypescriptConfig(baseTemplateOrParams) {
|
|
|
357
876
|
return { files, devDependencies };
|
|
358
877
|
}
|
|
359
878
|
|
|
879
|
+
const DEFAULT_LIBRARY_VERSION = "0.1.0";
|
|
360
880
|
function generatePackageJson(params) {
|
|
361
881
|
const {
|
|
362
882
|
name,
|
|
@@ -370,14 +890,15 @@ function generatePackageJson(params) {
|
|
|
370
890
|
workspaceDependencies
|
|
371
891
|
} = params;
|
|
372
892
|
const files = {};
|
|
373
|
-
const packageManager = options.packageManager
|
|
374
|
-
const isPnpm = packageManager === "pnpm";
|
|
893
|
+
const packageManager = getPackageManagerSpec(options.packageManager);
|
|
894
|
+
const isPnpm = packageManager.name === "pnpm";
|
|
375
895
|
const packageJson = {
|
|
376
896
|
name,
|
|
377
897
|
description: "Built with \u{1F339} create-krispya",
|
|
378
898
|
type: "module"
|
|
379
899
|
};
|
|
380
900
|
if (isLibrary) {
|
|
901
|
+
packageJson.version = DEFAULT_LIBRARY_VERSION;
|
|
381
902
|
packageJson.main = "./dist/index.mjs";
|
|
382
903
|
packageJson.module = "./dist/index.mjs";
|
|
383
904
|
if (language === "typescript") {
|
|
@@ -399,10 +920,16 @@ function generatePackageJson(params) {
|
|
|
399
920
|
allDependencies[pkgName] = "workspace:*";
|
|
400
921
|
}
|
|
401
922
|
}
|
|
923
|
+
const allDevDependencies = { ...devDependencies };
|
|
924
|
+
const engine = getEngineSpec(options.engine);
|
|
925
|
+
if (getEngineName(engine) === "node" && engine.version) {
|
|
926
|
+
const majorVersion = engine.version.split(".")[0];
|
|
927
|
+
allDevDependencies["@types/node"] ??= `^${majorVersion}.0.0`;
|
|
928
|
+
}
|
|
402
929
|
packageJson.scripts = scripts;
|
|
403
930
|
packageJson.dependencies = sortKeys(allDependencies);
|
|
404
|
-
if (Object.keys(
|
|
405
|
-
packageJson.devDependencies = sortKeys(
|
|
931
|
+
if (Object.keys(allDevDependencies).length > 0) {
|
|
932
|
+
packageJson.devDependencies = sortKeys(allDevDependencies);
|
|
406
933
|
}
|
|
407
934
|
if (isLibrary && Object.keys(peerDependencies).length > 0) {
|
|
408
935
|
packageJson.peerDependencies = sortKeys(peerDependencies);
|
|
@@ -410,25 +937,14 @@ function generatePackageJson(params) {
|
|
|
410
937
|
const isMonorepoPackage = options.workspaceRoot != null;
|
|
411
938
|
if (!isMonorepoPackage) {
|
|
412
939
|
const engines = {};
|
|
413
|
-
if (
|
|
414
|
-
const
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
packageJson.packageManager = `pnpm@${pnpmVersion}`;
|
|
418
|
-
} else if (packageManager === "yarn") {
|
|
419
|
-
const yarnVersion = options.yarnVersion ?? "4.6.0";
|
|
420
|
-
const majorVersion = yarnVersion.split(".")[0];
|
|
421
|
-
engines.yarn = `>=${majorVersion}.0.0`;
|
|
422
|
-
packageJson.packageManager = `yarn@${yarnVersion}`;
|
|
423
|
-
} else if (packageManager === "npm") {
|
|
424
|
-
const npmVersion = options.npmVersion ?? "11.0.0";
|
|
425
|
-
const majorVersion = npmVersion.split(".")[0];
|
|
426
|
-
engines.npm = `>=${majorVersion}.0.0`;
|
|
427
|
-
packageJson.packageManager = `npm@${npmVersion}`;
|
|
940
|
+
if (packageManager.version != null) {
|
|
941
|
+
const majorVersion = packageManager.version.split(".")[0];
|
|
942
|
+
engines[packageManager.name] = `>=${majorVersion}.0.0`;
|
|
943
|
+
packageJson.packageManager = formatPackageManager(packageManager);
|
|
428
944
|
}
|
|
429
|
-
if (
|
|
430
|
-
const majorVersion =
|
|
431
|
-
engines.
|
|
945
|
+
if (engine.version != null) {
|
|
946
|
+
const majorVersion = engine.version.split(".")[0];
|
|
947
|
+
engines[engine.name] = `>=${majorVersion}.0.0`;
|
|
432
948
|
}
|
|
433
949
|
if (Object.keys(engines).length > 0) {
|
|
434
950
|
packageJson.engines = engines;
|
|
@@ -746,6 +1262,22 @@ function generateTestFiles(params) {
|
|
|
746
1262
|
return files;
|
|
747
1263
|
}
|
|
748
1264
|
|
|
1265
|
+
const COMMON_GITIGNORE_LINES = [
|
|
1266
|
+
"node_modules",
|
|
1267
|
+
"dist",
|
|
1268
|
+
"*.tsbuildinfo",
|
|
1269
|
+
".env",
|
|
1270
|
+
".env.*",
|
|
1271
|
+
"!.env.example"
|
|
1272
|
+
];
|
|
1273
|
+
function generateGitignore(variant) {
|
|
1274
|
+
const lines = variant === "workspace-root" ? [...COMMON_GITIGNORE_LINES, ".DS_Store"] : COMMON_GITIGNORE_LINES;
|
|
1275
|
+
return {
|
|
1276
|
+
type: "text",
|
|
1277
|
+
content: lines.join("\n")
|
|
1278
|
+
};
|
|
1279
|
+
}
|
|
1280
|
+
|
|
749
1281
|
function generateVscodeFiles$1(params) {
|
|
750
1282
|
const { codeSnippets, vscodeSettings } = params;
|
|
751
1283
|
const files = {};
|
|
@@ -768,7 +1300,7 @@ function generateVscodeFiles$1(params) {
|
|
|
768
1300
|
);
|
|
769
1301
|
files[".vscode/settings.json"] = {
|
|
770
1302
|
type: "text",
|
|
771
|
-
content: JSON.stringify(sortedSettings, null,
|
|
1303
|
+
content: JSON.stringify(sortedSettings, null, 2)
|
|
772
1304
|
};
|
|
773
1305
|
}
|
|
774
1306
|
return files;
|
|
@@ -1221,25 +1753,31 @@ function generateMonorepo(params) {
|
|
|
1221
1753
|
linter,
|
|
1222
1754
|
formatter,
|
|
1223
1755
|
packageManager,
|
|
1224
|
-
pnpmVersion,
|
|
1225
1756
|
pnpmManageVersions,
|
|
1226
|
-
|
|
1757
|
+
engine,
|
|
1758
|
+
versions = {},
|
|
1227
1759
|
aiPlatforms
|
|
1228
1760
|
} = params;
|
|
1229
1761
|
const files = {};
|
|
1230
|
-
const isPnpm = packageManager === "pnpm";
|
|
1762
|
+
const isPnpm = packageManager.name === "pnpm";
|
|
1231
1763
|
const devDependencies = {};
|
|
1764
|
+
if (engine?.name === "node" && engine.version) {
|
|
1765
|
+
const majorVersion = engine.version.split(".")[0];
|
|
1766
|
+
devDependencies["@types/node"] = `^${majorVersion}.0.0`;
|
|
1767
|
+
} else {
|
|
1768
|
+
devDependencies["@types/node"] = "^22.0.0";
|
|
1769
|
+
}
|
|
1232
1770
|
if (linter === "oxlint") {
|
|
1233
|
-
devDependencies
|
|
1771
|
+
assignResolvedPackageVersion(devDependencies, versions, "oxlint");
|
|
1234
1772
|
} else if (linter === "eslint") {
|
|
1235
|
-
devDependencies
|
|
1773
|
+
assignResolvedPackageVersion(devDependencies, versions, "eslint");
|
|
1236
1774
|
} else if (linter === "biome") {
|
|
1237
|
-
devDependencies
|
|
1775
|
+
assignResolvedPackageVersion(devDependencies, versions, "@biomejs/biome");
|
|
1238
1776
|
}
|
|
1239
1777
|
if (formatter === "oxfmt") {
|
|
1240
|
-
devDependencies
|
|
1778
|
+
assignResolvedPackageVersion(devDependencies, versions, "oxfmt");
|
|
1241
1779
|
} else if (formatter === "prettier") {
|
|
1242
|
-
devDependencies
|
|
1780
|
+
assignResolvedPackageVersion(devDependencies, versions, "prettier");
|
|
1243
1781
|
}
|
|
1244
1782
|
const rootPackageJson = {
|
|
1245
1783
|
name: "root",
|
|
@@ -1256,14 +1794,14 @@ function generateMonorepo(params) {
|
|
|
1256
1794
|
devDependencies
|
|
1257
1795
|
};
|
|
1258
1796
|
const engines = {};
|
|
1259
|
-
if (isPnpm &&
|
|
1260
|
-
const majorVersion =
|
|
1797
|
+
if (isPnpm && packageManager.version) {
|
|
1798
|
+
const majorVersion = packageManager.version.split(".")[0];
|
|
1261
1799
|
engines.pnpm = `>=${majorVersion}.0.0`;
|
|
1262
|
-
rootPackageJson.packageManager =
|
|
1800
|
+
rootPackageJson.packageManager = formatPackageManager(packageManager);
|
|
1263
1801
|
}
|
|
1264
|
-
if (
|
|
1265
|
-
const majorVersion =
|
|
1266
|
-
engines.
|
|
1802
|
+
if (engine?.version) {
|
|
1803
|
+
const majorVersion = engine.version.split(".")[0];
|
|
1804
|
+
engines[engine.name] = `>=${majorVersion}.0.0`;
|
|
1267
1805
|
}
|
|
1268
1806
|
if (Object.keys(engines).length > 0) {
|
|
1269
1807
|
rootPackageJson.engines = engines;
|
|
@@ -1277,13 +1815,7 @@ function generateMonorepo(params) {
|
|
|
1277
1815
|
if (pnpmManageVersions) {
|
|
1278
1816
|
workspaceLines.push("manage-package-manager-versions: true", "");
|
|
1279
1817
|
}
|
|
1280
|
-
workspaceLines.push(
|
|
1281
|
-
"packages:",
|
|
1282
|
-
' - ".config/*"',
|
|
1283
|
-
' - "apps/*"',
|
|
1284
|
-
' - "packages/*"',
|
|
1285
|
-
""
|
|
1286
|
-
);
|
|
1818
|
+
workspaceLines.push("packages:", ' - ".config/*"', ' - "apps/*"', ' - "packages/*"', "");
|
|
1287
1819
|
workspaceLines.push("onlyBuiltDependencies:", " - esbuild");
|
|
1288
1820
|
files["pnpm-workspace.yaml"] = {
|
|
1289
1821
|
type: "text",
|
|
@@ -1328,8 +1860,9 @@ export default [...base];
|
|
|
1328
1860
|
`
|
|
1329
1861
|
};
|
|
1330
1862
|
} else if (linter === "biome") {
|
|
1863
|
+
const biomeVersion = getResolvedPackageVersion(versions, "@biomejs/biome");
|
|
1331
1864
|
const biomeConfig = {
|
|
1332
|
-
$schema:
|
|
1865
|
+
$schema: `https://biomejs.dev/schemas/${biomeVersion}/schema.json`,
|
|
1333
1866
|
vcs: {
|
|
1334
1867
|
enabled: true,
|
|
1335
1868
|
clientKind: "git",
|
|
@@ -1355,10 +1888,7 @@ export default [...base];
|
|
|
1355
1888
|
} else if (formatter === "prettier") {
|
|
1356
1889
|
generatePrettierConfigPackage(files);
|
|
1357
1890
|
}
|
|
1358
|
-
files[".gitignore"] =
|
|
1359
|
-
type: "text",
|
|
1360
|
-
content: ["node_modules", "dist", "*.tsbuildinfo", ".DS_Store"].join("\n")
|
|
1361
|
-
};
|
|
1891
|
+
files[".gitignore"] = generateGitignore("workspace-root");
|
|
1362
1892
|
files[".gitattributes"] = {
|
|
1363
1893
|
type: "text",
|
|
1364
1894
|
content: `* text=auto eol=lf
|
|
@@ -1381,12 +1911,12 @@ This monorepo workspace was generated with create-krispya.
|
|
|
1381
1911
|
|
|
1382
1912
|
## Development Commands
|
|
1383
1913
|
|
|
1384
|
-
- \`${packageManager} install\` to install all dependencies
|
|
1385
|
-
- \`${packageManager} run dev\` to run all applications in development mode
|
|
1386
|
-
- \`${packageManager} run build\` to build all packages and applications
|
|
1387
|
-
- \`${packageManager} run test\` to run tests across the workspace
|
|
1388
|
-
- \`${packageManager} run lint\` to lint all code
|
|
1389
|
-
- \`${packageManager} run format\` to format all code
|
|
1914
|
+
- \`${packageManager.name} install\` to install all dependencies
|
|
1915
|
+
- \`${packageManager.name} run dev\` to run all applications in development mode
|
|
1916
|
+
- \`${packageManager.name} run build\` to build all packages and applications
|
|
1917
|
+
- \`${packageManager.name} run test\` to run tests across the workspace
|
|
1918
|
+
- \`${packageManager.name} run lint\` to lint all code
|
|
1919
|
+
- \`${packageManager.name} run format\` to format all code
|
|
1390
1920
|
|
|
1391
1921
|
## Adding Packages
|
|
1392
1922
|
|
|
@@ -1396,7 +1926,7 @@ To add a new package to this workspace, run create-krispya from this directory a
|
|
|
1396
1926
|
if (aiPlatforms && aiPlatforms.length > 0) {
|
|
1397
1927
|
generateAiFiles(files, {
|
|
1398
1928
|
name,
|
|
1399
|
-
packageManager,
|
|
1929
|
+
packageManager: packageManager.name,
|
|
1400
1930
|
linter,
|
|
1401
1931
|
formatter,
|
|
1402
1932
|
isMonorepo: true,
|
|
@@ -1448,10 +1978,17 @@ function generateVscodeFiles(files, linter, formatter) {
|
|
|
1448
1978
|
type: "text",
|
|
1449
1979
|
content: JSON.stringify({ recommendations }, null, 2)
|
|
1450
1980
|
};
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
}
|
|
1981
|
+
const codeSnippets = {};
|
|
1982
|
+
if (recommendations.length > 0) {
|
|
1983
|
+
codeSnippets["vscode-extension-suggestion"] = recommendations;
|
|
1984
|
+
}
|
|
1985
|
+
Object.assign(
|
|
1986
|
+
files,
|
|
1987
|
+
generateVscodeFiles$1({
|
|
1988
|
+
codeSnippets,
|
|
1989
|
+
vscodeSettings: settings
|
|
1990
|
+
})
|
|
1991
|
+
);
|
|
1455
1992
|
}
|
|
1456
1993
|
|
|
1457
1994
|
const monorepo = {
|
|
@@ -1472,8 +2009,8 @@ function generateBiome(generator, options) {
|
|
|
1472
2009
|
if (options == null || !options.linter && !options.formatter) {
|
|
1473
2010
|
return;
|
|
1474
2011
|
}
|
|
1475
|
-
const version = generator.
|
|
1476
|
-
generator.addDevDependency("@biomejs/biome"
|
|
2012
|
+
const version = generator.getVersion("@biomejs/biome");
|
|
2013
|
+
generator.addDevDependency("@biomejs/biome");
|
|
1477
2014
|
const { rules } = defaultLinterConfig;
|
|
1478
2015
|
const biomeConfig = {
|
|
1479
2016
|
$schema: `https://biomejs.dev/schemas/${version}/schema.json`
|
|
@@ -1529,10 +2066,7 @@ function generateBiome(generator, options) {
|
|
|
1529
2066
|
generator.addScript("lint", "biome lint --config-path .config .");
|
|
1530
2067
|
}
|
|
1531
2068
|
if (options.formatter) {
|
|
1532
|
-
generator.addScript(
|
|
1533
|
-
"format",
|
|
1534
|
-
"biome format --config-path .config --write ."
|
|
1535
|
-
);
|
|
2069
|
+
generator.addScript("format", "biome format --config-path .config --write .");
|
|
1536
2070
|
}
|
|
1537
2071
|
generator.addVscodeSetting("biome.linter.configPath", ".config/biome.json");
|
|
1538
2072
|
} else {
|
|
@@ -1552,9 +2086,7 @@ function generateBiome(generator, options) {
|
|
|
1552
2086
|
if (options.formatter) roles.push("formatter");
|
|
1553
2087
|
generator.inject(
|
|
1554
2088
|
"readme-tools",
|
|
1555
|
-
`[Biome](https://biomejs.dev/) - Fast ${roles.join(
|
|
1556
|
-
" and "
|
|
1557
|
-
)} for JavaScript and TypeScript`
|
|
2089
|
+
`[Biome](https://biomejs.dev/) - Fast ${roles.join(" and ")} for JavaScript and TypeScript`
|
|
1558
2090
|
);
|
|
1559
2091
|
generator.inject("vscode-extension-suggestion", "biomejs.biome");
|
|
1560
2092
|
generator.addVscodeSetting("biome.enabled", true);
|
|
@@ -1567,7 +2099,7 @@ function generateDrei(generator, options) {
|
|
|
1567
2099
|
if (options == null) {
|
|
1568
2100
|
return;
|
|
1569
2101
|
}
|
|
1570
|
-
generator.addDependency("@react-three/drei"
|
|
2102
|
+
generator.addDependency("@react-three/drei");
|
|
1571
2103
|
generator.inject("import", `import { Environment } from "@react-three/drei"`);
|
|
1572
2104
|
generator.inject("scene", '<Environment background preset="city" />');
|
|
1573
2105
|
generator.inject(
|
|
@@ -1576,19 +2108,11 @@ function generateDrei(generator, options) {
|
|
|
1576
2108
|
);
|
|
1577
2109
|
}
|
|
1578
2110
|
|
|
1579
|
-
function getLanguageFromTemplate(template) {
|
|
1580
|
-
return template.endsWith("-js") ? "javascript" : "typescript";
|
|
1581
|
-
}
|
|
1582
|
-
function getBaseTemplate(template) {
|
|
1583
|
-
return template.replace("-js", "");
|
|
1584
|
-
}
|
|
1585
|
-
|
|
1586
2111
|
function toEslintLevel(level) {
|
|
1587
2112
|
return level;
|
|
1588
2113
|
}
|
|
1589
2114
|
function generateEslint(generator, options) {
|
|
1590
|
-
|
|
1591
|
-
generator.addDevDependency("eslint", `^${version}`);
|
|
2115
|
+
generator.addDevDependency("eslint");
|
|
1592
2116
|
const template = generator.options.template ?? "vanilla";
|
|
1593
2117
|
const baseTemplate = getBaseTemplate(template);
|
|
1594
2118
|
const isTypescript = getLanguageFromTemplate(template) === "typescript";
|
|
@@ -1597,12 +2121,12 @@ function generateEslint(generator, options) {
|
|
|
1597
2121
|
const imports = ['import js from "@eslint/js"'];
|
|
1598
2122
|
const configs = ["js.configs.recommended"];
|
|
1599
2123
|
if (isTypescript) {
|
|
1600
|
-
generator.addDevDependency("typescript-eslint"
|
|
2124
|
+
generator.addDevDependency("typescript-eslint");
|
|
1601
2125
|
imports.push('import tseslint from "typescript-eslint"');
|
|
1602
2126
|
configs.push("...tseslint.configs.recommended");
|
|
1603
2127
|
}
|
|
1604
2128
|
if (isReact) {
|
|
1605
|
-
generator.addDevDependency("eslint-plugin-react-hooks"
|
|
2129
|
+
generator.addDevDependency("eslint-plugin-react-hooks");
|
|
1606
2130
|
imports.push('import reactHooks from "eslint-plugin-react-hooks"');
|
|
1607
2131
|
}
|
|
1608
2132
|
const ignoresArray = JSON.stringify(defaultLinterConfig.ignorePatterns);
|
|
@@ -1704,7 +2228,7 @@ export function Box(props: ThreeElements['mesh']) {
|
|
|
1704
2228
|
}
|
|
1705
2229
|
|
|
1706
2230
|
function generateGithubPages(generator, options) {
|
|
1707
|
-
if (options === false || (generator.options.packageManager
|
|
2231
|
+
if (options === false || getPackageManagerName(generator.options.packageManager) !== "npm") {
|
|
1708
2232
|
return;
|
|
1709
2233
|
}
|
|
1710
2234
|
generator.addFile(".github/workflows/gh-pages.yml", {
|
|
@@ -1768,7 +2292,7 @@ function generateHandle(generator, options) {
|
|
|
1768
2292
|
if (options == null) {
|
|
1769
2293
|
return;
|
|
1770
2294
|
}
|
|
1771
|
-
generator.addDependency("@react-three/handle"
|
|
2295
|
+
generator.addDependency("@react-three/handle");
|
|
1772
2296
|
generator.inject(
|
|
1773
2297
|
"readme-libraries",
|
|
1774
2298
|
`[@react-three/handle](https://pmndrs.github.io/xr/docs/handles/introduction) - interactive controls and handles for your 3D objects`
|
|
@@ -1779,7 +2303,7 @@ function generateKoota(generator, options) {
|
|
|
1779
2303
|
if (options == null) {
|
|
1780
2304
|
return;
|
|
1781
2305
|
}
|
|
1782
|
-
generator.addDependency("koota"
|
|
2306
|
+
generator.addDependency("koota");
|
|
1783
2307
|
generator.inject(
|
|
1784
2308
|
"readme-libraries",
|
|
1785
2309
|
`[koota](https://github.com/pmndrs/koota) - ECS-based state management library optimized for real-time apps, games, and XR experiences`
|
|
@@ -1790,7 +2314,7 @@ function generateLeva(generator, options) {
|
|
|
1790
2314
|
if (options == null) {
|
|
1791
2315
|
return;
|
|
1792
2316
|
}
|
|
1793
|
-
generator.addDependency("leva"
|
|
2317
|
+
generator.addDependency("leva");
|
|
1794
2318
|
generator.inject(
|
|
1795
2319
|
"readme-libraries",
|
|
1796
2320
|
`[leva](https://github.com/pmndrs/leva) - HTML GUI panel for React with lightweight, beautiful and extensible controls`
|
|
@@ -1808,7 +2332,7 @@ function generateOffscreen(generator, options) {
|
|
|
1808
2332
|
);
|
|
1809
2333
|
return;
|
|
1810
2334
|
}
|
|
1811
|
-
generator.addDependency("@react-three/offscreen"
|
|
2335
|
+
generator.addDependency("@react-three/offscreen");
|
|
1812
2336
|
generator.inject(
|
|
1813
2337
|
"readme-libraries",
|
|
1814
2338
|
`[@react-three/offscreen](https://github.com/pmndrs/offscreen) - Offload your scene to a worker thread for better performance`
|
|
@@ -1818,13 +2342,12 @@ function generateOffscreen(generator, options) {
|
|
|
1818
2342
|
function generateOxfmt(generator, options) {
|
|
1819
2343
|
const isMonorepo = generator.options.workspaceRoot != null;
|
|
1820
2344
|
if (isMonorepo) {
|
|
1821
|
-
generator.addDevDependency("@config/oxfmt", "workspace:*");
|
|
2345
|
+
generator.addDevDependency("@config/oxfmt", { version: "workspace:*" });
|
|
1822
2346
|
const configPath = "node_modules/@config/oxfmt/base.json";
|
|
1823
2347
|
generator.addScript("format", `oxfmt -c ${configPath} --write .`);
|
|
1824
2348
|
generator.addVscodeSetting("oxc.fmt.configPath", configPath);
|
|
1825
2349
|
} else {
|
|
1826
|
-
|
|
1827
|
-
generator.addDevDependency("oxfmt", `^${version}`);
|
|
2350
|
+
generator.addDevDependency("oxfmt");
|
|
1828
2351
|
const isStealth = generator.isStealthConfig();
|
|
1829
2352
|
if (isStealth) {
|
|
1830
2353
|
generator.addFile(".config/oxfmt.json", {
|
|
@@ -1870,13 +2393,12 @@ function generateOxlint(generator, options) {
|
|
|
1870
2393
|
const isReact = baseTemplate === "react" || baseTemplate === "r3f";
|
|
1871
2394
|
const isMonorepo = generator.options.workspaceRoot != null;
|
|
1872
2395
|
if (isMonorepo) {
|
|
1873
|
-
generator.addDevDependency("@config/oxlint", "workspace:*");
|
|
2396
|
+
generator.addDevDependency("@config/oxlint", { version: "workspace:*" });
|
|
1874
2397
|
const configPath = isReact ? "node_modules/@config/oxlint/react.json" : "node_modules/@config/oxlint/base.json";
|
|
1875
2398
|
generator.addScript("lint", `oxlint -c ${configPath}`);
|
|
1876
2399
|
generator.addVscodeSetting("oxc.configPath", configPath);
|
|
1877
2400
|
} else {
|
|
1878
|
-
|
|
1879
|
-
generator.addDevDependency("oxlint", `^${version}`);
|
|
2401
|
+
generator.addDevDependency("oxlint");
|
|
1880
2402
|
const isStealth = generator.isStealthConfig();
|
|
1881
2403
|
const { rules } = defaultLinterConfig;
|
|
1882
2404
|
const plugins = ["unicorn", "typescript", "oxc"];
|
|
@@ -1937,7 +2459,7 @@ function generatePostprocessing(generator, options) {
|
|
|
1937
2459
|
);
|
|
1938
2460
|
return;
|
|
1939
2461
|
}
|
|
1940
|
-
generator.addDependency("@react-three/postprocessing"
|
|
2462
|
+
generator.addDependency("@react-three/postprocessing");
|
|
1941
2463
|
generator.inject(
|
|
1942
2464
|
"readme-libraries",
|
|
1943
2465
|
`[@react-three/postprocessing](https://react-postprocessing.docs.pmnd.rs/) - Post-processing effects for @react-three/fiber`
|
|
@@ -1945,18 +2467,14 @@ function generatePostprocessing(generator, options) {
|
|
|
1945
2467
|
}
|
|
1946
2468
|
|
|
1947
2469
|
function generatePrettier(generator, options) {
|
|
1948
|
-
|
|
1949
|
-
generator.addDevDependency("prettier", `^${version}`);
|
|
2470
|
+
generator.addDevDependency("prettier");
|
|
1950
2471
|
const isStealth = generator.isStealthConfig();
|
|
1951
2472
|
if (isStealth) {
|
|
1952
2473
|
generator.addFile(".config/prettier.json", {
|
|
1953
2474
|
type: "text",
|
|
1954
2475
|
content: JSON.stringify(defaultPrettierConfig, null, 2)
|
|
1955
2476
|
});
|
|
1956
|
-
generator.addScript(
|
|
1957
|
-
"format",
|
|
1958
|
-
"prettier --config .config/prettier.json --write ."
|
|
1959
|
-
);
|
|
2477
|
+
generator.addScript("format", "prettier --config .config/prettier.json --write .");
|
|
1960
2478
|
generator.addVscodeSetting("prettier.configPath", ".config/prettier.json");
|
|
1961
2479
|
} else {
|
|
1962
2480
|
generator.addFile(".prettierrc", {
|
|
@@ -1965,22 +2483,16 @@ function generatePrettier(generator, options) {
|
|
|
1965
2483
|
});
|
|
1966
2484
|
generator.addScript("format", "prettier --write .");
|
|
1967
2485
|
}
|
|
1968
|
-
generator.inject(
|
|
1969
|
-
"readme-tools",
|
|
1970
|
-
"[Prettier](https://prettier.io/) - Opinionated code formatter"
|
|
1971
|
-
);
|
|
2486
|
+
generator.inject("readme-tools", "[Prettier](https://prettier.io/) - Opinionated code formatter");
|
|
1972
2487
|
generator.inject("vscode-extension-suggestion", "esbenp.prettier-vscode");
|
|
1973
|
-
generator.addVscodeSetting(
|
|
1974
|
-
"editor.defaultFormatter",
|
|
1975
|
-
"esbenp.prettier-vscode"
|
|
1976
|
-
);
|
|
2488
|
+
generator.addVscodeSetting("editor.defaultFormatter", "esbenp.prettier-vscode");
|
|
1977
2489
|
}
|
|
1978
2490
|
|
|
1979
2491
|
function generateRapier(generator, options) {
|
|
1980
2492
|
if (options == null) {
|
|
1981
2493
|
return;
|
|
1982
2494
|
}
|
|
1983
|
-
generator.addDependency("@react-three/rapier"
|
|
2495
|
+
generator.addDependency("@react-three/rapier");
|
|
1984
2496
|
generator.inject(
|
|
1985
2497
|
"readme-libraries",
|
|
1986
2498
|
`[@react-three/rapier](https://github.com/pmndrs/react-three-rapier) - Physics based on Rapier for your @react-three/fiber scene`
|
|
@@ -2079,8 +2591,12 @@ function generateProvidersModule(generator) {
|
|
|
2079
2591
|
const wrappedComponents = resolvedProviders.filter(
|
|
2080
2592
|
(provider) => provider.type === "wrapped-jsx"
|
|
2081
2593
|
);
|
|
2082
|
-
const inlineComponents = resolvedProviders.filter(
|
|
2083
|
-
|
|
2594
|
+
const inlineComponents = resolvedProviders.filter(
|
|
2595
|
+
(provider) => provider.type === "inline-jsx"
|
|
2596
|
+
);
|
|
2597
|
+
const layoutEffects = resolvedProviders.filter(
|
|
2598
|
+
(provider) => provider.type === "layout-effect"
|
|
2599
|
+
);
|
|
2084
2600
|
const declaredProps = providerProps.map((prop) => `${prop.declaredPropName} = ${prop.declaredPropDefaultValue}`).join(", ");
|
|
2085
2601
|
const declaredTypes = providerProps.map((prop) => `${prop.declaredPropName}?: ${prop.declaredPropType}`).join("; ");
|
|
2086
2602
|
const reactImports = ["type ReactNode"];
|
|
@@ -2155,7 +2671,7 @@ function generateTriplex(generator, options) {
|
|
|
2155
2671
|
}
|
|
2156
2672
|
|
|
2157
2673
|
function generateTsdown(generator) {
|
|
2158
|
-
generator.addDevDependency("tsdown"
|
|
2674
|
+
generator.addDevDependency("tsdown");
|
|
2159
2675
|
const template = generator.options.template ?? "vanilla";
|
|
2160
2676
|
const baseTemplate = getBaseTemplate(template);
|
|
2161
2677
|
const language = getLanguageFromTemplate(template);
|
|
@@ -2191,7 +2707,7 @@ function generateUikit(generator, options) {
|
|
|
2191
2707
|
if (options == null) {
|
|
2192
2708
|
return;
|
|
2193
2709
|
}
|
|
2194
|
-
generator.addDependency("@react-three/uikit"
|
|
2710
|
+
generator.addDependency("@react-three/uikit");
|
|
2195
2711
|
generator.inject(
|
|
2196
2712
|
"readme-libraries",
|
|
2197
2713
|
`[@react-three/uikit](https://pmndrs.github.io/uikit/docs/) - UI primitives for React Three Fiber`
|
|
@@ -2199,7 +2715,7 @@ function generateUikit(generator, options) {
|
|
|
2199
2715
|
}
|
|
2200
2716
|
|
|
2201
2717
|
function generateUnbuild(generator) {
|
|
2202
|
-
generator.addDevDependency("unbuild"
|
|
2718
|
+
generator.addDevDependency("unbuild");
|
|
2203
2719
|
const template = generator.options.template ?? "vanilla";
|
|
2204
2720
|
const baseTemplate = getBaseTemplate(template);
|
|
2205
2721
|
const language = getLanguageFromTemplate(template);
|
|
@@ -2244,15 +2760,14 @@ function generateUnbuild(generator) {
|
|
|
2244
2760
|
}
|
|
2245
2761
|
|
|
2246
2762
|
function generateVitest(generator) {
|
|
2247
|
-
|
|
2248
|
-
generator.addDevDependency("vitest", `^${version}`);
|
|
2763
|
+
generator.addDevDependency("vitest");
|
|
2249
2764
|
const template = generator.options.template ?? "vanilla";
|
|
2250
2765
|
const baseTemplate = getBaseTemplate(template);
|
|
2251
2766
|
const isReact = baseTemplate === "react" || baseTemplate === "r3f";
|
|
2252
2767
|
if (isReact) {
|
|
2253
|
-
generator.addDevDependency("@testing-library/react"
|
|
2254
|
-
generator.addDevDependency("@testing-library/dom"
|
|
2255
|
-
generator.addDevDependency("jsdom"
|
|
2768
|
+
generator.addDevDependency("@testing-library/react");
|
|
2769
|
+
generator.addDevDependency("@testing-library/dom");
|
|
2770
|
+
generator.addDevDependency("jsdom");
|
|
2256
2771
|
}
|
|
2257
2772
|
if (isReact) {
|
|
2258
2773
|
generator.configureVite({ test: { environment: "jsdom" } });
|
|
@@ -2265,7 +2780,7 @@ function generateVitest(generator) {
|
|
|
2265
2780
|
}
|
|
2266
2781
|
|
|
2267
2782
|
function generateViverse(generator, options) {
|
|
2268
|
-
if (options == null || (generator.options.packageManager
|
|
2783
|
+
if (options == null || getPackageManagerName(generator.options.packageManager) !== "npm") {
|
|
2269
2784
|
return;
|
|
2270
2785
|
}
|
|
2271
2786
|
generator.addFile(".github/workflows/viverse.yml", {
|
|
@@ -2323,7 +2838,7 @@ jobs:
|
|
|
2323
2838
|
|
|
2324
2839
|
`
|
|
2325
2840
|
});
|
|
2326
|
-
generator.addDependency("@viverse/cli"
|
|
2841
|
+
generator.addDependency("@viverse/cli");
|
|
2327
2842
|
generator.inject(
|
|
2328
2843
|
"readme-start",
|
|
2329
2844
|
`A GitHub CI/CD workflow for publishing to Viverse is configured.
|
|
@@ -2350,8 +2865,8 @@ function generateXr(generator, options) {
|
|
|
2350
2865
|
if (options === true) {
|
|
2351
2866
|
options = {};
|
|
2352
2867
|
}
|
|
2353
|
-
generator.addDependency("@react-three/xr"
|
|
2354
|
-
generator.addDependency("@vitejs/plugin-basic-ssl"
|
|
2868
|
+
generator.addDependency("@react-three/xr");
|
|
2869
|
+
generator.addDependency("@vitejs/plugin-basic-ssl");
|
|
2355
2870
|
generator.inject("import", "import { XR, createXRStore } from '@react-three/xr'");
|
|
2356
2871
|
generator.inject(
|
|
2357
2872
|
`global-start`,
|
|
@@ -2408,7 +2923,7 @@ function generateZustand(generator, options) {
|
|
|
2408
2923
|
if (options == null) {
|
|
2409
2924
|
return;
|
|
2410
2925
|
}
|
|
2411
|
-
generator.addDependency("zustand"
|
|
2926
|
+
generator.addDependency("zustand");
|
|
2412
2927
|
generator.inject(
|
|
2413
2928
|
"readme-libraries",
|
|
2414
2929
|
`[zustand](https://zustand.docs.pmnd.rs/) - small, fast and scalable state-management solution`
|
|
@@ -2446,255 +2961,6 @@ function merge(target, modification) {
|
|
|
2446
2961
|
return modification;
|
|
2447
2962
|
}
|
|
2448
2963
|
|
|
2449
|
-
async function getLatestNpmVersion(packageName, fallback) {
|
|
2450
|
-
try {
|
|
2451
|
-
const response = await fetch(
|
|
2452
|
-
`https://registry.npmjs.org/${packageName}/latest`
|
|
2453
|
-
);
|
|
2454
|
-
const data = await response.json();
|
|
2455
|
-
return data.version;
|
|
2456
|
-
} catch {
|
|
2457
|
-
return fallback;
|
|
2458
|
-
}
|
|
2459
|
-
}
|
|
2460
|
-
async function getLatestPnpmVersion() {
|
|
2461
|
-
return getLatestNpmVersion("pnpm", "10.11.0");
|
|
2462
|
-
}
|
|
2463
|
-
async function getLatestYarnVersion() {
|
|
2464
|
-
return getLatestNpmVersion("yarn", "4.6.0");
|
|
2465
|
-
}
|
|
2466
|
-
async function getLatestNpmCliVersion() {
|
|
2467
|
-
return getLatestNpmVersion("npm", "11.0.0");
|
|
2468
|
-
}
|
|
2469
|
-
async function getLatestNodeVersion() {
|
|
2470
|
-
try {
|
|
2471
|
-
const response = await fetch("https://nodejs.org/dist/index.json");
|
|
2472
|
-
const data = await response.json();
|
|
2473
|
-
const ltsVersion = data.find((v) => v.lts);
|
|
2474
|
-
if (ltsVersion) {
|
|
2475
|
-
return ltsVersion.version.replace(/^v/, "");
|
|
2476
|
-
}
|
|
2477
|
-
return "22.0.0";
|
|
2478
|
-
} catch {
|
|
2479
|
-
return "22.0.0";
|
|
2480
|
-
}
|
|
2481
|
-
}
|
|
2482
|
-
function validateNameSegment(segment, label) {
|
|
2483
|
-
if (!segment.length) {
|
|
2484
|
-
return `${label} is required`;
|
|
2485
|
-
}
|
|
2486
|
-
if (!/^[a-z0-9-]+$/.test(segment)) {
|
|
2487
|
-
return `${label} must be lowercase and contain only letters, numbers, and hyphens`;
|
|
2488
|
-
}
|
|
2489
|
-
if (segment.startsWith("-") || segment.endsWith("-")) {
|
|
2490
|
-
return `${label} cannot start or end with a hyphen`;
|
|
2491
|
-
}
|
|
2492
|
-
if (segment.includes("--")) {
|
|
2493
|
-
return `${label} cannot contain consecutive hyphens`;
|
|
2494
|
-
}
|
|
2495
|
-
return void 0;
|
|
2496
|
-
}
|
|
2497
|
-
function validatePackageName(name) {
|
|
2498
|
-
if (!name.length) {
|
|
2499
|
-
return "Package name is required";
|
|
2500
|
-
}
|
|
2501
|
-
if (name.includes("..") || name.includes("\\")) {
|
|
2502
|
-
return "Package name cannot contain path traversal sequences";
|
|
2503
|
-
}
|
|
2504
|
-
if (name.startsWith("@")) {
|
|
2505
|
-
const slashIndex = name.indexOf("/");
|
|
2506
|
-
if (slashIndex === -1) {
|
|
2507
|
-
return "Scoped package name must include a package name after the scope (e.g., @scope/name)";
|
|
2508
|
-
}
|
|
2509
|
-
if (name.indexOf("/", slashIndex + 1) !== -1) {
|
|
2510
|
-
return "Package name can only have one slash for scoped packages";
|
|
2511
|
-
}
|
|
2512
|
-
const scope = name.slice(1, slashIndex);
|
|
2513
|
-
const packageName = name.slice(slashIndex + 1);
|
|
2514
|
-
const scopeError = validateNameSegment(scope, "Scope");
|
|
2515
|
-
if (scopeError) return scopeError;
|
|
2516
|
-
const nameError = validateNameSegment(packageName, "Package name");
|
|
2517
|
-
if (nameError) return nameError;
|
|
2518
|
-
return void 0;
|
|
2519
|
-
}
|
|
2520
|
-
if (name.includes("/")) {
|
|
2521
|
-
return "Unscoped package name cannot contain slashes. Use @scope/name format for scoped packages";
|
|
2522
|
-
}
|
|
2523
|
-
return validateNameSegment(name, "Package name");
|
|
2524
|
-
}
|
|
2525
|
-
function parseWorkspaceYamlContent(content) {
|
|
2526
|
-
const directories = [];
|
|
2527
|
-
let inPackagesSection = false;
|
|
2528
|
-
for (const line of content.split("\n")) {
|
|
2529
|
-
const trimmed = line.trim();
|
|
2530
|
-
if (trimmed === "packages:") {
|
|
2531
|
-
inPackagesSection = true;
|
|
2532
|
-
continue;
|
|
2533
|
-
}
|
|
2534
|
-
if (inPackagesSection && trimmed && !line.startsWith(" ") && !line.startsWith(" ") && !trimmed.startsWith("-")) {
|
|
2535
|
-
break;
|
|
2536
|
-
}
|
|
2537
|
-
if (inPackagesSection && trimmed.startsWith("-")) {
|
|
2538
|
-
const entry = trimmed.slice(1).trim().replace(/^["']|["']$/g, "").replace(/^\.\//, "").replace(/\/\*.*$/, "");
|
|
2539
|
-
if (entry && !entry.startsWith(".")) {
|
|
2540
|
-
directories.push(entry);
|
|
2541
|
-
}
|
|
2542
|
-
}
|
|
2543
|
-
}
|
|
2544
|
-
return directories;
|
|
2545
|
-
}
|
|
2546
|
-
async function pathExists(path) {
|
|
2547
|
-
try {
|
|
2548
|
-
await access(path, constants.F_OK);
|
|
2549
|
-
return true;
|
|
2550
|
-
} catch {
|
|
2551
|
-
return false;
|
|
2552
|
-
}
|
|
2553
|
-
}
|
|
2554
|
-
function detectLinterFromScript(script) {
|
|
2555
|
-
if (!script) return void 0;
|
|
2556
|
-
if (script.includes("oxlint")) return "oxlint";
|
|
2557
|
-
if (script.includes("eslint")) return "eslint";
|
|
2558
|
-
if (script.includes("biome check") || script.includes("biome lint")) return "biome";
|
|
2559
|
-
return void 0;
|
|
2560
|
-
}
|
|
2561
|
-
function detectFormatterFromScript(script) {
|
|
2562
|
-
if (!script) return void 0;
|
|
2563
|
-
if (script.includes("prettier")) return "prettier";
|
|
2564
|
-
if (script.includes("oxfmt")) return "oxfmt";
|
|
2565
|
-
if (script.includes("biome format")) return "biome";
|
|
2566
|
-
return void 0;
|
|
2567
|
-
}
|
|
2568
|
-
async function detectLinterFromConfig(root) {
|
|
2569
|
-
if (await pathExists(join(root, ".config/oxlint"))) return "oxlint";
|
|
2570
|
-
if (await pathExists(join(root, ".config/eslint"))) return "eslint";
|
|
2571
|
-
if (await pathExists(join(root, "biome.json"))) {
|
|
2572
|
-
try {
|
|
2573
|
-
const content = await readFile(join(root, "biome.json"), "utf-8");
|
|
2574
|
-
const config = JSON.parse(content);
|
|
2575
|
-
if (config.linter?.enabled !== false) return "biome";
|
|
2576
|
-
} catch {
|
|
2577
|
-
return "biome";
|
|
2578
|
-
}
|
|
2579
|
-
}
|
|
2580
|
-
return void 0;
|
|
2581
|
-
}
|
|
2582
|
-
async function detectFormatterFromConfig(root) {
|
|
2583
|
-
if (await pathExists(join(root, ".config/prettier"))) return "prettier";
|
|
2584
|
-
if (await pathExists(join(root, ".config/oxfmt"))) return "oxfmt";
|
|
2585
|
-
if (await pathExists(join(root, "biome.json"))) {
|
|
2586
|
-
try {
|
|
2587
|
-
const content = await readFile(join(root, "biome.json"), "utf-8");
|
|
2588
|
-
const config = JSON.parse(content);
|
|
2589
|
-
if (config.formatter?.enabled !== false) return "biome";
|
|
2590
|
-
} catch {
|
|
2591
|
-
return "biome";
|
|
2592
|
-
}
|
|
2593
|
-
}
|
|
2594
|
-
return void 0;
|
|
2595
|
-
}
|
|
2596
|
-
function detectLinterFromDeps(devDeps) {
|
|
2597
|
-
if (!devDeps) return void 0;
|
|
2598
|
-
if (devDeps["@biomejs/biome"]) return "biome";
|
|
2599
|
-
if (devDeps.eslint) return "eslint";
|
|
2600
|
-
if (devDeps.oxlint) return "oxlint";
|
|
2601
|
-
return void 0;
|
|
2602
|
-
}
|
|
2603
|
-
function detectFormatterFromDeps(devDeps) {
|
|
2604
|
-
if (!devDeps) return void 0;
|
|
2605
|
-
if (devDeps["@biomejs/biome"]) return "biome";
|
|
2606
|
-
if (devDeps.prettier) return "prettier";
|
|
2607
|
-
if (devDeps.oxfmt) return "oxfmt";
|
|
2608
|
-
return void 0;
|
|
2609
|
-
}
|
|
2610
|
-
async function detectTooling(root) {
|
|
2611
|
-
try {
|
|
2612
|
-
const pkgPath = join(root, "package.json");
|
|
2613
|
-
const content = await readFile(pkgPath, "utf-8");
|
|
2614
|
-
const pkg = JSON.parse(content);
|
|
2615
|
-
const linter = detectLinterFromScript(pkg.scripts?.lint) ?? await detectLinterFromConfig(root) ?? detectLinterFromDeps(pkg.devDependencies);
|
|
2616
|
-
const formatter = detectFormatterFromScript(pkg.scripts?.format) ?? await detectFormatterFromConfig(root) ?? detectFormatterFromDeps(pkg.devDependencies);
|
|
2617
|
-
return { linter, formatter };
|
|
2618
|
-
} catch {
|
|
2619
|
-
return { linter: void 0, formatter: void 0 };
|
|
2620
|
-
}
|
|
2621
|
-
}
|
|
2622
|
-
function generateRandomName() {
|
|
2623
|
-
const adjectives = [
|
|
2624
|
-
"red",
|
|
2625
|
-
"blue",
|
|
2626
|
-
"green",
|
|
2627
|
-
"yellow",
|
|
2628
|
-
"purple",
|
|
2629
|
-
"orange",
|
|
2630
|
-
"pink",
|
|
2631
|
-
"black",
|
|
2632
|
-
"white",
|
|
2633
|
-
"tiny",
|
|
2634
|
-
"big",
|
|
2635
|
-
"small",
|
|
2636
|
-
"large",
|
|
2637
|
-
"huge",
|
|
2638
|
-
"giant",
|
|
2639
|
-
"mini",
|
|
2640
|
-
"mega",
|
|
2641
|
-
"super",
|
|
2642
|
-
"happy",
|
|
2643
|
-
"sad",
|
|
2644
|
-
"angry",
|
|
2645
|
-
"calm",
|
|
2646
|
-
"quiet",
|
|
2647
|
-
"loud",
|
|
2648
|
-
"silent",
|
|
2649
|
-
"noisy",
|
|
2650
|
-
"shiny",
|
|
2651
|
-
"dull",
|
|
2652
|
-
"bright",
|
|
2653
|
-
"dark",
|
|
2654
|
-
"fuzzy",
|
|
2655
|
-
"smooth",
|
|
2656
|
-
"rough",
|
|
2657
|
-
"soft"
|
|
2658
|
-
];
|
|
2659
|
-
const nouns = [
|
|
2660
|
-
"apple",
|
|
2661
|
-
"banana",
|
|
2662
|
-
"cherry",
|
|
2663
|
-
"date",
|
|
2664
|
-
"elderberry",
|
|
2665
|
-
"fig",
|
|
2666
|
-
"grape",
|
|
2667
|
-
"honeydew",
|
|
2668
|
-
"cat",
|
|
2669
|
-
"dog",
|
|
2670
|
-
"elephant",
|
|
2671
|
-
"fox",
|
|
2672
|
-
"giraffe",
|
|
2673
|
-
"horse",
|
|
2674
|
-
"iguana",
|
|
2675
|
-
"jaguar",
|
|
2676
|
-
"mountain",
|
|
2677
|
-
"river",
|
|
2678
|
-
"ocean",
|
|
2679
|
-
"desert",
|
|
2680
|
-
"forest",
|
|
2681
|
-
"jungle",
|
|
2682
|
-
"meadow",
|
|
2683
|
-
"valley",
|
|
2684
|
-
"star",
|
|
2685
|
-
"moon",
|
|
2686
|
-
"sun",
|
|
2687
|
-
"planet",
|
|
2688
|
-
"comet",
|
|
2689
|
-
"asteroid",
|
|
2690
|
-
"galaxy",
|
|
2691
|
-
"universe"
|
|
2692
|
-
];
|
|
2693
|
-
const randomAdjective = adjectives[Math.floor(Math.random() * adjectives.length)];
|
|
2694
|
-
const randomNoun = nouns[Math.floor(Math.random() * nouns.length)];
|
|
2695
|
-
return `${randomAdjective}-${randomNoun}`;
|
|
2696
|
-
}
|
|
2697
|
-
|
|
2698
2964
|
function generate(options) {
|
|
2699
2965
|
const clonedOptions = structuredClone(options);
|
|
2700
2966
|
const template = clonedOptions.template ?? "vanilla";
|
|
@@ -2716,16 +2982,16 @@ function generate(options) {
|
|
|
2716
2982
|
const devDependencies = {};
|
|
2717
2983
|
const peerDependencies = {};
|
|
2718
2984
|
if (!isLibrary) {
|
|
2719
|
-
devDependencies
|
|
2985
|
+
assignResolvedPackageVersion(devDependencies, versions, "vite");
|
|
2720
2986
|
}
|
|
2721
2987
|
if (isReact || isR3f) {
|
|
2722
2988
|
if (isLibrary) {
|
|
2723
2989
|
peerDependencies["react"] = "^18.0.0 || ^19.0.0";
|
|
2724
2990
|
peerDependencies["react-dom"] = "^18.0.0 || ^19.0.0";
|
|
2725
2991
|
} else {
|
|
2726
|
-
dependencies
|
|
2727
|
-
dependencies
|
|
2728
|
-
devDependencies
|
|
2992
|
+
assignResolvedPackageVersion(dependencies, versions, "react");
|
|
2993
|
+
assignResolvedPackageVersion(dependencies, versions, "react-dom");
|
|
2994
|
+
assignResolvedPackageVersion(devDependencies, versions, "@vitejs/plugin-react");
|
|
2729
2995
|
}
|
|
2730
2996
|
}
|
|
2731
2997
|
if (isR3f) {
|
|
@@ -2733,15 +2999,17 @@ function generate(options) {
|
|
|
2733
2999
|
peerDependencies["three"] = ">=0.150.0";
|
|
2734
3000
|
peerDependencies["@react-three/fiber"] = "^8.0.0 || ^9.0.0";
|
|
2735
3001
|
} else {
|
|
2736
|
-
dependencies
|
|
2737
|
-
dependencies
|
|
3002
|
+
assignResolvedPackageVersion(dependencies, versions, "three", "~");
|
|
3003
|
+
assignResolvedPackageVersion(dependencies, versions, "@react-three/fiber");
|
|
2738
3004
|
}
|
|
2739
3005
|
}
|
|
2740
3006
|
if (language === "typescript") {
|
|
2741
3007
|
const tsResult = generateTypescriptConfig({
|
|
2742
3008
|
baseTemplate,
|
|
2743
3009
|
useConfigPackage: clonedOptions.workspaceRoot != null,
|
|
2744
|
-
configStrategy: clonedOptions.configStrategy
|
|
3010
|
+
configStrategy: clonedOptions.configStrategy,
|
|
3011
|
+
engine: clonedOptions.engine,
|
|
3012
|
+
versions
|
|
2745
3013
|
});
|
|
2746
3014
|
Object.assign(files, tsResult.files);
|
|
2747
3015
|
Object.assign(devDependencies, tsResult.devDependencies);
|
|
@@ -2753,9 +3021,7 @@ function generate(options) {
|
|
|
2753
3021
|
build: "vite build"
|
|
2754
3022
|
};
|
|
2755
3023
|
if (!isLibrary && (isReact || isR3f)) {
|
|
2756
|
-
codeSnippets["vite-config-import"] = [
|
|
2757
|
-
"import react from '@vitejs/plugin-react'"
|
|
2758
|
-
];
|
|
3024
|
+
codeSnippets["vite-config-import"] = ["import react from '@vitejs/plugin-react'"];
|
|
2759
3025
|
}
|
|
2760
3026
|
if (!isLibrary && isR3f) {
|
|
2761
3027
|
codeSnippets["import"] = [`import { Canvas } from "@react-three/fiber"`];
|
|
@@ -2775,16 +3041,29 @@ function generate(options) {
|
|
|
2775
3041
|
const generator = {
|
|
2776
3042
|
options: clonedOptions,
|
|
2777
3043
|
versions,
|
|
3044
|
+
getVersion(name2) {
|
|
3045
|
+
return getResolvedPackageVersion(versions, name2);
|
|
3046
|
+
},
|
|
2778
3047
|
isStealthConfig() {
|
|
2779
3048
|
return (clonedOptions.configStrategy ?? "stealth") === "stealth";
|
|
2780
3049
|
},
|
|
2781
|
-
addDependency(name2,
|
|
2782
|
-
dependencies[name2]
|
|
2783
|
-
|
|
3050
|
+
addDependency(name2, options2) {
|
|
3051
|
+
if (dependencies[name2] != null) {
|
|
3052
|
+
return;
|
|
3053
|
+
}
|
|
3054
|
+
dependencies[name2] = resolveDependencySemver(name2, versions, options2);
|
|
3055
|
+
},
|
|
3056
|
+
addDevDependency(name2, options2) {
|
|
3057
|
+
if (devDependencies[name2] != null) {
|
|
3058
|
+
return;
|
|
3059
|
+
}
|
|
3060
|
+
devDependencies[name2] = resolveDependencySemver(name2, versions, options2);
|
|
2784
3061
|
},
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
3062
|
+
addPeerDependency(name2, semver) {
|
|
3063
|
+
if (peerDependencies[name2] != null) {
|
|
3064
|
+
return;
|
|
3065
|
+
}
|
|
3066
|
+
peerDependencies[name2] = semver;
|
|
2788
3067
|
},
|
|
2789
3068
|
addFile(path, content) {
|
|
2790
3069
|
files[path] = content;
|
|
@@ -2833,11 +3112,8 @@ function generate(options) {
|
|
|
2833
3112
|
} else if (libraryBundler === "tsdown") {
|
|
2834
3113
|
generateTsdown(generator);
|
|
2835
3114
|
}
|
|
2836
|
-
const packageManager2 = clonedOptions.packageManager
|
|
2837
|
-
generator.addScript(
|
|
2838
|
-
"release",
|
|
2839
|
-
`${packageManager2} run build && ${packageManager2} publish`
|
|
2840
|
-
);
|
|
3115
|
+
const packageManager2 = getPackageManagerName(clonedOptions.packageManager);
|
|
3116
|
+
generator.addScript("release", `${packageManager2} run build && ${packageManager2} publish`);
|
|
2841
3117
|
}
|
|
2842
3118
|
const testing = clonedOptions.testing ?? (isLibrary ? "vitest" : "none");
|
|
2843
3119
|
if (testing === "vitest") {
|
|
@@ -2876,7 +3152,7 @@ function generate(options) {
|
|
|
2876
3152
|
if (!isLibrary) {
|
|
2877
3153
|
files["vite.config.ts"] = generateViteConfig({ viteConfig, codeSnippets });
|
|
2878
3154
|
}
|
|
2879
|
-
const packageManager = options.packageManager
|
|
3155
|
+
const packageManager = getPackageManagerName(options.packageManager);
|
|
2880
3156
|
files["README.md"] = generateReadme({
|
|
2881
3157
|
name,
|
|
2882
3158
|
baseTemplate,
|
|
@@ -2924,16 +3200,13 @@ function generate(options) {
|
|
|
2924
3200
|
Object.assign(files, generateVscodeFiles$1({ codeSnippets, vscodeSettings }));
|
|
2925
3201
|
}
|
|
2926
3202
|
if (!isMonorepoPackage) {
|
|
2927
|
-
files[".gitignore"] =
|
|
2928
|
-
type: "text",
|
|
2929
|
-
content: ["node_modules", "dist", "*.tsbuildinfo"].join("\n")
|
|
2930
|
-
};
|
|
3203
|
+
files[".gitignore"] = generateGitignore("standalone");
|
|
2931
3204
|
files[".gitattributes"] = { type: "text", content: GitAttributes };
|
|
2932
3205
|
}
|
|
2933
3206
|
if (!isMonorepoPackage && clonedOptions.aiPlatforms?.length) {
|
|
2934
3207
|
generateAiFiles(files, {
|
|
2935
3208
|
name,
|
|
2936
|
-
packageManager: clonedOptions.packageManager
|
|
3209
|
+
packageManager: getPackageManagerName(clonedOptions.packageManager),
|
|
2937
3210
|
linter: clonedOptions.linter ?? "oxlint",
|
|
2938
3211
|
formatter: clonedOptions.formatter ?? "prettier",
|
|
2939
3212
|
isMonorepo: false,
|
|
@@ -2943,5 +3216,11 @@ function generate(options) {
|
|
|
2943
3216
|
}
|
|
2944
3217
|
return files;
|
|
2945
3218
|
}
|
|
3219
|
+
function resolveDependencySemver(name, versions, options = {}) {
|
|
3220
|
+
if (options.version != null) {
|
|
3221
|
+
return options.version;
|
|
3222
|
+
}
|
|
3223
|
+
return formatResolvedPackageVersion(versions, name, options.prefix);
|
|
3224
|
+
}
|
|
2946
3225
|
|
|
2947
|
-
export { ALL_AI_PLATFORMS as A,
|
|
3226
|
+
export { ALL_AI_PLATFORMS as A, validatePackageName as B, generateMonorepo as C, getLatestNodeVersion as D, getLatestNpmCliVersion as E, getLatestNpmVersion as F, getLatestPnpmVersion as G, getLatestYarnVersion as H, monorepo as I, getBaseTemplate as a, getLanguageFromTemplate as b, getPackageManagerName as c, generateRandomName as d, detectTooling as e, generateAiFiles as f, getEngineName as g, generateVscodeFiles as h, generateTypescriptConfigPackage as i, generateOxlintConfigPackage as j, generateEslintConfigPackage as k, generateOxfmtConfigPackage as l, generatePrettierConfigPackage as m, generateGitignore as n, getResolvedPackageVersion as o, parseWorkspaceYamlContent as p, formatResolvedPackageVersion as q, resolveMonorepoRootPackageVersions as r, resolvePackageManager as s, resolveEngine as t, resolveProjectPackageVersions as u, generate as v, parsePackageManager as w, parseEngine as x, AI_PLATFORM_LABELS as y, AI_PLATFORM_HINTS as z };
|