pixelstart 1.0.0 → 1.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/dist/index.js +8 -4
- package/dist/modules/init.js +7 -3
- package/dist/modules/license.d.ts +8 -1
- package/dist/modules/license.js +6 -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.2.0';
|
|
9
9
|
async function main() {
|
|
10
10
|
const args = process.argv.slice(2);
|
|
11
11
|
const command = args[0];
|
|
@@ -47,7 +47,7 @@ async function main() {
|
|
|
47
47
|
async function retryPull() {
|
|
48
48
|
section('Pull Docker Image');
|
|
49
49
|
const inquirer = await import('inquirer');
|
|
50
|
-
const { validateLicense, exchangeDownloadToken } = await import('./modules/license.js');
|
|
50
|
+
const { validateLicense, exchangeDownloadToken, buildDockerCommands } = await import('./modules/license.js');
|
|
51
51
|
const { key } = await inquirer.default.prompt([
|
|
52
52
|
{
|
|
53
53
|
type: 'input',
|
|
@@ -71,14 +71,18 @@ async function retryPull() {
|
|
|
71
71
|
info('Pulling Docker image...');
|
|
72
72
|
const { execSync } = await import('child_process');
|
|
73
73
|
try {
|
|
74
|
-
|
|
74
|
+
const { login, pull } = buildDockerCommands(downloadResult);
|
|
75
|
+
execSync(login, { stdio: 'inherit' });
|
|
76
|
+
execSync(pull, { stdio: 'inherit' });
|
|
75
77
|
console.log('');
|
|
76
78
|
success(`Docker image ${chalk.bold(downloadResult.image)} pulled successfully!`);
|
|
77
79
|
}
|
|
78
80
|
catch {
|
|
79
81
|
error('Docker pull failed. You can retry manually:');
|
|
80
82
|
console.log('');
|
|
81
|
-
|
|
83
|
+
const { login, pull } = buildDockerCommands(downloadResult);
|
|
84
|
+
console.log(chalk.white(` ${login}`));
|
|
85
|
+
console.log(chalk.white(` ${pull}`));
|
|
82
86
|
}
|
|
83
87
|
}
|
|
84
88
|
function printHelp() {
|
package/dist/modules/init.js
CHANGED
|
@@ -4,7 +4,7 @@ import path from 'path';
|
|
|
4
4
|
import inquirer from 'inquirer';
|
|
5
5
|
import chalk from 'chalk';
|
|
6
6
|
import { section, success, error, info } from './ui.js';
|
|
7
|
-
import { validateLicense, exchangeDownloadToken } from './license.js';
|
|
7
|
+
import { validateLicense, exchangeDownloadToken, buildDockerCommands } from './license.js';
|
|
8
8
|
export async function initProject() {
|
|
9
9
|
section('Project Setup');
|
|
10
10
|
const config = await inquirer.prompt([
|
|
@@ -103,14 +103,18 @@ data/
|
|
|
103
103
|
info('Pulling Docker image...');
|
|
104
104
|
console.log('');
|
|
105
105
|
try {
|
|
106
|
-
|
|
106
|
+
const { login, pull } = buildDockerCommands(downloadResult);
|
|
107
|
+
execSync(login, { stdio: 'inherit' });
|
|
108
|
+
execSync(pull, { stdio: 'inherit' });
|
|
107
109
|
console.log('');
|
|
108
110
|
success(`Docker image ${chalk.bold(downloadResult.image)} pulled successfully!`);
|
|
109
111
|
}
|
|
110
112
|
catch (err) {
|
|
111
113
|
error('Docker pull failed. You can retry manually:');
|
|
112
114
|
console.log('');
|
|
113
|
-
|
|
115
|
+
const { login, pull } = buildDockerCommands(downloadResult);
|
|
116
|
+
console.log(chalk.white(` ${login}`));
|
|
117
|
+
console.log(chalk.white(` ${pull}`));
|
|
114
118
|
}
|
|
115
119
|
console.log('');
|
|
116
120
|
success(`Project "${chalk.bold(config.name)}" created!`);
|
|
@@ -7,12 +7,19 @@ export interface LicenseValidation {
|
|
|
7
7
|
}
|
|
8
8
|
export interface DownloadResult {
|
|
9
9
|
success: boolean;
|
|
10
|
-
|
|
10
|
+
token: string;
|
|
11
11
|
image: string;
|
|
12
|
+
owner: string;
|
|
13
|
+
imageName: string;
|
|
12
14
|
tag: string;
|
|
15
|
+
registry: string;
|
|
13
16
|
}
|
|
14
17
|
export declare function validateLicense(licenseKey: string, imageTag: string): Promise<LicenseValidation | null>;
|
|
15
18
|
export declare function exchangeDownloadToken(token: string): Promise<DownloadResult | null>;
|
|
19
|
+
export declare function buildDockerCommands(result: DownloadResult): {
|
|
20
|
+
login: string;
|
|
21
|
+
pull: string;
|
|
22
|
+
};
|
|
16
23
|
export declare function showLicense(): Promise<{
|
|
17
24
|
key: string;
|
|
18
25
|
imageTag: string;
|
package/dist/modules/license.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import {
|
|
2
|
+
import { success, error, info, section } from './ui.js';
|
|
3
3
|
const SUPABASE_URL = 'https://qnuzhgozszftvvxsnaos.supabase.co';
|
|
4
4
|
const ANON_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InFudXpoZ296c3pmdHZ2eHNuYW9zIiwicm9sZSI6ImFub24iLCJpYXQiOjE3ODM0MjEwODMsImV4cCI6MjA5ODk5NzA4M30.q3mgpAS8nm1OtvnlKuOgTEi_vLmb46bV0sf3bS-fSCg';
|
|
5
5
|
const EDGE_FUNCTION = `${SUPABASE_URL}/functions/v1/proxy-package`;
|
|
@@ -51,6 +51,11 @@ export async function exchangeDownloadToken(token) {
|
|
|
51
51
|
return null;
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
|
+
export function buildDockerCommands(result) {
|
|
55
|
+
const login = `echo ${result.token} | docker login ${result.registry} -u ${result.owner} --password-stdin`;
|
|
56
|
+
const pull = `docker pull ${result.image}`;
|
|
57
|
+
return { login, pull };
|
|
58
|
+
}
|
|
54
59
|
export async function showLicense() {
|
|
55
60
|
section('License');
|
|
56
61
|
console.log(chalk.white(' Enter your PixelStack license key to download the image.'));
|
|
@@ -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;
|