create-vitnode-app 1.2.0-canary.52 → 1.2.0-canary.53
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 +1 -1
- package/copy-of-vitnode-app/.vscode/settings.json +29 -0
- package/copy-of-vitnode-app/api/drizzle.config.ts +4 -4
- package/copy-of-vitnode-app/api/src/index.ts +7 -7
- package/copy-of-vitnode-app/api/src/vitnode.api.config.ts +8 -9
- package/copy-of-vitnode-app/api/tsconfig.json +1 -1
- package/copy-of-vitnode-app/api-bun/src/index.ts +4 -4
- package/copy-of-vitnode-app/api-single-app/drizzle.config.ts +4 -4
- package/copy-of-vitnode-app/api-single-app/src/app/api/[...route]/route.ts +5 -5
- package/copy-of-vitnode-app/api-single-app/src/vitnode.api.config.ts +6 -7
- package/copy-of-vitnode-app/biome/biome.json +5 -0
- package/copy-of-vitnode-app/monorepo/turbo.json +0 -6
- package/copy-of-vitnode-app/root/global.d.ts +2 -2
- package/copy-of-vitnode-app/root/next.config.ts +2 -2
- package/copy-of-vitnode-app/root/postcss.config.mjs +1 -1
- package/copy-of-vitnode-app/root/src/app/[locale]/(main)/[...rest]/page.tsx +1 -1
- package/copy-of-vitnode-app/root/src/app/[locale]/(main)/layout.tsx +3 -3
- package/copy-of-vitnode-app/root/src/app/[locale]/(main)/not-found.tsx +1 -1
- package/copy-of-vitnode-app/root/src/app/[locale]/(main)/page.tsx +11 -10
- package/copy-of-vitnode-app/root/src/app/[locale]/admin/(auth)/layout.tsx +2 -2
- package/copy-of-vitnode-app/root/src/app/[locale]/admin/page.tsx +1 -1
- package/copy-of-vitnode-app/root/src/app/[locale]/layout.tsx +9 -10
- package/copy-of-vitnode-app/root/src/app/global-error.tsx +8 -11
- package/copy-of-vitnode-app/root/src/app/global.css +3 -2
- package/copy-of-vitnode-app/root/src/app/layout.tsx +2 -2
- package/copy-of-vitnode-app/root/src/middleware.ts +5 -5
- package/copy-of-vitnode-app/root/src/vitnode.config.ts +8 -8
- package/copy-of-vitnode-app/root/tsconfig.json +1 -1
- package/dist/src/create/create-package-json.js +192 -201
- package/dist/src/create/create-vitnode.js +73 -73
- package/dist/src/helpers/get-available-package-managers.js +6 -6
- package/dist/src/helpers/get-package-json.js +2 -2
- package/dist/src/helpers/init-vitnode.js +7 -7
- package/dist/src/helpers/install-dependencies.js +35 -32
- package/dist/src/helpers/is-folder-empty.js +25 -26
- package/dist/src/helpers/is-online.js +16 -16
- package/dist/src/helpers/is-writeable.js +2 -2
- package/dist/src/helpers/validate-pkg.js +1 -1
- package/dist/src/index.js +28 -28
- package/dist/src/plugin/index.js +5 -5
- package/dist/src/prepare/prepare.js +5 -5
- package/dist/src/questions.js +29 -30
- package/dist/src/validation.js +15 -15
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -6
- package/copy-of-vitnode-app/eslint/.prettierrc.mjs +0 -11
- package/copy-of-vitnode-app/eslint/eslint.config.mjs +0 -17
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import { existsSync } from
|
|
2
|
-
import { copyFile, cp, mkdir, readFile, rename, writeFile } from
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import { generateMigrationsVitnode, initFilesVitnode, } from
|
|
8
|
-
import { installDependencies } from
|
|
9
|
-
import { isFolderEmpty } from
|
|
10
|
-
import { createPackageJSON } from
|
|
11
|
-
export const createVitNode = async ({ root, appName, packageManager,
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { copyFile, cp, mkdir, readFile, rename, writeFile, } from "node:fs/promises";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import ora from "ora";
|
|
6
|
+
import color from "picocolors";
|
|
7
|
+
import { generateMigrationsVitnode, initFilesVitnode, } from "../helpers/init-vitnode.js";
|
|
8
|
+
import { installDependencies } from "../helpers/install-dependencies.js";
|
|
9
|
+
import { isFolderEmpty } from "../helpers/is-folder-empty.js";
|
|
10
|
+
import { createPackageJSON } from "./create-package-json.js";
|
|
11
|
+
export const createVitNode = async ({ root, appName, packageManager, biome, install, docker, mode, monorepo, }) => {
|
|
12
12
|
const spinner = ora(`Creating a new VitNode app in ${color.green(root)}. Using ${color.green(packageManager)}...`).start();
|
|
13
13
|
const __filename = fileURLToPath(import.meta.url);
|
|
14
14
|
const __dirname = dirname(__filename);
|
|
15
|
-
const templatePath = join(__dirname,
|
|
15
|
+
const templatePath = join(__dirname, "..", "..", "..", "copy-of-vitnode-app");
|
|
16
16
|
if (!existsSync(templatePath)) {
|
|
17
|
-
spinner.fail(`\n${color.red(
|
|
17
|
+
spinner.fail(`\n${color.red("Error!")} Template path ${color.cyan(templatePath)} does not exist.`);
|
|
18
18
|
process.exit(1);
|
|
19
19
|
}
|
|
20
20
|
await mkdir(root, { recursive: true });
|
|
@@ -22,137 +22,137 @@ export const createVitNode = async ({ root, appName, packageManager, eslint, ins
|
|
|
22
22
|
process.exit(1);
|
|
23
23
|
}
|
|
24
24
|
const monorepoStructure = {
|
|
25
|
-
api: join(root,
|
|
26
|
-
web: join(root,
|
|
25
|
+
api: join(root, "apps", "api"),
|
|
26
|
+
web: join(root, "apps", "web"),
|
|
27
27
|
};
|
|
28
|
-
spinner.text =
|
|
29
|
-
if (monorepo || mode ===
|
|
28
|
+
spinner.text = "Preparing the project structure...";
|
|
29
|
+
if (monorepo || mode === "apiMonorepo") {
|
|
30
30
|
const dirsToCreate = [];
|
|
31
|
-
if (mode ===
|
|
31
|
+
if (mode === "apiMonorepo" || (monorepo && mode === "onlyApi")) {
|
|
32
32
|
dirsToCreate.push(monorepoStructure.api);
|
|
33
33
|
}
|
|
34
|
-
if (mode ===
|
|
34
|
+
if (mode === "apiMonorepo" || (monorepo && mode === "singleApp")) {
|
|
35
35
|
dirsToCreate.push(monorepoStructure.web);
|
|
36
36
|
}
|
|
37
37
|
await Promise.all(dirsToCreate.map(async (dir) => mkdir(dir, { recursive: true })));
|
|
38
38
|
}
|
|
39
|
-
spinner.text =
|
|
40
|
-
await cp(join(templatePath,
|
|
39
|
+
spinner.text = "Copying files...";
|
|
40
|
+
await cp(join(templatePath, ".vscode"), join(root, ".vscode"), {
|
|
41
41
|
recursive: true,
|
|
42
42
|
});
|
|
43
|
-
if (mode ===
|
|
43
|
+
if (mode === "singleApp") {
|
|
44
44
|
await Promise.all([
|
|
45
|
-
cp(join(templatePath,
|
|
45
|
+
cp(join(templatePath, "root"), monorepo ? monorepoStructure.web : root, {
|
|
46
46
|
recursive: true,
|
|
47
47
|
}),
|
|
48
|
-
cp(join(templatePath,
|
|
48
|
+
cp(join(templatePath, "api-single-app"), monorepo ? monorepoStructure.web : root, {
|
|
49
49
|
recursive: true,
|
|
50
50
|
}),
|
|
51
51
|
]);
|
|
52
52
|
}
|
|
53
|
-
else if (mode ===
|
|
53
|
+
else if (mode === "apiMonorepo") {
|
|
54
54
|
await Promise.all([
|
|
55
|
-
cp(join(templatePath,
|
|
55
|
+
cp(join(templatePath, "root"), monorepoStructure.web, {
|
|
56
56
|
recursive: true,
|
|
57
57
|
}),
|
|
58
|
-
cp(join(templatePath,
|
|
58
|
+
cp(join(templatePath, "api"), monorepoStructure.api, {
|
|
59
59
|
recursive: true,
|
|
60
60
|
}),
|
|
61
61
|
]);
|
|
62
|
-
if (packageManager ===
|
|
63
|
-
await cp(join(templatePath,
|
|
62
|
+
if (packageManager === "bun") {
|
|
63
|
+
await cp(join(templatePath, "api-bun"), monorepoStructure.api, {
|
|
64
64
|
recursive: true,
|
|
65
65
|
});
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
|
-
else if (mode ===
|
|
69
|
-
await cp(join(templatePath,
|
|
68
|
+
else if (mode === "onlyApi") {
|
|
69
|
+
await cp(join(templatePath, "api"), monorepo ? monorepoStructure.api : root, {
|
|
70
70
|
recursive: true,
|
|
71
71
|
});
|
|
72
|
-
if (packageManager ===
|
|
73
|
-
await cp(join(templatePath,
|
|
72
|
+
if (packageManager === "bun") {
|
|
73
|
+
await cp(join(templatePath, "api-bun"), monorepo ? monorepoStructure.api : root, {
|
|
74
74
|
recursive: true,
|
|
75
75
|
});
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
|
-
if (mode ===
|
|
79
|
-
await cp(join(templatePath,
|
|
78
|
+
if (mode === "apiMonorepo" || monorepo) {
|
|
79
|
+
await cp(join(templatePath, "monorepo"), root, {
|
|
80
80
|
recursive: true,
|
|
81
81
|
});
|
|
82
82
|
}
|
|
83
|
-
if (
|
|
84
|
-
spinner.text =
|
|
85
|
-
await cp(join(templatePath,
|
|
83
|
+
if (biome) {
|
|
84
|
+
spinner.text = "Copying Biome files...";
|
|
85
|
+
await cp(join(templatePath, "biome"), root, {
|
|
86
86
|
recursive: true,
|
|
87
87
|
});
|
|
88
88
|
}
|
|
89
|
-
spinner.text =
|
|
90
|
-
await rename(join(root,
|
|
91
|
-
if (mode ===
|
|
92
|
-
if (existsSync(join(monorepoStructure.api,
|
|
93
|
-
await rename(join(monorepoStructure.api,
|
|
89
|
+
spinner.text = "Renaming special files...";
|
|
90
|
+
await rename(join(root, ".gitignore_template"), join(root, ".gitignore"));
|
|
91
|
+
if (mode === "apiMonorepo" || monorepo) {
|
|
92
|
+
if (existsSync(join(monorepoStructure.api, ".gitignore_template"))) {
|
|
93
|
+
await rename(join(monorepoStructure.api, ".gitignore_template"), join(monorepoStructure.api, ".gitignore"));
|
|
94
94
|
}
|
|
95
|
-
if (existsSync(join(monorepoStructure.web,
|
|
96
|
-
await rename(join(monorepoStructure.web,
|
|
95
|
+
if (existsSync(join(monorepoStructure.web, ".gitignore_template"))) {
|
|
96
|
+
await rename(join(monorepoStructure.web, ".gitignore_template"), join(monorepoStructure.web, ".gitignore"));
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
|
-
spinner.text =
|
|
99
|
+
spinner.text = "Creating package.json...";
|
|
100
100
|
await createPackageJSON({
|
|
101
101
|
root,
|
|
102
102
|
appName,
|
|
103
103
|
packageManager,
|
|
104
|
-
|
|
104
|
+
biome,
|
|
105
105
|
docker,
|
|
106
106
|
mode,
|
|
107
107
|
monorepo,
|
|
108
108
|
});
|
|
109
|
-
if ((mode ===
|
|
110
|
-
spinner.text =
|
|
109
|
+
if ((mode === "apiMonorepo" || monorepo) && packageManager === "pnpm") {
|
|
110
|
+
spinner.text = "Creating pnpm-workspace.yaml...";
|
|
111
111
|
const pnpmWorkspaceContent = `packages:\n - 'apps/*'\n - 'plugins/*'\n`;
|
|
112
|
-
await writeFile(join(root,
|
|
112
|
+
await writeFile(join(root, "pnpm-workspace.yaml"), pnpmWorkspaceContent);
|
|
113
113
|
}
|
|
114
114
|
if (docker) {
|
|
115
|
-
spinner.text =
|
|
116
|
-
await copyFile(join(templatePath,
|
|
117
|
-
const dockerComposePath = join(root,
|
|
118
|
-
const dockerComposeContent = await readFile(dockerComposePath,
|
|
115
|
+
spinner.text = "Copying docker files...";
|
|
116
|
+
await copyFile(join(templatePath, "docker", "docker-compose.yml"), join(root, "docker-compose.yml"));
|
|
117
|
+
const dockerComposePath = join(root, "docker-compose.yml");
|
|
118
|
+
const dockerComposeContent = await readFile(dockerComposePath, "utf-8");
|
|
119
119
|
const updatedContent = dockerComposeContent.replace(/vitnode_postgres_dev/g, `${appName}_vitnode_postgres_dev`);
|
|
120
120
|
await writeFile(dockerComposePath, updatedContent);
|
|
121
121
|
}
|
|
122
|
-
spinner.text =
|
|
123
|
-
if ((mode ===
|
|
124
|
-
packageManager !==
|
|
125
|
-
mode !==
|
|
126
|
-
const globalCssPath = join(monorepoStructure.web,
|
|
127
|
-
const globalCssContent = await readFile(globalCssPath,
|
|
122
|
+
spinner.text = "Updating VitNode paths...";
|
|
123
|
+
if ((mode === "apiMonorepo" || monorepo) &&
|
|
124
|
+
packageManager !== "pnpm" &&
|
|
125
|
+
mode !== "onlyApi") {
|
|
126
|
+
const globalCssPath = join(monorepoStructure.web, "src", "app", "global.css");
|
|
127
|
+
const globalCssContent = await readFile(globalCssPath, "utf-8");
|
|
128
128
|
const updatedGlobalCssContent = globalCssContent.replaceAll('@source "../../node_modules/@vitnode/', '@source "../../../../node_modules/@vitnode/');
|
|
129
129
|
await writeFile(globalCssPath, updatedGlobalCssContent);
|
|
130
130
|
}
|
|
131
|
-
if (mode ===
|
|
132
|
-
spinner.text =
|
|
133
|
-
const envExamplePath = join(monorepoStructure.web,
|
|
131
|
+
if (mode === "apiMonorepo") {
|
|
132
|
+
spinner.text = "Setting up environment variables...";
|
|
133
|
+
const envExamplePath = join(monorepoStructure.web, ".env.example");
|
|
134
134
|
if (existsSync(envExamplePath)) {
|
|
135
|
-
await rename(envExamplePath, join(monorepoStructure.web,
|
|
135
|
+
await rename(envExamplePath, join(monorepoStructure.web, ".env"));
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
138
|
if (install) {
|
|
139
|
-
spinner.text =
|
|
139
|
+
spinner.text = "Installing dependencies...";
|
|
140
140
|
await installDependencies({
|
|
141
141
|
packageManager,
|
|
142
142
|
cwd: root,
|
|
143
143
|
});
|
|
144
|
-
spinner.text =
|
|
145
|
-
if (mode ===
|
|
144
|
+
spinner.text = "Initializing VitNode files...";
|
|
145
|
+
if (mode === "apiMonorepo") {
|
|
146
146
|
await Promise.all([
|
|
147
147
|
initFilesVitnode({
|
|
148
148
|
packageManager,
|
|
149
149
|
cwd: monorepoStructure.web,
|
|
150
|
-
flag:
|
|
150
|
+
flag: "web",
|
|
151
151
|
}),
|
|
152
152
|
initFilesVitnode({
|
|
153
153
|
packageManager,
|
|
154
154
|
cwd: monorepoStructure.api,
|
|
155
|
-
flag:
|
|
155
|
+
flag: "api",
|
|
156
156
|
}),
|
|
157
157
|
initFilesVitnode({
|
|
158
158
|
packageManager,
|
|
@@ -166,12 +166,12 @@ export const createVitNode = async ({ root, appName, packageManager, eslint, ins
|
|
|
166
166
|
cwd: root,
|
|
167
167
|
});
|
|
168
168
|
}
|
|
169
|
-
spinner.text =
|
|
169
|
+
spinner.text = "Generating migrations...";
|
|
170
170
|
let migrationsCwd;
|
|
171
|
-
if (mode ===
|
|
171
|
+
if (mode === "apiMonorepo" || (monorepo && mode !== "singleApp")) {
|
|
172
172
|
migrationsCwd = monorepoStructure.api;
|
|
173
173
|
}
|
|
174
|
-
else if (mode ===
|
|
174
|
+
else if (mode === "singleApp" && monorepo) {
|
|
175
175
|
migrationsCwd = monorepoStructure.web;
|
|
176
176
|
}
|
|
177
177
|
else {
|
|
@@ -182,5 +182,5 @@ export const createVitNode = async ({ root, appName, packageManager, eslint, ins
|
|
|
182
182
|
cwd: migrationsCwd,
|
|
183
183
|
});
|
|
184
184
|
}
|
|
185
|
-
spinner.succeed(`${color.green(
|
|
185
|
+
spinner.succeed(`${color.green("Success!")} Created ${color.cyan(appName)} at ${color.cyan(root)}`);
|
|
186
186
|
};
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import { exec } from
|
|
1
|
+
import { exec } from "node:child_process";
|
|
2
2
|
export const execShellCommand = async (cmd) => {
|
|
3
|
-
return new Promise(resolve => {
|
|
3
|
+
return await new Promise(resolve => {
|
|
4
4
|
exec(cmd, (error, stdout, stderr) => {
|
|
5
5
|
if (error) {
|
|
6
6
|
resolve(undefined);
|
|
7
7
|
}
|
|
8
8
|
const result = stdout ? stdout : stderr;
|
|
9
|
-
resolve(result.replace(/\s+/g,
|
|
9
|
+
resolve(result.replace(/\s+/g, ""));
|
|
10
10
|
});
|
|
11
11
|
});
|
|
12
12
|
};
|
|
13
13
|
export const getAvailablePackageManagers = async () => {
|
|
14
14
|
const [npm, pnpm, bun] = await Promise.all([
|
|
15
|
-
execShellCommand(
|
|
16
|
-
execShellCommand(
|
|
17
|
-
execShellCommand(
|
|
15
|
+
execShellCommand("npm --version"),
|
|
16
|
+
execShellCommand("pnpm --version"),
|
|
17
|
+
execShellCommand("bun --version"),
|
|
18
18
|
]);
|
|
19
19
|
return {
|
|
20
20
|
pnpm,
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { readFileSync } from
|
|
2
|
-
export const packageJson = JSON.parse(readFileSync(new URL(
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
export const packageJson = JSON.parse(readFileSync(new URL("../../../package.json", import.meta.url), "utf-8"));
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { spawn } from
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
2
|
export const initFilesVitnode = ({ packageManager: pm, cwd, flag, }) => {
|
|
3
|
-
const packageManager = pm.split(
|
|
3
|
+
const packageManager = pm.split("@")[0];
|
|
4
4
|
const args = [
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
flag ? `--${flag}` :
|
|
5
|
+
"vitnode",
|
|
6
|
+
"prepare-plugins",
|
|
7
|
+
flag ? `--${flag}` : "",
|
|
8
8
|
];
|
|
9
9
|
spawn(packageManager, args, {
|
|
10
10
|
cwd,
|
|
@@ -12,8 +12,8 @@ export const initFilesVitnode = ({ packageManager: pm, cwd, flag, }) => {
|
|
|
12
12
|
});
|
|
13
13
|
};
|
|
14
14
|
export const generateMigrationsVitnode = ({ packageManager: pm, cwd, }) => {
|
|
15
|
-
const packageManager = pm.split(
|
|
16
|
-
const args = [
|
|
15
|
+
const packageManager = pm.split("@")[0];
|
|
16
|
+
const args = ["vitnode", "migrate", "--generate"];
|
|
17
17
|
spawn(packageManager, args, {
|
|
18
18
|
cwd,
|
|
19
19
|
shell: true,
|
|
@@ -1,66 +1,69 @@
|
|
|
1
|
-
import { spawn } from
|
|
2
|
-
import color from
|
|
3
|
-
import { getOnline } from
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import color from "picocolors";
|
|
3
|
+
import { getOnline } from "./is-online.js";
|
|
4
|
+
function printInstallErrorSuggestions(stderr, color) {
|
|
5
|
+
if (stderr.includes("ENOTFOUND") || stderr.includes("network")) {
|
|
6
|
+
console.error(color.yellow("💡 Network error detected. Please check your internet connection."));
|
|
7
|
+
}
|
|
8
|
+
else if (stderr.includes("EACCES") ||
|
|
9
|
+
stderr.includes("permission denied")) {
|
|
10
|
+
console.error(color.yellow("💡 Permission error detected. Try running with elevated privileges or check file permissions."));
|
|
11
|
+
}
|
|
12
|
+
else if (stderr.includes("ENOSPC")) {
|
|
13
|
+
console.error(color.yellow("💡 Disk space error detected. Please free up some disk space."));
|
|
14
|
+
}
|
|
15
|
+
else if (stderr.includes("ERR_PNPM_PEER_DEP_ISSUES")) {
|
|
16
|
+
console.error(color.yellow("💡 Peer dependency issues detected. Consider using --force flag or resolve conflicts manually."));
|
|
17
|
+
}
|
|
18
|
+
}
|
|
4
19
|
export const installDependencies = async ({ packageManager: pm, cwd, }) => {
|
|
5
|
-
const packageManager = pm.split(
|
|
20
|
+
const packageManager = pm.split("@")[0];
|
|
6
21
|
const isOnline = await getOnline();
|
|
7
|
-
const args = [
|
|
22
|
+
const args = ["install"];
|
|
8
23
|
if (!isOnline) {
|
|
9
|
-
console.log(color.yellow(
|
|
10
|
-
args.push(
|
|
24
|
+
console.log(color.yellow("You appear to be offline.\nFalling back to the local cache."));
|
|
25
|
+
args.push("--offline");
|
|
11
26
|
}
|
|
12
27
|
return new Promise((resolve, reject) => {
|
|
13
|
-
let stdout =
|
|
14
|
-
let stderr =
|
|
28
|
+
let stdout = "";
|
|
29
|
+
let stderr = "";
|
|
15
30
|
const child = spawn(packageManager, args, {
|
|
16
|
-
stdio:
|
|
31
|
+
stdio: "pipe",
|
|
17
32
|
cwd,
|
|
18
33
|
shell: true,
|
|
19
34
|
env: {
|
|
20
35
|
...process.env,
|
|
21
|
-
ADBLOCK:
|
|
22
|
-
NODE_ENV:
|
|
23
|
-
DISABLE_OPENCOLLECTIVE:
|
|
36
|
+
ADBLOCK: "1",
|
|
37
|
+
NODE_ENV: "development",
|
|
38
|
+
DISABLE_OPENCOLLECTIVE: "1",
|
|
24
39
|
},
|
|
25
40
|
});
|
|
26
|
-
child.stdout?.on(
|
|
41
|
+
child.stdout?.on("data", (data) => {
|
|
27
42
|
const output = data.toString();
|
|
28
43
|
stdout += output;
|
|
29
44
|
});
|
|
30
|
-
child.stderr?.on(
|
|
45
|
+
child.stderr?.on("data", (data) => {
|
|
31
46
|
const output = data.toString();
|
|
32
47
|
stderr += output;
|
|
33
48
|
});
|
|
34
|
-
child.on(
|
|
49
|
+
child.on("close", code => {
|
|
35
50
|
if (code !== 0) {
|
|
36
51
|
console.error(color.red(`\n❌ Installation failed with exit code: ${code}`));
|
|
37
52
|
if (stderr) {
|
|
38
|
-
console.error(color.red(
|
|
53
|
+
console.error(color.red("Error output:"));
|
|
39
54
|
console.error(stderr);
|
|
40
55
|
}
|
|
41
56
|
if (stdout) {
|
|
42
|
-
console.log(color.yellow(
|
|
57
|
+
console.log(color.yellow("Standard output:"));
|
|
43
58
|
console.log(stdout);
|
|
44
59
|
}
|
|
45
|
-
|
|
46
|
-
console.error(color.yellow('💡 Network error detected. Please check your internet connection.'));
|
|
47
|
-
}
|
|
48
|
-
else if (stderr.includes('EACCES') ||
|
|
49
|
-
stderr.includes('permission denied')) {
|
|
50
|
-
console.error(color.yellow('💡 Permission error detected. Try running with elevated privileges or check file permissions.'));
|
|
51
|
-
}
|
|
52
|
-
else if (stderr.includes('ENOSPC')) {
|
|
53
|
-
console.error(color.yellow('💡 Disk space error detected. Please free up some disk space.'));
|
|
54
|
-
}
|
|
55
|
-
else if (stderr.includes('ERR_PNPM_PEER_DEP_ISSUES')) {
|
|
56
|
-
console.error(color.yellow('💡 Peer dependency issues detected. Consider using --force flag or resolve conflicts manually.'));
|
|
57
|
-
}
|
|
60
|
+
printInstallErrorSuggestions(stderr, color);
|
|
58
61
|
reject(new Error(`Failed to install dependencies using ${packageManager}. Exit code: ${code}\n${stderr || stdout}`));
|
|
59
62
|
return;
|
|
60
63
|
}
|
|
61
64
|
resolve();
|
|
62
65
|
});
|
|
63
|
-
child.on(
|
|
66
|
+
child.on("error", error => {
|
|
64
67
|
console.error(color.red(`❌ Failed to start ${packageManager}:`), error.message);
|
|
65
68
|
reject(new Error(`Failed to start ${packageManager}: ${error.message}`));
|
|
66
69
|
});
|
|
@@ -1,31 +1,30 @@
|
|
|
1
|
-
import { lstatSync, readdirSync } from
|
|
2
|
-
import { join } from
|
|
3
|
-
import colors from
|
|
1
|
+
import { lstatSync, readdirSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import colors from "picocolors";
|
|
4
4
|
export function isFolderEmpty(root, name) {
|
|
5
5
|
const validFiles = [
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
6
|
+
".DS_Store",
|
|
7
|
+
".git",
|
|
8
|
+
".gitattributes",
|
|
9
|
+
".gitignore",
|
|
10
|
+
".gitlab-ci.yml",
|
|
11
|
+
".hg",
|
|
12
|
+
".hgcheck",
|
|
13
|
+
".hgignore",
|
|
14
|
+
".idea",
|
|
15
|
+
".npmignore",
|
|
16
|
+
".travis.yml",
|
|
17
|
+
"LICENSE",
|
|
18
|
+
"Thumbs.db",
|
|
19
|
+
"docs",
|
|
20
|
+
"mkdocs.yml",
|
|
21
|
+
"npm-debug.log",
|
|
22
|
+
"yarn-debug.log",
|
|
23
|
+
"yarn-error.log",
|
|
24
|
+
"yarnrc.yml",
|
|
25
|
+
".yarn",
|
|
26
26
|
];
|
|
27
|
-
const conflicts = readdirSync(root).filter(file => !validFiles.includes(file)
|
|
28
|
-
!file.endsWith('.iml'));
|
|
27
|
+
const conflicts = readdirSync(root).filter(file => !(validFiles.includes(file) || file.endsWith(".iml")));
|
|
29
28
|
if (conflicts.length > 0) {
|
|
30
29
|
console.log(`The directory ${colors.green(name)} contains files that could conflict:\n`);
|
|
31
30
|
for (const file of conflicts) {
|
|
@@ -42,7 +41,7 @@ export function isFolderEmpty(root, name) {
|
|
|
42
41
|
console.log(file);
|
|
43
42
|
}
|
|
44
43
|
}
|
|
45
|
-
console.log(
|
|
44
|
+
console.log("\nEither try using a new directory name, or remove the files listed above.\n");
|
|
46
45
|
return false;
|
|
47
46
|
}
|
|
48
47
|
return true;
|
|
@@ -1,9 +1,21 @@
|
|
|
1
|
-
import { execSync } from
|
|
2
|
-
import { lookup } from
|
|
3
|
-
import { URL } from
|
|
1
|
+
import { execSync } from "node:child_process";
|
|
2
|
+
import { lookup } from "node:dns/promises";
|
|
3
|
+
import { URL } from "node:url";
|
|
4
|
+
function getProxy() {
|
|
5
|
+
if (process.env.https_proxy) {
|
|
6
|
+
return process.env.https_proxy;
|
|
7
|
+
}
|
|
8
|
+
try {
|
|
9
|
+
const httpsProxy = execSync("npm config get https-proxy").toString().trim();
|
|
10
|
+
return httpsProxy !== "null" ? httpsProxy : undefined;
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
4
16
|
export async function getOnline() {
|
|
5
17
|
try {
|
|
6
|
-
await lookup(
|
|
18
|
+
await lookup("registry.yarnpkg.com");
|
|
7
19
|
return true;
|
|
8
20
|
}
|
|
9
21
|
catch {
|
|
@@ -24,15 +36,3 @@ export async function getOnline() {
|
|
|
24
36
|
}
|
|
25
37
|
}
|
|
26
38
|
}
|
|
27
|
-
function getProxy() {
|
|
28
|
-
if (process.env.https_proxy) {
|
|
29
|
-
return process.env.https_proxy;
|
|
30
|
-
}
|
|
31
|
-
try {
|
|
32
|
-
const httpsProxy = execSync('npm config get https-proxy').toString().trim();
|
|
33
|
-
return httpsProxy !== 'null' ? httpsProxy : undefined;
|
|
34
|
-
}
|
|
35
|
-
catch {
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
}
|
package/dist/src/index.js
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import color from
|
|
6
|
-
import { createVitNode } from
|
|
7
|
-
import { packageJson } from
|
|
8
|
-
import { validateNpmName } from
|
|
9
|
-
import { createPlugin } from
|
|
10
|
-
import { createQuestionsCli } from
|
|
11
|
-
import { validationProject } from
|
|
12
|
-
const [major] = process.versions.node.split(
|
|
2
|
+
import { basename, resolve } from "node:path";
|
|
3
|
+
import { input } from "@inquirer/prompts";
|
|
4
|
+
import { Command, Option } from "commander";
|
|
5
|
+
import color from "picocolors";
|
|
6
|
+
import { createVitNode } from "./create/create-vitnode.js";
|
|
7
|
+
import { packageJson } from "./helpers/get-package-json.js";
|
|
8
|
+
import { validateNpmName } from "./helpers/validate-pkg.js";
|
|
9
|
+
import { createPlugin } from "./plugin/index.js";
|
|
10
|
+
import { createQuestionsCli } from "./questions.js";
|
|
11
|
+
import { validationProject } from "./validation.js";
|
|
12
|
+
const [major] = process.versions.node.split(".").map(Number);
|
|
13
13
|
if (major < 20) {
|
|
14
14
|
console.error(color.red(`\nError: VitNode requires Node.js version 20 or higher.\nYou are currently using Node.js ${process.versions.node}\n`));
|
|
15
15
|
process.exit(1);
|
|
16
16
|
}
|
|
17
|
-
process.on(
|
|
18
|
-
if (error.name ===
|
|
19
|
-
console.log(color.dim(
|
|
17
|
+
process.on("uncaughtException", (error) => {
|
|
18
|
+
if (error.name === "ExitPromptError") {
|
|
19
|
+
console.log(color.dim("👋 VitNode setup cancelled - see you next time!"));
|
|
20
20
|
process.exit(0);
|
|
21
21
|
}
|
|
22
|
-
console.error(color.red(
|
|
22
|
+
console.error(color.red("An unexpected error occurred:"));
|
|
23
23
|
console.error(color.red(error.stack ?? error.message));
|
|
24
24
|
process.exit(1);
|
|
25
25
|
});
|
|
26
26
|
const init = async () => {
|
|
27
|
-
let projectPath =
|
|
27
|
+
let projectPath = "";
|
|
28
28
|
const program = new Command()
|
|
29
|
-
.version(packageJson.version ??
|
|
30
|
-
.argument(
|
|
31
|
-
.usage(`${color.green(
|
|
29
|
+
.version(packageJson.version ?? "0.1.0")
|
|
30
|
+
.argument("[project-directory]")
|
|
31
|
+
.usage(`${color.green("[project-directory]")} [options]`)
|
|
32
32
|
.action(name => {
|
|
33
33
|
projectPath = name;
|
|
34
34
|
});
|
|
35
|
-
program.addOption(new Option(
|
|
36
|
-
program.option(
|
|
37
|
-
program.option(
|
|
38
|
-
program.option(
|
|
39
|
-
program.addOption(new Option(
|
|
40
|
-
program.option(
|
|
41
|
-
program.option(
|
|
35
|
+
program.addOption(new Option("--package-manager <package-manager>", "Specify the package manager to use").choices(["npm", "pnpm", "bun"]));
|
|
36
|
+
program.option("--biome", "Initialize with Biome config.");
|
|
37
|
+
program.option("--skip-install", "Skip installing packages after initializing the project.");
|
|
38
|
+
program.option("--plugin", "Enable plugin mode.");
|
|
39
|
+
program.addOption(new Option("--mode <mode>", "What type of app do you want to create?").choices(["singleApp", "apiMonorepo", "onlyApi"]));
|
|
40
|
+
program.option("--monorepo", "Create project with monorepo structure.");
|
|
41
|
+
program.option("--docker", "Initialize with Docker support.");
|
|
42
42
|
program.parse(process.argv);
|
|
43
43
|
const opts = program.opts();
|
|
44
44
|
if (opts.plugin) {
|
|
@@ -47,8 +47,8 @@ const init = async () => {
|
|
|
47
47
|
}
|
|
48
48
|
if (!projectPath) {
|
|
49
49
|
projectPath = await input({
|
|
50
|
-
message:
|
|
51
|
-
default:
|
|
50
|
+
message: "What is your project named?",
|
|
51
|
+
default: "my-vitnode",
|
|
52
52
|
validate: (name) => {
|
|
53
53
|
const validation = validateNpmName({ name: basename(resolve(name)) });
|
|
54
54
|
if (validation.valid)
|