@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
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Viktor LƔzƔr
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# @lazarv/create-react-server
|
|
2
|
+
|
|
3
|
+
To bootstrap your `@lazarv/react-server` project, you can also use `@lazarv/create-react-server`, the official CLI tool to create a new project and add initial tools, features and third-party integrations to your project with ease, just by answering a few questions. To use the tool, run:
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
npx @lazarv/create-react-server
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Completing the wizard, follow the instructions in your terminal to explore your new project and have fun!
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
Usage:
|
|
13
|
+
$ create-react-server [options]
|
|
14
|
+
|
|
15
|
+
Options:
|
|
16
|
+
--name <name> The name of the project
|
|
17
|
+
--preset <preset> The preset to use
|
|
18
|
+
--features <features> The features to use
|
|
19
|
+
--alias <alias> The TypeScript path alias to use
|
|
20
|
+
--host <host> The host to use
|
|
21
|
+
--port <port> The port to use
|
|
22
|
+
--deploy <deploy> The deployment adapter to use
|
|
23
|
+
--git Initialize a git repository
|
|
24
|
+
--dev Run in development mode
|
|
25
|
+
--open Open the project in the browser
|
|
26
|
+
--clean Clean the project directory before bootstrapping
|
|
27
|
+
--no-install Do not install dependencies (default: true)
|
|
28
|
+
--react-server <version> The version of @lazarv/react-server to use
|
|
29
|
+
-v, --version Display version number
|
|
30
|
+
-h, --help Display this message
|
|
31
|
+
```
|
package/generator.mjs
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { execSync, spawn } from "node:child_process";
|
|
2
|
+
import { statSync } from "node:fs";
|
|
3
|
+
import { cp, mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
4
|
+
import { extname, isAbsolute, join, relative } from "node:path";
|
|
5
|
+
|
|
6
|
+
import banner from "@lazarv/react-server/lib/utils/banner.mjs";
|
|
7
|
+
import merge from "@lazarv/react-server/lib/utils/merge.mjs";
|
|
8
|
+
import { filesize } from "filesize";
|
|
9
|
+
import colors from "picocolors";
|
|
10
|
+
|
|
11
|
+
import { mergeCodeFiles } from "./lib/code-merge.mjs";
|
|
12
|
+
import { format } from "./lib/formatter.mjs";
|
|
13
|
+
|
|
14
|
+
const extensionColor = {
|
|
15
|
+
".json": "magenta",
|
|
16
|
+
".css": "magenta",
|
|
17
|
+
".scss": "magenta",
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
function size(bytes) {
|
|
21
|
+
const s = filesize(bytes);
|
|
22
|
+
return " ".repeat(Math.max(0, 8 - s.length)) + s;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function logFileEmit(name, file, bytes, maxLength) {
|
|
26
|
+
const padding = " ".repeat(maxLength - file.length + 1);
|
|
27
|
+
console.log(
|
|
28
|
+
`${colors.gray(`${name}/${colors[extensionColor[extname(file)] ?? "cyan"](file.replace(/\\/g, "/"))}${padding} ${colors.bold(size(bytes))}`).replace(/^\/+/, "")}`
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const mergeFunctions = {
|
|
33
|
+
json: async (partials) => merge(...partials),
|
|
34
|
+
text: (partials) => partials.join("\n"),
|
|
35
|
+
code: (partials) => mergeCodeFiles(...partials),
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
function renderTemplate(template, context) {
|
|
39
|
+
return template.replace(/(?:\/\*)?<%=\s*([^\s]+)\s*%>(?:\*\/)?/g, (_, key) =>
|
|
40
|
+
key.split(".").reduce((acc, k) => acc?.[k] ?? "", context)
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export async function generate(context) {
|
|
45
|
+
const {
|
|
46
|
+
env: { logger },
|
|
47
|
+
} = context;
|
|
48
|
+
|
|
49
|
+
console.log();
|
|
50
|
+
banner("bootstrapping project");
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
if (statSync(context.env.projectDir).isDirectory()) {
|
|
54
|
+
if (context.env.options.clean) {
|
|
55
|
+
await rm(context.env.projectDir, { recursive: true });
|
|
56
|
+
} else {
|
|
57
|
+
logger.error(
|
|
58
|
+
`Directory ${colors.italic(relative(context.env.cwd, context.env.projectDir))} already exists!`
|
|
59
|
+
);
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
} catch {
|
|
64
|
+
// directory does not exist
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
await mkdir(context.env.projectDir, { recursive: true });
|
|
68
|
+
|
|
69
|
+
const maxLength = Math.max(
|
|
70
|
+
24,
|
|
71
|
+
...(context.files?.map((file) => file.length) ?? []),
|
|
72
|
+
...Object.keys(context.partials)
|
|
73
|
+
);
|
|
74
|
+
if (context.files?.length > 0) {
|
|
75
|
+
const { files } = context;
|
|
76
|
+
|
|
77
|
+
for (const file of files) {
|
|
78
|
+
const filename = relative(
|
|
79
|
+
context.env.projectDir,
|
|
80
|
+
Array.isArray(file) ? file[1] : file
|
|
81
|
+
);
|
|
82
|
+
if (context.partials[filename]) {
|
|
83
|
+
const partial = context.partials[filename];
|
|
84
|
+
if (partial.merge) {
|
|
85
|
+
const content = await readFile(
|
|
86
|
+
Array.isArray(file) ? file[0] : file,
|
|
87
|
+
"utf8"
|
|
88
|
+
);
|
|
89
|
+
partial.merge = [
|
|
90
|
+
...partial.merge,
|
|
91
|
+
partial.type === "json" ? JSON.parse(content) : content,
|
|
92
|
+
];
|
|
93
|
+
}
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
const [src, dest] = Array.isArray(file)
|
|
97
|
+
? file
|
|
98
|
+
: [
|
|
99
|
+
isAbsolute(file) ? file : join(context.env.templateAppDir, file),
|
|
100
|
+
join(
|
|
101
|
+
context.env.projectDir,
|
|
102
|
+
relative(context.env.templateDir, file)
|
|
103
|
+
),
|
|
104
|
+
];
|
|
105
|
+
logFileEmit(
|
|
106
|
+
context.props.projectName,
|
|
107
|
+
relative(context.env.projectDir, dest),
|
|
108
|
+
statSync(src).size,
|
|
109
|
+
maxLength
|
|
110
|
+
);
|
|
111
|
+
await cp(src, dest);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
for (const [file, partial] of Object.entries(context.partials)) {
|
|
116
|
+
if (partial.merge) {
|
|
117
|
+
partial.content = await mergeFunctions[partial.type](partial.merge);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (partial.template) {
|
|
121
|
+
partial.content = renderTemplate(partial.template, context);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (partial.type === "json") {
|
|
125
|
+
partial.content = `${JSON.stringify(partial.content, null, 2)}\n`;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const content =
|
|
129
|
+
partial.type === "json"
|
|
130
|
+
? await format(partial.content, "json")
|
|
131
|
+
: partial.format
|
|
132
|
+
? await format(
|
|
133
|
+
partial.content,
|
|
134
|
+
typeof partial.format === "string" ? partial.format : "js"
|
|
135
|
+
)
|
|
136
|
+
: partial.content;
|
|
137
|
+
logFileEmit(context.props.projectName, file, content.length, maxLength);
|
|
138
|
+
await writeFile(join(context.env.projectDir, file), content, "utf8");
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
console.log();
|
|
142
|
+
|
|
143
|
+
if (
|
|
144
|
+
context.env.options.git ||
|
|
145
|
+
(context.features.includes("git") && context.env.options.git !== false)
|
|
146
|
+
) {
|
|
147
|
+
logger.info("Initializing git repository šļø");
|
|
148
|
+
execSync("git init", { cwd: context.env.projectDir, stdio: "ignore" });
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (
|
|
152
|
+
context.props.packageManager &&
|
|
153
|
+
context.env.options.install !== false &&
|
|
154
|
+
context.props.packageManager.install !== false &&
|
|
155
|
+
(!context.props.custom ||
|
|
156
|
+
(context.props.custom && context.props.packageManager.install !== false))
|
|
157
|
+
) {
|
|
158
|
+
logger.info(
|
|
159
|
+
`Installing dependencies using ${context.props.packageManager.name} š¦`
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
await new Promise((resolve, reject) => {
|
|
163
|
+
const child = spawn(
|
|
164
|
+
context.props.packageManager.name,
|
|
165
|
+
["install", ...context.props.packageManager.ciInstallArgs.split(" ")],
|
|
166
|
+
{
|
|
167
|
+
cwd: context.env.projectDir,
|
|
168
|
+
encoding: "utf8",
|
|
169
|
+
stdio: ["inherit", "pipe", "pipe"],
|
|
170
|
+
env: { ...process.env, NPM_CONFIG_COLOR: "always", CI: "1" },
|
|
171
|
+
}
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
child.stdout.on("data", (data) => {
|
|
175
|
+
process.stdout.write(colors.gray(data));
|
|
176
|
+
});
|
|
177
|
+
child.stderr.on("data", (data) => {
|
|
178
|
+
process.stdout.write(colors.gray(data));
|
|
179
|
+
});
|
|
180
|
+
child.on("close", (code) => {
|
|
181
|
+
if (code === 0) {
|
|
182
|
+
resolve(code);
|
|
183
|
+
} else {
|
|
184
|
+
reject(new Error(`Process exited with code ${code}`));
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
console.log();
|
|
190
|
+
logger.info("Ready to launch your project! š");
|
|
191
|
+
} else {
|
|
192
|
+
logger.warn("You need to install dependencies to start your project!");
|
|
193
|
+
context.props.installInstructions = true;
|
|
194
|
+
}
|
|
195
|
+
}
|
package/globals.d.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
interface VitePlugin {
|
|
2
|
+
(): {
|
|
3
|
+
name: string;
|
|
4
|
+
};
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
declare module "vite" {
|
|
8
|
+
export interface UserConfig {
|
|
9
|
+
resolve?: {
|
|
10
|
+
alias?: Record<string, string>;
|
|
11
|
+
};
|
|
12
|
+
plugins?: VitePlugin[];
|
|
13
|
+
css?: {
|
|
14
|
+
transformer?: string;
|
|
15
|
+
lightningcss?: {
|
|
16
|
+
targets?: Record<string, string>;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
build?: {
|
|
20
|
+
cssMinify?: string;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export function defineConfig(config: UserConfig): UserConfig;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
declare namespace global {
|
|
27
|
+
interface ImportMeta {
|
|
28
|
+
readonly url: URL;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
declare module "@vitejs/plugin-react" {
|
|
33
|
+
export default function reactPlugin(options: {
|
|
34
|
+
babel?: {
|
|
35
|
+
plugins: [
|
|
36
|
+
[
|
|
37
|
+
"babel-plugin-react-compiler",
|
|
38
|
+
{
|
|
39
|
+
compilationMode: "annotation";
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
];
|
|
43
|
+
};
|
|
44
|
+
}): VitePlugin;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
declare module "@vitejs/plugin-react-swc" {
|
|
48
|
+
export default function reactSwcPlugin(): VitePlugin;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
declare module "browserslist" {
|
|
52
|
+
export default function browserslist(query: string): string[];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
declare module "lightningcss" {
|
|
56
|
+
export function browserslistToTargets(
|
|
57
|
+
browsers: string[]
|
|
58
|
+
): Record<string, string>;
|
|
59
|
+
}
|
package/index.mjs
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
experimentalWarningSilence,
|
|
5
|
+
suppressReactWarnings,
|
|
6
|
+
} from "@lazarv/react-server/lib/sys.mjs";
|
|
7
|
+
|
|
8
|
+
experimentalWarningSilence();
|
|
9
|
+
suppressReactWarnings();
|
|
10
|
+
|
|
11
|
+
import { dirname, join } from "node:path";
|
|
12
|
+
import { fileURLToPath } from "node:url";
|
|
13
|
+
|
|
14
|
+
import createLogger from "@lazarv/react-server/lib/dev/create-logger.mjs";
|
|
15
|
+
import cac from "cac";
|
|
16
|
+
|
|
17
|
+
const cli = cac();
|
|
18
|
+
|
|
19
|
+
const { default: packageJson } = await import("./package.json", {
|
|
20
|
+
with: { type: "json" },
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
cli.usage("[options]");
|
|
24
|
+
|
|
25
|
+
cli
|
|
26
|
+
.option("--name <name>", "The name of the project")
|
|
27
|
+
.option("--preset <preset>", "The preset to use")
|
|
28
|
+
.option("--features <features>", "The features to use")
|
|
29
|
+
.option("--alias <alias>", "The TypeScript path alias to use")
|
|
30
|
+
.option("--host <host>", "The host to use")
|
|
31
|
+
.option("--port <port>", "The port to use")
|
|
32
|
+
.option("--deploy <deploy>", "The deployment adapter to use")
|
|
33
|
+
.option("--git", "Initialize a git repository")
|
|
34
|
+
.option("--dev", "Run in development mode")
|
|
35
|
+
.option("--open", "Open the project in the browser")
|
|
36
|
+
.option("--clean", "Clean the project directory before bootstrapping")
|
|
37
|
+
.option("--no-install", "Do not install dependencies")
|
|
38
|
+
.option(
|
|
39
|
+
"--react-server <version>",
|
|
40
|
+
"The version of @lazarv/react-server to use"
|
|
41
|
+
)
|
|
42
|
+
.version(packageJson.version);
|
|
43
|
+
|
|
44
|
+
cli.name = packageJson.name.split("/").pop();
|
|
45
|
+
cli.help();
|
|
46
|
+
|
|
47
|
+
const { options } = cli.parse();
|
|
48
|
+
const {
|
|
49
|
+
help,
|
|
50
|
+
v: version,
|
|
51
|
+
reactServer,
|
|
52
|
+
install,
|
|
53
|
+
// eslint-disable-next-line no-unused-vars
|
|
54
|
+
"--": _,
|
|
55
|
+
...createOptions
|
|
56
|
+
} = options;
|
|
57
|
+
const hasOptions = Object.keys(createOptions).length > 1 || install === false;
|
|
58
|
+
createOptions.install = install;
|
|
59
|
+
|
|
60
|
+
if (help || version) {
|
|
61
|
+
process.exit(0);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
await import("./logo.mjs");
|
|
65
|
+
|
|
66
|
+
const logger = createLogger();
|
|
67
|
+
|
|
68
|
+
const cwd = process.cwd();
|
|
69
|
+
const templateDir = join(dirname(fileURLToPath(import.meta.url)), "templates");
|
|
70
|
+
|
|
71
|
+
const [{ wizard }, { generate }, { launch }] = await Promise.all([
|
|
72
|
+
import("./wizard.mjs"),
|
|
73
|
+
import("./generator.mjs"),
|
|
74
|
+
import("./launch.mjs"),
|
|
75
|
+
]);
|
|
76
|
+
|
|
77
|
+
const context = await wizard({
|
|
78
|
+
cwd,
|
|
79
|
+
logger,
|
|
80
|
+
templateDir,
|
|
81
|
+
hasOptions,
|
|
82
|
+
options: createOptions,
|
|
83
|
+
reactServer,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
await generate(context);
|
|
87
|
+
await launch(context);
|
package/launch.mjs
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { relative } from "node:path";
|
|
3
|
+
|
|
4
|
+
import { confirm } from "@inquirer/prompts";
|
|
5
|
+
import colors from "picocolors";
|
|
6
|
+
|
|
7
|
+
import { theme } from "./lib/theme.mjs";
|
|
8
|
+
|
|
9
|
+
export async function launch(context) {
|
|
10
|
+
const {
|
|
11
|
+
env: { cwd, logger, projectDir },
|
|
12
|
+
props: {
|
|
13
|
+
packageManager: { name: packageManager },
|
|
14
|
+
adapter,
|
|
15
|
+
projectName,
|
|
16
|
+
port,
|
|
17
|
+
},
|
|
18
|
+
} = context;
|
|
19
|
+
|
|
20
|
+
const launchInDev =
|
|
21
|
+
context.env.options.install !== false &&
|
|
22
|
+
context.props.packageManager.install !== false &&
|
|
23
|
+
(context.env.options.dev ??
|
|
24
|
+
(context.env.hasOptions
|
|
25
|
+
? false
|
|
26
|
+
: await confirm({
|
|
27
|
+
message: "Launch in development mode?",
|
|
28
|
+
theme,
|
|
29
|
+
})));
|
|
30
|
+
|
|
31
|
+
const devCommand = {
|
|
32
|
+
npm: "npm run dev",
|
|
33
|
+
pnpm: "pnpm dev",
|
|
34
|
+
yarn: "yarn dev",
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const buildCommand = {
|
|
38
|
+
npm: "npm run build",
|
|
39
|
+
pnpm: "pnpm build",
|
|
40
|
+
yarn: "yarn build",
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const startCommand = {
|
|
44
|
+
npm: "npm start",
|
|
45
|
+
pnpm: "pnpm start",
|
|
46
|
+
yarn: "yarn start",
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const instructions = () => {
|
|
50
|
+
console.log(`\nš You can launch your project later by changing into the project directory by running:
|
|
51
|
+
${colors.cyan(`cd ${relative(cwd, projectDir)}`)}
|
|
52
|
+
|
|
53
|
+
${
|
|
54
|
+
context.props.installInstructions
|
|
55
|
+
? `š¦ To install dependencies, run:
|
|
56
|
+
${colors.cyan(`${context.props.packageManager.name} install`)}
|
|
57
|
+
|
|
58
|
+
`
|
|
59
|
+
: ""
|
|
60
|
+
}Then choose from the following commands.
|
|
61
|
+
|
|
62
|
+
š§ To launch the project in development mode, run:
|
|
63
|
+
${colors.cyan(devCommand[packageManager])}
|
|
64
|
+
|
|
65
|
+
š§ To build the project for production, run:
|
|
66
|
+
${colors.cyan(buildCommand[packageManager])}
|
|
67
|
+
|
|
68
|
+
š To start the production server, run:
|
|
69
|
+
${colors.cyan(startCommand[packageManager])}
|
|
70
|
+
${
|
|
71
|
+
adapter === "docker"
|
|
72
|
+
? `\nš³ To build a Docker image and start your application in a Docker container, run:
|
|
73
|
+
${colors.cyan(`docker build -t ${projectName} .`)}
|
|
74
|
+
${colors.cyan(`docker run --rm -ti -p ${port}:${port} ${projectName}`)}\n`
|
|
75
|
+
: ""
|
|
76
|
+
}
|
|
77
|
+
š Thanks for choosing ${colors.bold("@lazarv/react-server")}!
|
|
78
|
+
š Check out the documentation at ${colors.underline("https://react-server.dev")}
|
|
79
|
+
š» Happy coding!
|
|
80
|
+
`);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
if (launchInDev) {
|
|
84
|
+
process.chdir(projectDir);
|
|
85
|
+
const server = spawn(
|
|
86
|
+
packageManager,
|
|
87
|
+
[
|
|
88
|
+
...(packageManager === "npm" ? ["run"] : []),
|
|
89
|
+
"dev",
|
|
90
|
+
...(packageManager === "pnpm" ? [] : ["--"]),
|
|
91
|
+
"--host",
|
|
92
|
+
context.props.host,
|
|
93
|
+
"--port",
|
|
94
|
+
context.props.port,
|
|
95
|
+
...(context.env.options.open || !context.props.custom
|
|
96
|
+
? ["--open"]
|
|
97
|
+
: []),
|
|
98
|
+
],
|
|
99
|
+
{
|
|
100
|
+
cwd: projectDir,
|
|
101
|
+
stdio: ["inherit", "pipe", "pipe"],
|
|
102
|
+
shell: true,
|
|
103
|
+
env: {
|
|
104
|
+
...process.env,
|
|
105
|
+
NODE_ENV: "development",
|
|
106
|
+
NO_REACT_SERVER_LOGO: "true",
|
|
107
|
+
FORCE_COLOR: process.env.NO_COLOR ? undefined : "true",
|
|
108
|
+
},
|
|
109
|
+
}
|
|
110
|
+
);
|
|
111
|
+
server.stdout.on("data", (data) => {
|
|
112
|
+
let out = data;
|
|
113
|
+
const message = data.toString();
|
|
114
|
+
const lines = message.split("\n");
|
|
115
|
+
if (lines.length > 1) {
|
|
116
|
+
out = lines.filter((line) => !line.startsWith("> ")).join("\n");
|
|
117
|
+
out = out.replace(/\n\n/g, "\n");
|
|
118
|
+
}
|
|
119
|
+
process.stdout.write(out);
|
|
120
|
+
});
|
|
121
|
+
server.stderr.on("data", (data) => {
|
|
122
|
+
process.stderr.write(data);
|
|
123
|
+
});
|
|
124
|
+
server.on("error", (error) => {
|
|
125
|
+
logger.error(error);
|
|
126
|
+
process.exit(1);
|
|
127
|
+
});
|
|
128
|
+
server.on("close", () => {
|
|
129
|
+
process.chdir(cwd);
|
|
130
|
+
instructions();
|
|
131
|
+
process.exit(server.status);
|
|
132
|
+
});
|
|
133
|
+
} else {
|
|
134
|
+
instructions();
|
|
135
|
+
}
|
|
136
|
+
}
|