@lazarv/create-react-server 0.0.0-experimental-d003259-20250211-2495688e
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/LICENSE +21 -0
- package/README.md +31 -0
- package/generator.mjs +195 -0
- package/globals.d.ts +59 -0
- package/index.mjs +87 -0
- package/launch.mjs +136 -0
- package/lib/code-merge.mjs +246 -0
- package/lib/dynamic-checkbox.mjs +259 -0
- package/lib/files.mjs +6 -0
- package/lib/formatter.mjs +16 -0
- package/lib/generate-name.mjs +220 -0
- package/lib/theme.mjs +56 -0
- package/logo.mjs +3 -0
- package/package.json +26 -0
- package/steps/alias.mjs +50 -0
- package/steps/authentication.mjs +62 -0
- package/steps/database.mjs +56 -0
- package/steps/deploy.mjs +151 -0
- package/steps/features.mjs +415 -0
- package/steps/host.mjs +40 -0
- package/steps/index.mjs +33 -0
- package/steps/integrations.mjs +104 -0
- package/steps/name.mjs +69 -0
- package/steps/package.mjs +104 -0
- package/steps/port.mjs +42 -0
- package/steps/preset.mjs +188 -0
- package/steps/state-management.mjs +68 -0
- package/steps/third-party.mjs +19 -0
- package/steps/ui.mjs +87 -0
- package/templates/.dockerignore +5 -0
- package/templates/.gitignore.template +19 -0
- package/templates/.prettierignore +3 -0
- package/templates/.prettierrc +11 -0
- package/templates/Dockerfile.npm +49 -0
- package/templates/Dockerfile.pnpm +71 -0
- package/templates/Dockerfile.yarn +71 -0
- package/templates/README.docker.md +15 -0
- package/templates/README.md +35 -0
- package/templates/blank/package.json +6 -0
- package/templates/blank/src/App.jsx +5 -0
- package/templates/blank-ts/package.json +6 -0
- package/templates/blank-ts/src/App.tsx +5 -0
- package/templates/eslint.config.template.mjs +98 -0
- package/templates/get-started/package.json +6 -0
- package/templates/get-started/src/App.jsx +60 -0
- package/templates/get-started/src/Button.jsx +14 -0
- package/templates/get-started/src/Confetti.jsx +19 -0
- package/templates/get-started/src/global.css +3 -0
- package/templates/get-started-ts/globals.d.ts +3 -0
- package/templates/get-started-ts/package.json +6 -0
- package/templates/get-started-ts/src/App.tsx +66 -0
- package/templates/get-started-ts/src/Button.tsx +18 -0
- package/templates/get-started-ts/src/Confetti.tsx +19 -0
- package/templates/get-started-ts/src/global.css +3 -0
- package/templates/nextjs/globals.d.ts +3 -0
- package/templates/nextjs/react-server.config.json +9 -0
- package/templates/nextjs/src/app/layout.tsx +38 -0
- package/templates/nextjs/src/app/page.tsx +33 -0
- package/templates/nextjs/src/components/Button.tsx +18 -0
- package/templates/nextjs/src/components/Confetti.tsx +19 -0
- package/templates/nextjs/src/global.css +3 -0
- package/templates/package.css.json +5 -0
- package/templates/package.eslint.json +19 -0
- package/templates/package.eslint.ts.json +7 -0
- package/templates/package.json +12 -0
- package/templates/package.lightningcss.json +6 -0
- package/templates/package.prettier.json +8 -0
- package/templates/package.react-compiler.json +7 -0
- package/templates/package.swc.json +5 -0
- package/templates/package.tailwind.json +7 -0
- package/templates/package.ts.json +11 -0
- package/templates/postcss.config.mjs +6 -0
- package/templates/router/globals.d.ts +3 -0
- package/templates/router/react-server.config.json +19 -0
- package/templates/router/src/app/@content/about.tsx +98 -0
- package/templates/router/src/app/@content/index.tsx +33 -0
- package/templates/router/src/app/layout.tsx +44 -0
- package/templates/router/src/app/page.tsx +17 -0
- package/templates/router/src/components/Button.tsx +18 -0
- package/templates/router/src/components/Confetti.tsx +19 -0
- package/templates/router/src/components/Navigation.tsx +31 -0
- package/templates/router/src/global.css +3 -0
- package/templates/shared/public/github.svg +4 -0
- package/templates/shared/public/react-server.svg +51 -0
- package/templates/tailwind.config.mjs +6 -0
- package/templates/tsconfig.css.json +9 -0
- package/templates/tsconfig.template.json +15 -0
- package/templates/vite.config.lightningcss.mjs +15 -0
- package/templates/vite.config.lightningcss.ts +15 -0
- package/templates/vite.config.react-compiler.mjs +19 -0
- package/templates/vite.config.react-compiler.ts +19 -0
- package/templates/vite.config.swc.mjs +6 -0
- package/templates/vite.config.swc.ts +6 -0
- package/templates/vite.config.ts +3 -0
- package/wizard.mjs +122 -0
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
4
|
+
import { checkbox, Separator } from "@inquirer/prompts";
|
|
5
|
+
import colors from "picocolors";
|
|
6
|
+
|
|
7
|
+
import { json } from "../lib/files.mjs";
|
|
8
|
+
import { createTheme } from "../lib/theme.mjs";
|
|
9
|
+
|
|
10
|
+
export default async (context) => {
|
|
11
|
+
const choices = [
|
|
12
|
+
{
|
|
13
|
+
selectedName: "TypeScript",
|
|
14
|
+
name: `TypeScript ${colors.yellow("(recommended)")}`,
|
|
15
|
+
value: "ts",
|
|
16
|
+
description: "Add TypeScript support",
|
|
17
|
+
checked: context.props.preset?.features.includes("ts"),
|
|
18
|
+
},
|
|
19
|
+
new Separator(),
|
|
20
|
+
{
|
|
21
|
+
name: "ESLint",
|
|
22
|
+
value: "eslint",
|
|
23
|
+
description: "Add ESLint support",
|
|
24
|
+
checked: context.props.preset?.features.includes("eslint"),
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: "Prettier",
|
|
28
|
+
value: "prettier",
|
|
29
|
+
description: "Add Prettier support",
|
|
30
|
+
checked: context.props.preset?.features.includes("prettier"),
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: "Tailwind CSS",
|
|
34
|
+
value: "tailwind",
|
|
35
|
+
description: "Add Tailwind CSS support",
|
|
36
|
+
checked: context.props.preset?.features.includes("tailwind"),
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: "Lightning CSS",
|
|
40
|
+
value: "lightningcss",
|
|
41
|
+
description: "Add Lightning CSS support",
|
|
42
|
+
checked: context.props.preset?.features.includes("lightningcss"),
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: "CSS Modules",
|
|
46
|
+
value: "css-modules",
|
|
47
|
+
description: "Add CSS Modules support",
|
|
48
|
+
checked: context.props.preset?.features.includes("css-modules"),
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: "React Compiler",
|
|
52
|
+
value: "react-compiler",
|
|
53
|
+
description: "Add React Compiler support",
|
|
54
|
+
checked: context.props.preset?.features.includes("react-compiler"),
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: "React SWC",
|
|
58
|
+
value: "react-swc",
|
|
59
|
+
description: "Use SWC for faster builds",
|
|
60
|
+
checked: context.props.preset?.features.includes("react-swc"),
|
|
61
|
+
},
|
|
62
|
+
new Separator(),
|
|
63
|
+
{
|
|
64
|
+
name: "Git",
|
|
65
|
+
value: "git",
|
|
66
|
+
description: "Initialize a Git repository",
|
|
67
|
+
checked: context.props.preset?.features.includes("git"),
|
|
68
|
+
},
|
|
69
|
+
new Separator(),
|
|
70
|
+
].map((choice) => ({
|
|
71
|
+
...choice,
|
|
72
|
+
disabled: context.props.preset?.features.includes(choice.value),
|
|
73
|
+
}));
|
|
74
|
+
|
|
75
|
+
const theme = createTheme("info", {
|
|
76
|
+
...context,
|
|
77
|
+
env: {
|
|
78
|
+
...context.env,
|
|
79
|
+
style: {
|
|
80
|
+
disabledChoice(text) {
|
|
81
|
+
const raw = text.replace("(disabled)", "").trim();
|
|
82
|
+
const choice = choices.find((choice) => choice.name === raw);
|
|
83
|
+
const isPresetFeature = context.props.preset?.features?.includes(
|
|
84
|
+
choice?.value
|
|
85
|
+
);
|
|
86
|
+
const message = ` ${isPresetFeature ? "✅" : " "} ${isPresetFeature ? colors.whiteBright(raw) : raw} ${colors.gray(`(${choice.reason ?? (isPresetFeature ? "preset" : "disabled")})`)}`;
|
|
87
|
+
return isPresetFeature ? message : colors.gray(message);
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
features: choices
|
|
91
|
+
.filter((choice) => choice.type !== "separator")
|
|
92
|
+
.reduce((features, choice) => {
|
|
93
|
+
features[choice.value] = choice;
|
|
94
|
+
return features;
|
|
95
|
+
}, {}),
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const answer = [
|
|
100
|
+
...(context.props.preset?.features ?? []),
|
|
101
|
+
...(context.env.options.features?.split(",") ??
|
|
102
|
+
(!context.props.custom || context.env.hasOptions
|
|
103
|
+
? context.props.preset.features ?? []
|
|
104
|
+
: await checkbox(
|
|
105
|
+
{
|
|
106
|
+
message: "Enabled features",
|
|
107
|
+
choices,
|
|
108
|
+
pageSize: choices.length - 2,
|
|
109
|
+
theme,
|
|
110
|
+
},
|
|
111
|
+
context
|
|
112
|
+
))),
|
|
113
|
+
];
|
|
114
|
+
|
|
115
|
+
const partials = {
|
|
116
|
+
...context.partials,
|
|
117
|
+
};
|
|
118
|
+
const props = {
|
|
119
|
+
...context.props,
|
|
120
|
+
};
|
|
121
|
+
const files = context.files;
|
|
122
|
+
|
|
123
|
+
if (answer.includes("eslint")) {
|
|
124
|
+
partials["package.json"] = {
|
|
125
|
+
...partials["package.json"],
|
|
126
|
+
merge: [
|
|
127
|
+
...partials["package.json"].merge,
|
|
128
|
+
await json(context.env.templateDir, "package.eslint.json"),
|
|
129
|
+
...(answer.includes("ts")
|
|
130
|
+
? [await json(context.env.templateDir, "package.eslint.ts.json")]
|
|
131
|
+
: []),
|
|
132
|
+
],
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
partials["eslint.config.mjs"] = {
|
|
136
|
+
type: "text",
|
|
137
|
+
format: "babel",
|
|
138
|
+
template: await readFile(
|
|
139
|
+
join(context.env.templateDir, "eslint.config.template.mjs"),
|
|
140
|
+
"utf8"
|
|
141
|
+
),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (answer.includes("ts")) {
|
|
146
|
+
partials["tsconfig.json"] = {
|
|
147
|
+
type: "json",
|
|
148
|
+
merge: [await json(context.env.templateDir, "tsconfig.template.json")],
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
partials["package.json"] = {
|
|
152
|
+
...partials["package.json"],
|
|
153
|
+
merge: [
|
|
154
|
+
...partials["package.json"].merge,
|
|
155
|
+
await json(context.env.templateDir, "package.ts.json"),
|
|
156
|
+
],
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
partials["vite.config.ts"] = {
|
|
160
|
+
type: "code",
|
|
161
|
+
merge: [
|
|
162
|
+
await readFile(join(context.env.templateDir, "vite.config.ts"), "utf8"),
|
|
163
|
+
],
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
props.eslint = {
|
|
167
|
+
...props.eslint,
|
|
168
|
+
typescript: {
|
|
169
|
+
import: `import typescriptEslint from "@typescript-eslint/eslint-plugin";
|
|
170
|
+
import tsParser from "@typescript-eslint/parser";`,
|
|
171
|
+
config: `...compat
|
|
172
|
+
.extends("eslint:recommended", "plugin:@typescript-eslint/recommended")
|
|
173
|
+
.map((config) => ({
|
|
174
|
+
...config,
|
|
175
|
+
files: ["**/*.{ts,tsx}"],
|
|
176
|
+
})),
|
|
177
|
+
{
|
|
178
|
+
files: ["**/*.{ts,tsx}"],
|
|
179
|
+
|
|
180
|
+
plugins: {
|
|
181
|
+
"@typescript-eslint": typescriptEslint,
|
|
182
|
+
},
|
|
183
|
+
|
|
184
|
+
languageOptions: {
|
|
185
|
+
globals: {
|
|
186
|
+
...globals.node,
|
|
187
|
+
},
|
|
188
|
+
|
|
189
|
+
parser: tsParser,
|
|
190
|
+
},
|
|
191
|
+
|
|
192
|
+
rules: {
|
|
193
|
+
"@typescript-eslint/no-unused-vars": [
|
|
194
|
+
"error",
|
|
195
|
+
{
|
|
196
|
+
argsIgnorePattern: "^_",
|
|
197
|
+
},
|
|
198
|
+
],
|
|
199
|
+
|
|
200
|
+
"@typescript-eslint/no-explicit-any": "off",
|
|
201
|
+
"@typescript-eslint/explicit-module-boundary-types": "off",
|
|
202
|
+
},
|
|
203
|
+
},`,
|
|
204
|
+
},
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (answer.includes("prettier")) {
|
|
209
|
+
partials["package.json"] = {
|
|
210
|
+
...partials["package.json"],
|
|
211
|
+
merge: [
|
|
212
|
+
...partials["package.json"].merge,
|
|
213
|
+
await json(context.env.templateDir, "package.prettier.json"),
|
|
214
|
+
],
|
|
215
|
+
};
|
|
216
|
+
files.push(
|
|
217
|
+
join(context.env.templateDir, ".prettierignore"),
|
|
218
|
+
join(context.env.templateDir, ".prettierrc")
|
|
219
|
+
);
|
|
220
|
+
props.eslint = {
|
|
221
|
+
...props.eslint,
|
|
222
|
+
prettier: {
|
|
223
|
+
import: `import prettier from "eslint-plugin-prettier";`,
|
|
224
|
+
compat: `,"plugin:prettier/recommended"`,
|
|
225
|
+
plugin: `prettier,`,
|
|
226
|
+
rules: `"prettier/prettier": [
|
|
227
|
+
"error",
|
|
228
|
+
{
|
|
229
|
+
endOfLine: "auto",
|
|
230
|
+
},
|
|
231
|
+
],`,
|
|
232
|
+
},
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (answer.includes("tailwind")) {
|
|
237
|
+
partials["package.json"] = {
|
|
238
|
+
...partials["package.json"],
|
|
239
|
+
merge: [
|
|
240
|
+
...partials["package.json"].merge,
|
|
241
|
+
await json(context.env.templateDir, "package.tailwind.json"),
|
|
242
|
+
],
|
|
243
|
+
};
|
|
244
|
+
files.push(
|
|
245
|
+
join(context.env.templateDir, "tailwind.config.mjs"),
|
|
246
|
+
join(context.env.templateDir, "postcss.config.mjs")
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (answer.includes("css-modules")) {
|
|
251
|
+
partials["package.json"] = {
|
|
252
|
+
...partials["package.json"],
|
|
253
|
+
merge: [
|
|
254
|
+
...partials["package.json"].merge,
|
|
255
|
+
await json(context.env.templateDir, "package.css.json"),
|
|
256
|
+
],
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
if (answer.includes("ts")) {
|
|
260
|
+
partials["tsconfig.json"] = {
|
|
261
|
+
...partials["tsconfig.json"],
|
|
262
|
+
merge: [
|
|
263
|
+
...partials["tsconfig.json"].merge,
|
|
264
|
+
await json(context.env.templateDir, "tsconfig.css.json"),
|
|
265
|
+
],
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if (answer.includes("lightningcss")) {
|
|
271
|
+
if (!answer.includes("tailwind")) {
|
|
272
|
+
partials["package.json"] = {
|
|
273
|
+
...partials["package.json"],
|
|
274
|
+
merge: [
|
|
275
|
+
...partials["package.json"].merge,
|
|
276
|
+
await json(context.env.templateDir, "package.lightningcss.json"),
|
|
277
|
+
],
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
if (answer.includes("ts")) {
|
|
281
|
+
partials["vite.config.ts"] = {
|
|
282
|
+
...partials["vite.config.ts"],
|
|
283
|
+
merge: [
|
|
284
|
+
await readFile(
|
|
285
|
+
join(context.env.templateDir, "vite.config.lightningcss.ts"),
|
|
286
|
+
"utf8"
|
|
287
|
+
),
|
|
288
|
+
],
|
|
289
|
+
};
|
|
290
|
+
} else {
|
|
291
|
+
partials["vite.config.mjs"] = {
|
|
292
|
+
...partials["vite.config.mjs"],
|
|
293
|
+
type: "code",
|
|
294
|
+
merge: [
|
|
295
|
+
await readFile(
|
|
296
|
+
join(context.env.templateDir, "vite.config.lightningcss.mjs"),
|
|
297
|
+
"utf8"
|
|
298
|
+
),
|
|
299
|
+
],
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
} else {
|
|
303
|
+
context.env.logger.warn(
|
|
304
|
+
"Lightning CSS is not compatible with Tailwind CSS v3. Lightning CSS will not be installed."
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
if (answer.includes("react-compiler")) {
|
|
310
|
+
partials["package.json"] = {
|
|
311
|
+
...partials["package.json"],
|
|
312
|
+
merge: [
|
|
313
|
+
...partials["package.json"].merge,
|
|
314
|
+
await json(context.env.templateDir, "package.react-compiler.json"),
|
|
315
|
+
],
|
|
316
|
+
};
|
|
317
|
+
props.eslint = {
|
|
318
|
+
...props.eslint,
|
|
319
|
+
reactCompiler: {
|
|
320
|
+
import: `import reactCompiler from "eslint-plugin-react-compiler";`,
|
|
321
|
+
plugin: `"react-compiler": reactCompiler,`,
|
|
322
|
+
rules: `"react-compiler/react-compiler": "error",`,
|
|
323
|
+
},
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
if (answer.includes("ts")) {
|
|
327
|
+
partials["vite.config.ts"] = {
|
|
328
|
+
...partials["vite.config.ts"],
|
|
329
|
+
merge: [
|
|
330
|
+
...(partials["vite.config.ts"]?.merge ?? []),
|
|
331
|
+
await readFile(
|
|
332
|
+
join(context.env.templateDir, "vite.config.react-compiler.ts"),
|
|
333
|
+
"utf8"
|
|
334
|
+
),
|
|
335
|
+
],
|
|
336
|
+
};
|
|
337
|
+
} else {
|
|
338
|
+
partials["vite.config.mjs"] = {
|
|
339
|
+
...partials["vite.config.mjs"],
|
|
340
|
+
type: "code",
|
|
341
|
+
merge: [
|
|
342
|
+
...(partials["vite.config.mjs"]?.merge ?? []),
|
|
343
|
+
await readFile(
|
|
344
|
+
join(context.env.templateDir, "vite.config.react-compiler.mjs"),
|
|
345
|
+
"utf8"
|
|
346
|
+
),
|
|
347
|
+
],
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
if (answer.includes("react-swc")) {
|
|
353
|
+
if (!answer.includes("react-compiler")) {
|
|
354
|
+
partials["package.json"] = {
|
|
355
|
+
...partials["package.json"],
|
|
356
|
+
merge: [
|
|
357
|
+
...partials["package.json"].merge,
|
|
358
|
+
await json(context.env.templateDir, "package.swc.json"),
|
|
359
|
+
],
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
if (answer.includes("ts")) {
|
|
363
|
+
partials["vite.config.ts"] = {
|
|
364
|
+
...partials["vite.config.ts"],
|
|
365
|
+
merge: [
|
|
366
|
+
...(partials["vite.config.ts"]?.merge ?? []),
|
|
367
|
+
await readFile(
|
|
368
|
+
join(context.env.templateDir, "vite.config.swc.ts"),
|
|
369
|
+
"utf8"
|
|
370
|
+
),
|
|
371
|
+
],
|
|
372
|
+
};
|
|
373
|
+
} else {
|
|
374
|
+
partials["vite.config.mjs"] = {
|
|
375
|
+
...partials["vite.config.mjs"],
|
|
376
|
+
type: "code",
|
|
377
|
+
merge: [
|
|
378
|
+
...(partials["vite.config.mjs"]?.merge ?? []),
|
|
379
|
+
await readFile(
|
|
380
|
+
join(context.env.templateDir, "vite.config.swc.mjs"),
|
|
381
|
+
"utf8"
|
|
382
|
+
),
|
|
383
|
+
],
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
} else {
|
|
387
|
+
context.env.logger.warn(
|
|
388
|
+
"React Compiler is not yet supported when using the SWC compiler. Falling back to using the Babel compiler."
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
if (answer.includes("git")) {
|
|
394
|
+
partials[".gitignore"] = {
|
|
395
|
+
...partials[".gitignore"],
|
|
396
|
+
type: "text",
|
|
397
|
+
merge: [
|
|
398
|
+
...(partials[".gitignore"]?.merge ?? []),
|
|
399
|
+
await readFile(
|
|
400
|
+
join(context.env.templateDir, ".gitignore.template"),
|
|
401
|
+
"utf8"
|
|
402
|
+
),
|
|
403
|
+
...(answer.includes("eslint") ? ["\n# Cache\n.eslintcache\n"] : []),
|
|
404
|
+
],
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
return {
|
|
409
|
+
...context,
|
|
410
|
+
features: answer,
|
|
411
|
+
props,
|
|
412
|
+
files,
|
|
413
|
+
partials,
|
|
414
|
+
};
|
|
415
|
+
};
|
package/steps/host.mjs
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { input } from "@inquirer/prompts";
|
|
2
|
+
|
|
3
|
+
import { theme } from "../lib/theme.mjs";
|
|
4
|
+
|
|
5
|
+
export default async (context) => {
|
|
6
|
+
const host =
|
|
7
|
+
context.env.options.host ??
|
|
8
|
+
(!context.props.custom || context.env.hasOptions
|
|
9
|
+
? "localhost"
|
|
10
|
+
: await input(
|
|
11
|
+
{
|
|
12
|
+
message: "Hostname",
|
|
13
|
+
default: "localhost",
|
|
14
|
+
description: "The hostname to use for the server",
|
|
15
|
+
theme,
|
|
16
|
+
},
|
|
17
|
+
context
|
|
18
|
+
));
|
|
19
|
+
return {
|
|
20
|
+
...context,
|
|
21
|
+
props: {
|
|
22
|
+
...context.props,
|
|
23
|
+
host,
|
|
24
|
+
},
|
|
25
|
+
partials:
|
|
26
|
+
host !== "localhost"
|
|
27
|
+
? {
|
|
28
|
+
...context.partials,
|
|
29
|
+
"react-server.config.json": {
|
|
30
|
+
...context.partials["react-server.config.json"],
|
|
31
|
+
type: "json",
|
|
32
|
+
merge: [
|
|
33
|
+
...(context.partials["react-server.config.json"]?.merge ?? []),
|
|
34
|
+
{ server: { host } },
|
|
35
|
+
],
|
|
36
|
+
},
|
|
37
|
+
}
|
|
38
|
+
: context.partials,
|
|
39
|
+
};
|
|
40
|
+
};
|
package/steps/index.mjs
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import alias from "./alias.mjs";
|
|
2
|
+
// import authentication from "./authentication.mjs";
|
|
3
|
+
// import database from "./database.mjs";
|
|
4
|
+
import deploy, { prepare as prepareDeploy } from "./deploy.mjs";
|
|
5
|
+
import features from "./features.mjs";
|
|
6
|
+
import host from "./host.mjs";
|
|
7
|
+
// import integrations from "./integrations.mjs";
|
|
8
|
+
import name from "./name.mjs";
|
|
9
|
+
import packageManager from "./package.mjs";
|
|
10
|
+
import port from "./port.mjs";
|
|
11
|
+
// import stateManagement from "./state-management.mjs";
|
|
12
|
+
import preset, { prepare as preparePreset } from "./preset.mjs";
|
|
13
|
+
// import thirdParty from "./third-party.mjs";
|
|
14
|
+
// import ui from "./ui.mjs";
|
|
15
|
+
|
|
16
|
+
export default [
|
|
17
|
+
name,
|
|
18
|
+
preset,
|
|
19
|
+
features,
|
|
20
|
+
alias,
|
|
21
|
+
// thirdParty,
|
|
22
|
+
// ui,
|
|
23
|
+
// stateManagement,
|
|
24
|
+
// database,
|
|
25
|
+
// authentication,
|
|
26
|
+
// integrations,
|
|
27
|
+
host,
|
|
28
|
+
port,
|
|
29
|
+
preparePreset,
|
|
30
|
+
deploy,
|
|
31
|
+
packageManager,
|
|
32
|
+
prepareDeploy,
|
|
33
|
+
];
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { checkbox, Separator } from "@inquirer/prompts";
|
|
2
|
+
|
|
3
|
+
import { theme } from "../lib/theme.mjs";
|
|
4
|
+
|
|
5
|
+
export default [
|
|
6
|
+
(context) => context.props.thirdParty,
|
|
7
|
+
async (context) => {
|
|
8
|
+
const integrations = !context.props.custom
|
|
9
|
+
? []
|
|
10
|
+
: await checkbox(
|
|
11
|
+
{
|
|
12
|
+
message: "Integrations",
|
|
13
|
+
choices: [
|
|
14
|
+
{
|
|
15
|
+
name: "None",
|
|
16
|
+
value: "none",
|
|
17
|
+
description: "No integrations",
|
|
18
|
+
},
|
|
19
|
+
new Separator(),
|
|
20
|
+
{
|
|
21
|
+
name: "Vitest",
|
|
22
|
+
value: "vitest",
|
|
23
|
+
description: "Run unit tests using Vitest",
|
|
24
|
+
disabled: "(coming soon)",
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: "Playwright",
|
|
28
|
+
value: "playwright",
|
|
29
|
+
description: "Run browser tests using Playwright",
|
|
30
|
+
disabled: "(coming soon)",
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: "Storybook",
|
|
34
|
+
value: "storybook",
|
|
35
|
+
description: "Create a Storybook setup",
|
|
36
|
+
disabled: "(coming soon)",
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: "Paraglide",
|
|
40
|
+
value: "paraglide",
|
|
41
|
+
description: "Localization using Paraglide",
|
|
42
|
+
disabled: "(coming soon)",
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: "Stripe",
|
|
46
|
+
value: "stripe",
|
|
47
|
+
description: "Add Stripe integration",
|
|
48
|
+
disabled: "(coming soon)",
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: "LemonSqueezy",
|
|
52
|
+
value: "lemonsqueezy",
|
|
53
|
+
description: "Add LemonSqueezy integration",
|
|
54
|
+
disabled: "(coming soon)",
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: "Sentry",
|
|
58
|
+
value: "sentry",
|
|
59
|
+
description: "Add Sentry integration",
|
|
60
|
+
disabled: "(coming soon)",
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: "Vercel Analytics",
|
|
64
|
+
value: "vercel-analytics",
|
|
65
|
+
description: "Add Vercel Analytics integration",
|
|
66
|
+
disabled: "(coming soon)",
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
name: "Vercel Speed Insights",
|
|
70
|
+
value: "vercel-speed-insights",
|
|
71
|
+
description: "Add Vercel Speed Insights integration",
|
|
72
|
+
disabled: "(coming soon)",
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: "Vercel Flags",
|
|
76
|
+
value: "vercel-flags",
|
|
77
|
+
description: "Add Vercel Flags SDK integration",
|
|
78
|
+
disabled: "(coming soon)",
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: "Resend",
|
|
82
|
+
value: "resend",
|
|
83
|
+
description: "Add Resend + react-email integration",
|
|
84
|
+
disabled: "(coming soon)",
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: "GitHub Actions",
|
|
88
|
+
value: "github-actions",
|
|
89
|
+
description: "Add GitHub Actions for CI",
|
|
90
|
+
disabled: "(coming soon)",
|
|
91
|
+
},
|
|
92
|
+
new Separator(),
|
|
93
|
+
],
|
|
94
|
+
theme,
|
|
95
|
+
},
|
|
96
|
+
context
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
...context,
|
|
101
|
+
props: { ...context.props, integrations },
|
|
102
|
+
};
|
|
103
|
+
},
|
|
104
|
+
];
|
package/steps/name.mjs
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { statSync } from "node:fs";
|
|
2
|
+
import { join, relative } from "node:path";
|
|
3
|
+
|
|
4
|
+
import { input } from "@inquirer/prompts";
|
|
5
|
+
|
|
6
|
+
import { generateProjectName } from "../lib/generate-name.mjs";
|
|
7
|
+
import { theme } from "../lib/theme.mjs";
|
|
8
|
+
|
|
9
|
+
const cwd = process.cwd();
|
|
10
|
+
|
|
11
|
+
export default async (context) => {
|
|
12
|
+
const answer =
|
|
13
|
+
context.env.options.name ??
|
|
14
|
+
(await input(
|
|
15
|
+
{
|
|
16
|
+
message: "Project name",
|
|
17
|
+
default: generateProjectName(),
|
|
18
|
+
theme,
|
|
19
|
+
validate: async (value) => {
|
|
20
|
+
if (
|
|
21
|
+
!/^(?:(?:@(?:[a-z0-9-*~][a-z0-9-*._~]*)?\/[a-z0-9-._~])|[a-z0-9-~])[a-z0-9-._~]*$/.test(
|
|
22
|
+
value
|
|
23
|
+
)
|
|
24
|
+
) {
|
|
25
|
+
return "Invalid project name!";
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
if (statSync(join(cwd, value)).isDirectory()) {
|
|
29
|
+
return "Project already exists!";
|
|
30
|
+
}
|
|
31
|
+
} catch {
|
|
32
|
+
// no directory exists, so it's valid
|
|
33
|
+
}
|
|
34
|
+
return true;
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
context
|
|
38
|
+
));
|
|
39
|
+
|
|
40
|
+
const projectDir = join(cwd, answer);
|
|
41
|
+
if (relative(cwd, projectDir).startsWith("..")) {
|
|
42
|
+
throw "Project name cannot be outside the current directory";
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
...context,
|
|
47
|
+
interactive: !context.env.options.name,
|
|
48
|
+
env: {
|
|
49
|
+
...context.env,
|
|
50
|
+
projectDir,
|
|
51
|
+
},
|
|
52
|
+
props: {
|
|
53
|
+
...context.props,
|
|
54
|
+
projectName: answer,
|
|
55
|
+
},
|
|
56
|
+
partials: {
|
|
57
|
+
...context.partials,
|
|
58
|
+
"package.json": {
|
|
59
|
+
type: "json",
|
|
60
|
+
merge: [
|
|
61
|
+
{
|
|
62
|
+
name: answer,
|
|
63
|
+
},
|
|
64
|
+
...(context.partials["package.json"]?.merge ?? []),
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
};
|