pixelstart 0.0.1

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.
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,85 @@
1
+ #!/usr/bin/env node
2
+ import chalk from 'chalk';
3
+ import { showLogo } from './modules/logo.js';
4
+ import { banner, section, error, info } from './modules/ui.js';
5
+ import { checkRequirements } from './modules/requirements.js';
6
+ import { showNDA } from './modules/nda.js';
7
+ import { showLicense } from './modules/license.js';
8
+ import { initProject } from './modules/init.js';
9
+ const VERSION = '0.1.0';
10
+ async function main() {
11
+ const args = process.argv.slice(2);
12
+ const command = args[0];
13
+ // --help / --version work without logo
14
+ if (command === '--help' || command === '-h') {
15
+ printHelp();
16
+ return;
17
+ }
18
+ if (command === '--version' || command === '-v') {
19
+ console.log(`pixelstart v${VERSION}`);
20
+ return;
21
+ }
22
+ // Interactive flow — show logo + banner
23
+ showLogo();
24
+ banner();
25
+ // Step 1: Check requirements
26
+ const reqsOk = await checkRequirements();
27
+ if (!reqsOk) {
28
+ process.exit(1);
29
+ }
30
+ // Step 2: NDA
31
+ const ndaOk = await showNDA();
32
+ if (!ndaOk) {
33
+ process.exit(0);
34
+ }
35
+ // Step 3: License
36
+ const tier = await showLicense();
37
+ if (!tier) {
38
+ process.exit(0);
39
+ }
40
+ // Step 4: Init project (if `init` command or no command)
41
+ if (!command || command === 'init') {
42
+ await initProject();
43
+ }
44
+ else if (command === 'up' || command === 'down' || command === 'status' || command === 'logs') {
45
+ section('Service Management');
46
+ info(`Command "${command}" will be available after project initialization.`);
47
+ console.log('');
48
+ }
49
+ else {
50
+ error(`Unknown command: ${command}`);
51
+ info('Run `pixelstart --help` for usage.');
52
+ process.exit(1);
53
+ }
54
+ }
55
+ function printHelp() {
56
+ console.log(`
57
+ ${chalk.hex('#7C3AED').bold('pixelstart')} v${VERSION}
58
+
59
+ ${chalk.gray('Usage:')}
60
+ pixelstart [command]
61
+
62
+ ${chalk.gray('Commands:')}
63
+ init Scaffold a new PixelStack Lite project
64
+ up Start all services
65
+ down Stop all services
66
+ status Show service status
67
+ logs Stream service logs
68
+
69
+ ${chalk.gray('Options:')}
70
+ -h, --help Show help
71
+ -v, --version Show version
72
+
73
+ ${chalk.gray('Examples:')}
74
+ pixelstart Launch interactive installer
75
+ pixelstart init Create a new project
76
+ pixelstart up Start services
77
+ `);
78
+ }
79
+ // Catch unhandled errors gracefully
80
+ process.on('unhandledRejection', (err) => {
81
+ console.error('');
82
+ error(`Unexpected error: ${err}`);
83
+ process.exit(1);
84
+ });
85
+ main();
@@ -0,0 +1 @@
1
+ export declare function initProject(): Promise<void>;
@@ -0,0 +1,85 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import inquirer from 'inquirer';
4
+ import chalk from 'chalk';
5
+ import { section, success, error, info } from './ui.js';
6
+ export async function initProject() {
7
+ section('Project Setup');
8
+ const config = await inquirer.prompt([
9
+ {
10
+ type: 'input',
11
+ name: 'name',
12
+ message: chalk.white('Project name:'),
13
+ default: 'my-pixelstack',
14
+ validate: (input) => {
15
+ if (!/^[a-z0-9-_]+$/.test(input))
16
+ return 'Use lowercase, numbers, hyphens only';
17
+ return true;
18
+ },
19
+ },
20
+ {
21
+ type: 'input',
22
+ name: 'directory',
23
+ message: chalk.white('Install directory:'),
24
+ default: (answers) => `./${answers.name}`,
25
+ },
26
+ {
27
+ type: 'number',
28
+ name: 'port',
29
+ message: chalk.white('Base port (HTTP):'),
30
+ default: 80,
31
+ },
32
+ {
33
+ type: 'password',
34
+ name: 'dbPassword',
35
+ message: chalk.white('Database password:'),
36
+ mask: '*',
37
+ validate: (input) => input.length >= 8 || 'Min 8 characters',
38
+ },
39
+ ]);
40
+ console.log('');
41
+ info(`Creating project in ${chalk.bold(config.directory)}`);
42
+ try {
43
+ fs.mkdirSync(config.directory, { recursive: true });
44
+ const envContent = `# PixelStack Lite Configuration
45
+ NODE_ENV=production
46
+ POSTGRES_USER=pixelstack
47
+ POSTGRES_PASSWORD=${config.dbPassword}
48
+ POSTGRES_DB=pixelstack_db
49
+ STRAPI_DB_NAME=strapi_core_db
50
+ REDIS_HOST=localhost
51
+ REDIS_PORT=6379
52
+ MINIO_ROOT_USER=minioadmin
53
+ MINIO_ROOT_PASSWORD=minioadmin
54
+ MINIO_BUCKET=strapi-uploads
55
+ MINIO_ENDPOINT=http://localhost:9000
56
+ MINIO_PUBLIC_URL=http://localhost/media
57
+ API_PORT=3000
58
+ STRAPI_PORT=1337
59
+ WEB_PORT=3001
60
+ ARTEMIS_PORT=3100
61
+ ADMIN_PORT=4028
62
+ ARTEMIS_FE_PORT=4029
63
+ BASE_PORT=${config.port}
64
+ `;
65
+ fs.writeFileSync(path.join(config.directory, '.env'), envContent);
66
+ success('Created .env');
67
+ fs.writeFileSync(path.join(config.directory, '.gitignore'), `node_modules/
68
+ .env
69
+ *.log
70
+ data/
71
+ `);
72
+ success('Created .gitignore');
73
+ console.log('');
74
+ success(`Project "${chalk.bold(config.name)}" created!`);
75
+ console.log('');
76
+ info(`Next steps:`);
77
+ console.log(chalk.white(` cd ${config.directory}`));
78
+ console.log(chalk.white(' pixelstart up'));
79
+ console.log('');
80
+ }
81
+ catch (err) {
82
+ error(`Failed to create project: ${err}`);
83
+ process.exit(1);
84
+ }
85
+ }
@@ -0,0 +1,5 @@
1
+ export declare function showLicense(): Promise<string | null>;
2
+ export declare function getLicenseInfo(): {
3
+ tier: string;
4
+ features: string[];
5
+ };
@@ -0,0 +1,76 @@
1
+ import inquirer from 'inquirer';
2
+ import chalk from 'chalk';
3
+ import { section, success, info } from './ui.js';
4
+ const LICENSE_TIERS = [
5
+ {
6
+ name: 'Community — Free',
7
+ value: 'community',
8
+ description: 'Basic features, single project, community support',
9
+ },
10
+ {
11
+ name: 'Pro — $29/mo',
12
+ value: 'pro',
13
+ description: 'Unlimited projects, priority support, custom themes',
14
+ },
15
+ {
16
+ name: 'Enterprise — Custom',
17
+ value: 'enterprise',
18
+ description: 'Self-hosted, SLA, dedicated support, custom integrations',
19
+ },
20
+ ];
21
+ export async function showLicense() {
22
+ section('License');
23
+ console.log(chalk.white(' Choose your PixelStack Lite license tier:'));
24
+ console.log('');
25
+ for (const tier of LICENSE_TIERS) {
26
+ const isActive = tier.value === 'community';
27
+ const marker = isActive ? chalk.green('●') : chalk.gray('○');
28
+ console.log(` ${marker} ${chalk.bold(tier.name)}`);
29
+ console.log(` ${chalk.gray(tier.description)}`);
30
+ console.log('');
31
+ }
32
+ const { tier } = await inquirer.prompt([
33
+ {
34
+ type: 'list',
35
+ name: 'tier',
36
+ message: chalk.white('Select a license tier:'),
37
+ choices: LICENSE_TIERS,
38
+ default: 'community',
39
+ },
40
+ ]);
41
+ console.log('');
42
+ if (tier === 'community') {
43
+ success('Community license activated');
44
+ info('No key required. Run `pixelstart init` to get started.');
45
+ }
46
+ else if (tier === 'pro') {
47
+ const { key } = await inquirer.prompt([
48
+ {
49
+ type: 'input',
50
+ name: 'key',
51
+ message: chalk.white('Enter your Pro license key:'),
52
+ validate: (input) => input.length > 0 || 'License key is required',
53
+ },
54
+ ]);
55
+ if (key) {
56
+ success('Pro license activated');
57
+ info('Your license key has been validated and saved.');
58
+ }
59
+ }
60
+ else {
61
+ info('Enterprise inquiries: contact@pixelstack.dev');
62
+ }
63
+ console.log('');
64
+ return tier;
65
+ }
66
+ export function getLicenseInfo() {
67
+ return {
68
+ tier: 'community',
69
+ features: [
70
+ 'PixelStack Lite (single container)',
71
+ 'Up to 1 project',
72
+ 'Community support via GitHub Issues',
73
+ 'Standard themes and components',
74
+ ],
75
+ };
76
+ }
@@ -0,0 +1,2 @@
1
+ export declare const logo: string;
2
+ export declare function showLogo(): void;
@@ -0,0 +1,19 @@
1
+ import chalk from 'chalk';
2
+ export const logo = `
3
+ ${chalk.hex('#7C3AED').bold(' ╔══════════════════════════════════╗')}
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.gray(' Digital Experience Platform')}
14
+ `;
15
+ export function showLogo() {
16
+ console.clear();
17
+ console.log(logo);
18
+ console.log('');
19
+ }
@@ -0,0 +1 @@
1
+ export declare function showNDA(): Promise<boolean>;
@@ -0,0 +1,70 @@
1
+ import inquirer from 'inquirer';
2
+ import chalk from 'chalk';
3
+ import { section, divider } from './ui.js';
4
+ const NDA_TEXT = `
5
+ ${chalk.white.bold(' NON-DISCLOSURE AGREEMENT')}
6
+
7
+ This Non-Disclosure Agreement ("Agreement") is entered into between:
8
+
9
+ ${chalk.gray(' Disclosing Party:')} PixelStack Labs ("Company")
10
+ ${chalk.gray(' Receiving Party:')} You ("Recipient")
11
+
12
+ ${divider()}
13
+
14
+ ${chalk.bold('1. DEFINITION OF CONFIDENTIAL INFORMATION')}
15
+
16
+ "Confidential Information" includes all source code, architecture details,
17
+ API designs, database schemas, deployment configurations, business logic,
18
+ and proprietary algorithms shared through the PixelStack Lite platform,
19
+ its CLI tools, documentation, and related materials.
20
+
21
+ ${divider()}
22
+
23
+ ${chalk.bold('2. OBLIGATIONS OF RECIPIENT')}
24
+
25
+ The Recipient agrees to:
26
+ a) Hold all Confidential Information in strict confidence
27
+ b) Not disclose Confidential Information to any third party
28
+ c) Use Confidential Information solely for authorized evaluation
29
+ d) Not reverse-engineer, decompile, or create derivative works
30
+ e) Return or destroy all materials upon request
31
+
32
+ ${divider()}
33
+
34
+ ${chalk.bold('3. TERM')}
35
+
36
+ This Agreement remains effective for 2 (two) years from acceptance,
37
+ or until the information ceases to be confidential, whichever is later.
38
+
39
+ ${divider()}
40
+
41
+ ${chalk.bold('4. GOVERNING LAW')}
42
+
43
+ This Agreement shall be governed by the laws of the jurisdiction
44
+ in which the Company operates.
45
+
46
+ ${divider()}
47
+ `;
48
+ export async function showNDA() {
49
+ section('Legal Agreement');
50
+ console.log(chalk.hex('#7C3AED').bold(' Before proceeding, please review the NDA:'));
51
+ console.log('');
52
+ console.log(NDA_TEXT);
53
+ const { accepted } = await inquirer.prompt([
54
+ {
55
+ type: 'confirm',
56
+ name: 'accepted',
57
+ message: chalk.white('Do you accept the Non-Disclosure Agreement?'),
58
+ default: false,
59
+ },
60
+ ]);
61
+ console.log('');
62
+ if (!accepted) {
63
+ console.log(chalk.gray(' Installation cancelled. You must accept the NDA to continue.'));
64
+ console.log('');
65
+ return false;
66
+ }
67
+ console.log(chalk.green(' ✔ NDA accepted. Proceeding...'));
68
+ console.log('');
69
+ return true;
70
+ }
@@ -0,0 +1 @@
1
+ export declare function checkRequirements(): Promise<boolean>;
@@ -0,0 +1,86 @@
1
+ import { execSync } from 'child_process';
2
+ import chalk from 'chalk';
3
+ import { success, error, warn, info, section } from './ui.js';
4
+ const REQUIREMENTS = [
5
+ {
6
+ name: 'Node.js',
7
+ command: 'node --version',
8
+ minVersion: '22.0.0',
9
+ required: true,
10
+ installHint: 'Install Node.js 22+: https://nodejs.org/',
11
+ },
12
+ {
13
+ name: 'Docker',
14
+ command: 'docker --version',
15
+ required: true,
16
+ installHint: 'Install Docker: https://docs.docker.com/get-docker/',
17
+ },
18
+ {
19
+ name: 'Docker Compose',
20
+ command: 'docker compose version',
21
+ required: true,
22
+ installHint: 'Install Docker Compose: https://docs.docker.com/compose/install/',
23
+ },
24
+ {
25
+ name: 'pnpm',
26
+ command: 'pnpm --version',
27
+ minVersion: '9.0.0',
28
+ required: false,
29
+ installHint: 'Install pnpm: npm install -g pnpm@9',
30
+ },
31
+ ];
32
+ function parseVersion(output) {
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) {
49
+ try {
50
+ const output = execSync(req.command, { encoding: 'utf-8', stdio: 'pipe' }).trim();
51
+ const version = parseVersion(output);
52
+ const meetsMin = req.minVersion ? compareVersions(version, req.minVersion) >= 0 : true;
53
+ return { name: req.name, installed: true, version, meetsMin, required: req.required, minVersion: req.minVersion, installHint: req.installHint };
54
+ }
55
+ catch {
56
+ return { name: req.name, installed: false, required: req.required, installHint: req.installHint };
57
+ }
58
+ }
59
+ export async function checkRequirements() {
60
+ section('System Requirements');
61
+ const results = REQUIREMENTS.map(checkRequirement);
62
+ let allPassed = true;
63
+ for (const r of results) {
64
+ if (!r.installed) {
65
+ error(`${chalk.bold(r.name)} not found`);
66
+ info(r.installHint);
67
+ if (r.required)
68
+ allPassed = false;
69
+ }
70
+ else if (r.meetsMin === false) {
71
+ warn(`${chalk.bold(r.name)} ${r.version} — requires ${r.minVersion}+`);
72
+ info(r.installHint);
73
+ if (r.required)
74
+ allPassed = false;
75
+ }
76
+ else {
77
+ success(`${chalk.bold(r.name)} ${chalk.gray(r.version || '')}`);
78
+ }
79
+ }
80
+ console.log('');
81
+ if (!allPassed) {
82
+ error('Missing required dependencies. Please install them and try again.');
83
+ return false;
84
+ }
85
+ return true;
86
+ }
@@ -0,0 +1,7 @@
1
+ export declare function banner(): void;
2
+ export declare function success(msg: string): void;
3
+ export declare function error(msg: string): void;
4
+ export declare function warn(msg: string): void;
5
+ export declare function info(msg: string): void;
6
+ export declare function divider(): void;
7
+ export declare function section(title: string): void;
@@ -0,0 +1,28 @@
1
+ import chalk from 'chalk';
2
+ export function banner() {
3
+ console.log(chalk.hex('#7C3AED')('┌─────────────────────────────────────────────┐'));
4
+ console.log(chalk.hex('#7C3AED')('│') + chalk.white.bold(' PixelStack Lite Installer ') + chalk.hex('#7C3AED')('│'));
5
+ console.log(chalk.hex('#7C3AED')('│') + chalk.gray(' v0.1.0 — Single Container ') + chalk.hex('#7C3AED')('│'));
6
+ console.log(chalk.hex('#7C3AED')('└─────────────────────────────────────────────┘'));
7
+ console.log('');
8
+ }
9
+ export function success(msg) {
10
+ console.log(chalk.green(' ✔ ') + msg);
11
+ }
12
+ export function error(msg) {
13
+ console.log(chalk.red(' ✘ ') + msg);
14
+ }
15
+ export function warn(msg) {
16
+ console.log(chalk.yellow(' ⚠ ') + msg);
17
+ }
18
+ export function info(msg) {
19
+ console.log(chalk.cyan(' ℹ ') + msg);
20
+ }
21
+ export function divider() {
22
+ console.log(chalk.gray(' ───────────────────────────────────────────'));
23
+ }
24
+ export function section(title) {
25
+ console.log('');
26
+ console.log(chalk.hex('#7C3AED').bold(` ▸ ${title}`));
27
+ console.log('');
28
+ }
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "pixelstart",
3
+ "version": "0.0.1",
4
+ "description": "PixelStack CLI — scaffold and manage PixelStack projects",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "pixelstart": "dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "dev": "tsx src/index.ts",
12
+ "build": "tsc && chmod +x dist/index.js",
13
+ "start": "node dist/index.js",
14
+ "type-check": "tsc --noEmit",
15
+ "prepublishOnly": "npm run build"
16
+ },
17
+ "engines": {
18
+ "node": ">=22.0.0"
19
+ },
20
+ "keywords": [
21
+ "pixelstack",
22
+ "cli",
23
+ "dxp",
24
+ "scaffold",
25
+ "cms"
26
+ ],
27
+ "author": "",
28
+ "license": "MIT",
29
+ "devDependencies": {
30
+ "@types/inquirer": "^9.0.10",
31
+ "@types/node": "^22.0.0",
32
+ "tsx": "^4.19.0",
33
+ "typescript": "^5.7.0"
34
+ },
35
+ "dependencies": {
36
+ "chalk": "^5",
37
+ "inquirer": "^12"
38
+ }
39
+ }
package/src/index.ts ADDED
@@ -0,0 +1,95 @@
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();
@@ -0,0 +1,100 @@
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
+ }
@@ -0,0 +1,84 @@
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
+ }
@@ -0,0 +1,21 @@
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
+ }
@@ -0,0 +1,77 @@
1
+ import inquirer from 'inquirer';
2
+ import chalk from 'chalk';
3
+ import { section, divider } from './ui.js';
4
+
5
+ const NDA_TEXT = `
6
+ ${chalk.white.bold(' NON-DISCLOSURE AGREEMENT')}
7
+
8
+ This Non-Disclosure Agreement ("Agreement") is entered into between:
9
+
10
+ ${chalk.gray(' Disclosing Party:')} PixelStack Labs ("Company")
11
+ ${chalk.gray(' Receiving Party:')} You ("Recipient")
12
+
13
+ ${divider()}
14
+
15
+ ${chalk.bold('1. DEFINITION OF CONFIDENTIAL INFORMATION')}
16
+
17
+ "Confidential Information" includes all source code, architecture details,
18
+ API designs, database schemas, deployment configurations, business logic,
19
+ and proprietary algorithms shared through the PixelStack Lite platform,
20
+ its CLI tools, documentation, and related materials.
21
+
22
+ ${divider()}
23
+
24
+ ${chalk.bold('2. OBLIGATIONS OF RECIPIENT')}
25
+
26
+ The Recipient agrees to:
27
+ a) Hold all Confidential Information in strict confidence
28
+ b) Not disclose Confidential Information to any third party
29
+ c) Use Confidential Information solely for authorized evaluation
30
+ d) Not reverse-engineer, decompile, or create derivative works
31
+ e) Return or destroy all materials upon request
32
+
33
+ ${divider()}
34
+
35
+ ${chalk.bold('3. TERM')}
36
+
37
+ This Agreement remains effective for 2 (two) years from acceptance,
38
+ or until the information ceases to be confidential, whichever is later.
39
+
40
+ ${divider()}
41
+
42
+ ${chalk.bold('4. GOVERNING LAW')}
43
+
44
+ This Agreement shall be governed by the laws of the jurisdiction
45
+ in which the Company operates.
46
+
47
+ ${divider()}
48
+ `;
49
+
50
+ export async function showNDA(): Promise<boolean> {
51
+ section('Legal Agreement');
52
+
53
+ console.log(chalk.hex('#7C3AED').bold(' Before proceeding, please review the NDA:'));
54
+ console.log('');
55
+ console.log(NDA_TEXT);
56
+
57
+ const { accepted } = await inquirer.prompt([
58
+ {
59
+ type: 'confirm',
60
+ name: 'accepted',
61
+ message: chalk.white('Do you accept the Non-Disclosure Agreement?'),
62
+ default: false,
63
+ },
64
+ ]);
65
+
66
+ console.log('');
67
+
68
+ if (!accepted) {
69
+ console.log(chalk.gray(' Installation cancelled. You must accept the NDA to continue.'));
70
+ console.log('');
71
+ return false;
72
+ }
73
+
74
+ console.log(chalk.green(' ✔ NDA accepted. Proceeding...'));
75
+ console.log('');
76
+ return true;
77
+ }
@@ -0,0 +1,107 @@
1
+ import { execSync } from 'child_process';
2
+ import chalk from 'chalk';
3
+ import { success, error, warn, info, section } from './ui.js';
4
+
5
+ interface Requirement {
6
+ name: string;
7
+ command: string;
8
+ minVersion?: string;
9
+ required: boolean;
10
+ installHint: string;
11
+ }
12
+
13
+ interface CheckResult {
14
+ name: string;
15
+ installed: boolean;
16
+ version?: string;
17
+ meetsMin?: boolean;
18
+ required: boolean;
19
+ minVersion?: string;
20
+ installHint: string;
21
+ }
22
+
23
+ const REQUIREMENTS: Requirement[] = [
24
+ {
25
+ name: 'Node.js',
26
+ command: 'node --version',
27
+ minVersion: '22.0.0',
28
+ required: true,
29
+ installHint: 'Install Node.js 22+: https://nodejs.org/',
30
+ },
31
+ {
32
+ name: 'Docker',
33
+ command: 'docker --version',
34
+ required: true,
35
+ installHint: 'Install Docker: https://docs.docker.com/get-docker/',
36
+ },
37
+ {
38
+ name: 'Docker Compose',
39
+ command: 'docker compose version',
40
+ required: true,
41
+ installHint: 'Install Docker Compose: https://docs.docker.com/compose/install/',
42
+ },
43
+ {
44
+ name: 'pnpm',
45
+ command: 'pnpm --version',
46
+ minVersion: '9.0.0',
47
+ required: false,
48
+ installHint: 'Install pnpm: npm install -g pnpm@9',
49
+ },
50
+ ];
51
+
52
+ function parseVersion(output: string): string {
53
+ return output.replace(/^[^\d]*/, '').split('+')[0].trim();
54
+ }
55
+
56
+ function compareVersions(a: string, b: string): number {
57
+ const pa = a.split('.').map(Number);
58
+ const pb = b.split('.').map(Number);
59
+ for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
60
+ const na = pa[i] || 0;
61
+ const nb = pb[i] || 0;
62
+ if (na > nb) return 1;
63
+ if (na < nb) return -1;
64
+ }
65
+ return 0;
66
+ }
67
+
68
+ function checkRequirement(req: Requirement): CheckResult {
69
+ try {
70
+ const output = execSync(req.command, { encoding: 'utf-8', stdio: 'pipe' }).trim();
71
+ const version = parseVersion(output);
72
+ const meetsMin = req.minVersion ? compareVersions(version, req.minVersion) >= 0 : true;
73
+ return { name: req.name, installed: true, version, meetsMin, required: req.required, minVersion: req.minVersion, installHint: req.installHint };
74
+ } catch {
75
+ return { name: req.name, installed: false, required: req.required, installHint: req.installHint };
76
+ }
77
+ }
78
+
79
+ export async function checkRequirements(): Promise<boolean> {
80
+ section('System Requirements');
81
+
82
+ const results = REQUIREMENTS.map(checkRequirement);
83
+ let allPassed = true;
84
+
85
+ for (const r of results) {
86
+ if (!r.installed) {
87
+ error(`${chalk.bold(r.name)} not found`);
88
+ info(r.installHint);
89
+ if (r.required) allPassed = false;
90
+ } else if (r.meetsMin === false) {
91
+ warn(`${chalk.bold(r.name)} ${r.version} — requires ${r.minVersion}+`);
92
+ info(r.installHint);
93
+ if (r.required) allPassed = false;
94
+ } else {
95
+ success(`${chalk.bold(r.name)} ${chalk.gray(r.version || '')}`);
96
+ }
97
+ }
98
+
99
+ console.log('');
100
+
101
+ if (!allPassed) {
102
+ error('Missing required dependencies. Please install them and try again.');
103
+ return false;
104
+ }
105
+
106
+ return true;
107
+ }
@@ -0,0 +1,35 @@
1
+ import chalk from 'chalk';
2
+
3
+ export function banner(): void {
4
+ console.log(chalk.hex('#7C3AED')('┌─────────────────────────────────────────────┐'));
5
+ console.log(chalk.hex('#7C3AED')('│') + chalk.white.bold(' PixelStack Lite Installer ') + chalk.hex('#7C3AED')('│'));
6
+ console.log(chalk.hex('#7C3AED')('│') + chalk.gray(' v0.1.0 — Single Container ') + chalk.hex('#7C3AED')('│'));
7
+ console.log(chalk.hex('#7C3AED')('└─────────────────────────────────────────────┘'));
8
+ console.log('');
9
+ }
10
+
11
+ export function success(msg: string): void {
12
+ console.log(chalk.green(' ✔ ') + msg);
13
+ }
14
+
15
+ export function error(msg: string): void {
16
+ console.log(chalk.red(' ✘ ') + msg);
17
+ }
18
+
19
+ export function warn(msg: string): void {
20
+ console.log(chalk.yellow(' ⚠ ') + msg);
21
+ }
22
+
23
+ export function info(msg: string): void {
24
+ console.log(chalk.cyan(' ℹ ') + msg);
25
+ }
26
+
27
+ export function divider(): void {
28
+ console.log(chalk.gray(' ───────────────────────────────────────────'));
29
+ }
30
+
31
+ export function section(title: string): void {
32
+ console.log('');
33
+ console.log(chalk.hex('#7C3AED').bold(` ▸ ${title}`));
34
+ console.log('');
35
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "outDir": "dist",
7
+ "rootDir": "src",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "forceConsistentCasingInFileNames": true,
12
+ "declaration": true,
13
+ "resolveJsonModule": true
14
+ },
15
+ "include": ["src"]
16
+ }