pixelstart 0.0.1 → 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 +44 -14
- package/dist/modules/init.js +49 -4
- package/dist/modules/license.d.ts +19 -5
- package/dist/modules/license.js +69 -66
- package/dist/modules/logo.js +9 -11
- package/dist/modules/nda.js +160 -51
- package/dist/modules/requirements.js +189 -33
- package/dist/modules/ui.d.ts +1 -0
- package/dist/modules/ui.js +5 -4
- package/package.json +18 -6
- package/src/index.ts +0 -95
- package/src/modules/init.ts +0 -100
- package/src/modules/license.ts +0 -84
- package/src/modules/logo.ts +0 -21
- package/src/modules/nda.ts +0 -77
- package/src/modules/requirements.ts +0 -107
- package/src/modules/ui.ts +0 -35
- package/tsconfig.json +0 -16
|
@@ -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;
|
package/dist/modules/ui.d.ts
CHANGED
|
@@ -4,4 +4,5 @@ export declare function error(msg: string): void;
|
|
|
4
4
|
export declare function warn(msg: string): void;
|
|
5
5
|
export declare function info(msg: string): void;
|
|
6
6
|
export declare function divider(): void;
|
|
7
|
+
export declare function dividerLine(): string;
|
|
7
8
|
export declare function section(title: string): void;
|
package/dist/modules/ui.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
export function banner() {
|
|
3
|
-
console.log(chalk.hex('#7C3AED')('
|
|
4
|
-
console.log(chalk.
|
|
5
|
-
console.log(chalk.hex('#7C3AED')('│') + chalk.gray(' v0.1.0 — Single Container ') + chalk.hex('#7C3AED')('│'));
|
|
6
|
-
console.log(chalk.hex('#7C3AED')('└─────────────────────────────────────────────┘'));
|
|
3
|
+
console.log(chalk.hex('#7C3AED').bold(' PIXELSTACK LITE'));
|
|
4
|
+
console.log(chalk.gray(' ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
7
5
|
console.log('');
|
|
8
6
|
}
|
|
9
7
|
export function success(msg) {
|
|
@@ -21,6 +19,9 @@ export function info(msg) {
|
|
|
21
19
|
export function divider() {
|
|
22
20
|
console.log(chalk.gray(' ───────────────────────────────────────────'));
|
|
23
21
|
}
|
|
22
|
+
export function dividerLine() {
|
|
23
|
+
return String(chalk.gray(' ───────────────────────────────────────────'));
|
|
24
|
+
}
|
|
24
25
|
export function section(title) {
|
|
25
26
|
console.log('');
|
|
26
27
|
console.log(chalk.hex('#7C3AED').bold(` ▸ ${title}`));
|
package/package.json
CHANGED
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pixelstart",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "PixelStack CLI — scaffold and
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "PixelStack Lite CLI — scaffold, license, and deploy PixelStack projects",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"bin": {
|
|
8
8
|
"pixelstart": "dist/index.js"
|
|
9
9
|
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
10
14
|
"scripts": {
|
|
11
15
|
"dev": "tsx src/index.ts",
|
|
12
16
|
"build": "tsc && chmod +x dist/index.js",
|
|
13
17
|
"start": "node dist/index.js",
|
|
14
18
|
"type-check": "tsc --noEmit",
|
|
15
|
-
"prepublishOnly": "npm run build"
|
|
19
|
+
"prepublishOnly": "npm run build",
|
|
20
|
+
"pack": "npm run build && npm pack"
|
|
16
21
|
},
|
|
17
22
|
"engines": {
|
|
18
23
|
"node": ">=22.0.0"
|
|
@@ -22,10 +27,17 @@
|
|
|
22
27
|
"cli",
|
|
23
28
|
"dxp",
|
|
24
29
|
"scaffold",
|
|
25
|
-
"cms"
|
|
30
|
+
"cms",
|
|
31
|
+
"docker",
|
|
32
|
+
"license"
|
|
26
33
|
],
|
|
27
|
-
"author": "",
|
|
28
|
-
"license": "
|
|
34
|
+
"author": "soroosh-assa",
|
|
35
|
+
"license": "UNLICENSED",
|
|
36
|
+
"private": false,
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "https://github.com/soroosh-assa/pixel-cicd"
|
|
40
|
+
},
|
|
29
41
|
"devDependencies": {
|
|
30
42
|
"@types/inquirer": "^9.0.10",
|
|
31
43
|
"@types/node": "^22.0.0",
|
package/src/index.ts
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import chalk from 'chalk';
|
|
4
|
-
import { showLogo } from './modules/logo.js';
|
|
5
|
-
import { banner, section, success, error, info, divider } from './modules/ui.js';
|
|
6
|
-
import { checkRequirements } from './modules/requirements.js';
|
|
7
|
-
import { showNDA } from './modules/nda.js';
|
|
8
|
-
import { showLicense } from './modules/license.js';
|
|
9
|
-
import { initProject } from './modules/init.js';
|
|
10
|
-
|
|
11
|
-
const VERSION = '0.1.0';
|
|
12
|
-
|
|
13
|
-
async function main(): Promise<void> {
|
|
14
|
-
const args = process.argv.slice(2);
|
|
15
|
-
const command = args[0];
|
|
16
|
-
|
|
17
|
-
// --help / --version work without logo
|
|
18
|
-
if (command === '--help' || command === '-h') {
|
|
19
|
-
printHelp();
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
if (command === '--version' || command === '-v') {
|
|
23
|
-
console.log(`pixelstart v${VERSION}`);
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Interactive flow — show logo + banner
|
|
28
|
-
showLogo();
|
|
29
|
-
banner();
|
|
30
|
-
|
|
31
|
-
// Step 1: Check requirements
|
|
32
|
-
const reqsOk = await checkRequirements();
|
|
33
|
-
if (!reqsOk) {
|
|
34
|
-
process.exit(1);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Step 2: NDA
|
|
38
|
-
const ndaOk = await showNDA();
|
|
39
|
-
if (!ndaOk) {
|
|
40
|
-
process.exit(0);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Step 3: License
|
|
44
|
-
const tier = await showLicense();
|
|
45
|
-
if (!tier) {
|
|
46
|
-
process.exit(0);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Step 4: Init project (if `init` command or no command)
|
|
50
|
-
if (!command || command === 'init') {
|
|
51
|
-
await initProject();
|
|
52
|
-
} else if (command === 'up' || command === 'down' || command === 'status' || command === 'logs') {
|
|
53
|
-
section('Service Management');
|
|
54
|
-
info(`Command "${command}" will be available after project initialization.`);
|
|
55
|
-
console.log('');
|
|
56
|
-
} else {
|
|
57
|
-
error(`Unknown command: ${command}`);
|
|
58
|
-
info('Run `pixelstart --help` for usage.');
|
|
59
|
-
process.exit(1);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function printHelp(): void {
|
|
64
|
-
console.log(`
|
|
65
|
-
${chalk.hex('#7C3AED').bold('pixelstart')} v${VERSION}
|
|
66
|
-
|
|
67
|
-
${chalk.gray('Usage:')}
|
|
68
|
-
pixelstart [command]
|
|
69
|
-
|
|
70
|
-
${chalk.gray('Commands:')}
|
|
71
|
-
init Scaffold a new PixelStack Lite project
|
|
72
|
-
up Start all services
|
|
73
|
-
down Stop all services
|
|
74
|
-
status Show service status
|
|
75
|
-
logs Stream service logs
|
|
76
|
-
|
|
77
|
-
${chalk.gray('Options:')}
|
|
78
|
-
-h, --help Show help
|
|
79
|
-
-v, --version Show version
|
|
80
|
-
|
|
81
|
-
${chalk.gray('Examples:')}
|
|
82
|
-
pixelstart Launch interactive installer
|
|
83
|
-
pixelstart init Create a new project
|
|
84
|
-
pixelstart up Start services
|
|
85
|
-
`);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Catch unhandled errors gracefully
|
|
89
|
-
process.on('unhandledRejection', (err) => {
|
|
90
|
-
console.error('');
|
|
91
|
-
error(`Unexpected error: ${err}`);
|
|
92
|
-
process.exit(1);
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
main();
|
package/src/modules/init.ts
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import { execSync } from 'child_process';
|
|
2
|
-
import fs from 'fs';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import inquirer from 'inquirer';
|
|
5
|
-
import chalk from 'chalk';
|
|
6
|
-
import { section, success, error, warn, info } from './ui.js';
|
|
7
|
-
|
|
8
|
-
interface ProjectConfig {
|
|
9
|
-
name: string;
|
|
10
|
-
directory: string;
|
|
11
|
-
port: number;
|
|
12
|
-
dbPassword: string;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export async function initProject(): Promise<void> {
|
|
16
|
-
section('Project Setup');
|
|
17
|
-
|
|
18
|
-
const config = await inquirer.prompt<ProjectConfig>([
|
|
19
|
-
{
|
|
20
|
-
type: 'input',
|
|
21
|
-
name: 'name',
|
|
22
|
-
message: chalk.white('Project name:'),
|
|
23
|
-
default: 'my-pixelstack',
|
|
24
|
-
validate: (input: string) => {
|
|
25
|
-
if (!/^[a-z0-9-_]+$/.test(input)) return 'Use lowercase, numbers, hyphens only';
|
|
26
|
-
return true;
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
type: 'input',
|
|
31
|
-
name: 'directory',
|
|
32
|
-
message: chalk.white('Install directory:'),
|
|
33
|
-
default: (answers: { name: string }) => `./${answers.name}`,
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
type: 'number',
|
|
37
|
-
name: 'port',
|
|
38
|
-
message: chalk.white('Base port (HTTP):'),
|
|
39
|
-
default: 80,
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
type: 'password',
|
|
43
|
-
name: 'dbPassword',
|
|
44
|
-
message: chalk.white('Database password:'),
|
|
45
|
-
mask: '*',
|
|
46
|
-
validate: (input: string) => input.length >= 8 || 'Min 8 characters',
|
|
47
|
-
},
|
|
48
|
-
]);
|
|
49
|
-
|
|
50
|
-
console.log('');
|
|
51
|
-
info(`Creating project in ${chalk.bold(config.directory)}`);
|
|
52
|
-
|
|
53
|
-
try {
|
|
54
|
-
fs.mkdirSync(config.directory, { recursive: true });
|
|
55
|
-
|
|
56
|
-
const envContent = `# PixelStack Lite Configuration
|
|
57
|
-
NODE_ENV=production
|
|
58
|
-
POSTGRES_USER=pixelstack
|
|
59
|
-
POSTGRES_PASSWORD=${config.dbPassword}
|
|
60
|
-
POSTGRES_DB=pixelstack_db
|
|
61
|
-
STRAPI_DB_NAME=strapi_core_db
|
|
62
|
-
REDIS_HOST=localhost
|
|
63
|
-
REDIS_PORT=6379
|
|
64
|
-
MINIO_ROOT_USER=minioadmin
|
|
65
|
-
MINIO_ROOT_PASSWORD=minioadmin
|
|
66
|
-
MINIO_BUCKET=strapi-uploads
|
|
67
|
-
MINIO_ENDPOINT=http://localhost:9000
|
|
68
|
-
MINIO_PUBLIC_URL=http://localhost/media
|
|
69
|
-
API_PORT=3000
|
|
70
|
-
STRAPI_PORT=1337
|
|
71
|
-
WEB_PORT=3001
|
|
72
|
-
ARTEMIS_PORT=3100
|
|
73
|
-
ADMIN_PORT=4028
|
|
74
|
-
ARTEMIS_FE_PORT=4029
|
|
75
|
-
BASE_PORT=${config.port}
|
|
76
|
-
`;
|
|
77
|
-
|
|
78
|
-
fs.writeFileSync(path.join(config.directory, '.env'), envContent);
|
|
79
|
-
success('Created .env');
|
|
80
|
-
|
|
81
|
-
fs.writeFileSync(path.join(config.directory, '.gitignore'), `node_modules/
|
|
82
|
-
.env
|
|
83
|
-
*.log
|
|
84
|
-
data/
|
|
85
|
-
`);
|
|
86
|
-
success('Created .gitignore');
|
|
87
|
-
|
|
88
|
-
console.log('');
|
|
89
|
-
success(`Project "${chalk.bold(config.name)}" created!`);
|
|
90
|
-
console.log('');
|
|
91
|
-
info(`Next steps:`);
|
|
92
|
-
console.log(chalk.white(` cd ${config.directory}`));
|
|
93
|
-
console.log(chalk.white(' pixelstart up'));
|
|
94
|
-
console.log('');
|
|
95
|
-
|
|
96
|
-
} catch (err) {
|
|
97
|
-
error(`Failed to create project: ${err}`);
|
|
98
|
-
process.exit(1);
|
|
99
|
-
}
|
|
100
|
-
}
|
package/src/modules/license.ts
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import inquirer from 'inquirer';
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
import { section, divider, success, info } from './ui.js';
|
|
4
|
-
|
|
5
|
-
const LICENSE_TIERS = [
|
|
6
|
-
{
|
|
7
|
-
name: 'Community — Free',
|
|
8
|
-
value: 'community',
|
|
9
|
-
description: 'Basic features, single project, community support',
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
name: 'Pro — $29/mo',
|
|
13
|
-
value: 'pro',
|
|
14
|
-
description: 'Unlimited projects, priority support, custom themes',
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
name: 'Enterprise — Custom',
|
|
18
|
-
value: 'enterprise',
|
|
19
|
-
description: 'Self-hosted, SLA, dedicated support, custom integrations',
|
|
20
|
-
},
|
|
21
|
-
];
|
|
22
|
-
|
|
23
|
-
export async function showLicense(): Promise<string | null> {
|
|
24
|
-
section('License');
|
|
25
|
-
|
|
26
|
-
console.log(chalk.white(' Choose your PixelStack Lite license tier:'));
|
|
27
|
-
console.log('');
|
|
28
|
-
|
|
29
|
-
for (const tier of LICENSE_TIERS) {
|
|
30
|
-
const isActive = tier.value === 'community';
|
|
31
|
-
const marker = isActive ? chalk.green('●') : chalk.gray('○');
|
|
32
|
-
console.log(` ${marker} ${chalk.bold(tier.name)}`);
|
|
33
|
-
console.log(` ${chalk.gray(tier.description)}`);
|
|
34
|
-
console.log('');
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const { tier } = await inquirer.prompt([
|
|
38
|
-
{
|
|
39
|
-
type: 'list',
|
|
40
|
-
name: 'tier',
|
|
41
|
-
message: chalk.white('Select a license tier:'),
|
|
42
|
-
choices: LICENSE_TIERS,
|
|
43
|
-
default: 'community',
|
|
44
|
-
},
|
|
45
|
-
]);
|
|
46
|
-
|
|
47
|
-
console.log('');
|
|
48
|
-
|
|
49
|
-
if (tier === 'community') {
|
|
50
|
-
success('Community license activated');
|
|
51
|
-
info('No key required. Run `pixelstart init` to get started.');
|
|
52
|
-
} else if (tier === 'pro') {
|
|
53
|
-
const { key } = await inquirer.prompt([
|
|
54
|
-
{
|
|
55
|
-
type: 'input',
|
|
56
|
-
name: 'key',
|
|
57
|
-
message: chalk.white('Enter your Pro license key:'),
|
|
58
|
-
validate: (input: string) => input.length > 0 || 'License key is required',
|
|
59
|
-
},
|
|
60
|
-
]);
|
|
61
|
-
|
|
62
|
-
if (key) {
|
|
63
|
-
success('Pro license activated');
|
|
64
|
-
info('Your license key has been validated and saved.');
|
|
65
|
-
}
|
|
66
|
-
} else {
|
|
67
|
-
info('Enterprise inquiries: contact@pixelstack.dev');
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
console.log('');
|
|
71
|
-
return tier;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export function getLicenseInfo(): { tier: string; features: string[] } {
|
|
75
|
-
return {
|
|
76
|
-
tier: 'community',
|
|
77
|
-
features: [
|
|
78
|
-
'PixelStack Lite (single container)',
|
|
79
|
-
'Up to 1 project',
|
|
80
|
-
'Community support via GitHub Issues',
|
|
81
|
-
'Standard themes and components',
|
|
82
|
-
],
|
|
83
|
-
};
|
|
84
|
-
}
|
package/src/modules/logo.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
|
-
|
|
3
|
-
export const logo = `
|
|
4
|
-
${chalk.hex('#7C3AED').bold(' ╔══════════════════════════════════╗')}
|
|
5
|
-
${chalk.hex('#7C3AED').bold(' ║ ║')}
|
|
6
|
-
${chalk.hex('#7C3AED').bold(' ║ ██████╗ ██╗██╗ ██╗███████╗██╗ ██████╗ ██████╗ ')}
|
|
7
|
-
${chalk.hex('#7C3AED').bold(' ║ ██╔══██╗██║╚██╗██╔╝██╔════╝██║ ██╔═══██╗██╔════╝ ')}
|
|
8
|
-
${chalk.hex('#7C3AED').bold(' ║ ██████╔╝██║ ╚███╔╝ █████╗ ██║ ██║ ██║██║ ███╗')}
|
|
9
|
-
${chalk.hex('#7C3AED').bold(' ║ ██╔═══╝ ██║ ██╔██╗ ██╔══╝ ██║ ██║ ██║██║ ██║')}
|
|
10
|
-
${chalk.hex('#7C3AED').bold(' ║ ██║ ██║██╔╝ ██╗███████╗███████╗╚██████╔╝╚██████╔╝')}
|
|
11
|
-
${chalk.hex('#7C3AED').bold(' ║ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚══════╝ ╚═════╝ ╚═════╝ ')}
|
|
12
|
-
${chalk.hex('#7C3AED').bold(' ║ ║')}
|
|
13
|
-
${chalk.hex('#7C3AED').bold(' ╚══════════════════════════════════╝')}
|
|
14
|
-
${chalk.gray(' Digital Experience Platform')}
|
|
15
|
-
`;
|
|
16
|
-
|
|
17
|
-
export function showLogo(): void {
|
|
18
|
-
console.clear();
|
|
19
|
-
console.log(logo);
|
|
20
|
-
console.log('');
|
|
21
|
-
}
|