@vixoniccom/module-packager 2.10.3-dev.8 → 2.11.0-dev.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/main.js +120 -104
- package/package.json +2 -1
package/dist/main.js
CHANGED
|
@@ -4,7 +4,7 @@ import commandLineArgs from 'command-line-args';
|
|
|
4
4
|
import path from 'path';
|
|
5
5
|
import webpack from 'webpack';
|
|
6
6
|
import WebpackDevServer from 'webpack-dev-server';
|
|
7
|
-
import {
|
|
7
|
+
import { spawn } from 'child_process';
|
|
8
8
|
import { fileURLToPath } from 'url';
|
|
9
9
|
import fs from 'fs';
|
|
10
10
|
import archiver from 'archiver';
|
|
@@ -12,9 +12,11 @@ import clc from 'cli-color';
|
|
|
12
12
|
import { Configuration } from '@vixoniccom/modules';
|
|
13
13
|
import tsNode from 'ts-node';
|
|
14
14
|
import { createRequire } from 'module';
|
|
15
|
+
import which from 'which';
|
|
15
16
|
const __filename = fileURLToPath(import.meta.url);
|
|
16
17
|
const __dirname = path.dirname(__filename);
|
|
17
18
|
const electronPath = path.join(__dirname, 'electron.js');
|
|
19
|
+
const npxPath = which.sync('npx');
|
|
18
20
|
const optionDefinitions = [
|
|
19
21
|
{ name: 'externals', type: String, defaultValue: [], multiple: true },
|
|
20
22
|
{ name: 'target', type: String, defaultValue: 'web' },
|
|
@@ -28,9 +30,91 @@ const optionDefinitions = [
|
|
|
28
30
|
{ name: 'tsOverride', type: Boolean }
|
|
29
31
|
];
|
|
30
32
|
const options = commandLineArgs(optionDefinitions);
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
// Validación de entrada mejorada
|
|
34
|
+
function validateOptions(options) {
|
|
35
|
+
if (options.target !== 'electron-renderer' && options.externals.length > 0) {
|
|
36
|
+
throw new Error(`Can't use external dependencies if target is not electron-renderer.`);
|
|
37
|
+
}
|
|
38
|
+
// Validar puerto
|
|
39
|
+
if (options.port < 1 || options.port > 65535) {
|
|
40
|
+
throw new Error('Port must be between 1 and 65535');
|
|
41
|
+
}
|
|
42
|
+
// Validar modo
|
|
43
|
+
const validModes = ['build', 'watch', 'run', 'generate-configuration', 'validate-configuration'];
|
|
44
|
+
if (!validModes.includes(options.mode)) {
|
|
45
|
+
throw new Error(`Invalid mode. Must be one of: ${validModes.join(', ')}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// Función para sanitizar rutas
|
|
49
|
+
function sanitizePath(inputPath) {
|
|
50
|
+
// Prevenir path traversal
|
|
51
|
+
if (inputPath.includes('..') || inputPath.includes('~')) {
|
|
52
|
+
throw new Error('Invalid path: path traversal detected');
|
|
53
|
+
}
|
|
54
|
+
return path.resolve(inputPath);
|
|
55
|
+
}
|
|
56
|
+
// Función centralizada para crear argumentos de Electron
|
|
57
|
+
function createElectronArgs(mode) {
|
|
58
|
+
return [
|
|
59
|
+
electronPath,
|
|
60
|
+
'--src', sanitizePath(options.src),
|
|
61
|
+
'--build', sanitizePath(options.build),
|
|
62
|
+
'--port', String(options.port),
|
|
63
|
+
'--mode', mode,
|
|
64
|
+
'--config', options.config,
|
|
65
|
+
'--externals', Array.isArray(options.externals) ? options.externals.join(',') : ''
|
|
66
|
+
];
|
|
67
|
+
}
|
|
68
|
+
// Función centralizada para manejar procesos Electron
|
|
69
|
+
function spawnElectronProcess(mode) {
|
|
70
|
+
const args = createElectronArgs(mode);
|
|
71
|
+
const nodeEnv = mode === 'run' ? 'production' : 'development';
|
|
72
|
+
const child = spawn(npxPath, ['electron', ...args], {
|
|
73
|
+
cwd: __dirname,
|
|
74
|
+
env: {
|
|
75
|
+
...process.env,
|
|
76
|
+
NODE_ENV: nodeEnv,
|
|
77
|
+
ELECTRON_DISABLE_SECURITY_WARNINGS: 'true',
|
|
78
|
+
NODE_NO_WARNINGS: '1'
|
|
79
|
+
},
|
|
80
|
+
stdio: 'inherit'
|
|
81
|
+
});
|
|
82
|
+
// Manejo centralizado de logs
|
|
83
|
+
setupChildProcessLogging(child);
|
|
84
|
+
return child;
|
|
33
85
|
}
|
|
86
|
+
// Función para manejar logging de procesos hijo
|
|
87
|
+
function setupChildProcessLogging(child) {
|
|
88
|
+
child.stdout?.on('data', (data) => {
|
|
89
|
+
const output = data.toString();
|
|
90
|
+
if (!shouldFilterLog(output)) {
|
|
91
|
+
process.stdout.write(output);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
child.stderr?.on('data', (data) => {
|
|
95
|
+
const output = data.toString();
|
|
96
|
+
if (!shouldFilterLog(output)) {
|
|
97
|
+
process.stderr.write(output);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
// Función centralizada para compilar webpack
|
|
102
|
+
async function compileWebpack() {
|
|
103
|
+
const cfgPath = path.resolve(__dirname, '..', 'dist/webpack.config.js');
|
|
104
|
+
const webpackConfigFactory = (await import(cfgPath)).default;
|
|
105
|
+
const compiler = webpack(webpackConfigFactory(options));
|
|
106
|
+
return new Promise((resolve, reject) => {
|
|
107
|
+
compiler.run((err, stats) => {
|
|
108
|
+
if (err)
|
|
109
|
+
return reject(err);
|
|
110
|
+
if (stats?.hasErrors()) {
|
|
111
|
+
return reject(new Error(stats.toString({ all: false, errors: true, colors: true })));
|
|
112
|
+
}
|
|
113
|
+
compiler.close(closeErr => (closeErr ? reject(closeErr) : resolve()));
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
validateOptions(options);
|
|
34
118
|
if (options.mode === 'build') {
|
|
35
119
|
pack(() => {
|
|
36
120
|
if (options.target === 'electron-renderer') {
|
|
@@ -59,6 +143,7 @@ async function pack(callback) {
|
|
|
59
143
|
console.log(clc.blue('Building module...'));
|
|
60
144
|
validateConfiguration();
|
|
61
145
|
const configPath = path.resolve(__dirname, options.config);
|
|
146
|
+
console.log("🚀 ~ pack ~ configPath:", configPath);
|
|
62
147
|
try {
|
|
63
148
|
const webpackConfig = (await import(configPath)).default(options);
|
|
64
149
|
function handleWebpackError(err) {
|
|
@@ -106,19 +191,27 @@ async function pack(callback) {
|
|
|
106
191
|
}
|
|
107
192
|
function installExternals(callback) {
|
|
108
193
|
let externals = options.externals.map((x) => {
|
|
109
|
-
|
|
194
|
+
// Validar nombre del paquete
|
|
195
|
+
if (!/^[@a-z0-9-_./]+$/i.test(x)) {
|
|
196
|
+
throw new Error(`Invalid package name: ${x}`);
|
|
197
|
+
}
|
|
198
|
+
const packageJsonPath = sanitizePath(path.resolve(options.src, '..', 'node_modules', x, 'package.json'));
|
|
199
|
+
return `${x}@${JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')).version}`;
|
|
110
200
|
});
|
|
111
201
|
if (externals.length) {
|
|
112
|
-
externals
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
202
|
+
console.log(clc.blue(`Installing externals ${externals.join(', ')}...`));
|
|
203
|
+
const npmPath = which.sync('npm');
|
|
204
|
+
const child = spawn(npmPath, ['install', '--prefix', './', '--production', ...externals], { cwd: sanitizePath(options.build), stdio: 'inherit' });
|
|
205
|
+
child.on('exit', (code) => {
|
|
206
|
+
if (code !== 0) {
|
|
207
|
+
return callback?.(new Error(`npm install failed with code ${code}`));
|
|
208
|
+
}
|
|
119
209
|
console.log(clc.green('Externals installed.'));
|
|
120
210
|
callback?.(null);
|
|
121
211
|
});
|
|
212
|
+
child.on('error', (err) => {
|
|
213
|
+
callback?.(err);
|
|
214
|
+
});
|
|
122
215
|
}
|
|
123
216
|
else {
|
|
124
217
|
callback?.(null);
|
|
@@ -127,11 +220,13 @@ function installExternals(callback) {
|
|
|
127
220
|
function zip() {
|
|
128
221
|
console.log(clc.blue('Archiving...'));
|
|
129
222
|
console.log(clc.blue('Cleaning build...'));
|
|
130
|
-
|
|
131
|
-
|
|
223
|
+
const buildPath = sanitizePath(options.build);
|
|
224
|
+
const zipPath = path.resolve(buildPath, '../', 'build.zip');
|
|
225
|
+
console.log("[DEBUG] Cleaning build folder", zipPath);
|
|
226
|
+
let output = fs.createWriteStream(zipPath);
|
|
132
227
|
let archive = archiver('zip');
|
|
133
228
|
archive.pipe(output);
|
|
134
|
-
archive.directory(
|
|
229
|
+
archive.directory(buildPath, './');
|
|
135
230
|
archive.finalize();
|
|
136
231
|
output.on('close', function () {
|
|
137
232
|
console.log(clc.green('Generated build.zip.'));
|
|
@@ -152,93 +247,12 @@ async function watch() {
|
|
|
152
247
|
historyApiFallback: true
|
|
153
248
|
}, compiler);
|
|
154
249
|
await server.start();
|
|
155
|
-
|
|
156
|
-
'npx', 'electron', electronPath,
|
|
157
|
-
'--src', path.resolve(options.src),
|
|
158
|
-
'--build', path.resolve(options.build),
|
|
159
|
-
'--port', String(options.port),
|
|
160
|
-
'--mode', 'watch',
|
|
161
|
-
'--config', options.config,
|
|
162
|
-
'--externals', options.externals.join(',')
|
|
163
|
-
].join(' ');
|
|
164
|
-
const child = exec(cmd, {
|
|
165
|
-
cwd: __dirname,
|
|
166
|
-
env: {
|
|
167
|
-
...process.env,
|
|
168
|
-
NODE_ENV: 'development',
|
|
169
|
-
ELECTRON_DISABLE_SECURITY_WARNINGS: 'true',
|
|
170
|
-
NODE_NO_WARNINGS: '1'
|
|
171
|
-
}
|
|
172
|
-
});
|
|
173
|
-
// Filtrar logs no deseados
|
|
174
|
-
child.stdout?.on('data', (data) => {
|
|
175
|
-
const output = data.toString();
|
|
176
|
-
if (!shouldFilterLog(output)) {
|
|
177
|
-
process.stdout.write(output);
|
|
178
|
-
}
|
|
179
|
-
});
|
|
180
|
-
child.stderr?.on('data', (data) => {
|
|
181
|
-
const output = data.toString();
|
|
182
|
-
if (!shouldFilterLog(output)) {
|
|
183
|
-
process.stderr.write(output);
|
|
184
|
-
}
|
|
185
|
-
});
|
|
250
|
+
spawnElectronProcess('watch');
|
|
186
251
|
}
|
|
187
252
|
async function run() {
|
|
188
|
-
await new Promise((resolve
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
const compiler = webpack(webpackConfigFactory(options));
|
|
192
|
-
await new Promise((resolve, reject) => {
|
|
193
|
-
compiler.run((err, stats) => {
|
|
194
|
-
if (err)
|
|
195
|
-
return reject(err);
|
|
196
|
-
if (stats?.hasErrors()) {
|
|
197
|
-
return reject(new Error(stats.toString({ all: false, errors: true, colors: true })));
|
|
198
|
-
}
|
|
199
|
-
compiler.close(closeErr => (closeErr ? reject(closeErr) : resolve()));
|
|
200
|
-
});
|
|
201
|
-
});
|
|
202
|
-
const cmd = [
|
|
203
|
-
'npx',
|
|
204
|
-
'electron',
|
|
205
|
-
electronPath,
|
|
206
|
-
'--src',
|
|
207
|
-
path.resolve(options.src),
|
|
208
|
-
'--build',
|
|
209
|
-
path.resolve(options.build),
|
|
210
|
-
'--port',
|
|
211
|
-
String(options.port),
|
|
212
|
-
'--mode',
|
|
213
|
-
'run',
|
|
214
|
-
'--config',
|
|
215
|
-
options.config,
|
|
216
|
-
'--externals',
|
|
217
|
-
options.externals.join(',')
|
|
218
|
-
].join(' ');
|
|
219
|
-
const child = exec(cmd, {
|
|
220
|
-
cwd: __dirname,
|
|
221
|
-
env: {
|
|
222
|
-
...process.env,
|
|
223
|
-
NODE_ENV: 'production',
|
|
224
|
-
// Suprimir warnings en producción también
|
|
225
|
-
ELECTRON_DISABLE_SECURITY_WARNINGS: 'true',
|
|
226
|
-
NODE_NO_WARNINGS: '1'
|
|
227
|
-
},
|
|
228
|
-
});
|
|
229
|
-
// Aplicar el mismo filtrado
|
|
230
|
-
child.stdout?.on('data', (data) => {
|
|
231
|
-
const output = data.toString();
|
|
232
|
-
if (!shouldFilterLog(output)) {
|
|
233
|
-
process.stdout.write(output);
|
|
234
|
-
}
|
|
235
|
-
});
|
|
236
|
-
child.stderr?.on('data', (data) => {
|
|
237
|
-
const output = data.toString();
|
|
238
|
-
if (!shouldFilterLog(output)) {
|
|
239
|
-
process.stderr.write(output);
|
|
240
|
-
}
|
|
241
|
-
});
|
|
253
|
+
await new Promise((resolve) => pack((err) => (err ? console.log(err) : resolve())));
|
|
254
|
+
await compileWebpack();
|
|
255
|
+
spawnElectronProcess('run');
|
|
242
256
|
}
|
|
243
257
|
async function loadConfiguration() {
|
|
244
258
|
const require = createRequire(import.meta.url);
|
|
@@ -250,14 +264,15 @@ async function loadConfiguration() {
|
|
|
250
264
|
checkJs: false
|
|
251
265
|
}
|
|
252
266
|
});
|
|
253
|
-
const configPath = path.resolve(options.confDefinition, 'index.ts');
|
|
267
|
+
const configPath = sanitizePath(path.resolve(options.confDefinition, 'index.ts'));
|
|
254
268
|
return require(configPath).configuration;
|
|
255
269
|
}
|
|
256
270
|
async function generateConfiguration() {
|
|
257
271
|
try {
|
|
258
272
|
let configuration = await loadConfiguration();
|
|
259
|
-
|
|
260
|
-
fs.writeFileSync(path.resolve(
|
|
273
|
+
const srcPath = sanitizePath(options.src);
|
|
274
|
+
fs.writeFileSync(path.resolve(srcPath, 'parameters.d.ts'), configuration.declarationFileString);
|
|
275
|
+
fs.writeFileSync(path.resolve(srcPath, '..', 'configuration.json'), JSON.stringify(configuration, undefined, 2));
|
|
261
276
|
console.log(clc.green(`Configuration generated`));
|
|
262
277
|
}
|
|
263
278
|
catch (e) {
|
|
@@ -267,11 +282,12 @@ async function generateConfiguration() {
|
|
|
267
282
|
}
|
|
268
283
|
function validateConfiguration() {
|
|
269
284
|
try {
|
|
270
|
-
const
|
|
285
|
+
const srcPath = sanitizePath(options.src);
|
|
286
|
+
const jsonPath = path.resolve(srcPath, '../', 'configuration.json');
|
|
271
287
|
const json = JSON.parse(fs.readFileSync(jsonPath, 'utf8'));
|
|
272
288
|
const conf = Configuration.fromJSON(json);
|
|
273
289
|
if (conf.durationFormula) {
|
|
274
|
-
const valuesPath = path.resolve(
|
|
290
|
+
const valuesPath = path.resolve(srcPath, 'test', 'parameters.json');
|
|
275
291
|
const values = JSON.parse(fs.readFileSync(valuesPath, 'utf8'));
|
|
276
292
|
console.log('Validate duration');
|
|
277
293
|
console.log('Duration on undefined:', conf.getDuration({}), 'seconds');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vixoniccom/module-packager",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.11.0-dev.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"vixonic-module-packager": "./dist/main.js"
|
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
"@types/command-line-args": "^5.2.3",
|
|
56
56
|
"@types/node": "^20.11.25",
|
|
57
57
|
"@types/webpack-env": "^1.18.8",
|
|
58
|
+
"@types/which": "^3.0.4",
|
|
58
59
|
"concurrently": "^9.1.2",
|
|
59
60
|
"css-loader": "^7.1.2",
|
|
60
61
|
"npm-run-all": "^4.1.5",
|