create-krispya 0.2.0 → 0.3.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/dist/cli.cjs +550 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.d.ts +1 -2
- package/dist/cli.mjs +531 -0
- package/dist/index.cjs +1688 -0
- package/dist/index.d.cts +148 -0
- package/dist/index.d.mts +148 -0
- package/dist/index.d.ts +88 -27
- package/dist/index.mjs +1676 -0
- package/package.json +6 -5
- package/dist/cli.js +0 -504
- package/dist/constants.d.ts +0 -33
- package/dist/constants.js +0 -110
- package/dist/index.js +0 -397
- package/dist/integrations/biome.d.ts +0 -8
- package/dist/integrations/biome.js +0 -80
- package/dist/integrations/drei.d.ts +0 -3
- package/dist/integrations/drei.js +0 -9
- package/dist/integrations/eslint.d.ts +0 -3
- package/dist/integrations/eslint.js +0 -78
- package/dist/integrations/fiber.d.ts +0 -8
- package/dist/integrations/fiber.js +0 -35
- package/dist/integrations/github-pages.d.ts +0 -3
- package/dist/integrations/github-pages.js +0 -58
- package/dist/integrations/handle.d.ts +0 -3
- package/dist/integrations/handle.js +0 -7
- package/dist/integrations/koota.d.ts +0 -8
- package/dist/integrations/koota.js +0 -7
- package/dist/integrations/leva.d.ts +0 -3
- package/dist/integrations/leva.js +0 -7
- package/dist/integrations/offscreen.d.ts +0 -3
- package/dist/integrations/offscreen.js +0 -12
- package/dist/integrations/oxfmt.d.ts +0 -3
- package/dist/integrations/oxfmt.js +0 -27
- package/dist/integrations/oxlint.d.ts +0 -3
- package/dist/integrations/oxlint.js +0 -52
- package/dist/integrations/postprocessing.d.ts +0 -3
- package/dist/integrations/postprocessing.js +0 -12
- package/dist/integrations/prettier.d.ts +0 -3
- package/dist/integrations/prettier.js +0 -28
- package/dist/integrations/rapier.d.ts +0 -3
- package/dist/integrations/rapier.js +0 -7
- package/dist/integrations/triplex.d.ts +0 -26
- package/dist/integrations/triplex.js +0 -159
- package/dist/integrations/uikit.d.ts +0 -3
- package/dist/integrations/uikit.js +0 -7
- package/dist/integrations/vitest.d.ts +0 -2
- package/dist/integrations/vitest.js +0 -20
- package/dist/integrations/viverse.d.ts +0 -3
- package/dist/integrations/viverse.js +0 -74
- package/dist/integrations/xr.d.ts +0 -5
- package/dist/integrations/xr.js +0 -51
- package/dist/integrations/zustand.d.ts +0 -8
- package/dist/integrations/zustand.js +0 -7
- package/dist/lib/array.d.ts +0 -1
- package/dist/lib/array.js +0 -9
- package/dist/merge.d.ts +0 -1
- package/dist/merge.js +0 -26
- package/dist/utils.d.ts +0 -22
- package/dist/utils.js +0 -123
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-krispya",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "🌹 CLI for creating web projects with (my) sensible defaults",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -12,12 +12,12 @@
|
|
|
12
12
|
],
|
|
13
13
|
"license": "ISC",
|
|
14
14
|
"author": "Kris Baumgartner",
|
|
15
|
-
"bin": "dist/cli.
|
|
15
|
+
"bin": "dist/cli.mjs",
|
|
16
16
|
"files": [
|
|
17
17
|
"dist"
|
|
18
18
|
],
|
|
19
19
|
"type": "module",
|
|
20
|
-
"main": "dist/index.
|
|
20
|
+
"main": "dist/index.mjs",
|
|
21
21
|
"types": "dist/index.d.ts",
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@clack/prompts": "^0.11.0",
|
|
@@ -29,10 +29,11 @@
|
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@types/node": "^20.17.32",
|
|
31
31
|
"tsx": "^4.20.5",
|
|
32
|
-
"typescript": "^5.8.3"
|
|
32
|
+
"typescript": "^5.8.3",
|
|
33
|
+
"unbuild": "^3.6.1"
|
|
33
34
|
},
|
|
34
35
|
"scripts": {
|
|
35
|
-
"build": "
|
|
36
|
+
"build": "unbuild",
|
|
36
37
|
"dev": "tsx src/cli.ts"
|
|
37
38
|
}
|
|
38
39
|
}
|
package/dist/cli.js
DELETED
|
@@ -1,504 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { cwd } from "process";
|
|
3
|
-
import { generate, generateRandomName, getBaseTemplate, getLanguageFromTemplate, getLatestPnpmVersion, } from "./index.js";
|
|
4
|
-
import { getLatestNodeVersion, getLatestNpmVersion } from "./utils.js";
|
|
5
|
-
import { dirname, join } from "path";
|
|
6
|
-
import { mkdir, writeFile } from "fs/promises";
|
|
7
|
-
import { Command } from "commander";
|
|
8
|
-
import * as p from "@clack/prompts";
|
|
9
|
-
import color from "chalk";
|
|
10
|
-
import { fetch } from "undici";
|
|
11
|
-
function getDefaultProjectName(template) {
|
|
12
|
-
const base = getBaseTemplate(template);
|
|
13
|
-
switch (base) {
|
|
14
|
-
case "vanilla":
|
|
15
|
-
return `vanilla-${generateRandomName()}`;
|
|
16
|
-
case "react":
|
|
17
|
-
return `react-${generateRandomName()}`;
|
|
18
|
-
case "r3f":
|
|
19
|
-
return `react-three-${generateRandomName()}`;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
function getDefaultOptions(template, name) {
|
|
23
|
-
const baseTemplate = getBaseTemplate(template);
|
|
24
|
-
const base = {
|
|
25
|
-
name,
|
|
26
|
-
template,
|
|
27
|
-
packageManager: "pnpm",
|
|
28
|
-
pnpmManageVersions: true,
|
|
29
|
-
nodeVersion: "latest",
|
|
30
|
-
linter: "oxlint",
|
|
31
|
-
formatter: "oxfmt",
|
|
32
|
-
};
|
|
33
|
-
if (baseTemplate === "r3f") {
|
|
34
|
-
return {
|
|
35
|
-
...base,
|
|
36
|
-
drei: {},
|
|
37
|
-
handle: {},
|
|
38
|
-
leva: {},
|
|
39
|
-
postprocessing: {},
|
|
40
|
-
rapier: {},
|
|
41
|
-
xr: {},
|
|
42
|
-
uikit: {},
|
|
43
|
-
offscreen: {},
|
|
44
|
-
zustand: {},
|
|
45
|
-
koota: {},
|
|
46
|
-
triplex: {},
|
|
47
|
-
viverse: {},
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
return base;
|
|
51
|
-
}
|
|
52
|
-
function formatConfigSummary(options) {
|
|
53
|
-
const lines = [];
|
|
54
|
-
const VALUE_COL = 27; // Start position for values
|
|
55
|
-
const formatRow = (label, value, indent = "") => {
|
|
56
|
-
const fullLabel = indent + label;
|
|
57
|
-
const dotCount = Math.max(1, VALUE_COL - fullLabel.length - 1);
|
|
58
|
-
const dots = color.gray(".".repeat(dotCount));
|
|
59
|
-
return `${indent}${label} ${dots} ${value}`;
|
|
60
|
-
};
|
|
61
|
-
const formatLanguage = (lang) => {
|
|
62
|
-
return lang === "typescript"
|
|
63
|
-
? "TypeScript"
|
|
64
|
-
: lang === "javascript"
|
|
65
|
-
? "JavaScript"
|
|
66
|
-
: lang;
|
|
67
|
-
};
|
|
68
|
-
// Language (derived from template)
|
|
69
|
-
const language = options.template
|
|
70
|
-
? getLanguageFromTemplate(options.template)
|
|
71
|
-
: "typescript";
|
|
72
|
-
lines.push(formatRow("Language", formatLanguage(language)));
|
|
73
|
-
// Bundler (always vite)
|
|
74
|
-
lines.push(formatRow("Bundler", "vite"));
|
|
75
|
-
// Node version
|
|
76
|
-
lines.push(formatRow("Node version", options.nodeVersion || "latest"));
|
|
77
|
-
// Package manager
|
|
78
|
-
lines.push(formatRow("Package manager", options.packageManager || "pnpm"));
|
|
79
|
-
// pnpm-specific options
|
|
80
|
-
if (options.packageManager === "pnpm") {
|
|
81
|
-
const versionManaged = options.pnpmManageVersions ? "yes" : "no";
|
|
82
|
-
lines.push(formatRow("↳ Version managed", versionManaged, ""));
|
|
83
|
-
}
|
|
84
|
-
// Linter
|
|
85
|
-
if (options.linter) {
|
|
86
|
-
lines.push(formatRow("Linter", options.linter));
|
|
87
|
-
}
|
|
88
|
-
// Formatter
|
|
89
|
-
if (options.formatter) {
|
|
90
|
-
lines.push(formatRow("Formatter", options.formatter));
|
|
91
|
-
}
|
|
92
|
-
// Testing (always vitest)
|
|
93
|
-
lines.push(formatRow("Testing", "vitest"));
|
|
94
|
-
// R3F integrations
|
|
95
|
-
if (options.template && getBaseTemplate(options.template) === "r3f") {
|
|
96
|
-
const integrationNames = [
|
|
97
|
-
options.drei && "drei",
|
|
98
|
-
options.handle && "handle",
|
|
99
|
-
options.leva && "leva",
|
|
100
|
-
options.postprocessing && "postproc",
|
|
101
|
-
options.rapier && "rapier",
|
|
102
|
-
options.xr && "xr",
|
|
103
|
-
options.uikit && "uikit",
|
|
104
|
-
options.offscreen && "offscreen",
|
|
105
|
-
options.zustand && "zustand",
|
|
106
|
-
options.koota && "koota",
|
|
107
|
-
options.triplex && "triplex",
|
|
108
|
-
options.viverse && "viverse",
|
|
109
|
-
].filter(Boolean);
|
|
110
|
-
lines.push("");
|
|
111
|
-
lines.push(color.dim("Integrations"));
|
|
112
|
-
// Two-column layout
|
|
113
|
-
for (let i = 0; i < integrationNames.length; i += 2) {
|
|
114
|
-
const left = `${color.green("●")} ${integrationNames[i]}`;
|
|
115
|
-
const right = integrationNames[i + 1]
|
|
116
|
-
? `${color.green("●")} ${integrationNames[i + 1]}`
|
|
117
|
-
: "";
|
|
118
|
-
const spacing = " ".repeat(Math.max(1, 16 - integrationNames[i].length));
|
|
119
|
-
lines.push(` ${left}${spacing}${right}`);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
return lines.join("\n");
|
|
123
|
-
}
|
|
124
|
-
async function promptForCustomization(template, name) {
|
|
125
|
-
const nodeVersion = await p.text({
|
|
126
|
-
message: "Node.js version",
|
|
127
|
-
placeholder: "latest",
|
|
128
|
-
defaultValue: "latest",
|
|
129
|
-
validate: (value) => {
|
|
130
|
-
if (!value.length)
|
|
131
|
-
return "Required";
|
|
132
|
-
if (value !== "latest" && !/^\d+(\.\d+(\.\d+)?)?$/.test(value)) {
|
|
133
|
-
return 'Must be "latest" or a valid semver (e.g., "22" or "22.13.0")';
|
|
134
|
-
}
|
|
135
|
-
},
|
|
136
|
-
});
|
|
137
|
-
if (p.isCancel(nodeVersion)) {
|
|
138
|
-
p.cancel("Operation cancelled.");
|
|
139
|
-
process.exit(0);
|
|
140
|
-
}
|
|
141
|
-
const packageManager = await p.select({
|
|
142
|
-
message: "Package manager",
|
|
143
|
-
options: [
|
|
144
|
-
{ value: "pnpm", label: "pnpm" },
|
|
145
|
-
{ value: "npm", label: "npm" },
|
|
146
|
-
{ value: "yarn", label: "yarn" },
|
|
147
|
-
{ value: "custom", label: "Other (custom)" },
|
|
148
|
-
],
|
|
149
|
-
initialValue: "pnpm",
|
|
150
|
-
});
|
|
151
|
-
if (p.isCancel(packageManager)) {
|
|
152
|
-
p.cancel("Operation cancelled.");
|
|
153
|
-
process.exit(0);
|
|
154
|
-
}
|
|
155
|
-
let finalPackageManager = packageManager;
|
|
156
|
-
if (packageManager === "custom") {
|
|
157
|
-
const customPm = await p.text({
|
|
158
|
-
message: "Enter package manager command",
|
|
159
|
-
validate: (value) => {
|
|
160
|
-
if (!value.length)
|
|
161
|
-
return "Required";
|
|
162
|
-
},
|
|
163
|
-
});
|
|
164
|
-
if (p.isCancel(customPm)) {
|
|
165
|
-
p.cancel("Operation cancelled.");
|
|
166
|
-
process.exit(0);
|
|
167
|
-
}
|
|
168
|
-
finalPackageManager = customPm;
|
|
169
|
-
}
|
|
170
|
-
let pnpmManageVersions = true;
|
|
171
|
-
if (packageManager === "pnpm") {
|
|
172
|
-
const managePnpm = await p.confirm({
|
|
173
|
-
message: "Enable manage-package-manager-versions?",
|
|
174
|
-
initialValue: true,
|
|
175
|
-
});
|
|
176
|
-
if (p.isCancel(managePnpm)) {
|
|
177
|
-
p.cancel("Operation cancelled.");
|
|
178
|
-
process.exit(0);
|
|
179
|
-
}
|
|
180
|
-
pnpmManageVersions = managePnpm;
|
|
181
|
-
}
|
|
182
|
-
const linter = await p.select({
|
|
183
|
-
message: "Linter",
|
|
184
|
-
options: [
|
|
185
|
-
{ value: "oxlint", label: "Oxlint", hint: "fast, from OXC" },
|
|
186
|
-
{ value: "eslint", label: "ESLint", hint: "classic" },
|
|
187
|
-
{ value: "biome", label: "Biome", hint: "all-in-one" },
|
|
188
|
-
],
|
|
189
|
-
initialValue: "oxlint",
|
|
190
|
-
});
|
|
191
|
-
if (p.isCancel(linter)) {
|
|
192
|
-
p.cancel("Operation cancelled.");
|
|
193
|
-
process.exit(0);
|
|
194
|
-
}
|
|
195
|
-
const formatter = await p.select({
|
|
196
|
-
message: "Formatter",
|
|
197
|
-
options: [
|
|
198
|
-
{ value: "oxfmt", label: "Oxfmt", hint: "fast, Prettier-compatible" },
|
|
199
|
-
{ value: "prettier", label: "Prettier", hint: "classic" },
|
|
200
|
-
{ value: "biome", label: "Biome", hint: "all-in-one" },
|
|
201
|
-
],
|
|
202
|
-
initialValue: "oxfmt",
|
|
203
|
-
});
|
|
204
|
-
if (p.isCancel(formatter)) {
|
|
205
|
-
p.cancel("Operation cancelled.");
|
|
206
|
-
process.exit(0);
|
|
207
|
-
}
|
|
208
|
-
const language = await p.select({
|
|
209
|
-
message: "Language",
|
|
210
|
-
options: [
|
|
211
|
-
{ value: "typescript", label: "TypeScript" },
|
|
212
|
-
{ value: "javascript", label: "JavaScript" },
|
|
213
|
-
],
|
|
214
|
-
initialValue: "typescript",
|
|
215
|
-
});
|
|
216
|
-
if (p.isCancel(language)) {
|
|
217
|
-
p.cancel("Operation cancelled.");
|
|
218
|
-
process.exit(0);
|
|
219
|
-
}
|
|
220
|
-
// Derive final template based on language selection
|
|
221
|
-
const baseTemplate = getBaseTemplate(template);
|
|
222
|
-
const finalTemplate = language === "javascript"
|
|
223
|
-
? `${baseTemplate}-js`
|
|
224
|
-
: baseTemplate;
|
|
225
|
-
let integrations = [];
|
|
226
|
-
if (baseTemplate === "r3f") {
|
|
227
|
-
const selected = await p.multiselect({
|
|
228
|
-
message: "R3F integrations",
|
|
229
|
-
options: [
|
|
230
|
-
{ value: "drei", label: "Drei" },
|
|
231
|
-
{ value: "handle", label: "Handle" },
|
|
232
|
-
{ value: "leva", label: "Leva" },
|
|
233
|
-
{ value: "postprocessing", label: "Postprocessing" },
|
|
234
|
-
{ value: "rapier", label: "Rapier" },
|
|
235
|
-
{ value: "xr", label: "XR" },
|
|
236
|
-
{ value: "uikit", label: "UIKit" },
|
|
237
|
-
{ value: "offscreen", label: "Offscreen" },
|
|
238
|
-
{ value: "zustand", label: "Zustand" },
|
|
239
|
-
{ value: "koota", label: "Koota" },
|
|
240
|
-
{ value: "triplex", label: "Triplex" },
|
|
241
|
-
{ value: "viverse", label: "Viverse" },
|
|
242
|
-
],
|
|
243
|
-
initialValues: [
|
|
244
|
-
"drei",
|
|
245
|
-
"handle",
|
|
246
|
-
"leva",
|
|
247
|
-
"postprocessing",
|
|
248
|
-
"rapier",
|
|
249
|
-
"xr",
|
|
250
|
-
"uikit",
|
|
251
|
-
"offscreen",
|
|
252
|
-
"zustand",
|
|
253
|
-
"koota",
|
|
254
|
-
"triplex",
|
|
255
|
-
"viverse",
|
|
256
|
-
],
|
|
257
|
-
required: false,
|
|
258
|
-
});
|
|
259
|
-
if (p.isCancel(selected)) {
|
|
260
|
-
p.cancel("Operation cancelled.");
|
|
261
|
-
process.exit(0);
|
|
262
|
-
}
|
|
263
|
-
integrations = selected;
|
|
264
|
-
}
|
|
265
|
-
return {
|
|
266
|
-
name,
|
|
267
|
-
template: finalTemplate,
|
|
268
|
-
nodeVersion,
|
|
269
|
-
packageManager: finalPackageManager,
|
|
270
|
-
pnpmManageVersions,
|
|
271
|
-
linter: linter,
|
|
272
|
-
formatter: formatter,
|
|
273
|
-
...(baseTemplate === "r3f" && {
|
|
274
|
-
drei: integrations.includes("drei") ? {} : undefined,
|
|
275
|
-
handle: integrations.includes("handle") ? {} : undefined,
|
|
276
|
-
leva: integrations.includes("leva") ? {} : undefined,
|
|
277
|
-
postprocessing: integrations.includes("postprocessing") ? {} : undefined,
|
|
278
|
-
rapier: integrations.includes("rapier") ? {} : undefined,
|
|
279
|
-
xr: integrations.includes("xr") ? {} : undefined,
|
|
280
|
-
uikit: integrations.includes("uikit") ? {} : undefined,
|
|
281
|
-
offscreen: integrations.includes("offscreen") ? {} : undefined,
|
|
282
|
-
zustand: integrations.includes("zustand") ? {} : undefined,
|
|
283
|
-
koota: integrations.includes("koota") ? {} : undefined,
|
|
284
|
-
triplex: integrations.includes("triplex") ? {} : undefined,
|
|
285
|
-
viverse: integrations.includes("viverse") ? {} : undefined,
|
|
286
|
-
}),
|
|
287
|
-
};
|
|
288
|
-
}
|
|
289
|
-
async function promptForOptions(name) {
|
|
290
|
-
// Step 1: Project Name (if not provided via argument)
|
|
291
|
-
let projectName = name;
|
|
292
|
-
if (!projectName) {
|
|
293
|
-
const nameResult = await p.text({
|
|
294
|
-
message: "What is your project named?",
|
|
295
|
-
placeholder: generateRandomName(),
|
|
296
|
-
defaultValue: generateRandomName(),
|
|
297
|
-
validate: (value) => {
|
|
298
|
-
if (!value.length)
|
|
299
|
-
return "Project name is required";
|
|
300
|
-
},
|
|
301
|
-
});
|
|
302
|
-
if (p.isCancel(nameResult)) {
|
|
303
|
-
p.cancel("Operation cancelled.");
|
|
304
|
-
process.exit(0);
|
|
305
|
-
}
|
|
306
|
-
projectName = nameResult;
|
|
307
|
-
}
|
|
308
|
-
// Step 2: Select template (TypeScript by default, customize for JavaScript)
|
|
309
|
-
const template = await p.select({
|
|
310
|
-
message: "Select a template",
|
|
311
|
-
options: [
|
|
312
|
-
{ value: "vanilla", label: "Vanilla" },
|
|
313
|
-
{ value: "react", label: "React" },
|
|
314
|
-
{ value: "r3f", label: "React Three Fiber" },
|
|
315
|
-
],
|
|
316
|
-
initialValue: "vanilla",
|
|
317
|
-
});
|
|
318
|
-
if (p.isCancel(template)) {
|
|
319
|
-
p.cancel("Operation cancelled.");
|
|
320
|
-
process.exit(0);
|
|
321
|
-
}
|
|
322
|
-
const defaultOptions = getDefaultOptions(template, projectName);
|
|
323
|
-
// Step 3: Show summary and ask confirm/customize
|
|
324
|
-
p.note(formatConfigSummary(defaultOptions), "Template Configuration");
|
|
325
|
-
const action = await p.select({
|
|
326
|
-
message: "Proceed with these settings?",
|
|
327
|
-
options: [
|
|
328
|
-
{ value: "confirm", label: "Yes, create project" },
|
|
329
|
-
{ value: "customize", label: "No, let me customize" },
|
|
330
|
-
],
|
|
331
|
-
initialValue: "confirm",
|
|
332
|
-
});
|
|
333
|
-
if (p.isCancel(action)) {
|
|
334
|
-
p.cancel("Operation cancelled.");
|
|
335
|
-
process.exit(0);
|
|
336
|
-
}
|
|
337
|
-
if (action === "confirm") {
|
|
338
|
-
return defaultOptions;
|
|
339
|
-
}
|
|
340
|
-
// Step 4: Customize
|
|
341
|
-
return promptForCustomization(template, projectName);
|
|
342
|
-
}
|
|
343
|
-
async function main() {
|
|
344
|
-
const program = new Command()
|
|
345
|
-
.name("create-krispya")
|
|
346
|
-
.description("CLI for creating Vanilla, React, and React Three Fiber projects")
|
|
347
|
-
.argument("[name]", "name for the app")
|
|
348
|
-
.option("--template <type>", "project template: vanilla, vanilla-js, react, react-js, r3f, r3f-js (default: vanilla)")
|
|
349
|
-
.option("--linter <type>", "linter: eslint, oxlint, or biome (default: oxlint)")
|
|
350
|
-
.option("--formatter <type>", "formatter: prettier, oxfmt, or biome (default: oxfmt)")
|
|
351
|
-
.option("--drei", "add @react-three/drei (r3f only)")
|
|
352
|
-
.option("--handle", "add @react-three/handle (r3f only)")
|
|
353
|
-
.option("--leva", "add leva (r3f only)")
|
|
354
|
-
.option("--postprocessing", "add @react-three/postprocessing (r3f only)")
|
|
355
|
-
.option("--rapier", "add @react-three/rapier (r3f only)")
|
|
356
|
-
.option("--xr", "add @react-three/xr (r3f only)")
|
|
357
|
-
.option("--uikit", "add @react-three/uikit (r3f only)")
|
|
358
|
-
.option("--offscreen", "add @react-three/offscreen (r3f only)")
|
|
359
|
-
.option("--zustand", "add zustand (r3f only)")
|
|
360
|
-
.option("--koota", "add koota (r3f only)")
|
|
361
|
-
.option("--triplex", "set up triplex development environment (r3f only)")
|
|
362
|
-
.option("--viverse", "set up viverse deployment (r3f only)")
|
|
363
|
-
.option("--package-manager <manager>", "specify package manager (e.g. npm, yarn, pnpm)")
|
|
364
|
-
.option("--pnpm-manage-versions", "enable manage-package-manager-versions in pnpm-workspace.yaml (default: true)")
|
|
365
|
-
.option("--no-pnpm-manage-versions", "disable manage-package-manager-versions in pnpm-workspace.yaml")
|
|
366
|
-
.option("--node-version <version>", 'set Node.js version for engines.node field (default: "latest")')
|
|
367
|
-
.option("-y, --yes", "Skip prompts and use default values")
|
|
368
|
-
.action(async (name, options) => {
|
|
369
|
-
console.clear();
|
|
370
|
-
p.intro(color.bgCyan(color.black(" create-krispya ")));
|
|
371
|
-
let generateOptions;
|
|
372
|
-
if (Object.keys(options).length > 0) {
|
|
373
|
-
const template = options.template ?? "vanilla";
|
|
374
|
-
const baseTemplate = getBaseTemplate(template);
|
|
375
|
-
const defaultName = getDefaultProjectName(template);
|
|
376
|
-
generateOptions = {
|
|
377
|
-
name: name || defaultName,
|
|
378
|
-
template,
|
|
379
|
-
linter: options.linter ?? "oxlint",
|
|
380
|
-
formatter: options.formatter ?? "oxfmt",
|
|
381
|
-
...(baseTemplate === "r3f" && {
|
|
382
|
-
drei: options.drei ? {} : undefined,
|
|
383
|
-
handle: options.handle ? {} : undefined,
|
|
384
|
-
leva: options.leva ? {} : undefined,
|
|
385
|
-
postprocessing: options.postprocessing ? {} : undefined,
|
|
386
|
-
rapier: options.rapier ? {} : undefined,
|
|
387
|
-
xr: options.xr ? {} : undefined,
|
|
388
|
-
uikit: options.uikit ? {} : undefined,
|
|
389
|
-
offscreen: options.offscreen ? {} : undefined,
|
|
390
|
-
zustand: options.zustand ? {} : undefined,
|
|
391
|
-
koota: options.koota ? {} : undefined,
|
|
392
|
-
viverse: options.viverse ? {} : undefined,
|
|
393
|
-
triplex: options.triplex ? {} : undefined,
|
|
394
|
-
}),
|
|
395
|
-
packageManager: options.packageManager,
|
|
396
|
-
pnpmManageVersions: options.pnpmManageVersions,
|
|
397
|
-
nodeVersion: options.nodeVersion ?? "latest",
|
|
398
|
-
};
|
|
399
|
-
}
|
|
400
|
-
else {
|
|
401
|
-
generateOptions = await promptForOptions(name);
|
|
402
|
-
}
|
|
403
|
-
const base = generateOptions.template
|
|
404
|
-
? getBaseTemplate(generateOptions.template)
|
|
405
|
-
: "vanilla";
|
|
406
|
-
const defaultFallbackName = base === "vanilla"
|
|
407
|
-
? "vanilla-app"
|
|
408
|
-
: base === "react"
|
|
409
|
-
? "react-app"
|
|
410
|
-
: "react-three-app";
|
|
411
|
-
generateOptions.name ??= defaultFallbackName;
|
|
412
|
-
// Fetch latest pnpm version if pnpm is selected
|
|
413
|
-
const packageManager = generateOptions.packageManager || "pnpm";
|
|
414
|
-
if (packageManager === "pnpm") {
|
|
415
|
-
generateOptions.pnpmVersion = await getLatestPnpmVersion();
|
|
416
|
-
}
|
|
417
|
-
// Fetch latest Node version if "latest" is specified or default
|
|
418
|
-
const nodeVersion = generateOptions.nodeVersion ?? "latest";
|
|
419
|
-
if (nodeVersion === "latest") {
|
|
420
|
-
generateOptions.nodeVersion = await getLatestNodeVersion();
|
|
421
|
-
}
|
|
422
|
-
// Fetch latest package versions in parallel
|
|
423
|
-
const versions = {};
|
|
424
|
-
const versionPromises = [
|
|
425
|
-
getLatestNpmVersion("vite", "6.3.4").then((v) => {
|
|
426
|
-
versions.vite = v;
|
|
427
|
-
}),
|
|
428
|
-
getLatestNpmVersion("vitest", "4.0.0").then((v) => {
|
|
429
|
-
versions.vitest = v;
|
|
430
|
-
}),
|
|
431
|
-
];
|
|
432
|
-
// Fetch linter version
|
|
433
|
-
const linter = generateOptions.linter ?? "oxlint";
|
|
434
|
-
if (linter === "eslint") {
|
|
435
|
-
versionPromises.push(getLatestNpmVersion("eslint", "9.17.0").then((v) => {
|
|
436
|
-
versions.eslint = v;
|
|
437
|
-
}));
|
|
438
|
-
}
|
|
439
|
-
else if (linter === "oxlint") {
|
|
440
|
-
versionPromises.push(getLatestNpmVersion("oxlint", "0.16.0").then((v) => {
|
|
441
|
-
versions.oxlint = v;
|
|
442
|
-
}));
|
|
443
|
-
}
|
|
444
|
-
else if (linter === "biome") {
|
|
445
|
-
versionPromises.push(getLatestNpmVersion("@biomejs/biome", "1.9.4").then((v) => {
|
|
446
|
-
versions.biome = v;
|
|
447
|
-
}));
|
|
448
|
-
}
|
|
449
|
-
// Fetch formatter version
|
|
450
|
-
const formatter = generateOptions.formatter ?? "oxfmt";
|
|
451
|
-
if (formatter === "prettier") {
|
|
452
|
-
versionPromises.push(getLatestNpmVersion("prettier", "3.4.2").then((v) => {
|
|
453
|
-
versions.prettier = v;
|
|
454
|
-
}));
|
|
455
|
-
}
|
|
456
|
-
else if (formatter === "oxfmt") {
|
|
457
|
-
versionPromises.push(getLatestNpmVersion("oxfmt", "0.1.0").then((v) => {
|
|
458
|
-
versions.oxfmt = v;
|
|
459
|
-
}));
|
|
460
|
-
}
|
|
461
|
-
else if (formatter === "biome" && linter !== "biome") {
|
|
462
|
-
// Only fetch if not already fetched for linter
|
|
463
|
-
versionPromises.push(getLatestNpmVersion("@biomejs/biome", "1.9.4").then((v) => {
|
|
464
|
-
versions.biome = v;
|
|
465
|
-
}));
|
|
466
|
-
}
|
|
467
|
-
await Promise.all(versionPromises);
|
|
468
|
-
generateOptions.versions = versions;
|
|
469
|
-
const basePath = join(cwd(), generateOptions.name);
|
|
470
|
-
const s = p.spinner();
|
|
471
|
-
s.start("Creating project...");
|
|
472
|
-
try {
|
|
473
|
-
const files = generate(generateOptions);
|
|
474
|
-
const filePaths = Object.keys(files).sort();
|
|
475
|
-
for (const filePath of filePaths) {
|
|
476
|
-
const fullFilePath = join(basePath, filePath);
|
|
477
|
-
await mkdir(dirname(fullFilePath), { recursive: true });
|
|
478
|
-
const file = files[filePath];
|
|
479
|
-
if (file.type === "text") {
|
|
480
|
-
await writeFile(fullFilePath, file.content);
|
|
481
|
-
}
|
|
482
|
-
else {
|
|
483
|
-
const response = await fetch(file.url);
|
|
484
|
-
await writeFile(fullFilePath, response.body);
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
s.stop("Project created!");
|
|
488
|
-
const nextSteps = [
|
|
489
|
-
`cd ${generateOptions.name}`,
|
|
490
|
-
`${packageManager} install`,
|
|
491
|
-
`${packageManager} run dev`,
|
|
492
|
-
].join("\n");
|
|
493
|
-
p.note(nextSteps, "Next steps");
|
|
494
|
-
p.outro(color.green("Happy coding! ✨"));
|
|
495
|
-
}
|
|
496
|
-
catch (error) {
|
|
497
|
-
s.stop("Failed to create project");
|
|
498
|
-
p.log.error(String(error));
|
|
499
|
-
process.exit(1);
|
|
500
|
-
}
|
|
501
|
-
});
|
|
502
|
-
await program.parseAsync();
|
|
503
|
-
}
|
|
504
|
-
main().catch(console.error);
|
package/dist/constants.d.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
export declare const HtmlContent = "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>$title</title>\n</head>\n<body style=\"margin: 0; overscroll-behavior: none; user-select: none; touch-action: none;\">\n <script type=\"module\" src=\"$indexPath\"></script>\n <div style=\"width: 100dvw; height: 100dvh; overflow: hidden;\" id=\"root\"></div>\n</body>\n</html>";
|
|
2
|
-
export declare const ViteHtmlContent = "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>$title</title>\n</head>\n<body>\n <div id=\"app\"></div>\n <script type=\"module\" src=\"$indexPath\"></script>\n</body>\n</html>";
|
|
3
|
-
export declare const IndexContent = "import { StrictMode } from 'react'\nimport { createRoot } from 'react-dom/client'\nimport { App } from './app.js'\n\ncreateRoot(document.getElementById('root')!).render(\n <StrictMode>\n <App />\n </StrictMode>,\n)";
|
|
4
|
-
export declare const ViteIndexContent = "import './style.css'\n\ndocument.querySelector('#app')!.innerHTML = `\n <h1>Hello Vite!</h1>\n <p>Edit src/main.ts and save to see HMR in action.</p>\n`";
|
|
5
|
-
export declare const ViteStyleContent = "body {\n font-family: system-ui, -apple-system, sans-serif;\n margin: 0;\n padding: 2rem;\n min-height: 100vh;\n background: #1a1a1a;\n color: #fff;\n}\n\nh1 {\n color: #646cff;\n}\n\na {\n color: #646cff;\n}";
|
|
6
|
-
export declare const GitAttributes: string;
|
|
7
|
-
export type FormatterConfig = {
|
|
8
|
-
printWidth: number;
|
|
9
|
-
tabWidth: number;
|
|
10
|
-
useTabs: boolean;
|
|
11
|
-
semi: boolean;
|
|
12
|
-
singleQuote: boolean;
|
|
13
|
-
trailingComma: "none" | "es5" | "all";
|
|
14
|
-
bracketSpacing: boolean;
|
|
15
|
-
arrowParens: "always" | "avoid";
|
|
16
|
-
};
|
|
17
|
-
export declare const defaultFormatterConfig: FormatterConfig;
|
|
18
|
-
export type LinterConfig = {
|
|
19
|
-
ignorePatterns: string[];
|
|
20
|
-
rules: {
|
|
21
|
-
noUnusedVars: {
|
|
22
|
-
level: "off" | "warn" | "error";
|
|
23
|
-
argsIgnorePattern: string;
|
|
24
|
-
varsIgnorePattern: string;
|
|
25
|
-
caughtErrorsIgnorePattern: string;
|
|
26
|
-
};
|
|
27
|
-
noUnusedExpressions: {
|
|
28
|
-
level: "off" | "warn" | "error";
|
|
29
|
-
allowShortCircuit: boolean;
|
|
30
|
-
};
|
|
31
|
-
};
|
|
32
|
-
};
|
|
33
|
-
export declare const defaultLinterConfig: LinterConfig;
|
package/dist/constants.js
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
// HTML for React and R3F templates
|
|
2
|
-
export const HtmlContent = `<!DOCTYPE html>
|
|
3
|
-
<html lang="en">
|
|
4
|
-
<head>
|
|
5
|
-
<meta charset="UTF-8">
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
-
<title>$title</title>
|
|
8
|
-
</head>
|
|
9
|
-
<body style="margin: 0; overscroll-behavior: none; user-select: none; touch-action: none;">
|
|
10
|
-
<script type="module" src="$indexPath"></script>
|
|
11
|
-
<div style="width: 100dvw; height: 100dvh; overflow: hidden;" id="root"></div>
|
|
12
|
-
</body>
|
|
13
|
-
</html>`;
|
|
14
|
-
// HTML for vanilla Vite template
|
|
15
|
-
export const ViteHtmlContent = `<!DOCTYPE html>
|
|
16
|
-
<html lang="en">
|
|
17
|
-
<head>
|
|
18
|
-
<meta charset="UTF-8">
|
|
19
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
20
|
-
<title>$title</title>
|
|
21
|
-
</head>
|
|
22
|
-
<body>
|
|
23
|
-
<div id="app"></div>
|
|
24
|
-
<script type="module" src="$indexPath"></script>
|
|
25
|
-
</body>
|
|
26
|
-
</html>`;
|
|
27
|
-
// Entry point for React and R3F templates
|
|
28
|
-
export const IndexContent = `import { StrictMode } from 'react'
|
|
29
|
-
import { createRoot } from 'react-dom/client'
|
|
30
|
-
import { App } from './app.js'
|
|
31
|
-
|
|
32
|
-
createRoot(document.getElementById('root')!).render(
|
|
33
|
-
<StrictMode>
|
|
34
|
-
<App />
|
|
35
|
-
</StrictMode>,
|
|
36
|
-
)`;
|
|
37
|
-
// Entry point for vanilla Vite template
|
|
38
|
-
export const ViteIndexContent = `import './style.css'
|
|
39
|
-
|
|
40
|
-
document.querySelector('#app')!.innerHTML = \`
|
|
41
|
-
<h1>Hello Vite!</h1>
|
|
42
|
-
<p>Edit src/main.ts and save to see HMR in action.</p>
|
|
43
|
-
\``;
|
|
44
|
-
// Default styles for vanilla Vite template
|
|
45
|
-
export const ViteStyleContent = `body {
|
|
46
|
-
font-family: system-ui, -apple-system, sans-serif;
|
|
47
|
-
margin: 0;
|
|
48
|
-
padding: 2rem;
|
|
49
|
-
min-height: 100vh;
|
|
50
|
-
background: #1a1a1a;
|
|
51
|
-
color: #fff;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
h1 {
|
|
55
|
-
color: #646cff;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
a {
|
|
59
|
-
color: #646cff;
|
|
60
|
-
}`;
|
|
61
|
-
export const GitAttributes = [
|
|
62
|
-
"* text eol=lf",
|
|
63
|
-
"*.png binary",
|
|
64
|
-
"*.jpg binary",
|
|
65
|
-
"*.jpeg binary",
|
|
66
|
-
"*.gif binary",
|
|
67
|
-
"*.ico binary",
|
|
68
|
-
"*.mov binary",
|
|
69
|
-
"*.mp4 binary",
|
|
70
|
-
"*.mp3 binary",
|
|
71
|
-
"*.flv binary",
|
|
72
|
-
"*.fla binary",
|
|
73
|
-
"*.wav binary",
|
|
74
|
-
"*.swf binary",
|
|
75
|
-
"*.gz binary",
|
|
76
|
-
"*.zip binary",
|
|
77
|
-
"*.7z binary",
|
|
78
|
-
"*.ttf binary",
|
|
79
|
-
"*.eot binary",
|
|
80
|
-
"*.woff binary",
|
|
81
|
-
"*.pyc binary",
|
|
82
|
-
"*.pdf binary",
|
|
83
|
-
"*.glb binary",
|
|
84
|
-
"*.gltf binary",
|
|
85
|
-
].join("\n");
|
|
86
|
-
export const defaultFormatterConfig = {
|
|
87
|
-
printWidth: 102,
|
|
88
|
-
tabWidth: 4,
|
|
89
|
-
useTabs: false,
|
|
90
|
-
semi: true,
|
|
91
|
-
singleQuote: true,
|
|
92
|
-
trailingComma: "es5",
|
|
93
|
-
bracketSpacing: true,
|
|
94
|
-
arrowParens: "always",
|
|
95
|
-
};
|
|
96
|
-
export const defaultLinterConfig = {
|
|
97
|
-
ignorePatterns: ["dist"],
|
|
98
|
-
rules: {
|
|
99
|
-
noUnusedVars: {
|
|
100
|
-
level: "warn",
|
|
101
|
-
argsIgnorePattern: "^_",
|
|
102
|
-
varsIgnorePattern: "^_",
|
|
103
|
-
caughtErrorsIgnorePattern: "^_",
|
|
104
|
-
},
|
|
105
|
-
noUnusedExpressions: {
|
|
106
|
-
level: "warn",
|
|
107
|
-
allowShortCircuit: true,
|
|
108
|
-
},
|
|
109
|
-
},
|
|
110
|
-
};
|