@puzzle-ui/create 0.0.0-stage → 0.2.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 +40 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +596 -0
- package/dist/index.js.map +1 -0
- package/package.json +34 -4
package/README.md
CHANGED
|
@@ -1,3 +1,41 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @puzzle-ui/create
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Create React applications with Puzzle UI.
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
- Node.js >= 20.19
|
|
8
|
+
- npm or Bun
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
|
|
12
|
+
With npm:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npx @puzzle-ui/create
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
With Bun:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
bunx @puzzle-ui/create
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Supported frameworks
|
|
25
|
+
|
|
26
|
+
- Next.js
|
|
27
|
+
- TanStack Start
|
|
28
|
+
- Basic React (Vite + TypeScript)
|
|
29
|
+
|
|
30
|
+
## Features
|
|
31
|
+
|
|
32
|
+
- Interactive project setup
|
|
33
|
+
- Automatic kebab-case project names
|
|
34
|
+
- Framework scaffolding using official CLI tools
|
|
35
|
+
- Automatic Puzzle UI installation
|
|
36
|
+
- Automatic Puzzle Theme configuration
|
|
37
|
+
- React 19 compatibility
|
|
38
|
+
|
|
39
|
+
## License
|
|
40
|
+
|
|
41
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,596 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import * as p from "@clack/prompts";
|
|
3
|
+
import { access, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { spawn } from "node:child_process";
|
|
6
|
+
// src/constants.ts
|
|
7
|
+
const PUZZLE_PACKAGES = ["@puzzle-ui/ui@latest", "@puzzle-ui/theme@latest"];
|
|
8
|
+
const FRAMEWORKS = [
|
|
9
|
+
{
|
|
10
|
+
value: "react",
|
|
11
|
+
label: "Basic React Project",
|
|
12
|
+
hint: "React + Vite + TypeScript"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
value: "tanstack",
|
|
16
|
+
label: "TanStack Start",
|
|
17
|
+
hint: "Full-stack React framework"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
value: "next",
|
|
21
|
+
label: "Next.js",
|
|
22
|
+
hint: "React framework with App Router"
|
|
23
|
+
}
|
|
24
|
+
];
|
|
25
|
+
// src/utils/kebab-case.ts
|
|
26
|
+
const toKebabCase = (value) => value.normalize("NFKD").replace(/[\u0300-\u036f]/g, "").replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/([A-Z])([A-Z][a-z])/g, "$1-$2").replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase();
|
|
27
|
+
// src/utils/detect-package-manager.ts
|
|
28
|
+
const detectPackageManager = (userAgent = process.env.npm_config_user_agent ?? "") => {
|
|
29
|
+
if (userAgent.startsWith("bun/")) return "bun";
|
|
30
|
+
return "npm";
|
|
31
|
+
};
|
|
32
|
+
// src/prompts.ts
|
|
33
|
+
const getProjectOptions = async () => {
|
|
34
|
+
p.intro("Create a Puzzle application");
|
|
35
|
+
const name = await p.text({
|
|
36
|
+
message: "What is the name of your project?",
|
|
37
|
+
placeholder: "my-awesome-app",
|
|
38
|
+
validate: (value) => {
|
|
39
|
+
if (!value?.trim()) return "Project name is required.";
|
|
40
|
+
if (!toKebabCase(value)) return "Please enter a valid project name.";
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
if (p.isCancel(name)) return null;
|
|
44
|
+
const directory = toKebabCase(name);
|
|
45
|
+
const framework = await p.select({
|
|
46
|
+
message: "Which framework would you like to use?",
|
|
47
|
+
options: FRAMEWORKS.map((item) => ({
|
|
48
|
+
value: item.value,
|
|
49
|
+
label: item.label,
|
|
50
|
+
hint: item.hint
|
|
51
|
+
}))
|
|
52
|
+
});
|
|
53
|
+
if (p.isCancel(framework)) return null;
|
|
54
|
+
const tailwind = await p.confirm({
|
|
55
|
+
message: "Would you like to install Tailwind CSS?",
|
|
56
|
+
initialValue: true
|
|
57
|
+
});
|
|
58
|
+
if (p.isCancel(tailwind)) {
|
|
59
|
+
p.cancel("Project creation cancelled.");
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
name: directory,
|
|
64
|
+
directory,
|
|
65
|
+
framework,
|
|
66
|
+
packageManager: detectPackageManager(),
|
|
67
|
+
tailwind
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
// src/utils/execute.ts
|
|
71
|
+
const runCommand = (command, args, options = {}) => new Promise((resolve, reject) => {
|
|
72
|
+
const child = spawn(command, args, {
|
|
73
|
+
cwd: options.cwd ?? process.cwd(),
|
|
74
|
+
stdio: options.stdio ?? "inherit",
|
|
75
|
+
shell: false,
|
|
76
|
+
env: process.env
|
|
77
|
+
});
|
|
78
|
+
child.once("error", reject);
|
|
79
|
+
child.once("close", (code, signal) => {
|
|
80
|
+
if (code === 0) {
|
|
81
|
+
resolve();
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
reject(/* @__PURE__ */ new Error(signal ? `${command} terminated with signal ${signal}` : `${command} exited with code ${code ?? "unknown"}`));
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
// src/frameworks/next.ts
|
|
88
|
+
const createNextProject = async (directory, packageManager, runner = runCommand, cwd) => {
|
|
89
|
+
const args = [
|
|
90
|
+
"create-next-app@latest",
|
|
91
|
+
directory,
|
|
92
|
+
"--ts",
|
|
93
|
+
"--app",
|
|
94
|
+
"--src-dir",
|
|
95
|
+
"--skip-install",
|
|
96
|
+
"--disable-git",
|
|
97
|
+
"--no-tailwind",
|
|
98
|
+
"--yes",
|
|
99
|
+
packageManager === "bun" ? "--use-bun" : "--use-npm"
|
|
100
|
+
];
|
|
101
|
+
const command = packageManager === "bun" ? "bunx" : "npx";
|
|
102
|
+
const commandArgs = packageManager === "bun" ? args : ["--yes", ...args];
|
|
103
|
+
if (cwd) {
|
|
104
|
+
await runner(command, commandArgs, { cwd });
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
await runner(command, commandArgs);
|
|
108
|
+
};
|
|
109
|
+
// src/frameworks/tanstack.ts
|
|
110
|
+
const createTanStackProject = async (directory, packageManager, runner = runCommand, cwd) => {
|
|
111
|
+
const args = [
|
|
112
|
+
"@tanstack/cli@latest",
|
|
113
|
+
"create",
|
|
114
|
+
directory,
|
|
115
|
+
"--framework",
|
|
116
|
+
"React",
|
|
117
|
+
"--package-manager",
|
|
118
|
+
packageManager,
|
|
119
|
+
"--blank",
|
|
120
|
+
"--no-install",
|
|
121
|
+
"--no-git",
|
|
122
|
+
"--yes"
|
|
123
|
+
];
|
|
124
|
+
const command = packageManager === "bun" ? "bunx" : "npx";
|
|
125
|
+
const commandArgs = packageManager === "bun" ? args : ["--yes", ...args];
|
|
126
|
+
if (cwd) {
|
|
127
|
+
await runner(command, commandArgs, { cwd });
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
await runner(command, commandArgs);
|
|
131
|
+
};
|
|
132
|
+
// src/frameworks/react.ts
|
|
133
|
+
const createReactProject = async (directory, _packageManager, _runner) => {
|
|
134
|
+
await mkdir(path.join(directory, "src"), { recursive: true });
|
|
135
|
+
const packageJson = {
|
|
136
|
+
name: path.basename(directory),
|
|
137
|
+
private: true,
|
|
138
|
+
version: "0.0.0",
|
|
139
|
+
type: "module",
|
|
140
|
+
scripts: {
|
|
141
|
+
dev: "vite",
|
|
142
|
+
build: "tsc --noEmit -p tsconfig.app.json && vite build",
|
|
143
|
+
preview: "vite preview"
|
|
144
|
+
},
|
|
145
|
+
dependencies: {
|
|
146
|
+
react: "^19.0.0",
|
|
147
|
+
"react-dom": "^19.0.0"
|
|
148
|
+
},
|
|
149
|
+
devDependencies: {
|
|
150
|
+
"@types/node": "latest",
|
|
151
|
+
"@types/react": "^19.0.0",
|
|
152
|
+
"@types/react-dom": "^19.0.0",
|
|
153
|
+
"@vitejs/plugin-react": "latest",
|
|
154
|
+
typescript: "latest",
|
|
155
|
+
vite: "latest"
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
const files = {
|
|
159
|
+
"package.json": JSON.stringify(packageJson, null, 2),
|
|
160
|
+
"index.html": `<!doctype html>
|
|
161
|
+
<html lang="en">
|
|
162
|
+
<head>
|
|
163
|
+
<meta charset="UTF-8" />
|
|
164
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
165
|
+
<title>Puzzle App</title>
|
|
166
|
+
</head>
|
|
167
|
+
<body>
|
|
168
|
+
<div id="root"></div>
|
|
169
|
+
<script type="module" src="/src/main.tsx"><\/script>
|
|
170
|
+
</body>
|
|
171
|
+
</html>`,
|
|
172
|
+
"tsconfig.json": JSON.stringify({
|
|
173
|
+
files: [],
|
|
174
|
+
references: [{ path: "./tsconfig.app.json" }, { path: "./tsconfig.node.json" }]
|
|
175
|
+
}, null, 2),
|
|
176
|
+
"tsconfig.app.json": JSON.stringify({
|
|
177
|
+
compilerOptions: {
|
|
178
|
+
tsBuildInfoFile: "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
|
179
|
+
target: "ES2022",
|
|
180
|
+
useDefineForClassFields: true,
|
|
181
|
+
lib: [
|
|
182
|
+
"ES2022",
|
|
183
|
+
"DOM",
|
|
184
|
+
"DOM.Iterable"
|
|
185
|
+
],
|
|
186
|
+
module: "ESNext",
|
|
187
|
+
skipLibCheck: true,
|
|
188
|
+
moduleResolution: "bundler",
|
|
189
|
+
allowImportingTsExtensions: true,
|
|
190
|
+
verbatimModuleSyntax: true,
|
|
191
|
+
moduleDetection: "force",
|
|
192
|
+
noEmit: true,
|
|
193
|
+
jsx: "react-jsx",
|
|
194
|
+
strict: true,
|
|
195
|
+
noUnusedLocals: true,
|
|
196
|
+
noUnusedParameters: true,
|
|
197
|
+
noFallthroughCasesInSwitch: true,
|
|
198
|
+
types: ["vite/client"]
|
|
199
|
+
},
|
|
200
|
+
include: ["src"]
|
|
201
|
+
}, null, 2),
|
|
202
|
+
"tsconfig.node.json": JSON.stringify({
|
|
203
|
+
compilerOptions: {
|
|
204
|
+
tsBuildInfoFile: "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
|
205
|
+
target: "ES2023",
|
|
206
|
+
lib: ["ES2023"],
|
|
207
|
+
module: "ESNext",
|
|
208
|
+
skipLibCheck: true,
|
|
209
|
+
moduleResolution: "bundler",
|
|
210
|
+
allowImportingTsExtensions: true,
|
|
211
|
+
verbatimModuleSyntax: true,
|
|
212
|
+
moduleDetection: "force",
|
|
213
|
+
noEmit: true,
|
|
214
|
+
strict: true
|
|
215
|
+
},
|
|
216
|
+
include: ["vite.config.ts"]
|
|
217
|
+
}, null, 2),
|
|
218
|
+
"vite.config.ts": `import { defineConfig } from "vite";
|
|
219
|
+
import react from "@vitejs/plugin-react";
|
|
220
|
+
|
|
221
|
+
export default defineConfig({
|
|
222
|
+
plugins: [react()],
|
|
223
|
+
});`,
|
|
224
|
+
"src/main.tsx": "",
|
|
225
|
+
"src/App.tsx": "",
|
|
226
|
+
"src/index.css": `* {
|
|
227
|
+
box-sizing: border-box;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
html,
|
|
231
|
+
body,
|
|
232
|
+
#root {
|
|
233
|
+
min-height: 100%;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
body {
|
|
237
|
+
margin: 0;
|
|
238
|
+
font-family: var(--puzzle-font-family-body, sans-serif);
|
|
239
|
+
}`
|
|
240
|
+
};
|
|
241
|
+
await Promise.all(Object.entries(files).map(([file, content]) => writeFile(path.join(directory, file), content, "utf8")));
|
|
242
|
+
};
|
|
243
|
+
// src/frameworks/index.ts
|
|
244
|
+
const frameworkGenerators = {
|
|
245
|
+
next: createNextProject,
|
|
246
|
+
tanstack: createTanStackProject,
|
|
247
|
+
react: createReactProject
|
|
248
|
+
};
|
|
249
|
+
const themeTemplates = {
|
|
250
|
+
next: {
|
|
251
|
+
"src/app/providers.tsx": `"use client";
|
|
252
|
+
|
|
253
|
+
import type { ReactNode } from "react";
|
|
254
|
+
|
|
255
|
+
import { Theme } from "@puzzle-ui/theme";
|
|
256
|
+
|
|
257
|
+
type ProvidersProps = {
|
|
258
|
+
children: ReactNode;
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
const Providers = ({ children }: ProvidersProps) => (
|
|
262
|
+
<Theme theme="system">
|
|
263
|
+
{children}
|
|
264
|
+
</Theme>
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
export { Providers };
|
|
268
|
+
`,
|
|
269
|
+
"src/app/layout.tsx": `import "./globals.css";
|
|
270
|
+
|
|
271
|
+
import type { ReactNode } from "react";
|
|
272
|
+
|
|
273
|
+
import { Providers } from "./providers";
|
|
274
|
+
|
|
275
|
+
type RootLayoutProps = {
|
|
276
|
+
children: ReactNode;
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
const RootLayout = ({ children }: RootLayoutProps) => (
|
|
280
|
+
<html lang="en">
|
|
281
|
+
<body>
|
|
282
|
+
<Providers>
|
|
283
|
+
{children}
|
|
284
|
+
</Providers>
|
|
285
|
+
</body>
|
|
286
|
+
</html>
|
|
287
|
+
);
|
|
288
|
+
|
|
289
|
+
export default RootLayout;
|
|
290
|
+
`,
|
|
291
|
+
"src/app/page.tsx": `"use client";
|
|
292
|
+
import { Button } from "@puzzle-ui/ui";
|
|
293
|
+
|
|
294
|
+
const HomePage = () => (
|
|
295
|
+
<main style={{ padding: "2rem" }}>
|
|
296
|
+
<h1>Welcome to Puzzle</h1>
|
|
297
|
+
<p>Your new Puzzle application is ready.</p>
|
|
298
|
+
|
|
299
|
+
<Button onClick={() => console.log("Hello, Puzzle!")}>
|
|
300
|
+
Get started
|
|
301
|
+
</Button>
|
|
302
|
+
</main>
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
export default HomePage;
|
|
306
|
+
`
|
|
307
|
+
},
|
|
308
|
+
tanstack: {
|
|
309
|
+
"src/routes/__root.tsx": `import {
|
|
310
|
+
createRootRoute,
|
|
311
|
+
HeadContent,
|
|
312
|
+
Outlet,
|
|
313
|
+
Scripts,
|
|
314
|
+
} from "@tanstack/react-router";
|
|
315
|
+
|
|
316
|
+
import { Theme } from "@puzzle-ui/theme";
|
|
317
|
+
|
|
318
|
+
const RootComponent = () => (
|
|
319
|
+
<html lang="en">
|
|
320
|
+
<head>
|
|
321
|
+
<HeadContent />
|
|
322
|
+
</head>
|
|
323
|
+
<body>
|
|
324
|
+
<Theme theme="system">
|
|
325
|
+
<Outlet />
|
|
326
|
+
</Theme>
|
|
327
|
+
<Scripts />
|
|
328
|
+
</body>
|
|
329
|
+
</html>
|
|
330
|
+
);
|
|
331
|
+
|
|
332
|
+
export const Route = createRootRoute({
|
|
333
|
+
component: RootComponent,
|
|
334
|
+
});
|
|
335
|
+
`,
|
|
336
|
+
"src/routes/index.tsx": `import { createFileRoute } from "@tanstack/react-router";
|
|
337
|
+
|
|
338
|
+
import { Button } from "@puzzle-ui/ui";
|
|
339
|
+
|
|
340
|
+
const HomePage = () => (
|
|
341
|
+
<main style={{ padding: "2rem" }}>
|
|
342
|
+
<h1>Welcome to Puzzle</h1>
|
|
343
|
+
<p>Your new Puzzle application is ready.</p>
|
|
344
|
+
|
|
345
|
+
<Button onClick={() => console.log("Hello, Puzzle!")}>
|
|
346
|
+
Get started
|
|
347
|
+
</Button>
|
|
348
|
+
</main>
|
|
349
|
+
);
|
|
350
|
+
|
|
351
|
+
export const Route = createFileRoute("/")({
|
|
352
|
+
component: HomePage,
|
|
353
|
+
});
|
|
354
|
+
`
|
|
355
|
+
},
|
|
356
|
+
react: {
|
|
357
|
+
"src/main.tsx": `import React from "react";
|
|
358
|
+
import ReactDOM from "react-dom/client";
|
|
359
|
+
|
|
360
|
+
import { Theme } from "@puzzle-ui/theme";
|
|
361
|
+
|
|
362
|
+
import App from "./App";
|
|
363
|
+
|
|
364
|
+
import "./index.css";
|
|
365
|
+
|
|
366
|
+
ReactDOM.createRoot(
|
|
367
|
+
document.getElementById("root")!,
|
|
368
|
+
).render(
|
|
369
|
+
<React.StrictMode>
|
|
370
|
+
<Theme theme="system">
|
|
371
|
+
<App />
|
|
372
|
+
</Theme>
|
|
373
|
+
</React.StrictMode>,
|
|
374
|
+
);
|
|
375
|
+
`,
|
|
376
|
+
"src/App.tsx": `import { Button } from "@puzzle-ui/ui";
|
|
377
|
+
|
|
378
|
+
const App = () => (
|
|
379
|
+
<main style={{ padding: "2rem" }}>
|
|
380
|
+
<h1>Welcome to Puzzle</h1>
|
|
381
|
+
<p>Your new Puzzle application is ready.</p>
|
|
382
|
+
|
|
383
|
+
<Button onClick={() => console.log("Hello, Puzzle!")}>
|
|
384
|
+
Get started
|
|
385
|
+
</Button>
|
|
386
|
+
</main>
|
|
387
|
+
);
|
|
388
|
+
|
|
389
|
+
export default App;
|
|
390
|
+
`
|
|
391
|
+
}
|
|
392
|
+
};
|
|
393
|
+
// src/theme/configure-theme.ts
|
|
394
|
+
const configureTheme = async (directory, framework) => {
|
|
395
|
+
const templates = themeTemplates[framework];
|
|
396
|
+
await Promise.all(Object.entries(templates).map(async ([relativePath, content]) => {
|
|
397
|
+
const filePath = path.join(directory, relativePath);
|
|
398
|
+
await mkdir(path.dirname(filePath), { recursive: true });
|
|
399
|
+
await writeFile(filePath, content, "utf8");
|
|
400
|
+
}));
|
|
401
|
+
};
|
|
402
|
+
// src/utils/validate-project.ts
|
|
403
|
+
const validateProjectDirectory = async (directory, cwd = process.cwd()) => {
|
|
404
|
+
const root = path.resolve(cwd);
|
|
405
|
+
const target = path.resolve(root, directory);
|
|
406
|
+
if (target === root || !target.startsWith(`${root}${path.sep}`)) throw new Error("Invalid project directory.");
|
|
407
|
+
try {
|
|
408
|
+
await access(target);
|
|
409
|
+
throw new Error(`The directory "${directory}" already exists. Choose another name.`);
|
|
410
|
+
} catch (error) {
|
|
411
|
+
if (error instanceof Error && error.message.includes("already exists")) throw error;
|
|
412
|
+
if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") return target;
|
|
413
|
+
throw error;
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
// src/tailwind/configure-tailwind.ts
|
|
417
|
+
const readIfExists = async (filePath) => {
|
|
418
|
+
try {
|
|
419
|
+
return await readFile(filePath, "utf8");
|
|
420
|
+
} catch {
|
|
421
|
+
return null;
|
|
422
|
+
}
|
|
423
|
+
};
|
|
424
|
+
const prependCssImport = async (filePath) => {
|
|
425
|
+
const importStatement = "@import \"tailwindcss\";";
|
|
426
|
+
const current = await readIfExists(filePath);
|
|
427
|
+
if (current === null) {
|
|
428
|
+
await mkdir(path.dirname(filePath), { recursive: true });
|
|
429
|
+
await writeFile(filePath, `${importStatement}\n`, "utf8");
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
if (current.includes(importStatement)) return;
|
|
433
|
+
await writeFile(filePath, `${importStatement}\n\n${current}`, "utf8");
|
|
434
|
+
};
|
|
435
|
+
const configureNextTailwind = async (directory) => {
|
|
436
|
+
const cssPath = path.join(directory, "src", "app", "globals.css");
|
|
437
|
+
await prependCssImport(cssPath);
|
|
438
|
+
const postcssConfigPath = path.join(directory, "postcss.config.mjs");
|
|
439
|
+
await writeFile(postcssConfigPath, `const config = {
|
|
440
|
+
plugins: {
|
|
441
|
+
"@tailwindcss/postcss": {},
|
|
442
|
+
},
|
|
443
|
+
};
|
|
444
|
+
|
|
445
|
+
export default config;
|
|
446
|
+
`, "utf8");
|
|
447
|
+
};
|
|
448
|
+
const findTanStackCssPath = async (directory) => {
|
|
449
|
+
const rootRoutePath = path.join(directory, "src", "routes", "__root.tsx");
|
|
450
|
+
const matches = [...(await readFile(rootRoutePath, "utf8")).matchAll(/import\s+(?:[\w{}\s,*]+\s+from\s+)?["']([^"']+\.css(?:\?url)?)["']/g)];
|
|
451
|
+
for (const match of matches) {
|
|
452
|
+
const importedPath = match[1];
|
|
453
|
+
if (!importedPath.startsWith(".")) continue;
|
|
454
|
+
const cleanPath = importedPath.replace(/\?[^/]*$/, "");
|
|
455
|
+
return path.resolve(path.dirname(rootRoutePath), cleanPath);
|
|
456
|
+
}
|
|
457
|
+
return path.join(directory, "src", "styles.css");
|
|
458
|
+
};
|
|
459
|
+
const configureTanStackTailwind = async (directory) => {
|
|
460
|
+
const cssPath = await findTanStackCssPath(directory);
|
|
461
|
+
await prependCssImport(cssPath);
|
|
462
|
+
const rootRoutePath = path.join(directory, "src", "routes", "__root.tsx");
|
|
463
|
+
const rootRoute = await readFile(rootRoutePath, "utf8");
|
|
464
|
+
if (!rootRoute.includes(".css")) await writeFile(rootRoutePath, `import "../styles.css";\n${rootRoute}`, "utf8");
|
|
465
|
+
const viteConfigPath = path.join(directory, "vite.config.ts");
|
|
466
|
+
let viteConfig = await readFile(viteConfigPath, "utf8");
|
|
467
|
+
if (!viteConfig.includes("@tailwindcss/vite")) viteConfig = `import tailwindcss from "@tailwindcss/vite";\n` + viteConfig;
|
|
468
|
+
if (!viteConfig.includes("tailwindcss()")) viteConfig = viteConfig.replace(/plugins:\s*\[/, "plugins: [\n tailwindcss(),");
|
|
469
|
+
if (!viteConfig.includes("noExternal")) viteConfig = viteConfig.replace(/defineConfig\(\s*\{/, `defineConfig({
|
|
470
|
+
ssr: {
|
|
471
|
+
noExternal: ["@puzzle-ui/ui", "@puzzle-ui/theme"],
|
|
472
|
+
},`);
|
|
473
|
+
await writeFile(viteConfigPath, viteConfig, "utf8");
|
|
474
|
+
};
|
|
475
|
+
const configureReactTailwind = async (directory) => {
|
|
476
|
+
const cssPath = path.join(directory, "src", "index.css");
|
|
477
|
+
await prependCssImport(cssPath);
|
|
478
|
+
const viteConfigPath = path.join(directory, "vite.config.ts");
|
|
479
|
+
let viteConfig = await readFile(viteConfigPath, "utf8");
|
|
480
|
+
if (!viteConfig.includes("@tailwindcss/vite")) viteConfig = `import tailwindcss from "@tailwindcss/vite";\n` + viteConfig;
|
|
481
|
+
if (!viteConfig.includes("tailwindcss()")) viteConfig = viteConfig.replace(/plugins:\s*\[/, "plugins: [\n tailwindcss(),");
|
|
482
|
+
await writeFile(viteConfigPath, viteConfig, "utf8");
|
|
483
|
+
};
|
|
484
|
+
const configureTailwind = async (directory, framework) => {
|
|
485
|
+
if (framework === "next") {
|
|
486
|
+
await configureNextTailwind(directory);
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
if (framework === "tanstack") {
|
|
490
|
+
await configureTanStackTailwind(directory);
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
await configureReactTailwind(directory);
|
|
494
|
+
};
|
|
495
|
+
// src/tailwind/install-tailwind.ts
|
|
496
|
+
const getTailwindPackages = (framework) => {
|
|
497
|
+
if (framework === "next") return [
|
|
498
|
+
"tailwindcss@latest",
|
|
499
|
+
"@tailwindcss/postcss@latest",
|
|
500
|
+
"postcss@latest"
|
|
501
|
+
];
|
|
502
|
+
return ["tailwindcss@latest", "@tailwindcss/vite@latest"];
|
|
503
|
+
};
|
|
504
|
+
const installTailwind = async ({ directory, framework, packageManager, runner }) => {
|
|
505
|
+
const packages = getTailwindPackages(framework);
|
|
506
|
+
if (packageManager === "bun") {
|
|
507
|
+
await runner("bun", [
|
|
508
|
+
"add",
|
|
509
|
+
"-d",
|
|
510
|
+
...packages
|
|
511
|
+
], { cwd: directory });
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
514
|
+
await runner("npm", [
|
|
515
|
+
"install",
|
|
516
|
+
"--save-dev",
|
|
517
|
+
...packages
|
|
518
|
+
], { cwd: directory });
|
|
519
|
+
};
|
|
520
|
+
// src/create-project.ts
|
|
521
|
+
const installDependencies = async (directory, packageManager, runner) => {
|
|
522
|
+
const packages = [...PUZZLE_PACKAGES];
|
|
523
|
+
if (packageManager === "bun") {
|
|
524
|
+
await runner("bun", ["add", ...packages], { cwd: directory });
|
|
525
|
+
return;
|
|
526
|
+
}
|
|
527
|
+
await runner("npm", ["install", ...packages], { cwd: directory });
|
|
528
|
+
};
|
|
529
|
+
const configureProjectName = async (directory, projectName) => {
|
|
530
|
+
const packageJsonPath = path.join(directory, "package.json");
|
|
531
|
+
const packageJson = JSON.parse(await readFile(packageJsonPath, "utf8"));
|
|
532
|
+
packageJson.name = projectName;
|
|
533
|
+
await writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`, "utf8");
|
|
534
|
+
};
|
|
535
|
+
const createProject = async (options, { cwd = process.cwd(), runner = runCommand } = {}) => {
|
|
536
|
+
const targetDirectory = await validateProjectDirectory(options.directory, cwd);
|
|
537
|
+
const projectName = path.basename(targetDirectory);
|
|
538
|
+
const projectParent = path.dirname(targetDirectory);
|
|
539
|
+
const spinner = p.spinner();
|
|
540
|
+
let spinnerActive = false;
|
|
541
|
+
const startStep = (message) => {
|
|
542
|
+
spinner.start(message);
|
|
543
|
+
spinnerActive = true;
|
|
544
|
+
};
|
|
545
|
+
const finishStep = (message) => {
|
|
546
|
+
spinner.stop(message);
|
|
547
|
+
spinnerActive = false;
|
|
548
|
+
};
|
|
549
|
+
try {
|
|
550
|
+
startStep("Generating framework");
|
|
551
|
+
if (options.framework === "react") await frameworkGenerators.react(targetDirectory, options.packageManager, runner);
|
|
552
|
+
else await frameworkGenerators[options.framework](projectName, options.packageManager, runner, projectParent);
|
|
553
|
+
finishStep("Framework generated");
|
|
554
|
+
startStep("Configuring Puzzle theme");
|
|
555
|
+
await configureTheme(targetDirectory, options.framework);
|
|
556
|
+
await configureProjectName(targetDirectory, projectName);
|
|
557
|
+
finishStep("Puzzle theme configured");
|
|
558
|
+
if (options.tailwind) {
|
|
559
|
+
startStep("Configuring Tailwind CSS");
|
|
560
|
+
await configureTailwind(targetDirectory, options.framework);
|
|
561
|
+
finishStep("Tailwind CSS configured");
|
|
562
|
+
startStep("Installing Tailwind CSS");
|
|
563
|
+
await installTailwind({
|
|
564
|
+
directory: targetDirectory,
|
|
565
|
+
framework: options.framework,
|
|
566
|
+
packageManager: options.packageManager,
|
|
567
|
+
runner
|
|
568
|
+
});
|
|
569
|
+
finishStep("Tailwind CSS installed");
|
|
570
|
+
}
|
|
571
|
+
startStep("Installing Puzzle");
|
|
572
|
+
await installDependencies(targetDirectory, options.packageManager, runner);
|
|
573
|
+
finishStep("Puzzle installed");
|
|
574
|
+
} catch (error) {
|
|
575
|
+
if (spinnerActive) spinner.error("Project creation failed");
|
|
576
|
+
throw error;
|
|
577
|
+
}
|
|
578
|
+
p.log.success(`Project "${projectName}" created successfully.`);
|
|
579
|
+
p.outro(`Next steps:\n\n cd ${path.relative(process.cwd(), targetDirectory) || "."}\n ${options.packageManager} run dev`);
|
|
580
|
+
};
|
|
581
|
+
// src/index.ts
|
|
582
|
+
const main = async () => {
|
|
583
|
+
const options = await getProjectOptions();
|
|
584
|
+
if (!options) {
|
|
585
|
+
p.cancel("Project creation cancelled.");
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
await createProject(options);
|
|
589
|
+
};
|
|
590
|
+
main().catch((error) => {
|
|
591
|
+
p.log.error(error instanceof Error ? error.message : String(error));
|
|
592
|
+
process.exitCode = 1;
|
|
593
|
+
});
|
|
594
|
+
export {};
|
|
595
|
+
|
|
596
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/constants.ts","../src/utils/kebab-case.ts","../src/utils/detect-package-manager.ts","../src/prompts.ts","../src/utils/execute.ts","../src/frameworks/next.ts","../src/frameworks/tanstack.ts","../src/frameworks/react.ts","../src/frameworks/index.ts","../src/theme/templates.ts","../src/theme/configure-theme.ts","../src/utils/validate-project.ts","../src/tailwind/configure-tailwind.ts","../src/tailwind/install-tailwind.ts","../src/create-project.ts","../src/index.ts"],"sourcesContent":["import type { Framework } from \"./types\";\n\nexport const PACKAGE_NAME = \"@puzzle-ui/create\";\n\nexport const PUZZLE_PACKAGES = [\n \"@puzzle-ui/ui@latest\",\n \"@puzzle-ui/theme@latest\",\n] as const;\n\nexport const FRAMEWORKS: {\n value: Framework;\n label: string;\n hint: string;\n}[] = [\n {\n value: \"react\",\n label: \"Basic React Project\",\n hint: \"React + Vite + TypeScript\",\n },\n {\n value: \"tanstack\",\n label: \"TanStack Start\",\n hint: \"Full-stack React framework\",\n },\n {\n value: \"next\",\n label: \"Next.js\",\n hint: \"React framework with App Router\",\n },\n];\n","const toKebabCase = (value: string): string =>\n value\n .normalize(\"NFKD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .replace(/([a-z0-9])([A-Z])/g, \"$1-$2\")\n .replace(/([A-Z])([A-Z][a-z])/g, \"$1-$2\")\n .replace(/[^a-zA-Z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .toLowerCase();\n\nexport { toKebabCase };\n","import type { PackageManager } from \"../types\";\n\nconst detectPackageManager = (\n userAgent = process.env.npm_config_user_agent ?? \"\",\n): PackageManager => {\n if (userAgent.startsWith(\"bun/\")) {\n return \"bun\";\n }\n\n return \"npm\";\n};\n\nexport { detectPackageManager };\n","import * as p from \"@clack/prompts\";\n\nimport { FRAMEWORKS } from \"./constants\";\n\nimport type { Framework, ProjectOptions } from \"./types\";\n\nimport { toKebabCase } from \"./utils/kebab-case\";\n\nimport { detectPackageManager } from \"./utils/detect-package-manager\";\n\nconst getProjectOptions = async (): Promise<ProjectOptions | null> => {\n p.intro(\"Create a Puzzle application\");\n\n const name = await p.text({\n message: \"What is the name of your project?\",\n placeholder: \"my-awesome-app\",\n validate: (value) => {\n if (!value?.trim()) {\n return \"Project name is required.\";\n }\n\n if (!toKebabCase(value)) {\n return \"Please enter a valid project name.\";\n }\n },\n });\n\n if (p.isCancel(name)) {\n return null;\n }\n\n const directory = toKebabCase(name);\n\n const framework = await p.select({\n message: \"Which framework would you like to use?\",\n options: FRAMEWORKS.map((item) => ({\n value: item.value,\n label: item.label,\n hint: item.hint,\n })),\n });\n\n if (p.isCancel(framework)) {\n return null;\n }\n\n const tailwind = await p.confirm({\n message: \"Would you like to install Tailwind CSS?\",\n initialValue: true,\n });\n\n if (p.isCancel(tailwind)) {\n p.cancel(\"Project creation cancelled.\");\n return null;\n }\n\n return {\n name: directory,\n directory,\n framework: framework as Framework,\n packageManager: detectPackageManager(),\n tailwind,\n };\n};\n\nexport { getProjectOptions };\n","import { spawn } from \"node:child_process\";\n\nimport type { CommandRunner } from \"../types\";\n\nconst runCommand: CommandRunner = (command, args, options = {}) =>\n new Promise((resolve, reject) => {\n const child = spawn(command, args, {\n cwd: options.cwd ?? process.cwd(),\n stdio: options.stdio ?? \"inherit\",\n shell: false,\n env: process.env,\n });\n\n child.once(\"error\", reject);\n\n child.once(\"close\", (code, signal) => {\n if (code === 0) {\n resolve();\n return;\n }\n\n reject(\n new Error(\n signal\n ? `${command} terminated with signal ${signal}`\n : `${command} exited with code ${code ?? \"unknown\"}`,\n ),\n );\n });\n });\n\nexport { runCommand };\n","import type { FrameworkGenerator } from \"../types\";\n\nimport { runCommand } from \"../utils/execute\";\n\nconst createNextProject: FrameworkGenerator = async (\n directory,\n packageManager,\n runner = runCommand,\n cwd,\n) => {\n const args = [\n \"create-next-app@latest\",\n directory,\n \"--ts\",\n \"--app\",\n \"--src-dir\",\n \"--skip-install\",\n \"--disable-git\",\n \"--no-tailwind\",\n \"--yes\",\n packageManager === \"bun\" ? \"--use-bun\" : \"--use-npm\",\n ];\n\n const command = packageManager === \"bun\" ? \"bunx\" : \"npx\";\n const commandArgs = packageManager === \"bun\" ? args : [\"--yes\", ...args];\n\n if (cwd) {\n await runner(command, commandArgs, { cwd });\n return;\n }\n\n await runner(command, commandArgs);\n};\n\nexport { createNextProject };\n","import type { FrameworkGenerator } from \"../types\";\n\nimport { runCommand } from \"../utils/execute\";\n\nconst createTanStackProject: FrameworkGenerator = async (\n directory,\n packageManager,\n runner = runCommand,\n cwd,\n) => {\n const args = [\n \"@tanstack/cli@latest\",\n \"create\",\n directory,\n \"--framework\",\n \"React\",\n \"--package-manager\",\n packageManager,\n \"--blank\",\n \"--no-install\",\n \"--no-git\",\n \"--yes\",\n ];\n\n const command = packageManager === \"bun\" ? \"bunx\" : \"npx\";\n const commandArgs = packageManager === \"bun\" ? args : [\"--yes\", ...args];\n\n if (cwd) {\n await runner(command, commandArgs, { cwd });\n return;\n }\n\n await runner(command, commandArgs);\n};\n\nexport { createTanStackProject };\n","import { mkdir, writeFile } from \"node:fs/promises\";\n\nimport path from \"node:path\";\n\nimport type { FrameworkGenerator } from \"../types\";\n\nconst createReactProject: FrameworkGenerator = async (\n directory,\n _packageManager,\n _runner,\n) => {\n await mkdir(path.join(directory, \"src\"), {\n recursive: true,\n });\n\n const packageJson = {\n name: path.basename(directory),\n private: true,\n version: \"0.0.0\",\n type: \"module\",\n scripts: {\n dev: \"vite\",\n build: \"tsc --noEmit -p tsconfig.app.json && vite build\",\n preview: \"vite preview\",\n },\n dependencies: {\n react: \"^19.0.0\",\n \"react-dom\": \"^19.0.0\",\n },\n devDependencies: {\n \"@types/node\": \"latest\",\n \"@types/react\": \"^19.0.0\",\n \"@types/react-dom\": \"^19.0.0\",\n \"@vitejs/plugin-react\": \"latest\",\n typescript: \"latest\",\n vite: \"latest\",\n },\n };\n\n const files: Record<string, string> = {\n \"package.json\": JSON.stringify(packageJson, null, 2),\n\n \"index.html\": `<!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>Puzzle App</title>\n </head>\n <body>\n <div id=\"root\"></div>\n <script type=\"module\" src=\"/src/main.tsx\"></script>\n </body>\n</html>`,\n\n \"tsconfig.json\": JSON.stringify(\n {\n files: [],\n references: [\n { path: \"./tsconfig.app.json\" },\n { path: \"./tsconfig.node.json\" },\n ],\n },\n null,\n 2,\n ),\n\n \"tsconfig.app.json\": JSON.stringify(\n {\n compilerOptions: {\n tsBuildInfoFile: \"./node_modules/.tmp/tsconfig.app.tsbuildinfo\",\n target: \"ES2022\",\n useDefineForClassFields: true,\n lib: [\"ES2022\", \"DOM\", \"DOM.Iterable\"],\n module: \"ESNext\",\n skipLibCheck: true,\n moduleResolution: \"bundler\",\n allowImportingTsExtensions: true,\n verbatimModuleSyntax: true,\n moduleDetection: \"force\",\n noEmit: true,\n jsx: \"react-jsx\",\n strict: true,\n noUnusedLocals: true,\n noUnusedParameters: true,\n noFallthroughCasesInSwitch: true,\n types: [\"vite/client\"],\n },\n include: [\"src\"],\n },\n null,\n 2,\n ),\n\n \"tsconfig.node.json\": JSON.stringify(\n {\n compilerOptions: {\n tsBuildInfoFile: \"./node_modules/.tmp/tsconfig.node.tsbuildinfo\",\n target: \"ES2023\",\n lib: [\"ES2023\"],\n module: \"ESNext\",\n skipLibCheck: true,\n moduleResolution: \"bundler\",\n allowImportingTsExtensions: true,\n verbatimModuleSyntax: true,\n moduleDetection: \"force\",\n noEmit: true,\n strict: true,\n },\n include: [\"vite.config.ts\"],\n },\n null,\n 2,\n ),\n\n \"vite.config.ts\": `import { defineConfig } from \"vite\";\nimport react from \"@vitejs/plugin-react\";\n\nexport default defineConfig({\n plugins: [react()],\n});`,\n\n \"src/main.tsx\": \"\",\n \"src/App.tsx\": \"\",\n \"src/index.css\": `* {\n box-sizing: border-box;\n}\n\nhtml,\nbody,\n#root {\n min-height: 100%;\n}\n\nbody {\n margin: 0;\n font-family: var(--puzzle-font-family-body, sans-serif);\n}`,\n };\n\n await Promise.all(\n Object.entries(files).map(([file, content]) =>\n writeFile(path.join(directory, file), content, \"utf8\"),\n ),\n );\n};\n\nexport { createReactProject };\n","import { createNextProject } from \"./next\";\nimport { createTanStackProject } from \"./tanstack\";\nimport { createReactProject } from \"./react\";\n\nimport type { Framework, FrameworkGenerator } from \"../types\";\n\nconst frameworkGenerators: Record<Framework, FrameworkGenerator> = {\n next: createNextProject,\n tanstack: createTanStackProject,\n react: createReactProject,\n};\n\nexport {\n createNextProject,\n createTanStackProject,\n createReactProject,\n frameworkGenerators,\n};\n","const nextProviders = `\"use client\";\n\nimport type { ReactNode } from \"react\";\n\nimport { Theme } from \"@puzzle-ui/theme\";\n\ntype ProvidersProps = {\n children: ReactNode;\n};\n\nconst Providers = ({ children }: ProvidersProps) => (\n <Theme theme=\"system\">\n {children}\n </Theme>\n);\n\nexport { Providers };\n`;\n\nconst nextLayout = `import \"./globals.css\";\n\nimport type { ReactNode } from \"react\";\n\nimport { Providers } from \"./providers\";\n\ntype RootLayoutProps = {\n children: ReactNode;\n};\n\nconst RootLayout = ({ children }: RootLayoutProps) => (\n <html lang=\"en\">\n <body>\n <Providers>\n {children}\n </Providers>\n </body>\n </html>\n);\n\nexport default RootLayout;\n`;\n\nconst nextPage = `\"use client\";\nimport { Button } from \"@puzzle-ui/ui\";\n\nconst HomePage = () => (\n <main style={{ padding: \"2rem\" }}>\n <h1>Welcome to Puzzle</h1>\n <p>Your new Puzzle application is ready.</p>\n\n <Button onClick={() => console.log(\"Hello, Puzzle!\")}>\n Get started\n </Button>\n </main>\n);\n\nexport default HomePage;\n`;\n\nconst tanstackRootRoute = `import {\n createRootRoute,\n HeadContent,\n Outlet,\n Scripts,\n} from \"@tanstack/react-router\";\n\nimport { Theme } from \"@puzzle-ui/theme\";\n\nconst RootComponent = () => (\n <html lang=\"en\">\n <head>\n <HeadContent />\n </head>\n <body>\n <Theme theme=\"system\">\n <Outlet />\n </Theme>\n <Scripts />\n </body>\n </html>\n);\n\nexport const Route = createRootRoute({\n component: RootComponent,\n});\n`;\n\nconst tanstackIndexRoute = `import { createFileRoute } from \"@tanstack/react-router\";\n\nimport { Button } from \"@puzzle-ui/ui\";\n\nconst HomePage = () => (\n <main style={{ padding: \"2rem\" }}>\n <h1>Welcome to Puzzle</h1>\n <p>Your new Puzzle application is ready.</p>\n\n <Button onClick={() => console.log(\"Hello, Puzzle!\")}>\n Get started\n </Button>\n </main>\n);\n\nexport const Route = createFileRoute(\"/\")({\n component: HomePage,\n});\n`;\n\nconst reactMain = `import React from \"react\";\nimport ReactDOM from \"react-dom/client\";\n\nimport { Theme } from \"@puzzle-ui/theme\";\n\nimport App from \"./App\";\n\nimport \"./index.css\";\n\nReactDOM.createRoot(\n document.getElementById(\"root\")!,\n).render(\n <React.StrictMode>\n <Theme theme=\"system\">\n <App />\n </Theme>\n </React.StrictMode>,\n);\n`;\n\nconst reactApp = `import { Button } from \"@puzzle-ui/ui\";\n\nconst App = () => (\n <main style={{ padding: \"2rem\" }}>\n <h1>Welcome to Puzzle</h1>\n <p>Your new Puzzle application is ready.</p>\n\n <Button onClick={() => console.log(\"Hello, Puzzle!\")}>\n Get started\n </Button>\n </main>\n);\n\nexport default App;\n`;\n\nconst themeTemplates = {\n next: {\n \"src/app/providers.tsx\": nextProviders,\n \"src/app/layout.tsx\": nextLayout,\n \"src/app/page.tsx\": nextPage,\n },\n tanstack: {\n \"src/routes/__root.tsx\": tanstackRootRoute,\n \"src/routes/index.tsx\": tanstackIndexRoute,\n },\n react: {\n \"src/main.tsx\": reactMain,\n \"src/App.tsx\": reactApp,\n },\n} as const;\n\nexport {\n nextProviders,\n nextLayout,\n nextPage,\n tanstackRootRoute,\n tanstackIndexRoute,\n reactMain,\n reactApp,\n themeTemplates,\n};\n","import { mkdir, writeFile } from \"node:fs/promises\";\n\nimport path from \"node:path\";\n\nimport type { Framework } from \"../types\";\n\nimport { themeTemplates } from \"./templates\";\n\nconst configureTheme = async (\n directory: string,\n framework: Framework,\n): Promise<void> => {\n const templates = themeTemplates[framework];\n\n await Promise.all(\n Object.entries(templates).map(async ([relativePath, content]) => {\n const filePath = path.join(directory, relativePath);\n\n await mkdir(path.dirname(filePath), {\n recursive: true,\n });\n\n await writeFile(filePath, content, \"utf8\");\n }),\n );\n};\n\nexport { configureTheme };\n","import { access } from \"node:fs/promises\";\n\nimport path from \"node:path\";\n\nconst validateProjectDirectory = async (\n directory: string,\n cwd = process.cwd(),\n): Promise<string> => {\n const root = path.resolve(cwd);\n const target = path.resolve(root, directory);\n\n if (target === root || !target.startsWith(`${root}${path.sep}`)) {\n throw new Error(\"Invalid project directory.\");\n }\n\n try {\n await access(target);\n\n throw new Error(\n `The directory \"${directory}\" already exists. Choose another name.`,\n );\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"already exists\")) {\n throw error;\n }\n\n if (\n error &&\n typeof error === \"object\" &&\n \"code\" in error &&\n error.code === \"ENOENT\"\n ) {\n return target;\n }\n\n throw error;\n }\n};\n\nexport { validateProjectDirectory };\n","import { mkdir, readFile, writeFile } from \"node:fs/promises\";\n\nimport path from \"node:path\";\n\nimport type { Framework } from \"../types\";\n\nconst readIfExists = async (filePath: string) => {\n try {\n return await readFile(filePath, \"utf8\");\n } catch {\n return null;\n }\n};\n\nconst writeIfMissingImport = async (\n filePath: string,\n importStatement: string,\n) => {\n const current = await readIfExists(filePath);\n\n if (current === null) {\n await mkdir(path.dirname(filePath), {\n recursive: true,\n });\n\n await writeFile(filePath, `${importStatement}\\n`, \"utf8\");\n\n return;\n }\n\n if (current.includes(importStatement)) {\n return;\n }\n\n await writeFile(filePath, `${importStatement}\\n\\n${current}`, \"utf8\");\n};\n\nconst prependCssImport = async (filePath: string) => {\n const importStatement = '@import \"tailwindcss\";';\n const current = await readIfExists(filePath);\n\n if (current === null) {\n await mkdir(path.dirname(filePath), {\n recursive: true,\n });\n\n await writeFile(filePath, `${importStatement}\\n`, \"utf8\");\n\n return;\n }\n\n if (current.includes(importStatement)) {\n return;\n }\n\n await writeFile(filePath, `${importStatement}\\n\\n${current}`, \"utf8\");\n};\n\nconst configureNextTailwind = async (directory: string) => {\n const cssPath = path.join(directory, \"src\", \"app\", \"globals.css\");\n\n await prependCssImport(cssPath);\n\n const postcssConfigPath = path.join(directory, \"postcss.config.mjs\");\n\n await writeFile(\n postcssConfigPath,\n `const config = {\n plugins: {\n \"@tailwindcss/postcss\": {},\n },\n};\n\nexport default config;\n`,\n \"utf8\",\n );\n};\n\nconst findTanStackCssPath = async (directory: string) => {\n const rootRoutePath = path.join(directory, \"src\", \"routes\", \"__root.tsx\");\n\n const rootRoute = await readFile(rootRoutePath, \"utf8\");\n\n const cssImportPattern =\n /import\\s+(?:[\\w{}\\s,*]+\\s+from\\s+)?[\"']([^\"']+\\.css(?:\\?url)?)[\"']/g;\n\n const matches = [...rootRoute.matchAll(cssImportPattern)];\n\n for (const match of matches) {\n const importedPath = match[1];\n\n if (!importedPath.startsWith(\".\")) {\n continue;\n }\n\n const cleanPath = importedPath.replace(/\\?[^/]*$/, \"\");\n\n return path.resolve(path.dirname(rootRoutePath), cleanPath);\n }\n\n // Default stylesheet location used by TanStack Start templates.\n return path.join(directory, \"src\", \"styles.css\");\n};\n\nconst configureTanStackTailwind = async (directory: string) => {\n const cssPath = await findTanStackCssPath(directory);\n\n await prependCssImport(cssPath);\n\n const rootRoutePath = path.join(directory, \"src\", \"routes\", \"__root.tsx\");\n\n const rootRoute = await readFile(rootRoutePath, \"utf8\");\n\n if (!rootRoute.includes(\".css\")) {\n await writeFile(\n rootRoutePath,\n `import \"../styles.css\";\\n${rootRoute}`,\n \"utf8\",\n );\n }\n\n const viteConfigPath = path.join(directory, \"vite.config.ts\");\n\n let viteConfig = await readFile(viteConfigPath, \"utf8\");\n\n if (!viteConfig.includes(\"@tailwindcss/vite\")) {\n viteConfig = `import tailwindcss from \"@tailwindcss/vite\";\\n` + viteConfig;\n }\n\n if (!viteConfig.includes(\"tailwindcss()\")) {\n viteConfig = viteConfig.replace(\n /plugins:\\s*\\[/,\n \"plugins: [\\n tailwindcss(),\",\n );\n }\n\n if (!viteConfig.includes(\"noExternal\")) {\n viteConfig = viteConfig.replace(\n /defineConfig\\(\\s*\\{/,\n `defineConfig({\n ssr: {\n noExternal: [\"@puzzle-ui/ui\", \"@puzzle-ui/theme\"],\n },`,\n );\n }\n\n await writeFile(viteConfigPath, viteConfig, \"utf8\");\n};\n\nconst configureReactTailwind = async (directory: string) => {\n const cssPath = path.join(directory, \"src\", \"index.css\");\n\n await prependCssImport(cssPath);\n\n const viteConfigPath = path.join(directory, \"vite.config.ts\");\n\n let viteConfig = await readFile(viteConfigPath, \"utf8\");\n\n if (!viteConfig.includes(\"@tailwindcss/vite\")) {\n viteConfig = `import tailwindcss from \"@tailwindcss/vite\";\\n` + viteConfig;\n }\n\n if (!viteConfig.includes(\"tailwindcss()\")) {\n viteConfig = viteConfig.replace(\n /plugins:\\s*\\[/,\n \"plugins: [\\n tailwindcss(),\",\n );\n }\n\n await writeFile(viteConfigPath, viteConfig, \"utf8\");\n};\n\nconst configureTailwind = async (directory: string, framework: Framework) => {\n if (framework === \"next\") {\n await configureNextTailwind(directory);\n return;\n }\n\n if (framework === \"tanstack\") {\n await configureTanStackTailwind(directory);\n return;\n }\n\n await configureReactTailwind(directory);\n};\n\nexport { configureTailwind };\n","import type { CommandRunner, Framework, PackageManager } from \"../types\";\n\nconst getTailwindPackages = (framework: Framework) => {\n if (framework === \"next\") {\n return [\n \"tailwindcss@latest\",\n \"@tailwindcss/postcss@latest\",\n \"postcss@latest\",\n ];\n }\n\n return [\"tailwindcss@latest\", \"@tailwindcss/vite@latest\"];\n};\n\nconst installTailwind = async ({\n directory,\n framework,\n packageManager,\n runner,\n}: {\n directory: string;\n framework: Framework;\n packageManager: PackageManager;\n runner: CommandRunner;\n}) => {\n const packages = getTailwindPackages(framework);\n\n if (packageManager === \"bun\") {\n await runner(\"bun\", [\"add\", \"-d\", ...packages], { cwd: directory });\n\n return;\n }\n\n await runner(\"npm\", [\"install\", \"--save-dev\", ...packages], {\n cwd: directory,\n });\n};\n\nexport { installTailwind };\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport * as p from \"@clack/prompts\";\n\nimport type { CommandRunner, ProjectOptions } from \"./types\";\nimport { frameworkGenerators } from \"./frameworks\";\nimport { configureTheme } from \"./theme/configure-theme\";\nimport { runCommand } from \"./utils/execute\";\nimport { validateProjectDirectory } from \"./utils/validate-project\";\nimport { PUZZLE_PACKAGES } from \"./constants\";\nimport { configureTailwind } from \"./tailwind/configure-tailwind\";\nimport { installTailwind } from \"./tailwind/install-tailwind\";\n\ntype CreateProjectContext = {\n /** Directory the project directory is resolved from. Defaults to `process.cwd()`. */\n cwd?: string;\n /** Runs external commands. Defaults to spawning a child process. */\n runner?: CommandRunner;\n};\n\nconst installDependencies = async (\n directory: string,\n packageManager: ProjectOptions[\"packageManager\"],\n runner: CommandRunner,\n) => {\n const packages = [...PUZZLE_PACKAGES];\n\n if (packageManager === \"bun\") {\n await runner(\"bun\", [\"add\", ...packages], { cwd: directory });\n return;\n }\n\n await runner(\"npm\", [\"install\", ...packages], { cwd: directory });\n};\n\nconst configureProjectName = async (directory: string, projectName: string) => {\n const packageJsonPath = path.join(directory, \"package.json\");\n\n const packageJson = JSON.parse(await readFile(packageJsonPath, \"utf8\")) as {\n name?: string;\n [key: string]: unknown;\n };\n\n packageJson.name = projectName;\n\n await writeFile(\n packageJsonPath,\n `${JSON.stringify(packageJson, null, 2)}\\n`,\n \"utf8\",\n );\n};\n\nconst createProject = async (\n options: ProjectOptions,\n { cwd = process.cwd(), runner = runCommand }: CreateProjectContext = {},\n) => {\n // Validate before starting the spinner, so nothing is generated or reported\n // as a failed step when the target directory cannot be used.\n const targetDirectory = await validateProjectDirectory(\n options.directory,\n cwd,\n );\n\n const projectName = path.basename(targetDirectory);\n const projectParent = path.dirname(targetDirectory);\n\n const spinner = p.spinner();\n let spinnerActive = false;\n\n const startStep = (message: string) => {\n spinner.start(message);\n spinnerActive = true;\n };\n\n const finishStep = (message: string) => {\n spinner.stop(message);\n spinnerActive = false;\n };\n\n try {\n startStep(\"Generating framework\");\n\n if (options.framework === \"react\") {\n // The Basic React generator writes directly into its target directory.\n await frameworkGenerators.react(\n targetDirectory,\n options.packageManager,\n runner,\n );\n } else {\n // Next.js and TanStack CLI create their own project directory.\n await frameworkGenerators[options.framework](\n projectName,\n options.packageManager,\n runner,\n projectParent,\n );\n }\n\n finishStep(\"Framework generated\");\n\n startStep(\"Configuring Puzzle theme\");\n await configureTheme(targetDirectory, options.framework);\n await configureProjectName(targetDirectory, projectName);\n finishStep(\"Puzzle theme configured\");\n\n if (options.tailwind) {\n startStep(\"Configuring Tailwind CSS\");\n await configureTailwind(targetDirectory, options.framework);\n finishStep(\"Tailwind CSS configured\");\n\n startStep(\"Installing Tailwind CSS\");\n await installTailwind({\n directory: targetDirectory,\n framework: options.framework,\n packageManager: options.packageManager,\n runner,\n });\n finishStep(\"Tailwind CSS installed\");\n }\n\n startStep(\"Installing Puzzle\");\n await installDependencies(targetDirectory, options.packageManager, runner);\n finishStep(\"Puzzle installed\");\n } catch (error) {\n if (spinnerActive) {\n spinner.error(\"Project creation failed\");\n }\n\n throw error;\n }\n\n p.log.success(`Project \"${projectName}\" created successfully.`);\n\n p.outro(\n `Next steps:\\n\\n cd ${path.relative(process.cwd(), targetDirectory) || \".\"}\\n ${options.packageManager} run dev`,\n );\n};\n\nexport { createProject, type CreateProjectContext };\n","#!/usr/bin/env node\n\nimport * as p from \"@clack/prompts\";\n\nimport { getProjectOptions } from \"./prompts\";\n\nimport { createProject } from \"./create-project\";\n\nconst main = async (): Promise<void> => {\n const options = await getProjectOptions();\n\n if (!options) {\n p.cancel(\"Project creation cancelled.\");\n return;\n }\n\n await createProject(options);\n};\n\nmain().catch((error: unknown) => {\n p.log.error(error instanceof Error ? error.message : String(error));\n\n process.exitCode = 1;\n});\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,36 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@puzzle-ui/create",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Create Beautiful React applications fast with Puzzle UI",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"create-puzzle": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=20.19.0"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsdown",
|
|
19
|
+
"test": "vitest run",
|
|
20
|
+
"test:watch": "bunx vitest run --watch --passWithNoTests",
|
|
21
|
+
"prepack": "npm run build"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@clack/prompts": "^1.0.0"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/node": "^26.0.0",
|
|
28
|
+
"tsdown": "^0.23.1",
|
|
29
|
+
"typescript": "^6.0.3",
|
|
30
|
+
"vitest": "^5.1.0"
|
|
31
|
+
},
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public",
|
|
34
|
+
"registry": "https://registry.npmjs.org/"
|
|
35
|
+
}
|
|
36
|
+
}
|