fabrica-e-commerce 0.1.17 → 0.2.2
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/package.json +12 -5
- package/src/clean.js +184 -0
- package/src/cli.js +84 -54
- package/src/deps.js +160 -52
- package/src/sql.js +227 -16
- package/src/ui.js +100 -73
package/src/ui.js
CHANGED
|
@@ -1,60 +1,50 @@
|
|
|
1
1
|
import process from 'node:process';
|
|
2
2
|
import boxen from 'boxen';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export const
|
|
9
|
-
export const
|
|
10
|
-
export const
|
|
11
|
-
export const
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import gradient from 'gradient-string';
|
|
5
|
+
import figures from 'figures';
|
|
6
|
+
|
|
7
|
+
// ── palette ───────────────────────────────────────────────────────────────────
|
|
8
|
+
export const orange = (t) => chalk.hex('#ff8a00')(t);
|
|
9
|
+
export const dimOrange = (t) => chalk.hex('#b65f00')(t);
|
|
10
|
+
export const bold = (t) => chalk.bold(t);
|
|
11
|
+
export const red = (t) => chalk.hex('#dc3232')(t);
|
|
12
|
+
export const dim = (t) => chalk.dim(t);
|
|
13
|
+
export const green = (t) => chalk.hex('#50c850')(t);
|
|
14
|
+
export const cyan = (t) => chalk.hex('#00c8ff')(t);
|
|
15
|
+
export const yellow = (t) => chalk.hex('#ffc846')(t);
|
|
16
|
+
export const gray = (t) => chalk.hex('#888888')(t);
|
|
17
|
+
export const white = (t) => chalk.white(t);
|
|
12
18
|
|
|
13
19
|
// strip ANSI for length calculations
|
|
14
20
|
function stripAnsi(s) { return s.replace(/\x1b\[[0-9;]*m/g, ''); }
|
|
15
21
|
|
|
16
22
|
// ── section buffer ─────────────────────────────────────────────────────────────
|
|
17
|
-
// Each section accumulates lines, then flushes as ONE boxen box when the
|
|
18
|
-
// next section (or flushSection) is called.
|
|
19
23
|
let _currentTitle = null;
|
|
20
|
-
let _lines = [];
|
|
24
|
+
let _lines = [];
|
|
21
25
|
let _sectionCount = 0;
|
|
22
|
-
let _isError = false;
|
|
23
26
|
|
|
24
27
|
function flushSection() {
|
|
25
28
|
if (_currentTitle === null) return;
|
|
26
|
-
|
|
27
29
|
const content = _lines.join('\n');
|
|
28
30
|
const rendered = boxen(content || ' ', {
|
|
29
|
-
title: bold(orange(_currentTitle))
|
|
31
|
+
title: ` ${bold(orange(_currentTitle))} `,
|
|
30
32
|
titleAlignment: 'left',
|
|
31
|
-
padding: { top: 0, bottom: 0, left:
|
|
33
|
+
padding: { top: 0, bottom: 0, left: 2, right: 2 },
|
|
32
34
|
margin: { top: 0, bottom: 0, left: 0, right: 0 },
|
|
33
35
|
borderStyle: 'round',
|
|
34
36
|
borderColor: '#ff8a00',
|
|
35
37
|
});
|
|
36
|
-
|
|
37
|
-
if (_sectionCount > 1) console.log(orange(' │'));
|
|
38
|
+
if (_sectionCount > 1) console.log(dimOrange(' │'));
|
|
38
39
|
console.log(rendered);
|
|
39
|
-
|
|
40
40
|
_currentTitle = null;
|
|
41
41
|
_lines = [];
|
|
42
|
-
_isError = false;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Add a line into the current section buffer
|
|
46
|
-
function addLine(text) {
|
|
47
|
-
_lines.push(text);
|
|
48
42
|
}
|
|
49
43
|
|
|
50
|
-
|
|
51
|
-
flushSection();
|
|
52
|
-
_sectionCount = 0;
|
|
53
|
-
}
|
|
44
|
+
function addLine(text) { _lines.push(text); }
|
|
54
45
|
|
|
55
|
-
|
|
46
|
+
export function resetSectionCount() { flushSection(); _sectionCount = 0; }
|
|
56
47
|
|
|
57
|
-
// Start a new named section (flushes previous one)
|
|
58
48
|
export function section(title) {
|
|
59
49
|
flushSection();
|
|
60
50
|
_sectionCount++;
|
|
@@ -62,49 +52,56 @@ export function section(title) {
|
|
|
62
52
|
_lines = [];
|
|
63
53
|
}
|
|
64
54
|
|
|
65
|
-
|
|
66
|
-
export function endSections() {
|
|
67
|
-
flushSection();
|
|
68
|
-
}
|
|
55
|
+
export function endSections() { flushSection(); }
|
|
69
56
|
|
|
70
|
-
// kv row inside current section
|
|
71
57
|
export function kv(key, value) {
|
|
72
|
-
|
|
58
|
+
const k = bold(orange(key));
|
|
59
|
+
const arrow = dimOrange(figures.arrowRight);
|
|
60
|
+
const v = typeof value === 'string' && value.startsWith('http') ? cyan(value) : white(String(value));
|
|
61
|
+
addLine(` ${dimOrange(figures.pointer)} ${k} ${arrow} ${v}`);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function kvSuccess(key, value) {
|
|
65
|
+
addLine(` ${green(figures.tick)} ${bold(key)} ${dimOrange(figures.arrowRight)} ${green(String(value))}`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function kvFail(key, value) {
|
|
69
|
+
addLine(` ${red(figures.cross)} ${bold(key)} ${dimOrange(figures.arrowRight)} ${red(String(value))}`);
|
|
73
70
|
}
|
|
74
71
|
|
|
75
|
-
// spinner —
|
|
72
|
+
// spinner — inline stdout, then adds result line to buffer
|
|
76
73
|
const CLEAR_LINE = '\x1b[K';
|
|
77
74
|
export function spinner(text) {
|
|
78
|
-
process.stdout.write(`
|
|
75
|
+
process.stdout.write(` ${dimOrange(figures.ellipsis)} ${dim(text)}`);
|
|
79
76
|
return {
|
|
80
77
|
succeed(msg) {
|
|
81
78
|
process.stdout.write(`\r${CLEAR_LINE}`);
|
|
82
|
-
addLine(`
|
|
79
|
+
addLine(` ${green(figures.tick)} ${msg}`);
|
|
83
80
|
},
|
|
84
81
|
fail(msg) {
|
|
85
82
|
process.stdout.write(`\r${CLEAR_LINE}`);
|
|
86
|
-
addLine(`
|
|
83
|
+
addLine(` ${red(figures.cross)} ${msg}`);
|
|
87
84
|
},
|
|
88
85
|
};
|
|
89
86
|
}
|
|
90
87
|
|
|
91
|
-
|
|
92
|
-
export function
|
|
93
|
-
|
|
94
|
-
|
|
88
|
+
export function log(text) { addLine(` ${dim(figures.line)} ${text}`); }
|
|
89
|
+
export function logInfo(text) { addLine(` ${cyan(figures.info)} ${text}`); }
|
|
90
|
+
export function logWarn(text) { addLine(` ${yellow(figures.warning)} ${yellow(text)}`); }
|
|
91
|
+
|
|
92
|
+
export function divider() { addLine(` ${dimOrange('─'.repeat(48))}`); }
|
|
95
93
|
|
|
96
|
-
// sub-step block
|
|
94
|
+
// sub-step block
|
|
97
95
|
export function subBox(lines, { isError = false } = {}) {
|
|
98
96
|
if (!lines || !lines.length) return;
|
|
99
|
-
const colored = isError ? lines.map((l) => red(l)) : lines.map((l) =>
|
|
97
|
+
const colored = isError ? lines.map((l) => red(l)) : lines.map((l) => dim(l));
|
|
100
98
|
const content = colored.join('\n');
|
|
101
99
|
const rendered = boxen(content, {
|
|
102
|
-
padding: { top: 0, bottom: 0, left:
|
|
103
|
-
margin: { top: 0, bottom: 0, left:
|
|
100
|
+
padding: { top: 0, bottom: 0, left: 2, right: 2 },
|
|
101
|
+
margin: { top: 0, bottom: 0, left: 3, right: 0 },
|
|
104
102
|
borderStyle: 'single',
|
|
105
103
|
borderColor: isError ? '#dc3232' : '#b65f00',
|
|
106
104
|
});
|
|
107
|
-
// add each rendered line into buffer so it stays inside the section box
|
|
108
105
|
for (const line of rendered.split('\n')) addLine(line);
|
|
109
106
|
}
|
|
110
107
|
|
|
@@ -116,55 +113,85 @@ export function banner() {
|
|
|
116
113
|
_lines = [];
|
|
117
114
|
|
|
118
115
|
const art = [
|
|
119
|
-
'███████╗ █████╗ ██████╗ ██████╗ ██╗ ██████╗ █████╗
|
|
116
|
+
'███████╗ █████╗ ██████╗ ██████╗ ██╗ ██████╗ █████╗',
|
|
120
117
|
'██╔════╝██╔══██╗██╔══██╗██╔══██╗██║██╔════╝██╔══██╗',
|
|
121
118
|
'█████╗ ███████║██████╔╝██████╔╝██║██║ ███████║',
|
|
122
119
|
'██╔══╝ ██╔══██║██╔══██╗██╔══██╗██║██║ ██╔══██║',
|
|
123
120
|
'██║ ██║ ██║██████╔╝██║ ██║██║╚██████╗██║ ██║',
|
|
124
121
|
'╚═╝ ╚═╝ ╚═╝╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═════╝╚═╝ ╚═╝',
|
|
125
|
-
]
|
|
122
|
+
];
|
|
123
|
+
|
|
124
|
+
const gradientArt = gradient(['#ff8a00', '#ff4500', '#ff8a00'])(art.join('\n'));
|
|
126
125
|
|
|
127
126
|
const subtitle = [
|
|
128
|
-
|
|
129
|
-
dim('by SPARROW AI SOLUTION'),
|
|
127
|
+
cyan(' Supabase + Vercel · Deploy in minutes'),
|
|
128
|
+
dim(' by SPARROW AI SOLUTION'),
|
|
130
129
|
].join('\n');
|
|
131
130
|
|
|
132
|
-
console.log(boxen(`${
|
|
133
|
-
padding: { top:
|
|
131
|
+
console.log(boxen(`${gradientArt}\n\n${subtitle}`, {
|
|
132
|
+
padding: { top: 1, bottom: 1, left: 3, right: 3 },
|
|
134
133
|
borderStyle: 'double',
|
|
135
134
|
borderColor: '#ff8a00',
|
|
135
|
+
textAlignment: 'center',
|
|
136
136
|
}));
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
// ── help ──────────────────────────────────────────────────────────────────────
|
|
140
140
|
export function help() {
|
|
141
141
|
banner();
|
|
142
|
+
|
|
143
|
+
const commands = [
|
|
144
|
+
{ cmd: 'build', desc: 'Connect Supabase · collect secrets · deploy or run locally' },
|
|
145
|
+
{ cmd: 'list', desc: 'Show all Fabrica projects (local & cloud)' },
|
|
146
|
+
{ cmd: 'env', desc: 'View and update environment variables for any project' },
|
|
147
|
+
{ cmd: 'rerun', desc: 'Re-run or re-open an existing project' },
|
|
148
|
+
{ cmd: 'vins', desc: 'Verify & auto-install CLI dependencies (git, gh, vercel)' },
|
|
149
|
+
{ cmd: 'clean', desc: 'Remove local data, env files, or logout from Vercel / GitHub' },
|
|
150
|
+
{ cmd: 'info', desc: 'Package, bridge, repo and storage info' },
|
|
151
|
+
{ cmd: 'help', desc: 'Show this help screen' },
|
|
152
|
+
];
|
|
153
|
+
|
|
154
|
+
const cmdRows = commands.map(({ cmd, desc }) =>
|
|
155
|
+
` ${bold(orange(cmd.padEnd(10)))} ${dim(desc)}`
|
|
156
|
+
).join('\n');
|
|
157
|
+
|
|
158
|
+
const examples = [
|
|
159
|
+
` ${dimOrange('$')} npx fabrica-e-commerce build`,
|
|
160
|
+
` ${dimOrange('$')} npx fabrica-e-commerce vins`,
|
|
161
|
+
` ${dimOrange('$')} npx fabrica-e-commerce list`,
|
|
162
|
+
` ${dimOrange('$')} npx fabrica-e-commerce clean`,
|
|
163
|
+
` ${dimOrange('$')} npx fabrica-e-commerce env`,
|
|
164
|
+
` ${dimOrange('$')} npx fabrica-e-commerce rerun`,
|
|
165
|
+
].join('\n');
|
|
166
|
+
|
|
142
167
|
const content = [
|
|
143
|
-
bold(orange('Commands')),
|
|
168
|
+
bold(orange(' Commands')),
|
|
169
|
+
dimOrange(' ' + '─'.repeat(52)),
|
|
144
170
|
'',
|
|
145
|
-
|
|
146
|
-
` ${bold('list')} Show Fabrica projects (local & cloud)`,
|
|
147
|
-
` ${bold('env')} View and update environment variables for any project`,
|
|
148
|
-
` ${bold('rerun')} Re-run or re-open an existing project`,
|
|
149
|
-
` ${bold('vins')} Verify & auto-install CLI dependencies`,
|
|
150
|
-
` ${bold('info')} Package, bridge, repo and storage info`,
|
|
151
|
-
` ${bold('help')} Show this screen`,
|
|
171
|
+
cmdRows,
|
|
152
172
|
'',
|
|
153
|
-
bold(orange('Examples')),
|
|
173
|
+
bold(orange(' Examples')),
|
|
174
|
+
dimOrange(' ' + '─'.repeat(52)),
|
|
154
175
|
'',
|
|
155
|
-
|
|
156
|
-
` ${dimOrange('$')} npx fabrica-e-commerce env`,
|
|
157
|
-
` ${dimOrange('$')} npx fabrica-e-commerce rerun`,
|
|
158
|
-
` ${dimOrange('$')} npx fabrica-e-commerce list`,
|
|
176
|
+
examples,
|
|
159
177
|
'',
|
|
160
|
-
dim(
|
|
178
|
+
dim(` Creator: SPARROW AI SOLUTION · MIT License`),
|
|
161
179
|
].join('\n');
|
|
162
|
-
|
|
180
|
+
|
|
181
|
+
console.log(dimOrange(' │'));
|
|
163
182
|
console.log(boxen(content, {
|
|
164
|
-
title: bold(orange('Help'))
|
|
183
|
+
title: ` ${bold(orange('Help & Commands'))} `,
|
|
165
184
|
titleAlignment: 'left',
|
|
166
|
-
padding: { top:
|
|
185
|
+
padding: { top: 1, bottom: 1, left: 1, right: 1 },
|
|
167
186
|
borderStyle: 'round',
|
|
168
187
|
borderColor: '#ff8a00',
|
|
169
188
|
}));
|
|
170
189
|
}
|
|
190
|
+
|
|
191
|
+
// ── step progress ─────────────────────────────────────────────────────────────
|
|
192
|
+
export function stepHeader(step, total, title) {
|
|
193
|
+
endSections();
|
|
194
|
+
const badge = orange(`[${step}/${total}]`);
|
|
195
|
+
const line = `${badge} ${bold(white(title))}`;
|
|
196
|
+
console.log(`\n ${dimOrange(figures.arrowRight)} ${line}`);
|
|
197
|
+
}
|