pixelstart 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -1
- package/dist/modules/requirements.js +189 -33
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { banner, section, success, error, info } from './modules/ui.js';
|
|
|
5
5
|
import { checkRequirements } from './modules/requirements.js';
|
|
6
6
|
import { showNDA } from './modules/nda.js';
|
|
7
7
|
import { initProject } from './modules/init.js';
|
|
8
|
-
const VERSION = '1.
|
|
8
|
+
const VERSION = '1.1.0';
|
|
9
9
|
async function main() {
|
|
10
10
|
const args = process.argv.slice(2);
|
|
11
11
|
const command = args[0];
|
|
@@ -1,77 +1,232 @@
|
|
|
1
1
|
import { execSync } from 'child_process';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
2
3
|
import chalk from 'chalk';
|
|
3
4
|
import { success, error, warn, info, section } from './ui.js';
|
|
5
|
+
const P = '#7C3AED';
|
|
6
|
+
const R = '#EF4444';
|
|
7
|
+
const G = '#22C55E';
|
|
8
|
+
const Y = '#EAB308';
|
|
9
|
+
const C = '#06B6D4';
|
|
10
|
+
function c(hex, text) {
|
|
11
|
+
return String(chalk.hex(hex)(text));
|
|
12
|
+
}
|
|
13
|
+
function cb(hex, text) {
|
|
14
|
+
return String(chalk.hex(hex).bold(text));
|
|
15
|
+
}
|
|
16
|
+
function getPlatform() {
|
|
17
|
+
return process.platform;
|
|
18
|
+
}
|
|
19
|
+
function isRoot() {
|
|
20
|
+
if (getPlatform() === 'win32')
|
|
21
|
+
return true;
|
|
22
|
+
try {
|
|
23
|
+
execSync('id -u', { stdio: 'pipe' });
|
|
24
|
+
return execSync('id -u', { encoding: 'utf-8', stdio: 'pipe' }).trim() === '0';
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function run(cmd, opts = {}) {
|
|
31
|
+
try {
|
|
32
|
+
const full = opts.sudo && !isRoot() ? `sudo ${cmd}` : cmd;
|
|
33
|
+
execSync(full, { stdio: 'pipe', timeout: 120000 });
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function parseVersion(output) {
|
|
41
|
+
return output.replace(/^[^\d]*/, '').split('+')[0].trim();
|
|
42
|
+
}
|
|
43
|
+
function compareVersions(a, b) {
|
|
44
|
+
const pa = a.split('.').map(Number);
|
|
45
|
+
const pb = b.split('.').map(Number);
|
|
46
|
+
for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
|
|
47
|
+
const na = pa[i] || 0;
|
|
48
|
+
const nb = pb[i] || 0;
|
|
49
|
+
if (na > nb)
|
|
50
|
+
return 1;
|
|
51
|
+
if (na < nb)
|
|
52
|
+
return -1;
|
|
53
|
+
}
|
|
54
|
+
return 0;
|
|
55
|
+
}
|
|
56
|
+
// ── Install functions per platform ──────────────────────────────────────────
|
|
57
|
+
function getNodeInstallCmd(platform) {
|
|
58
|
+
switch (platform) {
|
|
59
|
+
case 'linux':
|
|
60
|
+
return [
|
|
61
|
+
'curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -',
|
|
62
|
+
'sudo apt-get install -y nodejs',
|
|
63
|
+
];
|
|
64
|
+
case 'darwin':
|
|
65
|
+
return ['brew install node@22'];
|
|
66
|
+
case 'win32':
|
|
67
|
+
return ['winget install OpenJS.NodeJS.LTS --accept-package-agreements --accept-source-agreements'];
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function getDockerInstallCmd(platform) {
|
|
71
|
+
switch (platform) {
|
|
72
|
+
case 'linux':
|
|
73
|
+
return [
|
|
74
|
+
'curl -fsSL https://get.docker.com | sudo sh',
|
|
75
|
+
'sudo usermod -aG docker $USER',
|
|
76
|
+
];
|
|
77
|
+
case 'darwin':
|
|
78
|
+
return ['brew install --cask docker'];
|
|
79
|
+
case 'win32':
|
|
80
|
+
return ['winget install Docker.DockerDesktop --accept-package-agreements --accept-source-agreements'];
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function getPnpmInstallCmd() {
|
|
84
|
+
return ['npm install -g pnpm@9'];
|
|
85
|
+
}
|
|
4
86
|
const REQUIREMENTS = [
|
|
5
87
|
{
|
|
6
88
|
name: 'Node.js',
|
|
7
89
|
command: 'node --version',
|
|
8
90
|
minVersion: '22.0.0',
|
|
9
91
|
required: true,
|
|
10
|
-
|
|
92
|
+
getInstallCmd: getNodeInstallCmd,
|
|
93
|
+
installHint: 'https://nodejs.org/',
|
|
11
94
|
},
|
|
12
95
|
{
|
|
13
96
|
name: 'Docker',
|
|
14
97
|
command: 'docker --version',
|
|
15
98
|
required: true,
|
|
16
|
-
|
|
99
|
+
getInstallCmd: getDockerInstallCmd,
|
|
100
|
+
installHint: 'https://docs.docker.com/get-docker/',
|
|
17
101
|
},
|
|
18
102
|
{
|
|
19
103
|
name: 'Docker Compose',
|
|
20
104
|
command: 'docker compose version',
|
|
21
105
|
required: true,
|
|
22
|
-
|
|
106
|
+
getInstallCmd: () => [],
|
|
107
|
+
installHint: 'Included with Docker Desktop',
|
|
23
108
|
},
|
|
24
109
|
{
|
|
25
110
|
name: 'pnpm',
|
|
26
111
|
command: 'pnpm --version',
|
|
27
112
|
minVersion: '9.0.0',
|
|
28
113
|
required: false,
|
|
29
|
-
|
|
114
|
+
getInstallCmd: getPnpmInstallCmd,
|
|
115
|
+
installHint: 'npm install -g pnpm@9',
|
|
30
116
|
},
|
|
31
117
|
];
|
|
32
|
-
function
|
|
33
|
-
return output.replace(/^[^\d]*/, '').split('+')[0].trim();
|
|
34
|
-
}
|
|
35
|
-
function compareVersions(a, b) {
|
|
36
|
-
const pa = a.split('.').map(Number);
|
|
37
|
-
const pb = b.split('.').map(Number);
|
|
38
|
-
for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
|
|
39
|
-
const na = pa[i] || 0;
|
|
40
|
-
const nb = pb[i] || 0;
|
|
41
|
-
if (na > nb)
|
|
42
|
-
return 1;
|
|
43
|
-
if (na < nb)
|
|
44
|
-
return -1;
|
|
45
|
-
}
|
|
46
|
-
return 0;
|
|
47
|
-
}
|
|
48
|
-
function checkRequirement(req) {
|
|
118
|
+
function checkRequirement(req, platform) {
|
|
49
119
|
try {
|
|
50
120
|
const output = execSync(req.command, { encoding: 'utf-8', stdio: 'pipe' }).trim();
|
|
51
121
|
const version = parseVersion(output);
|
|
52
122
|
const meetsMin = req.minVersion ? compareVersions(version, req.minVersion) >= 0 : true;
|
|
53
|
-
return {
|
|
123
|
+
return {
|
|
124
|
+
name: req.name, installed: true, version, meetsMin,
|
|
125
|
+
required: req.required, minVersion: req.minVersion,
|
|
126
|
+
installCmds: req.getInstallCmd(platform), installHint: req.installHint,
|
|
127
|
+
};
|
|
54
128
|
}
|
|
55
129
|
catch {
|
|
56
|
-
return {
|
|
130
|
+
return {
|
|
131
|
+
name: req.name, installed: false,
|
|
132
|
+
required: req.required, minVersion: req.minVersion,
|
|
133
|
+
installCmds: req.getInstallCmd(platform), installHint: req.installHint,
|
|
134
|
+
};
|
|
57
135
|
}
|
|
58
136
|
}
|
|
137
|
+
async function autoInstall(name, cmds) {
|
|
138
|
+
console.log('');
|
|
139
|
+
info(c(C, `Installing ${name}...`));
|
|
140
|
+
console.log('');
|
|
141
|
+
for (const cmd of cmds) {
|
|
142
|
+
console.log(c(P, ` $ ${cmd}`));
|
|
143
|
+
const sudo = cmd.startsWith('sudo');
|
|
144
|
+
const ok = run(cmd, { sudo });
|
|
145
|
+
if (!ok) {
|
|
146
|
+
error(c(R, `Failed to install ${name}.`));
|
|
147
|
+
info('You may need to run this command manually or check your internet connection.');
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
console.log('');
|
|
152
|
+
success(c(G, `${name} installed successfully!`));
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
59
155
|
export async function checkRequirements() {
|
|
60
156
|
section('System Requirements');
|
|
61
|
-
const
|
|
157
|
+
const platform = getPlatform();
|
|
158
|
+
const platformNames = { linux: 'Linux', darwin: 'macOS', win32: 'Windows' };
|
|
159
|
+
info(c(C, `Detected platform: ${platformNames[platform]}`));
|
|
160
|
+
if (!isRoot() && platform !== 'win32') {
|
|
161
|
+
info(c(Y, 'Some operations may require sudo (password may be prompted)'));
|
|
162
|
+
}
|
|
163
|
+
console.log('');
|
|
164
|
+
const results = REQUIREMENTS.map(r => checkRequirement(r, platform));
|
|
62
165
|
let allPassed = true;
|
|
63
166
|
for (const r of results) {
|
|
64
167
|
if (!r.installed) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
168
|
+
if (r.installCmds.length > 0) {
|
|
169
|
+
const { wantInstall } = await inquirer.prompt([{
|
|
170
|
+
type: 'confirm',
|
|
171
|
+
name: 'wantInstall',
|
|
172
|
+
message: cb(R, ` ${r.name} is not installed. Install it now?`),
|
|
173
|
+
default: true,
|
|
174
|
+
}]);
|
|
175
|
+
if (wantInstall) {
|
|
176
|
+
const ok = await autoInstall(r.name, r.installCmds);
|
|
177
|
+
if (!ok) {
|
|
178
|
+
if (r.required)
|
|
179
|
+
allPassed = false;
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
// Re-check after install
|
|
183
|
+
const recheck = checkRequirement(REQUIREMENTS.find(x => x.name === r.name), platform);
|
|
184
|
+
if (recheck.installed && recheck.meetsMin !== false) {
|
|
185
|
+
success(cb(G, `${r.name} ${recheck.version || ''}`));
|
|
186
|
+
}
|
|
187
|
+
else if (r.required) {
|
|
188
|
+
allPassed = false;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
error(`${chalk.bold(r.name)} is required but not installed.`);
|
|
194
|
+
info(r.installHint);
|
|
195
|
+
if (r.required)
|
|
196
|
+
allPassed = false;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
error(`${chalk.bold(r.name)} not found`);
|
|
201
|
+
info(r.installHint);
|
|
202
|
+
if (r.required)
|
|
203
|
+
allPassed = false;
|
|
204
|
+
}
|
|
69
205
|
}
|
|
70
206
|
else if (r.meetsMin === false) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
207
|
+
if (r.installCmds.length > 0) {
|
|
208
|
+
const { wantUpgrade } = await inquirer.prompt([{
|
|
209
|
+
type: 'confirm',
|
|
210
|
+
name: 'wantUpgrade',
|
|
211
|
+
message: cb(Y, ` ${r.name} ${r.version} is too old (need ${r.minVersion}+). Upgrade?`),
|
|
212
|
+
default: true,
|
|
213
|
+
}]);
|
|
214
|
+
if (wantUpgrade) {
|
|
215
|
+
const ok = await autoInstall(r.name, r.installCmds);
|
|
216
|
+
if (!ok && r.required)
|
|
217
|
+
allPassed = false;
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
if (r.required)
|
|
221
|
+
allPassed = false;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
warn(`${chalk.bold(r.name)} ${r.version} — requires ${r.minVersion}+`);
|
|
226
|
+
info(r.installHint);
|
|
227
|
+
if (r.required)
|
|
228
|
+
allPassed = false;
|
|
229
|
+
}
|
|
75
230
|
}
|
|
76
231
|
else {
|
|
77
232
|
success(`${chalk.bold(r.name)} ${chalk.gray(r.version || '')}`);
|
|
@@ -79,7 +234,8 @@ export async function checkRequirements() {
|
|
|
79
234
|
}
|
|
80
235
|
console.log('');
|
|
81
236
|
if (!allPassed) {
|
|
82
|
-
error('
|
|
237
|
+
error('Some required dependencies could not be installed.');
|
|
238
|
+
info('Please install them manually and try again.');
|
|
83
239
|
return false;
|
|
84
240
|
}
|
|
85
241
|
return true;
|