slicejs-cli 2.2.5 → 2.2.6
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/commands/buildProduction/buildProduction.js +221 -350
- package/commands/startServer/startServer.js +34 -11
- package/package.json +28 -28
- package/post.js +29 -52
|
@@ -1,274 +1,198 @@
|
|
|
1
|
-
// commands/buildProduction/buildProduction.js
|
|
1
|
+
// commands/buildProduction/buildProduction.js - CON SLICECONFIG PORT
|
|
2
2
|
|
|
3
3
|
import fs from 'fs-extra';
|
|
4
4
|
import path from 'path';
|
|
5
5
|
import { fileURLToPath } from 'url';
|
|
6
|
-
import
|
|
6
|
+
import UglifyJS from 'uglify-js';
|
|
7
|
+
import { minify } from 'html-minifier-terser';
|
|
7
8
|
import CleanCSS from 'clean-css';
|
|
8
|
-
import htmlMinifier from 'html-minifier-terser';
|
|
9
9
|
import Print from '../Print.js';
|
|
10
10
|
|
|
11
11
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
14
|
+
* Carga la configuración desde sliceConfig.json
|
|
15
15
|
*/
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
keep_classnames: true, // IMPORTANTE: Preservar nombres de clases
|
|
25
|
-
keep_fnames: true // IMPORTANTE: Preservar nombres de funciones
|
|
26
|
-
},
|
|
27
|
-
mangle: {
|
|
28
|
-
toplevel: false, // NO hacer mangle a nivel superior
|
|
29
|
-
keep_classnames: true, // Preservar nombres de clases
|
|
30
|
-
keep_fnames: true, // Preservar nombres de funciones
|
|
31
|
-
reserved: [
|
|
32
|
-
// Framework core
|
|
33
|
-
'Slice', 'Controller', 'StylesManager', 'ThemeManager', 'Logger',
|
|
34
|
-
// Métodos importantes
|
|
35
|
-
'slice', 'build', 'init', 'attachTemplate', 'getComponent',
|
|
36
|
-
// Eventos y propiedades de componentes
|
|
37
|
-
'constructor', 'connectedCallback', 'disconnectedCallback',
|
|
38
|
-
'attributeChangedCallback', 'adoptedCallback',
|
|
39
|
-
// Variables comunes en componentes
|
|
40
|
-
'componentName', 'props', 'options', 'value', 'disabled',
|
|
41
|
-
// HTML Elements y DOM
|
|
42
|
-
'HTMLElement', 'customElements', 'define', 'querySelector',
|
|
43
|
-
'querySelectorAll', 'addEventListener', 'removeEventListener',
|
|
44
|
-
// Métodos de componentes Slice.js
|
|
45
|
-
'setComponentProps', 'componentCategories', 'templates',
|
|
46
|
-
'activeComponents', 'classes', 'requestedStyles'
|
|
47
|
-
]
|
|
48
|
-
},
|
|
49
|
-
output: {
|
|
50
|
-
comments: false,
|
|
51
|
-
beautify: false,
|
|
52
|
-
keep_quoted_props: true // Preservar propiedades entre comillas
|
|
53
|
-
},
|
|
54
|
-
toplevel: false // NO optimizar a nivel superior
|
|
55
|
-
},
|
|
56
|
-
css: {
|
|
57
|
-
level: 1, // Optimización moderada en lugar de agresiva
|
|
58
|
-
returnPromise: false
|
|
59
|
-
},
|
|
60
|
-
html: {
|
|
61
|
-
collapseWhitespace: true,
|
|
62
|
-
removeComments: true,
|
|
63
|
-
removeRedundantAttributes: true,
|
|
64
|
-
removeEmptyAttributes: true,
|
|
65
|
-
minifyCSS: false, // NO minificar CSS inline para evitar problemas
|
|
66
|
-
minifyJS: false, // NO minificar JS inline para evitar problemas
|
|
67
|
-
useShortDoctype: true,
|
|
68
|
-
removeAttributeQuotes: false, // Mantener comillas en atributos
|
|
69
|
-
removeOptionalTags: false // Mantener tags opcionales
|
|
16
|
+
const loadConfig = () => {
|
|
17
|
+
try {
|
|
18
|
+
const configPath = path.join(__dirname, '../../../../src/sliceConfig.json');
|
|
19
|
+
const rawData = fs.readFileSync(configPath, 'utf-8');
|
|
20
|
+
return JSON.parse(rawData);
|
|
21
|
+
} catch (error) {
|
|
22
|
+
Print.error(`Loading configuration: ${error.message}`);
|
|
23
|
+
return null;
|
|
70
24
|
}
|
|
71
|
-
}
|
|
25
|
+
};
|
|
72
26
|
|
|
73
27
|
/**
|
|
74
|
-
*
|
|
28
|
+
* Verifica dependencias necesarias para el build
|
|
75
29
|
*/
|
|
76
|
-
async function
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
if (isComponentFile) {
|
|
84
|
-
// Configuración especial para archivos de componentes
|
|
85
|
-
options = {
|
|
86
|
-
...options,
|
|
87
|
-
compress: {
|
|
88
|
-
...options.compress,
|
|
89
|
-
passes: 1,
|
|
90
|
-
keep_classnames: true,
|
|
91
|
-
keep_fnames: true
|
|
92
|
-
},
|
|
93
|
-
mangle: false // NO hacer mangle en archivos de componentes
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const result = await terserMinify(content, options);
|
|
98
|
-
|
|
99
|
-
if (result.error) {
|
|
100
|
-
throw result.error;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const originalSize = Buffer.byteLength(content, 'utf8');
|
|
104
|
-
const minifiedSize = Buffer.byteLength(result.code, 'utf8');
|
|
105
|
-
const savings = ((originalSize - minifiedSize) / originalSize * 100).toFixed(1);
|
|
106
|
-
|
|
107
|
-
Print.minificationResult(filename, originalSize, minifiedSize, savings);
|
|
108
|
-
|
|
109
|
-
return result.code;
|
|
110
|
-
} catch (error) {
|
|
111
|
-
Print.error(`Error minifying ${filename}: ${error.message}`);
|
|
112
|
-
// En caso de error, devolver contenido original
|
|
113
|
-
Print.warning(`Using original content for ${filename}`);
|
|
114
|
-
return content;
|
|
30
|
+
async function checkBuildDependencies() {
|
|
31
|
+
const srcDir = path.join(__dirname, '../../../../src');
|
|
32
|
+
|
|
33
|
+
if (!await fs.pathExists(srcDir)) {
|
|
34
|
+
Print.error('Source directory (/src) not found');
|
|
35
|
+
Print.info('Run "slice init" to initialize your project');
|
|
36
|
+
return false;
|
|
115
37
|
}
|
|
38
|
+
|
|
39
|
+
return true;
|
|
116
40
|
}
|
|
117
41
|
|
|
118
42
|
/**
|
|
119
|
-
*
|
|
43
|
+
* Copia sliceConfig.json al directorio dist
|
|
120
44
|
*/
|
|
121
|
-
async function
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
const originalSize = Buffer.byteLength(content, 'utf8');
|
|
131
|
-
const minifiedSize = Buffer.byteLength(result.styles, 'utf8');
|
|
132
|
-
const savings = ((originalSize - minifiedSize) / originalSize * 100).toFixed(1);
|
|
133
|
-
|
|
134
|
-
Print.minificationResult(filename, originalSize, minifiedSize, savings);
|
|
135
|
-
|
|
136
|
-
return result.styles;
|
|
137
|
-
} catch (error) {
|
|
138
|
-
Print.error(`Error minifying ${filename}: ${error.message}`);
|
|
139
|
-
throw error;
|
|
45
|
+
async function copySliceConfig() {
|
|
46
|
+
const srcConfig = path.join(__dirname, '../../../../src/sliceConfig.json');
|
|
47
|
+
const distConfig = path.join(__dirname, '../../../../dist/sliceConfig.json');
|
|
48
|
+
|
|
49
|
+
if (await fs.pathExists(srcConfig)) {
|
|
50
|
+
await fs.copy(srcConfig, distConfig);
|
|
51
|
+
Print.info('sliceConfig.json copied to dist');
|
|
140
52
|
}
|
|
141
53
|
}
|
|
142
54
|
|
|
143
55
|
/**
|
|
144
|
-
*
|
|
56
|
+
* Procesa un directorio completo
|
|
145
57
|
*/
|
|
146
|
-
async function
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
const
|
|
151
|
-
const
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
Print.minificationResult(filename, originalSize, minifiedSize, savings);
|
|
58
|
+
async function processDirectory(srcPath, distPath, baseSrcPath) {
|
|
59
|
+
const items = await fs.readdir(srcPath);
|
|
60
|
+
|
|
61
|
+
for (const item of items) {
|
|
62
|
+
const srcItemPath = path.join(srcPath, item);
|
|
63
|
+
const distItemPath = path.join(distPath, item);
|
|
64
|
+
const stat = await fs.stat(srcItemPath);
|
|
155
65
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
66
|
+
if (stat.isDirectory()) {
|
|
67
|
+
await fs.ensureDir(distItemPath);
|
|
68
|
+
await processDirectory(srcItemPath, distItemPath, baseSrcPath);
|
|
69
|
+
} else {
|
|
70
|
+
await processFile(srcItemPath, distItemPath);
|
|
71
|
+
}
|
|
160
72
|
}
|
|
161
73
|
}
|
|
162
74
|
|
|
163
75
|
/**
|
|
164
|
-
* Procesa un archivo
|
|
76
|
+
* Procesa un archivo individual
|
|
165
77
|
*/
|
|
166
|
-
async function processFile(
|
|
78
|
+
async function processFile(srcFilePath, distFilePath) {
|
|
79
|
+
const ext = path.extname(srcFilePath).toLowerCase();
|
|
80
|
+
|
|
167
81
|
try {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
processedContent = await minifyCSS(content, relativePath);
|
|
178
|
-
break;
|
|
179
|
-
case '.html':
|
|
180
|
-
processedContent = await minifyHTML(content, relativePath);
|
|
181
|
-
break;
|
|
182
|
-
default:
|
|
183
|
-
// Para otros archivos (JSON, etc.), solo copiar
|
|
184
|
-
await fs.copy(srcPath, destPath);
|
|
185
|
-
return;
|
|
82
|
+
if (ext === '.js') {
|
|
83
|
+
await minifyJavaScript(srcFilePath, distFilePath);
|
|
84
|
+
} else if (ext === '.css') {
|
|
85
|
+
await minifyCSS(srcFilePath, distFilePath);
|
|
86
|
+
} else if (ext === '.html') {
|
|
87
|
+
await minifyHTML(srcFilePath, distFilePath);
|
|
88
|
+
} else {
|
|
89
|
+
// Copiar archivos que no necesitan minificación
|
|
90
|
+
await fs.copy(srcFilePath, distFilePath);
|
|
186
91
|
}
|
|
187
|
-
|
|
188
|
-
await fs.writeFile(destPath, processedContent, 'utf8');
|
|
189
|
-
|
|
190
92
|
} catch (error) {
|
|
191
|
-
Print.error(`
|
|
192
|
-
|
|
93
|
+
Print.error(`Processing ${path.basename(srcFilePath)}: ${error.message}`);
|
|
94
|
+
// Copiar archivo original si falla la minificación
|
|
95
|
+
await fs.copy(srcFilePath, distFilePath);
|
|
193
96
|
}
|
|
194
97
|
}
|
|
195
98
|
|
|
196
99
|
/**
|
|
197
|
-
*
|
|
100
|
+
* Minifica archivos JavaScript
|
|
198
101
|
*/
|
|
199
|
-
async function
|
|
200
|
-
const
|
|
102
|
+
async function minifyJavaScript(srcPath, distPath) {
|
|
103
|
+
const content = await fs.readFile(srcPath, 'utf8');
|
|
104
|
+
const originalSize = Buffer.byteLength(content, 'utf8');
|
|
201
105
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
const ext = path.extname(srcPath).toLowerCase();
|
|
214
|
-
|
|
215
|
-
// Procesar archivos que pueden ser minificados
|
|
216
|
-
if (['.js', '.css', '.html'].includes(ext)) {
|
|
217
|
-
await processFile(srcPath, destPath, relativePath);
|
|
218
|
-
} else {
|
|
219
|
-
// Copiar otros archivos sin modificar
|
|
220
|
-
await fs.copy(srcPath, destPath);
|
|
221
|
-
}
|
|
106
|
+
const result = UglifyJS.minify(content, {
|
|
107
|
+
compress: {
|
|
108
|
+
drop_console: false,
|
|
109
|
+
drop_debugger: true,
|
|
110
|
+
pure_funcs: ['console.log']
|
|
111
|
+
},
|
|
112
|
+
mangle: {
|
|
113
|
+
reserved: ['slice', 'Slice']
|
|
114
|
+
},
|
|
115
|
+
output: {
|
|
116
|
+
comments: false
|
|
222
117
|
}
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
if (result.error) {
|
|
121
|
+
throw new Error(`UglifyJS error: ${result.error}`);
|
|
223
122
|
}
|
|
123
|
+
|
|
124
|
+
await fs.writeFile(distPath, result.code, 'utf8');
|
|
125
|
+
|
|
126
|
+
const minifiedSize = Buffer.byteLength(result.code, 'utf8');
|
|
127
|
+
const savings = Math.round(((originalSize - minifiedSize) / originalSize) * 100);
|
|
128
|
+
|
|
129
|
+
Print.minificationResult(path.basename(srcPath), originalSize, minifiedSize, savings);
|
|
224
130
|
}
|
|
225
131
|
|
|
226
132
|
/**
|
|
227
|
-
*
|
|
133
|
+
* Minifica archivos CSS
|
|
228
134
|
*/
|
|
229
|
-
async function
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
const minifiedContent = await minifyJavaScript(content, 'Slice/Slice.js');
|
|
243
|
-
|
|
244
|
-
await fs.ensureDir(path.dirname(distSlicePath));
|
|
245
|
-
await fs.writeFile(distSlicePath, minifiedContent, 'utf8');
|
|
246
|
-
|
|
247
|
-
Print.success('Optimized Slice.js bundle created');
|
|
248
|
-
|
|
249
|
-
} catch (error) {
|
|
250
|
-
Print.error(`Error creating optimized bundle: ${error.message}`);
|
|
251
|
-
throw error;
|
|
135
|
+
async function minifyCSS(srcPath, distPath) {
|
|
136
|
+
const content = await fs.readFile(srcPath, 'utf8');
|
|
137
|
+
const originalSize = Buffer.byteLength(content, 'utf8');
|
|
138
|
+
|
|
139
|
+
const cleanCSS = new CleanCSS({
|
|
140
|
+
level: 2,
|
|
141
|
+
returnPromise: false
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
const result = cleanCSS.minify(content);
|
|
145
|
+
|
|
146
|
+
if (result.errors.length > 0) {
|
|
147
|
+
throw new Error(`CleanCSS errors: ${result.errors.join(', ')}`);
|
|
252
148
|
}
|
|
149
|
+
|
|
150
|
+
await fs.writeFile(distPath, result.styles, 'utf8');
|
|
151
|
+
|
|
152
|
+
const minifiedSize = Buffer.byteLength(result.styles, 'utf8');
|
|
153
|
+
const savings = Math.round(((originalSize - minifiedSize) / originalSize) * 100);
|
|
154
|
+
|
|
155
|
+
Print.minificationResult(path.basename(srcPath), originalSize, minifiedSize, savings);
|
|
253
156
|
}
|
|
254
157
|
|
|
255
158
|
/**
|
|
256
|
-
*
|
|
159
|
+
* Minifica archivos HTML
|
|
257
160
|
*/
|
|
258
|
-
async function
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
161
|
+
async function minifyHTML(srcPath, distPath) {
|
|
162
|
+
const content = await fs.readFile(srcPath, 'utf8');
|
|
163
|
+
const originalSize = Buffer.byteLength(content, 'utf8');
|
|
164
|
+
|
|
165
|
+
const minified = await minify(content, {
|
|
166
|
+
collapseWhitespace: true,
|
|
167
|
+
removeComments: true,
|
|
168
|
+
removeRedundantAttributes: true,
|
|
169
|
+
removeScriptTypeAttributes: true,
|
|
170
|
+
removeStyleLinkTypeAttributes: true,
|
|
171
|
+
useShortDoctype: true,
|
|
172
|
+
minifyCSS: true,
|
|
173
|
+
minifyJS: true
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
await fs.writeFile(distPath, minified, 'utf8');
|
|
177
|
+
|
|
178
|
+
const minifiedSize = Buffer.byteLength(minified, 'utf8');
|
|
179
|
+
const savings = Math.round(((originalSize - minifiedSize) / originalSize) * 100);
|
|
180
|
+
|
|
181
|
+
Print.minificationResult(path.basename(srcPath), originalSize, minifiedSize, savings);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Crea un bundle optimizado del archivo principal
|
|
186
|
+
*/
|
|
187
|
+
async function createOptimizedBundle() {
|
|
188
|
+
Print.buildProgress('Creating optimized bundle...');
|
|
189
|
+
|
|
190
|
+
const mainJSPath = path.join(__dirname, '../../../../dist/App/index.js');
|
|
191
|
+
|
|
192
|
+
if (await fs.pathExists(mainJSPath)) {
|
|
193
|
+
Print.success('Main bundle optimized');
|
|
194
|
+
} else {
|
|
195
|
+
Print.warning('No main JavaScript file found for bundling');
|
|
272
196
|
}
|
|
273
197
|
}
|
|
274
198
|
|
|
@@ -276,56 +200,76 @@ async function copySliceConfig() {
|
|
|
276
200
|
* Genera estadísticas del build
|
|
277
201
|
*/
|
|
278
202
|
async function generateBuildStats(srcDir, distDir) {
|
|
279
|
-
|
|
280
|
-
|
|
203
|
+
Print.buildProgress('Generating build statistics...');
|
|
204
|
+
|
|
205
|
+
const getDirectorySize = async (dirPath) => {
|
|
206
|
+
let totalSize = 0;
|
|
207
|
+
const items = await fs.readdir(dirPath);
|
|
281
208
|
|
|
282
|
-
const
|
|
283
|
-
|
|
284
|
-
const
|
|
209
|
+
for (const item of items) {
|
|
210
|
+
const itemPath = path.join(dirPath, item);
|
|
211
|
+
const stat = await fs.stat(itemPath);
|
|
285
212
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
} else {
|
|
291
|
-
const stats = await fs.stat(filePath);
|
|
292
|
-
totalSize += stats.size;
|
|
293
|
-
}
|
|
213
|
+
if (stat.isDirectory()) {
|
|
214
|
+
totalSize += await getDirectorySize(itemPath);
|
|
215
|
+
} else {
|
|
216
|
+
totalSize += stat.size;
|
|
294
217
|
}
|
|
295
|
-
|
|
296
|
-
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return totalSize;
|
|
221
|
+
};
|
|
297
222
|
|
|
298
|
-
|
|
299
|
-
const
|
|
300
|
-
const
|
|
223
|
+
try {
|
|
224
|
+
const srcSize = await getDirectorySize(srcDir);
|
|
225
|
+
const distSize = await getDirectorySize(distDir);
|
|
226
|
+
const savings = Math.round(((srcSize - distSize) / srcSize) * 100);
|
|
301
227
|
|
|
302
228
|
Print.newLine();
|
|
303
|
-
Print.
|
|
304
|
-
console.log(
|
|
305
|
-
console.log(
|
|
306
|
-
console.log(
|
|
229
|
+
Print.info(`📊 Build Statistics:`);
|
|
230
|
+
console.log(` Source: ${(srcSize / 1024).toFixed(1)} KB`);
|
|
231
|
+
console.log(` Built: ${(distSize / 1024).toFixed(1)} KB`);
|
|
232
|
+
console.log(` Saved: ${savings}% smaller`);
|
|
307
233
|
|
|
308
234
|
} catch (error) {
|
|
309
|
-
Print.warning(
|
|
235
|
+
Print.warning('Could not generate build statistics');
|
|
310
236
|
}
|
|
311
237
|
}
|
|
312
238
|
|
|
313
239
|
/**
|
|
314
|
-
*
|
|
240
|
+
* Analiza el build sin construir
|
|
241
|
+
*/
|
|
242
|
+
async function analyzeBuild() {
|
|
243
|
+
const distDir = path.join(__dirname, '../../../../dist');
|
|
244
|
+
|
|
245
|
+
if (!await fs.pathExists(distDir)) {
|
|
246
|
+
Print.error('No build found to analyze. Run "slice build" first.');
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
Print.info('Analyzing production build...');
|
|
251
|
+
await generateBuildStats(
|
|
252
|
+
path.join(__dirname, '../../../../src'),
|
|
253
|
+
distDir
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Función principal de build
|
|
315
259
|
*/
|
|
316
260
|
export default async function buildProduction(options = {}) {
|
|
317
261
|
const startTime = Date.now();
|
|
318
262
|
|
|
319
263
|
try {
|
|
320
|
-
Print.title('
|
|
264
|
+
Print.title('🔨 Building Slice.js project for production...');
|
|
321
265
|
Print.newLine();
|
|
322
266
|
|
|
323
|
-
// Verificar que existe src
|
|
324
267
|
const srcDir = path.join(__dirname, '../../../../src');
|
|
325
268
|
const distDir = path.join(__dirname, '../../../../dist');
|
|
326
269
|
|
|
270
|
+
// Verificar que existe el directorio src
|
|
327
271
|
if (!await fs.pathExists(srcDir)) {
|
|
328
|
-
throw new Error('
|
|
272
|
+
throw new Error('Source directory not found. Run "slice init" first.');
|
|
329
273
|
}
|
|
330
274
|
|
|
331
275
|
// 1. Limpiar directorio dist
|
|
@@ -361,10 +305,9 @@ export default async function buildProduction(options = {}) {
|
|
|
361
305
|
Print.info('Your optimized project is ready in the /dist directory');
|
|
362
306
|
Print.newLine();
|
|
363
307
|
Print.info('Next steps:');
|
|
364
|
-
console.log(' •
|
|
365
|
-
console.log(' • Update your Express server to serve from /dist instead of /src');
|
|
308
|
+
console.log(' • Use "npm run slice:start" to test the production build');
|
|
366
309
|
console.log(' • Deploy both /api and /dist directories to your hosting provider');
|
|
367
|
-
console.log(' • Use "slice build --serve" to preview the production build
|
|
310
|
+
console.log(' • Use "slice build --serve" to preview the production build');
|
|
368
311
|
|
|
369
312
|
return true;
|
|
370
313
|
|
|
@@ -375,52 +318,64 @@ export default async function buildProduction(options = {}) {
|
|
|
375
318
|
}
|
|
376
319
|
|
|
377
320
|
/**
|
|
378
|
-
* Servidor de
|
|
379
|
-
* Usa Express como el servidor principal pero sirviendo desde /dist
|
|
321
|
+
* Servidor de preview para testing del build de producción
|
|
380
322
|
*/
|
|
381
|
-
export async function serveProductionBuild(port
|
|
323
|
+
export async function serveProductionBuild(port) {
|
|
382
324
|
try {
|
|
325
|
+
const config = loadConfig();
|
|
326
|
+
const defaultPort = config?.server?.port || 3001;
|
|
327
|
+
const finalPort = port || defaultPort;
|
|
328
|
+
|
|
383
329
|
const distDir = path.join(__dirname, '../../../../dist');
|
|
384
330
|
|
|
385
331
|
if (!await fs.pathExists(distDir)) {
|
|
386
332
|
throw new Error('No production build found. Run "slice build" first.');
|
|
387
333
|
}
|
|
388
334
|
|
|
389
|
-
Print.info(`Starting production
|
|
335
|
+
Print.info(`Starting production preview server on port ${finalPort}...`);
|
|
390
336
|
|
|
391
|
-
// Implementar servidor estático simple
|
|
337
|
+
// Implementar servidor estático simple
|
|
392
338
|
const express = await import('express');
|
|
393
339
|
const app = express.default();
|
|
394
340
|
|
|
395
|
-
// Servir archivos estáticos desde dist
|
|
341
|
+
// Servir archivos estáticos desde dist
|
|
396
342
|
app.use(express.default.static(distDir));
|
|
397
343
|
|
|
398
344
|
// SPA fallback - servir index.html para rutas no encontradas
|
|
399
345
|
app.get('*', (req, res) => {
|
|
400
|
-
const indexPath = path.join(distDir, 'index.html');
|
|
346
|
+
const indexPath = path.join(distDir, 'App/index.html');
|
|
347
|
+
const fallbackPath = path.join(distDir, 'index.html');
|
|
348
|
+
|
|
349
|
+
// Intentar primero App/index.html, luego index.html
|
|
401
350
|
if (fs.existsSync(indexPath)) {
|
|
402
351
|
res.sendFile(indexPath);
|
|
352
|
+
} else if (fs.existsSync(fallbackPath)) {
|
|
353
|
+
res.sendFile(fallbackPath);
|
|
403
354
|
} else {
|
|
404
|
-
res.status(404).send('Production build not found');
|
|
355
|
+
res.status(404).send('Production build index.html not found');
|
|
405
356
|
}
|
|
406
357
|
});
|
|
407
358
|
|
|
408
|
-
app.listen(
|
|
409
|
-
Print.success(`Production
|
|
359
|
+
app.listen(finalPort, () => {
|
|
360
|
+
Print.success(`Production preview server running at http://localhost:${finalPort}`);
|
|
410
361
|
Print.info('Press Ctrl+C to stop the server');
|
|
411
|
-
Print.info('This server
|
|
362
|
+
Print.info('This server previews your production build from /dist');
|
|
363
|
+
Print.warning('This is a preview server - use "npm run slice:start" for the full production server');
|
|
412
364
|
});
|
|
413
365
|
|
|
414
366
|
} catch (error) {
|
|
415
|
-
Print.error(`Error starting production server: ${error.message}`);
|
|
367
|
+
Print.error(`Error starting production preview server: ${error.message}`);
|
|
416
368
|
throw error;
|
|
417
369
|
}
|
|
418
370
|
}
|
|
419
371
|
|
|
420
372
|
/**
|
|
421
|
-
* Comando build con opciones
|
|
373
|
+
* Comando build con opciones
|
|
422
374
|
*/
|
|
423
375
|
export async function buildCommand(options = {}) {
|
|
376
|
+
const config = loadConfig();
|
|
377
|
+
const defaultPort = config?.server?.port || 3001;
|
|
378
|
+
|
|
424
379
|
// Verificar dependencias necesarias
|
|
425
380
|
if (!await checkBuildDependencies()) {
|
|
426
381
|
return false;
|
|
@@ -428,7 +383,7 @@ export async function buildCommand(options = {}) {
|
|
|
428
383
|
|
|
429
384
|
if (options.serve) {
|
|
430
385
|
// Solo servir build existente
|
|
431
|
-
await serveProductionBuild(options.port);
|
|
386
|
+
await serveProductionBuild(options.port || defaultPort);
|
|
432
387
|
return true;
|
|
433
388
|
}
|
|
434
389
|
|
|
@@ -441,96 +396,12 @@ export async function buildCommand(options = {}) {
|
|
|
441
396
|
// Build completo
|
|
442
397
|
const success = await buildProduction(options);
|
|
443
398
|
|
|
444
|
-
// Solo mostrar mensaje informativo, no ejecutar servidor automáticamente
|
|
445
399
|
if (success && options.preview) {
|
|
446
400
|
Print.newLine();
|
|
447
401
|
Print.info('✨ Build completed successfully!');
|
|
448
|
-
Print.info(
|
|
449
|
-
|
|
402
|
+
Print.info(`Starting preview server on port ${options.port || defaultPort}...`);
|
|
403
|
+
await serveProductionBuild(options.port || defaultPort);
|
|
450
404
|
}
|
|
451
405
|
|
|
452
406
|
return success;
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
/**
|
|
457
|
-
* Verifica que las dependencias de build estén instaladas en el CLI
|
|
458
|
-
*/
|
|
459
|
-
async function checkBuildDependencies() {
|
|
460
|
-
try {
|
|
461
|
-
Print.info('Checking build dependencies...');
|
|
462
|
-
|
|
463
|
-
// Verificar dependencias en el CLI en lugar del proyecto
|
|
464
|
-
const cliPackageJsonPath = path.join(__dirname, '../../package.json');
|
|
465
|
-
|
|
466
|
-
if (!await fs.pathExists(cliPackageJsonPath)) {
|
|
467
|
-
throw new Error('CLI package.json not found');
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
const cliPackageJson = await fs.readJson(cliPackageJsonPath);
|
|
471
|
-
const deps = { ...cliPackageJson.dependencies, ...cliPackageJson.devDependencies };
|
|
472
|
-
|
|
473
|
-
const requiredDeps = ['terser', 'clean-css', 'html-minifier-terser'];
|
|
474
|
-
const missing = requiredDeps.filter(dep => !deps[dep]);
|
|
475
|
-
|
|
476
|
-
if (missing.length > 0) {
|
|
477
|
-
Print.error('Missing build dependencies in CLI:');
|
|
478
|
-
missing.forEach(dep => console.log(` • ${dep}`));
|
|
479
|
-
Print.newLine();
|
|
480
|
-
Print.info('Please update slicejs-cli to the latest version:');
|
|
481
|
-
console.log('npm install -g slicejs-cli@latest');
|
|
482
|
-
return false;
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
Print.success('All build dependencies are available in CLI');
|
|
486
|
-
return true;
|
|
487
|
-
|
|
488
|
-
} catch (error) {
|
|
489
|
-
Print.error(`Error checking dependencies: ${error.message}`);
|
|
490
|
-
return false;
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
/**
|
|
495
|
-
* Analiza el tamaño y composición del build
|
|
496
|
-
*/
|
|
497
|
-
async function analyzeBuild() {
|
|
498
|
-
try {
|
|
499
|
-
const distDir = path.join(__dirname, '../../../../dist');
|
|
500
|
-
|
|
501
|
-
if (!await fs.pathExists(distDir)) {
|
|
502
|
-
throw new Error('No production build found. Run "slice build" first.');
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
Print.title('📊 Build Analysis');
|
|
506
|
-
Print.newLine();
|
|
507
|
-
|
|
508
|
-
const analyzeDirectory = async (dir, prefix = '') => {
|
|
509
|
-
const items = await fs.readdir(dir);
|
|
510
|
-
let totalSize = 0;
|
|
511
|
-
|
|
512
|
-
for (const item of items) {
|
|
513
|
-
const itemPath = path.join(dir, item);
|
|
514
|
-
const stat = await fs.stat(itemPath);
|
|
515
|
-
|
|
516
|
-
if (stat.isDirectory()) {
|
|
517
|
-
const dirSize = await analyzeDirectory(itemPath, `${prefix}${item}/`);
|
|
518
|
-
totalSize += dirSize;
|
|
519
|
-
} else {
|
|
520
|
-
const size = (stat.size / 1024).toFixed(1);
|
|
521
|
-
console.log(`📄 ${prefix}${item}: ${size} KB`);
|
|
522
|
-
totalSize += stat.size;
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
return totalSize;
|
|
527
|
-
};
|
|
528
|
-
|
|
529
|
-
const totalSize = await analyzeDirectory(distDir);
|
|
530
|
-
Print.newLine();
|
|
531
|
-
Print.info(`Total build size: ${(totalSize / 1024).toFixed(1)} KB`);
|
|
532
|
-
|
|
533
|
-
} catch (error) {
|
|
534
|
-
Print.error(`Error analyzing build: ${error.message}`);
|
|
535
|
-
}
|
|
536
407
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// commands/startServer/startServer.js -
|
|
1
|
+
// commands/startServer/startServer.js - CON ARGUMENTOS
|
|
2
2
|
|
|
3
3
|
import fs from 'fs-extra';
|
|
4
4
|
import path from 'path';
|
|
@@ -8,6 +8,20 @@ import Print from '../Print.js';
|
|
|
8
8
|
|
|
9
9
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Carga la configuración desde sliceConfig.json
|
|
13
|
+
*/
|
|
14
|
+
const loadConfig = () => {
|
|
15
|
+
try {
|
|
16
|
+
const configPath = path.join(__dirname, '../../../../src/sliceConfig.json');
|
|
17
|
+
const rawData = fs.readFileSync(configPath, 'utf-8');
|
|
18
|
+
return JSON.parse(rawData);
|
|
19
|
+
} catch (error) {
|
|
20
|
+
Print.error(`Loading configuration: ${error.message}`);
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
|
|
11
25
|
/**
|
|
12
26
|
* Verifica si existe un build de producción
|
|
13
27
|
*/
|
|
@@ -27,7 +41,7 @@ async function checkDevelopmentStructure() {
|
|
|
27
41
|
}
|
|
28
42
|
|
|
29
43
|
/**
|
|
30
|
-
* Inicia el servidor Node.js
|
|
44
|
+
* Inicia el servidor Node.js con argumentos
|
|
31
45
|
*/
|
|
32
46
|
function startNodeServer(port, mode) {
|
|
33
47
|
return new Promise((resolve, reject) => {
|
|
@@ -35,13 +49,20 @@ function startNodeServer(port, mode) {
|
|
|
35
49
|
|
|
36
50
|
Print.info(`Starting ${mode} server on port ${port}...`);
|
|
37
51
|
|
|
38
|
-
|
|
52
|
+
// Construir argumentos basados en el modo
|
|
53
|
+
const args = [apiIndexPath];
|
|
54
|
+
if (mode === 'production') {
|
|
55
|
+
args.push('--production');
|
|
56
|
+
} else {
|
|
57
|
+
args.push('--development');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const serverProcess = spawn('node', args, {
|
|
39
61
|
stdio: 'inherit',
|
|
40
62
|
env: {
|
|
41
63
|
...process.env,
|
|
42
|
-
PORT: port
|
|
43
|
-
|
|
44
|
-
SLICE_CLI_MODE: 'true' // Flag para que api/index.js sepa que viene del CLI
|
|
64
|
+
PORT: port
|
|
65
|
+
// Ya no necesitamos NODE_ENV ni SLICE_CLI_MODE
|
|
45
66
|
}
|
|
46
67
|
});
|
|
47
68
|
|
|
@@ -50,7 +71,7 @@ function startNodeServer(port, mode) {
|
|
|
50
71
|
reject(error);
|
|
51
72
|
});
|
|
52
73
|
|
|
53
|
-
// Manejar Ctrl+C
|
|
74
|
+
// Manejar Ctrl+C
|
|
54
75
|
process.on('SIGINT', () => {
|
|
55
76
|
Print.info('Shutting down server...');
|
|
56
77
|
serverProcess.kill('SIGINT');
|
|
@@ -61,7 +82,6 @@ function startNodeServer(port, mode) {
|
|
|
61
82
|
serverProcess.kill('SIGTERM');
|
|
62
83
|
});
|
|
63
84
|
|
|
64
|
-
// NO mostrar mensajes duplicados - el api/index.js ya se encarga
|
|
65
85
|
setTimeout(() => {
|
|
66
86
|
resolve(serverProcess);
|
|
67
87
|
}, 500);
|
|
@@ -69,10 +89,13 @@ function startNodeServer(port, mode) {
|
|
|
69
89
|
}
|
|
70
90
|
|
|
71
91
|
/**
|
|
72
|
-
* Función principal para iniciar servidor
|
|
92
|
+
* Función principal para iniciar servidor
|
|
73
93
|
*/
|
|
74
94
|
export default async function startServer(options = {}) {
|
|
75
|
-
const
|
|
95
|
+
const config = loadConfig();
|
|
96
|
+
const defaultPort = config?.server?.port || 3000;
|
|
97
|
+
|
|
98
|
+
const { mode = 'development', port = defaultPort } = options;
|
|
76
99
|
|
|
77
100
|
try {
|
|
78
101
|
Print.title(`🚀 Starting Slice.js ${mode} server...`);
|
|
@@ -93,7 +116,7 @@ export default async function startServer(options = {}) {
|
|
|
93
116
|
Print.info('Development mode: serving files from /src with hot reload');
|
|
94
117
|
}
|
|
95
118
|
|
|
96
|
-
// Iniciar el servidor
|
|
119
|
+
// Iniciar el servidor con argumentos
|
|
97
120
|
await startNodeServer(port, mode);
|
|
98
121
|
|
|
99
122
|
} catch (error) {
|
package/package.json
CHANGED
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "slicejs-cli",
|
|
3
|
-
"version": "2.2.
|
|
4
|
-
"description": "Command client for developing web applications with Slice.js framework",
|
|
5
|
-
"main": "client.js",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"test": "echo \"Error: no test specified\" && exit 1",
|
|
8
|
-
"postinstall": "node post.js"
|
|
9
|
-
},
|
|
10
|
-
"keywords": [
|
|
11
|
-
"framework",
|
|
12
|
-
"web",
|
|
13
|
-
"client",
|
|
14
|
-
"cli"
|
|
15
|
-
],
|
|
16
|
-
"author": "vkneider",
|
|
17
|
-
"type": "module",
|
|
18
|
-
"license": "ISC",
|
|
19
|
-
"dependencies": {
|
|
20
|
-
"clean-css": "^5.3.3",
|
|
21
|
-
"commander": "^12.0.0",
|
|
22
|
-
"fs-extra": "^11.2.0",
|
|
23
|
-
"html-minifier-terser": "^7.2.0",
|
|
24
|
-
"inquirer": "^12.4.2",
|
|
25
|
-
"slicejs-web-framework": "latest",
|
|
26
|
-
"terser": "^5.43.1"
|
|
27
|
-
}
|
|
28
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "slicejs-cli",
|
|
3
|
+
"version": "2.2.6",
|
|
4
|
+
"description": "Command client for developing web applications with Slice.js framework",
|
|
5
|
+
"main": "client.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
8
|
+
"postinstall": "node post.js"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"framework",
|
|
12
|
+
"web",
|
|
13
|
+
"client",
|
|
14
|
+
"cli"
|
|
15
|
+
],
|
|
16
|
+
"author": "vkneider",
|
|
17
|
+
"type": "module",
|
|
18
|
+
"license": "ISC",
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"clean-css": "^5.3.3",
|
|
21
|
+
"commander": "^12.0.0",
|
|
22
|
+
"fs-extra": "^11.2.0",
|
|
23
|
+
"html-minifier-terser": "^7.2.0",
|
|
24
|
+
"inquirer": "^12.4.2",
|
|
25
|
+
"slicejs-web-framework": "latest",
|
|
26
|
+
"terser": "^5.43.1"
|
|
27
|
+
}
|
|
28
|
+
}
|
package/post.js
CHANGED
|
@@ -24,8 +24,8 @@ fs.promises.access(projectPackageJsonPath, fs.constants.F_OK)
|
|
|
24
24
|
|
|
25
25
|
// Main project commands
|
|
26
26
|
projectPackageJson.scripts['slice:init'] = 'node node_modules/slicejs-cli/client.js init';
|
|
27
|
-
projectPackageJson.scripts['slice:dev'] = 'node
|
|
28
|
-
projectPackageJson.scripts['slice:start'] = 'node
|
|
27
|
+
projectPackageJson.scripts['slice:dev'] = 'node api/index.js --development';
|
|
28
|
+
projectPackageJson.scripts['slice:start'] = 'node api/index.js --production';
|
|
29
29
|
projectPackageJson.scripts['slice:build'] = 'node node_modules/slicejs-cli/client.js build';
|
|
30
30
|
projectPackageJson.scripts['slice:version'] = 'node node_modules/slicejs-cli/client.js version';
|
|
31
31
|
projectPackageJson.scripts['slice:update'] = 'node node_modules/slicejs-cli/client.js update';
|
|
@@ -50,9 +50,9 @@ fs.promises.access(projectPackageJsonPath, fs.constants.F_OK)
|
|
|
50
50
|
projectPackageJson.scripts['slice:build-preview'] = 'node node_modules/slicejs-cli/client.js build --preview';
|
|
51
51
|
projectPackageJson.scripts['slice:build-analyze'] = 'node node_modules/slicejs-cli/client.js build --analyze';
|
|
52
52
|
|
|
53
|
-
// Legacy/compatibility commands
|
|
54
|
-
projectPackageJson.scripts['run'] = 'node api/index.js';
|
|
55
|
-
projectPackageJson.scripts['development'] = 'node
|
|
53
|
+
// Legacy/compatibility commands - ACTUALIZADOS
|
|
54
|
+
projectPackageJson.scripts['run'] = 'node api/index.js --development';
|
|
55
|
+
projectPackageJson.scripts['development'] = 'node api/index.js --development';
|
|
56
56
|
|
|
57
57
|
// Module configuration
|
|
58
58
|
projectPackageJson.type = 'module';
|
|
@@ -91,6 +91,10 @@ fs.promises.access(projectPackageJsonPath, fs.constants.F_OK)
|
|
|
91
91
|
console.log(' 3. npm run slice:build - Build for production');
|
|
92
92
|
console.log(' 4. npm run slice:start - Test production build');
|
|
93
93
|
console.log('\n💡 Tip: Use "slice:sync" to keep your components updated');
|
|
94
|
+
console.log('\n🔧 New argument-based system:');
|
|
95
|
+
console.log(' • slice:dev → node api/index.js --development');
|
|
96
|
+
console.log(' • slice:start → node api/index.js --production');
|
|
97
|
+
console.log(' • Arguments take precedence over environment variables');
|
|
94
98
|
})
|
|
95
99
|
.catch(err => {
|
|
96
100
|
if (err.code === 'ENOENT') {
|
|
@@ -101,83 +105,56 @@ fs.promises.access(projectPackageJsonPath, fs.constants.F_OK)
|
|
|
101
105
|
description: 'Slice.js project',
|
|
102
106
|
main: 'api/index.js',
|
|
103
107
|
scripts: {
|
|
104
|
-
// Main workflow commands
|
|
108
|
+
// Main workflow commands - UPDATED with arguments
|
|
105
109
|
'slice:init': 'node node_modules/slicejs-cli/client.js init',
|
|
106
|
-
'slice:dev': 'node
|
|
107
|
-
'slice:start': 'node
|
|
110
|
+
'slice:dev': 'node api/index.js --development',
|
|
111
|
+
'slice:start': 'node api/index.js --production',
|
|
108
112
|
'slice:build': 'node node_modules/slicejs-cli/client.js build',
|
|
109
113
|
'slice:version': 'node node_modules/slicejs-cli/client.js version',
|
|
110
114
|
'slice:update': 'node node_modules/slicejs-cli/client.js update',
|
|
111
115
|
|
|
112
|
-
// Local
|
|
116
|
+
// Local component commands
|
|
113
117
|
'slice:create': 'node node_modules/slicejs-cli/client.js component create',
|
|
114
118
|
'slice:list': 'node node_modules/slicejs-cli/client.js component list',
|
|
115
119
|
'slice:delete': 'node node_modules/slicejs-cli/client.js component delete',
|
|
116
120
|
|
|
117
|
-
//
|
|
121
|
+
// Repository commands
|
|
118
122
|
'slice:get': 'node node_modules/slicejs-cli/client.js get',
|
|
119
123
|
'slice:browse': 'node node_modules/slicejs-cli/client.js browse',
|
|
120
124
|
'slice:sync': 'node node_modules/slicejs-cli/client.js sync',
|
|
121
125
|
|
|
122
|
-
// Detailed registry
|
|
123
|
-
'slice:registry-get': 'node node_modules/slicejs-cli/client.js registry get',
|
|
124
|
-
'slice:registry-list': 'node node_modules/slicejs-cli/client.js registry list',
|
|
125
|
-
'slice:registry-sync': 'node node_modules/slicejs-cli/client.js registry sync',
|
|
126
|
-
|
|
127
126
|
// Build utilities
|
|
128
127
|
'slice:build-serve': 'node node_modules/slicejs-cli/client.js build --serve',
|
|
129
128
|
'slice:build-preview': 'node node_modules/slicejs-cli/client.js build --preview',
|
|
130
129
|
'slice:build-analyze': 'node node_modules/slicejs-cli/client.js build --analyze',
|
|
131
130
|
|
|
132
|
-
// Legacy
|
|
133
|
-
'run': 'node api/index.js',
|
|
134
|
-
'development': 'node
|
|
131
|
+
// Legacy commands - UPDATED
|
|
132
|
+
'run': 'node api/index.js --development',
|
|
133
|
+
'development': 'node api/index.js --development'
|
|
135
134
|
},
|
|
136
|
-
keywords: ['slicejs', 'web-framework', 'components'],
|
|
137
|
-
author: '',
|
|
138
|
-
license: 'ISC',
|
|
139
135
|
type: 'module',
|
|
140
136
|
engines: {
|
|
141
137
|
"node": ">=20.0.0"
|
|
142
138
|
}
|
|
143
139
|
};
|
|
144
140
|
|
|
145
|
-
// Save the new package.json
|
|
146
141
|
return fs.promises.writeFile(projectPackageJsonPath, JSON.stringify(defaultPackageJson, null, 2), 'utf8');
|
|
147
142
|
} else {
|
|
148
|
-
console.error('Error:', err);
|
|
149
143
|
throw err;
|
|
150
144
|
}
|
|
151
145
|
})
|
|
152
146
|
.then(() => {
|
|
153
|
-
console.log('✅
|
|
154
|
-
console.log('\n
|
|
155
|
-
console.log(' npm run slice:
|
|
156
|
-
console.log(' npm run slice:
|
|
157
|
-
console.log('
|
|
158
|
-
console.log('
|
|
159
|
-
console.log('
|
|
160
|
-
console.log('
|
|
161
|
-
console.log('
|
|
162
|
-
console.log(' npm run slice:sync - Update local components to latest versions');
|
|
163
|
-
console.log('\n⚙️ Local component management:');
|
|
164
|
-
console.log(' npm run slice:create - Create local component');
|
|
165
|
-
console.log(' npm run slice:list - List local components');
|
|
166
|
-
console.log(' npm run slice:delete - Delete local component');
|
|
167
|
-
console.log('\n🔧 Build utilities:');
|
|
168
|
-
console.log(' npm run slice:build-serve - Build and serve immediately');
|
|
169
|
-
console.log(' npm run slice:build-preview- Build and preview');
|
|
170
|
-
console.log(' npm run slice:build-analyze- Analyze build size');
|
|
171
|
-
console.log('\n🔧 Other utilities:');
|
|
172
|
-
console.log(' npm run slice:version - View version information');
|
|
173
|
-
console.log(' npm run slice:update - Check for available updates');
|
|
174
|
-
console.log('\n🎯 Development workflow:');
|
|
175
|
-
console.log(' 1. npm run slice:init - Initialize project');
|
|
176
|
-
console.log(' 2. npm run slice:dev - Develop with hot reload');
|
|
177
|
-
console.log(' 3. npm run slice:build - Build for production');
|
|
178
|
-
console.log(' 4. npm run slice:start - Test production build');
|
|
179
|
-
console.log('\n💡 Tip: Use "slice:sync" to keep your components updated');
|
|
147
|
+
console.log('✅ SliceJS CLI commands configured successfully');
|
|
148
|
+
console.log('\n🎯 Updated workflow:');
|
|
149
|
+
console.log(' npm run slice:dev → node api/index.js --development (serves /src)');
|
|
150
|
+
console.log(' npm run slice:start → node api/index.js --production (serves /dist)');
|
|
151
|
+
console.log('\n🔧 Benefits:');
|
|
152
|
+
console.log(' • Clear argument-based mode detection');
|
|
153
|
+
console.log(' • No confusion between src/dist directories');
|
|
154
|
+
console.log(' • Maintains backward compatibility with NODE_ENV');
|
|
155
|
+
console.log(' • More reliable and predictable behavior');
|
|
180
156
|
})
|
|
181
157
|
.catch(err => {
|
|
182
|
-
console.error('Error
|
|
183
|
-
|
|
158
|
+
console.error('❌ Error setting up package.json:', err.message);
|
|
159
|
+
process.exit(1);
|
|
160
|
+
});
|