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/dist/index.js
DELETED
|
@@ -1,397 +0,0 @@
|
|
|
1
|
-
import { GitAttributes, HtmlContent, IndexContent, ViteHtmlContent, ViteIndexContent, ViteStyleContent, } from "./constants.js";
|
|
2
|
-
import { generateBiome } from "./integrations/biome.js";
|
|
3
|
-
import { generateDrei } from "./integrations/drei.js";
|
|
4
|
-
import { generateEslint } from "./integrations/eslint.js";
|
|
5
|
-
import { generateFiber } from "./integrations/fiber.js";
|
|
6
|
-
import { generateGithubPages } from "./integrations/github-pages.js";
|
|
7
|
-
import { generateHandle } from "./integrations/handle.js";
|
|
8
|
-
import { generateKoota } from "./integrations/koota.js";
|
|
9
|
-
import { generateLeva } from "./integrations/leva.js";
|
|
10
|
-
import { generateOffscreen } from "./integrations/offscreen.js";
|
|
11
|
-
import { generateOxfmt } from "./integrations/oxfmt.js";
|
|
12
|
-
import { generateOxlint } from "./integrations/oxlint.js";
|
|
13
|
-
import { generatePostprocessing, } from "./integrations/postprocessing.js";
|
|
14
|
-
import { generatePrettier } from "./integrations/prettier.js";
|
|
15
|
-
import { generateRapier } from "./integrations/rapier.js";
|
|
16
|
-
import { generateUikit } from "./integrations/uikit.js";
|
|
17
|
-
import { generateXr } from "./integrations/xr.js";
|
|
18
|
-
import { generateZustand } from "./integrations/zustand.js";
|
|
19
|
-
import { generateTriplex } from "./integrations/triplex.js";
|
|
20
|
-
import { generateVitest } from "./integrations/vitest.js";
|
|
21
|
-
import { merge } from "./merge.js";
|
|
22
|
-
import { generateViverse } from "./integrations/viverse.js";
|
|
23
|
-
export * from "./utils.js";
|
|
24
|
-
export function getLanguageFromTemplate(template) {
|
|
25
|
-
return template.endsWith("-js") ? "javascript" : "typescript";
|
|
26
|
-
}
|
|
27
|
-
export function getBaseTemplate(template) {
|
|
28
|
-
return template.replace("-js", "");
|
|
29
|
-
}
|
|
30
|
-
export function generate(options) {
|
|
31
|
-
//deep cloning since integrations might decide to modify the options
|
|
32
|
-
const clonedOptions = structuredClone(options);
|
|
33
|
-
const template = clonedOptions.template ?? "vanilla";
|
|
34
|
-
const baseTemplate = getBaseTemplate(template);
|
|
35
|
-
const language = getLanguageFromTemplate(template);
|
|
36
|
-
const isVanilla = baseTemplate === "vanilla";
|
|
37
|
-
const isReact = baseTemplate === "react";
|
|
38
|
-
const isR3f = baseTemplate === "r3f";
|
|
39
|
-
const files = {
|
|
40
|
-
...clonedOptions.files,
|
|
41
|
-
};
|
|
42
|
-
const replacements = clonedOptions.replacements ?? [];
|
|
43
|
-
// Base dependencies - always include vite
|
|
44
|
-
const versions = clonedOptions.versions ?? {};
|
|
45
|
-
const dependencies = {
|
|
46
|
-
vite: versions.vite ? `^${versions.vite}` : "^6.3.4",
|
|
47
|
-
...clonedOptions.dependencies,
|
|
48
|
-
};
|
|
49
|
-
// Add React dependencies for react and r3f templates
|
|
50
|
-
if (isReact || isR3f) {
|
|
51
|
-
dependencies["react"] = "^19.0.0";
|
|
52
|
-
dependencies["react-dom"] = "^19.0.0";
|
|
53
|
-
dependencies["@vitejs/plugin-react"] = "^4.4.1";
|
|
54
|
-
}
|
|
55
|
-
// Add Three.js dependencies for r3f template
|
|
56
|
-
if (isR3f) {
|
|
57
|
-
dependencies["three"] = "~0.175.0";
|
|
58
|
-
dependencies["@react-three/fiber"] = "^9.0.0";
|
|
59
|
-
}
|
|
60
|
-
// TypeScript configuration
|
|
61
|
-
if (language === "typescript") {
|
|
62
|
-
const tsConfig = {
|
|
63
|
-
compilerOptions: {
|
|
64
|
-
target: "ESNext",
|
|
65
|
-
module: "ESNext",
|
|
66
|
-
moduleResolution: "bundler",
|
|
67
|
-
esModuleInterop: true,
|
|
68
|
-
strict: true,
|
|
69
|
-
skipLibCheck: true,
|
|
70
|
-
outDir: "dist",
|
|
71
|
-
},
|
|
72
|
-
include: ["src/**/*"],
|
|
73
|
-
};
|
|
74
|
-
// Add JSX config for React templates
|
|
75
|
-
if (isReact || isR3f) {
|
|
76
|
-
tsConfig.compilerOptions.jsx = "react-jsx";
|
|
77
|
-
dependencies["@types/react"] = "^19.0.0";
|
|
78
|
-
dependencies["@types/react-dom"] = "^19.0.0";
|
|
79
|
-
}
|
|
80
|
-
// Add Three.js types for r3f
|
|
81
|
-
if (isR3f) {
|
|
82
|
-
dependencies["@types/three"] = "~0.175.0";
|
|
83
|
-
}
|
|
84
|
-
files["tsconfig.json"] = {
|
|
85
|
-
type: "text",
|
|
86
|
-
content: JSON.stringify(tsConfig, null, 2),
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
const codeSnippets = {};
|
|
90
|
-
const vscodeSettings = {};
|
|
91
|
-
const scripts = {
|
|
92
|
-
dev: "vite",
|
|
93
|
-
build: "vite build",
|
|
94
|
-
};
|
|
95
|
-
// Setup vite config imports based on template
|
|
96
|
-
if (isReact || isR3f) {
|
|
97
|
-
codeSnippets["vite-config-import"] = ["import react from '@vitejs/plugin-react'"];
|
|
98
|
-
}
|
|
99
|
-
// Setup R3F-specific imports
|
|
100
|
-
if (isR3f) {
|
|
101
|
-
codeSnippets["import"] = [`import { Canvas } from "@react-three/fiber"`];
|
|
102
|
-
}
|
|
103
|
-
const defaultName = isVanilla ? "vanilla-app" : isReact ? "react-app" : "react-three-app";
|
|
104
|
-
const name = clonedOptions.name ?? defaultName;
|
|
105
|
-
// Build vite config based on template
|
|
106
|
-
let viteConfig = {
|
|
107
|
-
base: "./",
|
|
108
|
-
};
|
|
109
|
-
if (isReact || isR3f) {
|
|
110
|
-
viteConfig.plugins = ["$raw:react()"];
|
|
111
|
-
}
|
|
112
|
-
if (isR3f) {
|
|
113
|
-
viteConfig.resolve = { dedupe: ["three"] };
|
|
114
|
-
}
|
|
115
|
-
const generator = {
|
|
116
|
-
options: clonedOptions,
|
|
117
|
-
versions,
|
|
118
|
-
addDependency(name, semver) {
|
|
119
|
-
const existingSemver = dependencies[name];
|
|
120
|
-
if (existingSemver != null) {
|
|
121
|
-
//TODO: intersect existingSemver with semver and write to semver
|
|
122
|
-
//TODO: throw error if no overlap
|
|
123
|
-
}
|
|
124
|
-
dependencies[name] = semver;
|
|
125
|
-
},
|
|
126
|
-
addFile(path, content) {
|
|
127
|
-
files[path] = content;
|
|
128
|
-
},
|
|
129
|
-
addScript(name, command) {
|
|
130
|
-
scripts[name] = command;
|
|
131
|
-
},
|
|
132
|
-
inject(location, code) {
|
|
133
|
-
let entries = codeSnippets[location];
|
|
134
|
-
if (entries == null) {
|
|
135
|
-
codeSnippets[location] = entries = [];
|
|
136
|
-
}
|
|
137
|
-
entries.push(code);
|
|
138
|
-
},
|
|
139
|
-
replace(search, replace) {
|
|
140
|
-
replacements.push({ search, replace });
|
|
141
|
-
},
|
|
142
|
-
configureVite(config) {
|
|
143
|
-
viteConfig = merge(viteConfig, config);
|
|
144
|
-
},
|
|
145
|
-
addVscodeSetting(key, value) {
|
|
146
|
-
vscodeSettings[key] = value;
|
|
147
|
-
},
|
|
148
|
-
};
|
|
149
|
-
// Only run R3F integrations for r3f template
|
|
150
|
-
if (isR3f) {
|
|
151
|
-
generateDrei(generator, clonedOptions.drei);
|
|
152
|
-
generateHandle(generator, clonedOptions.handle);
|
|
153
|
-
generateKoota(generator, clonedOptions.koota);
|
|
154
|
-
generateLeva(generator, clonedOptions.leva);
|
|
155
|
-
generateOffscreen(generator, clonedOptions.offscreen);
|
|
156
|
-
generatePostprocessing(generator, clonedOptions.postprocessing);
|
|
157
|
-
generateRapier(generator, clonedOptions.rapier);
|
|
158
|
-
generateUikit(generator, clonedOptions.uikit);
|
|
159
|
-
generateXr(generator, clonedOptions.xr);
|
|
160
|
-
generateZustand(generator, clonedOptions.zustand);
|
|
161
|
-
generateFiber(generator, clonedOptions.fiber);
|
|
162
|
-
generateTriplex(generator, clonedOptions.triplex);
|
|
163
|
-
generateViverse(generator, clonedOptions.viverse);
|
|
164
|
-
}
|
|
165
|
-
// GitHub Pages works for all templates
|
|
166
|
-
generateGithubPages(generator, clonedOptions.githubPages);
|
|
167
|
-
// Testing - always include vitest
|
|
168
|
-
generateVitest(generator);
|
|
169
|
-
// Linter and formatter integrations
|
|
170
|
-
const linter = clonedOptions.linter;
|
|
171
|
-
const formatter = clonedOptions.formatter;
|
|
172
|
-
// Generate linter integrations
|
|
173
|
-
if (linter === "eslint") {
|
|
174
|
-
generateEslint(generator, true);
|
|
175
|
-
generator.addVscodeSetting("biome.enabled", false);
|
|
176
|
-
generator.addVscodeSetting("oxc.enable", false);
|
|
177
|
-
}
|
|
178
|
-
else if (linter === "oxlint") {
|
|
179
|
-
generateOxlint(generator, true);
|
|
180
|
-
generator.addVscodeSetting("eslint.enable", false);
|
|
181
|
-
generator.addVscodeSetting("biome.enabled", false);
|
|
182
|
-
}
|
|
183
|
-
else if (linter === "biome") {
|
|
184
|
-
generateBiome(generator, { linter: true, formatter: formatter === "biome" });
|
|
185
|
-
generator.addVscodeSetting("eslint.enable", false);
|
|
186
|
-
generator.addVscodeSetting("oxc.enable", false);
|
|
187
|
-
}
|
|
188
|
-
// Generate formatter integrations (skip biome if already handled above)
|
|
189
|
-
if (formatter === "prettier") {
|
|
190
|
-
generatePrettier(generator, true);
|
|
191
|
-
}
|
|
192
|
-
else if (formatter === "oxfmt") {
|
|
193
|
-
generateOxfmt(generator, true);
|
|
194
|
-
}
|
|
195
|
-
else if (formatter === "biome" && linter !== "biome") {
|
|
196
|
-
// Only generate biome for formatting if it wasn't already generated for linting
|
|
197
|
-
generateBiome(generator, { linter: false, formatter: true });
|
|
198
|
-
generator.addVscodeSetting("eslint.enable", false);
|
|
199
|
-
generator.addVscodeSetting("oxc.enable", false);
|
|
200
|
-
}
|
|
201
|
-
for (const { code, location } of clonedOptions.injections ?? []) {
|
|
202
|
-
generator.inject(location, code);
|
|
203
|
-
}
|
|
204
|
-
// Generate vite.config.js
|
|
205
|
-
const viteConfigContent = [
|
|
206
|
-
`import { defineConfig } from 'vite'`,
|
|
207
|
-
...(codeSnippets["vite-config-import"] ?? []),
|
|
208
|
-
`export default defineConfig(${JSON.stringify(viteConfig).replace(/"\$raw:([^"]+)"/g, (_, raw) => raw)})`,
|
|
209
|
-
].join("\n");
|
|
210
|
-
files["vite.config.js"] = { type: "text", content: viteConfigContent };
|
|
211
|
-
const packageManager = options.packageManager ?? "pnpm";
|
|
212
|
-
const isPnpm = packageManager === "pnpm";
|
|
213
|
-
// Build package.json with conditional pnpm-specific fields
|
|
214
|
-
const packageJson = {
|
|
215
|
-
name,
|
|
216
|
-
type: "module",
|
|
217
|
-
dependencies,
|
|
218
|
-
scripts,
|
|
219
|
-
};
|
|
220
|
-
// Add engines field if needed
|
|
221
|
-
const engines = {};
|
|
222
|
-
if (isPnpm) {
|
|
223
|
-
const pnpmVersion = options.pnpmVersion ?? "10.11.0";
|
|
224
|
-
const majorVersion = pnpmVersion.split(".")[0];
|
|
225
|
-
engines.pnpm = `>=${majorVersion}.0.0`;
|
|
226
|
-
packageJson.packageManager = `pnpm@${pnpmVersion}`;
|
|
227
|
-
}
|
|
228
|
-
if (options.nodeVersion) {
|
|
229
|
-
const majorVersion = options.nodeVersion.split(".")[0];
|
|
230
|
-
engines.node = `>=${majorVersion}.0.0`;
|
|
231
|
-
}
|
|
232
|
-
if (Object.keys(engines).length > 0) {
|
|
233
|
-
packageJson.engines = engines;
|
|
234
|
-
}
|
|
235
|
-
files["package.json"] = {
|
|
236
|
-
type: "text",
|
|
237
|
-
content: JSON.stringify(packageJson, null, 2),
|
|
238
|
-
};
|
|
239
|
-
// Add pnpm-workspace.yaml when pnpm is selected
|
|
240
|
-
if (isPnpm) {
|
|
241
|
-
const manageVersions = options.pnpmManageVersions ?? true;
|
|
242
|
-
const workspaceLines = [];
|
|
243
|
-
if (manageVersions) {
|
|
244
|
-
workspaceLines.push("manage-package-manager-versions: true", "");
|
|
245
|
-
}
|
|
246
|
-
workspaceLines.push("onlyBuiltDependencies:", " - esbuild");
|
|
247
|
-
files["pnpm-workspace.yaml"] = {
|
|
248
|
-
type: "text",
|
|
249
|
-
content: workspaceLines.join("\n"),
|
|
250
|
-
};
|
|
251
|
-
}
|
|
252
|
-
files[".gitignore"] = { type: "text", content: ["node_modules", "dist"].join("\n") };
|
|
253
|
-
files[".gitattributes"] = { type: "text", content: GitAttributes };
|
|
254
|
-
codeSnippets["readme-libraries"] ??= [];
|
|
255
|
-
codeSnippets["readme-commands"] ??= [];
|
|
256
|
-
// Add library descriptions based on template
|
|
257
|
-
if (isVanilla) {
|
|
258
|
-
codeSnippets["readme-libraries"].unshift(`[Vite](https://vitejs.dev/) - Next generation frontend tooling`);
|
|
259
|
-
}
|
|
260
|
-
else if (isReact) {
|
|
261
|
-
codeSnippets["readme-libraries"].unshift(`[React](https://react.dev/) - A JavaScript library for building user interfaces`, `[Vite](https://vitejs.dev/) - Next generation frontend tooling`);
|
|
262
|
-
}
|
|
263
|
-
else {
|
|
264
|
-
codeSnippets["readme-libraries"].unshift(`[React](https://react.dev/) - A JavaScript library for building user interfaces`, `[Three.js](https://threejs.org/) - JavaScript 3D library`, `[@react-three/fiber](https://docs.pmnd.rs/react-three-fiber) - lets you create Three.js scenes using React components`);
|
|
265
|
-
}
|
|
266
|
-
codeSnippets["readme-commands"].unshift(`\`${packageManager} install\` to install the dependencies`, `\`${packageManager} run dev\` to run the development server and preview the app with live updates`, `\`${packageManager} run build\` to build the app into the \`dist\` folder`);
|
|
267
|
-
// Generate template-specific architecture description
|
|
268
|
-
const ext = language === "javascript" ? "js" : "ts";
|
|
269
|
-
const jsxExt = language === "javascript" ? "jsx" : "tsx";
|
|
270
|
-
let architectureDesc;
|
|
271
|
-
if (isVanilla) {
|
|
272
|
-
architectureDesc = [
|
|
273
|
-
`- \`src/main.${ext}\` is the entry point for your application`,
|
|
274
|
-
`- Static assets can be placed in the \`public\` folder`,
|
|
275
|
-
];
|
|
276
|
-
}
|
|
277
|
-
else if (isReact) {
|
|
278
|
-
architectureDesc = [
|
|
279
|
-
`- \`src/app.${jsxExt}\` defines the main application component`,
|
|
280
|
-
`- \`src/index.${jsxExt}\` renders the React app into the DOM`,
|
|
281
|
-
`- Static assets can be placed in the \`public\` folder`,
|
|
282
|
-
];
|
|
283
|
-
}
|
|
284
|
-
else {
|
|
285
|
-
architectureDesc = [
|
|
286
|
-
`- \`app.${jsxExt}\` defines the main application component containing your 3D content`,
|
|
287
|
-
`- Modify the content inside the \`<Canvas>\` component to change what is visible on screen`,
|
|
288
|
-
`- Static assets can be placed in the \`public\` folder`,
|
|
289
|
-
];
|
|
290
|
-
}
|
|
291
|
-
files[`README.md`] = {
|
|
292
|
-
type: "text",
|
|
293
|
-
content: [
|
|
294
|
-
`# ${name}`,
|
|
295
|
-
`This project was generated with create-krispya`,
|
|
296
|
-
...(codeSnippets["readme-start"] ?? []),
|
|
297
|
-
"\n",
|
|
298
|
-
`## Project Architecture`,
|
|
299
|
-
`This project uses [Vite](https://vitejs.dev/) as the bundler for fast development and optimized production builds.`,
|
|
300
|
-
...architectureDesc,
|
|
301
|
-
"\n",
|
|
302
|
-
`## Libraries`,
|
|
303
|
-
`The following libraries are used - checkout the linked docs to learn more`,
|
|
304
|
-
...(codeSnippets["readme-libraries"] ?? []).map((library) => `- ${library}`),
|
|
305
|
-
"\n",
|
|
306
|
-
codeSnippets["readme-tools"] && `## Tools`,
|
|
307
|
-
...(codeSnippets["readme-tools"] ?? []).map((tool) => `- ${tool}`),
|
|
308
|
-
codeSnippets["readme-tools"] && `\n`,
|
|
309
|
-
`## Development Commands`,
|
|
310
|
-
...(codeSnippets["readme-commands"] ?? []).map((command) => `- ${command}`),
|
|
311
|
-
...(codeSnippets["readme-end"] ?? []),
|
|
312
|
-
]
|
|
313
|
-
.filter(Boolean)
|
|
314
|
-
.join("\n"),
|
|
315
|
-
};
|
|
316
|
-
// Generate template-specific source files
|
|
317
|
-
if (isVanilla) {
|
|
318
|
-
// Vanilla template
|
|
319
|
-
const ext = language === "javascript" ? "js" : "ts";
|
|
320
|
-
files[`src/main.${ext}`] = { type: "text", content: ViteIndexContent };
|
|
321
|
-
files["src/style.css"] = { type: "text", content: ViteStyleContent };
|
|
322
|
-
const indexHtml = ViteHtmlContent.replace("$indexPath", `./src/main.${ext}`).replace("$title", name);
|
|
323
|
-
files["index.html"] = { type: "text", content: indexHtml };
|
|
324
|
-
}
|
|
325
|
-
else {
|
|
326
|
-
// React and R3F templates
|
|
327
|
-
files[`src/index.tsx`] = { type: "text", content: IndexContent };
|
|
328
|
-
const indexHtml = HtmlContent.replace("$indexPath", language === "javascript" ? "./src/index.jsx" : "./src/index.tsx").replace("$title", name);
|
|
329
|
-
files["index.html"] = { type: "text", content: indexHtml };
|
|
330
|
-
// Generate app.tsx
|
|
331
|
-
codeSnippets["dom-end"]?.reverse();
|
|
332
|
-
codeSnippets["global-end"]?.reverse();
|
|
333
|
-
codeSnippets["scene-end"]?.reverse();
|
|
334
|
-
let appCode;
|
|
335
|
-
if (isReact) {
|
|
336
|
-
// Simple React app without Canvas
|
|
337
|
-
appCode = [
|
|
338
|
-
...(codeSnippets["import"] ?? []),
|
|
339
|
-
...(codeSnippets["global-start"] ?? []),
|
|
340
|
-
`export function App() {`,
|
|
341
|
-
" return (",
|
|
342
|
-
' <div style={{ padding: "2rem" }}>',
|
|
343
|
-
" <h1>Hello React!</h1>",
|
|
344
|
-
" <p>Edit src/app.tsx and save to see changes.</p>",
|
|
345
|
-
" </div>",
|
|
346
|
-
" )",
|
|
347
|
-
"}",
|
|
348
|
-
...(codeSnippets["global-end"] ?? []),
|
|
349
|
-
].join("\n");
|
|
350
|
-
}
|
|
351
|
-
else {
|
|
352
|
-
// R3F app with Canvas
|
|
353
|
-
appCode = [
|
|
354
|
-
...(codeSnippets["import"] ?? []),
|
|
355
|
-
...(codeSnippets["global-start"] ?? []),
|
|
356
|
-
`export function App() {`,
|
|
357
|
-
" return <>",
|
|
358
|
-
...(codeSnippets["dom-start"] ?? []),
|
|
359
|
-
...(codeSnippets["dom"] ?? []),
|
|
360
|
-
" <Canvas>",
|
|
361
|
-
...(codeSnippets["scene-start"] ?? []),
|
|
362
|
-
...(codeSnippets["scene"] ?? []),
|
|
363
|
-
...(codeSnippets["scene-end"] ?? []),
|
|
364
|
-
" </Canvas>",
|
|
365
|
-
...(codeSnippets["dom-end"] ?? []),
|
|
366
|
-
" </>",
|
|
367
|
-
"}",
|
|
368
|
-
...(codeSnippets["global-end"] ?? []),
|
|
369
|
-
].join("\n");
|
|
370
|
-
}
|
|
371
|
-
for (const { search, replace } of replacements) {
|
|
372
|
-
appCode = appCode.replace(search, replace);
|
|
373
|
-
}
|
|
374
|
-
files[`src/app.tsx`] = { type: "text", content: appCode };
|
|
375
|
-
}
|
|
376
|
-
if (codeSnippets["vscode-extension-suggestion"]?.length) {
|
|
377
|
-
// Deduplicate extension recommendations
|
|
378
|
-
const uniqueRecommendations = [...new Set(codeSnippets["vscode-extension-suggestion"])];
|
|
379
|
-
files[".vscode/extensions.json"] = {
|
|
380
|
-
type: "text",
|
|
381
|
-
content: JSON.stringify({
|
|
382
|
-
recommendations: uniqueRecommendations,
|
|
383
|
-
}, null, 2),
|
|
384
|
-
};
|
|
385
|
-
}
|
|
386
|
-
if (Object.keys(vscodeSettings).length > 0) {
|
|
387
|
-
files[".vscode/settings.json"] = {
|
|
388
|
-
type: "text",
|
|
389
|
-
content: JSON.stringify(vscodeSettings, null, "\t"),
|
|
390
|
-
};
|
|
391
|
-
}
|
|
392
|
-
if (language === "javascript") {
|
|
393
|
-
//TODO: transpile tsx? to jsx? files}
|
|
394
|
-
}
|
|
395
|
-
//TODO: execute prettier on ts(x), js(x), and json files``
|
|
396
|
-
return files;
|
|
397
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { Generator } from "../index.js";
|
|
2
|
-
export type GenerateBiomeOptions = {
|
|
3
|
-
/** Whether biome is used as a linter */
|
|
4
|
-
linter?: boolean;
|
|
5
|
-
/** Whether biome is used as a formatter */
|
|
6
|
-
formatter?: boolean;
|
|
7
|
-
};
|
|
8
|
-
export declare function generateBiome(generator: Generator, options: GenerateBiomeOptions | undefined): void;
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import { defaultFormatterConfig, defaultLinterConfig } from "../constants.js";
|
|
2
|
-
// Helper to convert level to Biome format
|
|
3
|
-
function toBiomeLevel(level) {
|
|
4
|
-
return level;
|
|
5
|
-
}
|
|
6
|
-
export function generateBiome(generator, options) {
|
|
7
|
-
if (options == null || (!options.linter && !options.formatter)) {
|
|
8
|
-
return;
|
|
9
|
-
}
|
|
10
|
-
const version = generator.versions.biome ?? "1.9.4";
|
|
11
|
-
generator.addDependency("@biomejs/biome", `^${version}`);
|
|
12
|
-
const { rules } = defaultLinterConfig;
|
|
13
|
-
// Build biome config based on roles
|
|
14
|
-
const biomeConfig = {
|
|
15
|
-
$schema: "https://biomejs.dev/schemas/1.9.4/schema.json",
|
|
16
|
-
files: {
|
|
17
|
-
ignore: defaultLinterConfig.ignorePatterns,
|
|
18
|
-
},
|
|
19
|
-
};
|
|
20
|
-
if (options.linter) {
|
|
21
|
-
biomeConfig.linter = {
|
|
22
|
-
enabled: true,
|
|
23
|
-
rules: {
|
|
24
|
-
recommended: true,
|
|
25
|
-
correctness: {
|
|
26
|
-
noUnusedVariables: toBiomeLevel(rules.noUnusedVars.level),
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
else {
|
|
32
|
-
biomeConfig.linter = {
|
|
33
|
-
enabled: false,
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
if (options.formatter) {
|
|
37
|
-
// Translate common formatter settings to Biome format
|
|
38
|
-
biomeConfig.formatter = {
|
|
39
|
-
enabled: true,
|
|
40
|
-
lineWidth: defaultFormatterConfig.printWidth,
|
|
41
|
-
indentWidth: defaultFormatterConfig.tabWidth,
|
|
42
|
-
indentStyle: defaultFormatterConfig.useTabs ? "tab" : "space",
|
|
43
|
-
};
|
|
44
|
-
biomeConfig.javascript = {
|
|
45
|
-
formatter: {
|
|
46
|
-
semicolons: defaultFormatterConfig.semi ? "always" : "asNeeded",
|
|
47
|
-
quoteStyle: defaultFormatterConfig.singleQuote ? "single" : "double",
|
|
48
|
-
trailingCommas: defaultFormatterConfig.trailingComma,
|
|
49
|
-
bracketSpacing: defaultFormatterConfig.bracketSpacing,
|
|
50
|
-
arrowParentheses: defaultFormatterConfig.arrowParens === "always" ? "always" : "asNeeded",
|
|
51
|
-
},
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
biomeConfig.formatter = {
|
|
56
|
-
enabled: false,
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
generator.addFile("biome.json", {
|
|
60
|
-
type: "text",
|
|
61
|
-
content: JSON.stringify(biomeConfig, null, 2),
|
|
62
|
-
});
|
|
63
|
-
if (options.linter) {
|
|
64
|
-
generator.addScript("lint", "biome lint .");
|
|
65
|
-
}
|
|
66
|
-
if (options.formatter) {
|
|
67
|
-
generator.addScript("format", "biome format --write .");
|
|
68
|
-
}
|
|
69
|
-
const roles = [];
|
|
70
|
-
if (options.linter)
|
|
71
|
-
roles.push("linter");
|
|
72
|
-
if (options.formatter)
|
|
73
|
-
roles.push("formatter");
|
|
74
|
-
generator.inject("readme-tools", `[Biome](https://biomejs.dev/) - Fast ${roles.join(" and ")} for JavaScript and TypeScript`);
|
|
75
|
-
generator.inject("vscode-extension-suggestion", "biomejs.biome");
|
|
76
|
-
generator.addVscodeSetting("biome.enabled", true);
|
|
77
|
-
if (options.formatter) {
|
|
78
|
-
generator.addVscodeSetting("editor.defaultFormatter", "biomejs.biome");
|
|
79
|
-
}
|
|
80
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export function generateDrei(generator, options) {
|
|
2
|
-
if (options == null) {
|
|
3
|
-
return;
|
|
4
|
-
}
|
|
5
|
-
generator.addDependency("@react-three/drei", "^10.0.0");
|
|
6
|
-
generator.inject("import", `import { Environment } from "@react-three/drei"`);
|
|
7
|
-
generator.inject("scene", '<Environment background preset="city" />');
|
|
8
|
-
generator.inject("readme-libraries", `[@react-three/drei](https://drei.docs.pmnd.rs/) - Useful helpers for @react-three/fiber`);
|
|
9
|
-
}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { defaultLinterConfig } from "../constants.js";
|
|
2
|
-
import { getBaseTemplate, getLanguageFromTemplate } from "../index.js";
|
|
3
|
-
// Helper to convert level to eslint format
|
|
4
|
-
function toEslintLevel(level) {
|
|
5
|
-
return level;
|
|
6
|
-
}
|
|
7
|
-
export function generateEslint(generator, options) {
|
|
8
|
-
if (options == null) {
|
|
9
|
-
return;
|
|
10
|
-
}
|
|
11
|
-
const version = generator.versions.eslint ?? "9.17.0";
|
|
12
|
-
generator.addDependency("eslint", `^${version}`);
|
|
13
|
-
// Add eslint flat config
|
|
14
|
-
const template = generator.options.template ?? "vanilla";
|
|
15
|
-
const baseTemplate = getBaseTemplate(template);
|
|
16
|
-
const isTypescript = getLanguageFromTemplate(template) === "typescript";
|
|
17
|
-
const isReact = baseTemplate === "react" || baseTemplate === "r3f";
|
|
18
|
-
const { rules } = defaultLinterConfig;
|
|
19
|
-
const imports = ['import js from "@eslint/js"'];
|
|
20
|
-
const configs = ["js.configs.recommended"];
|
|
21
|
-
if (isTypescript) {
|
|
22
|
-
generator.addDependency("typescript-eslint", "^8.18.0");
|
|
23
|
-
imports.push('import tseslint from "typescript-eslint"');
|
|
24
|
-
configs.push("...tseslint.configs.recommended");
|
|
25
|
-
}
|
|
26
|
-
if (isReact) {
|
|
27
|
-
generator.addDependency("eslint-plugin-react-hooks", "^5.1.0");
|
|
28
|
-
imports.push('import reactHooks from "eslint-plugin-react-hooks"');
|
|
29
|
-
}
|
|
30
|
-
// Build ignore patterns string
|
|
31
|
-
const ignoresArray = JSON.stringify(defaultLinterConfig.ignorePatterns);
|
|
32
|
-
// Build rules object - use @typescript-eslint/no-unused-vars for TS projects
|
|
33
|
-
const unusedVarsRule = isTypescript ? "@typescript-eslint/no-unused-vars" : "no-unused-vars";
|
|
34
|
-
const rulesConfig = {
|
|
35
|
-
[unusedVarsRule]: [
|
|
36
|
-
toEslintLevel(rules.noUnusedVars.level),
|
|
37
|
-
{
|
|
38
|
-
argsIgnorePattern: rules.noUnusedVars.argsIgnorePattern,
|
|
39
|
-
varsIgnorePattern: rules.noUnusedVars.varsIgnorePattern,
|
|
40
|
-
caughtErrorsIgnorePattern: rules.noUnusedVars.caughtErrorsIgnorePattern,
|
|
41
|
-
},
|
|
42
|
-
],
|
|
43
|
-
"no-unused-expressions": [
|
|
44
|
-
toEslintLevel(rules.noUnusedExpressions.level),
|
|
45
|
-
{ allowShortCircuit: rules.noUnusedExpressions.allowShortCircuit },
|
|
46
|
-
],
|
|
47
|
-
};
|
|
48
|
-
const rulesString = JSON.stringify(rulesConfig, null, 4).replace(/\n/g, "\n ");
|
|
49
|
-
const configContent = [
|
|
50
|
-
...imports,
|
|
51
|
-
"",
|
|
52
|
-
"export default [",
|
|
53
|
-
` { ignores: ${ignoresArray} },`,
|
|
54
|
-
` ${configs.join(",\n ")},`,
|
|
55
|
-
isReact
|
|
56
|
-
? ` {
|
|
57
|
-
plugins: {
|
|
58
|
-
"react-hooks": reactHooks,
|
|
59
|
-
},
|
|
60
|
-
rules: reactHooks.configs.recommended.rules,
|
|
61
|
-
},`
|
|
62
|
-
: "",
|
|
63
|
-
` {
|
|
64
|
-
rules: ${rulesString},
|
|
65
|
-
},`,
|
|
66
|
-
"]",
|
|
67
|
-
]
|
|
68
|
-
.filter(Boolean)
|
|
69
|
-
.join("\n");
|
|
70
|
-
generator.addFile("eslint.config.js", {
|
|
71
|
-
type: "text",
|
|
72
|
-
content: configContent,
|
|
73
|
-
});
|
|
74
|
-
generator.addScript("lint", "eslint .");
|
|
75
|
-
generator.inject("readme-tools", "[ESLint](https://eslint.org/) - Linter for JavaScript and TypeScript");
|
|
76
|
-
generator.inject("vscode-extension-suggestion", "dbaeumer.vscode-eslint");
|
|
77
|
-
generator.addVscodeSetting("eslint.enable", true);
|
|
78
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
export function generateFiber(generator, _options) {
|
|
2
|
-
generator.inject("import", `import { Box } from "./box.js"`);
|
|
3
|
-
generator.inject("scene", [
|
|
4
|
-
`<ambientLight intensity={Math.PI / 2} />`,
|
|
5
|
-
`<spotLight position={[10, 10, 10]} angle={0.15} penumbra={1} decay={0} intensity={Math.PI} />`,
|
|
6
|
-
`<pointLight position={[-10, -10, -10]} decay={0} intensity={Math.PI} />`,
|
|
7
|
-
`<Box position={[-1.2, 0, 0]} />`,
|
|
8
|
-
`<Box position={[1.2, 0, 0]} />`,
|
|
9
|
-
].join("\n"));
|
|
10
|
-
generator.addFile("src/box.tsx", {
|
|
11
|
-
type: "text",
|
|
12
|
-
content: `import type { Mesh } from 'three'
|
|
13
|
-
import { useRef, useState } from 'react'
|
|
14
|
-
import { useFrame, ThreeElements } from '@react-three/fiber'
|
|
15
|
-
|
|
16
|
-
export function Box(props: ThreeElements['mesh']) {
|
|
17
|
-
const meshRef = useRef<Mesh>(null!)
|
|
18
|
-
const [hovered, setHover] = useState(false)
|
|
19
|
-
const [active, setActive] = useState(false)
|
|
20
|
-
useFrame((state, delta) => (meshRef.current.rotation.x += delta))
|
|
21
|
-
return (
|
|
22
|
-
<mesh
|
|
23
|
-
{...props}
|
|
24
|
-
ref={meshRef}
|
|
25
|
-
scale={active ? 1.5 : 1}
|
|
26
|
-
onClick={(event) => setActive(!active)}
|
|
27
|
-
onPointerOver={(event) => setHover(true)}
|
|
28
|
-
onPointerOut={(event) => setHover(false)}>
|
|
29
|
-
<boxGeometry args={[1, 1, 1]} />
|
|
30
|
-
<meshStandardMaterial color={hovered ? 'hotpink' : '#2f74c0'} />
|
|
31
|
-
</mesh>
|
|
32
|
-
)
|
|
33
|
-
}`,
|
|
34
|
-
});
|
|
35
|
-
}
|