innetjs 2.6.0-alpha.1 → 2.6.0-alpha.10

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/index.mjs CHANGED
@@ -31,638 +31,638 @@ import { preserveShebangs } from 'rollup-plugin-preserve-shebangs';
31
31
  import env from 'rollup-plugin-process-env';
32
32
  import styles from 'rollup-plugin-styles';
33
33
  import { terser } from 'rollup-plugin-terser';
34
+ import stream from 'node:stream';
34
35
  import tmp from 'tmp';
35
- import typescript from 'typescript';
36
+ import { Extract } from 'unzipper';
36
37
  import { promisify } from 'node:util';
37
38
  import { stringExcludeNode, imageInclude, stringExcludeDom, lintInclude } from './constants.mjs';
38
- import { Extract } from './extract.mjs';
39
39
  import { reporter, convertIndexFile, getFile } from './helpers.mjs';
40
40
  import { updateDotenv } from './updateDotenv.mjs';
41
41
 
42
- const livereload = require('rollup-plugin-livereload');
43
- const { string } = require('rollup-plugin-string');
44
- const { exec, spawn } = require('child_process');
45
- const readline = require('readline');
46
- const importAssets = require('rollup-plugin-import-assets');
47
- const execAsync = promisify(exec);
48
- const copyFiles = promisify(fs.copy);
49
- updateDotenv();
50
- const REG_CLEAR_TEXT = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
51
- const REG_RPT_ERROR_FILE = /(src[^:]+):(\d+):(\d+)/;
52
- const REG_TJSX = /\.[tj]sx?$/;
53
- const REG_EXT = /\.([^.]+)$/;
54
- const scriptExtensions = ['ts', 'js', 'tsx', 'jsx'];
55
- const indexExt = scriptExtensions.join(',');
56
- class InnetJS {
57
- constructor({ envPrefix = process.env.INNETJS_ENV_PREFIX || 'INNETJS_', projectFolder = process.env.PROJECT_FOLDER || '', baseUrl = process.env.BASE_URL || '', publicFolder = process.env.PUBLIC_FOLDER || 'public', releaseFolder = process.env.RELEASE_FOLDER || 'release', buildFolder = process.env.BUILD_FOLDER || 'build', srcFolder = process.env.SRC_FOLDER || 'src', sourcemap = process.env.SOURCEMAP ? process.env.SOURCEMAP === 'true' : false, cssModules = process.env.CSS_MODULES ? process.env.CSS_MODULES === 'true' : true, cssInJs = process.env.CSS_IN_JS ? process.env.CSS_IN_JS === 'true' : true, sslKey = process.env.SSL_KEY || 'localhost.key', sslCrt = process.env.SSL_CRT || 'localhost.crt', proxy = process.env.PROXY || '', simulateIP = process.env.IP, port = process.env.PORT ? +process.env.PORT : 3000, api = process.env.API || '/api/?*', } = {}) {
58
- this.projectFolder = path.resolve(projectFolder);
59
- this.publicFolder = path.resolve(publicFolder);
60
- this.releaseFolder = path.resolve(releaseFolder);
61
- this.buildFolder = path.resolve(buildFolder);
62
- this.srcFolder = path.resolve(srcFolder);
63
- this.licenseFile = path.join(projectFolder, 'LICENSE');
64
- this.licenseReleaseFile = path.join(releaseFolder, 'LICENSE');
65
- this.readmeFile = path.join(projectFolder, 'README.md');
66
- this.readmeReleaseFile = path.join(releaseFolder, 'README.md');
67
- this.declarationFile = path.join(srcFolder, 'declaration.d.ts');
68
- this.declarationReleaseFile = path.join(releaseFolder, 'declaration.d.ts');
69
- this.publicIndexFile = path.join(publicFolder, 'index.html');
70
- this.buildIndexFile = path.join(buildFolder, 'index.html');
71
- this.devBuildFolder = path.resolve(projectFolder, 'node_modules', '.cache', 'innetjs', 'build');
72
- this.devBuildIndexFile = path.join(this.devBuildFolder, 'index.html');
73
- this.sourcemap = sourcemap;
74
- this.cssModules = cssModules;
75
- this.cssInJs = cssInJs;
76
- this.sslKey = sslKey;
77
- this.sslCrt = sslCrt;
78
- this.port = port;
79
- this.proxy = proxy;
80
- this.api = api;
81
- this.baseUrl = baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`;
82
- this.envPrefix = envPrefix;
83
- this.simulateIP = simulateIP;
84
- }
85
- // Methods
86
- init(appName, { template, force = false } = {}) {
87
- return __awaiter(this, void 0, void 0, function* () {
88
- const appPath = path.resolve(appName);
89
- const { data } = yield logger.start('Get templates list', () => __awaiter(this, void 0, void 0, function* () { return yield axios.get('https://api.github.com/repos/d8corp/innetjs-templates/branches'); }));
90
- const templates = data.map(({ name }) => name).filter(name => name !== 'main');
91
- if (!template || !templates.includes(template)) {
92
- logger.log(chalk.green('Select one of those templates'));
93
- const { value } = yield selector({
94
- values: templates,
95
- });
96
- template = value;
97
- readline.moveCursor(process.stdout, 0, -1);
98
- const text = `Selected template: ${chalk.white(value)}`;
99
- logger.start(text);
100
- logger.end(text);
101
- }
102
- if (!force) {
103
- yield logger.start('Check if app folder is available', () => __awaiter(this, void 0, void 0, function* () {
104
- if (fs.existsSync(appPath)) {
105
- logger.log(chalk.red(`'${appPath}' already exist, what do you want?`));
106
- const { id: result, value } = yield selector({
107
- values: ['Stop the process', 'Remove the folder', 'Merge with template'],
108
- });
109
- readline.moveCursor(process.stdout, 0, -1);
110
- logger.log(`Already exist, selected: ${value}`);
111
- if (!result) {
112
- throw Error(`'${appPath}' already exist`);
113
- }
114
- if (result === 1) {
115
- yield fs.remove(appPath);
116
- }
117
- }
118
- }));
119
- }
120
- yield logger.start('Download template', () => __awaiter(this, void 0, void 0, function* () {
121
- const { data } = yield axios.get(`https://github.com/d8corp/innetjs-templates/archive/refs/heads/${template}.zip`, {
122
- responseType: 'stream',
123
- });
124
- yield new Promise((resolve, reject) => {
125
- data.pipe(Extract({
126
- path: appPath,
127
- }, template)).on('finish', resolve).on('error', reject);
128
- });
129
- }));
130
- yield logger.start('Install packages', () => execAsync(`cd ${appPath} && npm i`));
131
- });
132
- }
133
- build({ node = false, inject = false, index = 'index' } = {}) {
134
- return __awaiter(this, void 0, void 0, function* () {
135
- const input = glob.sync(`src/${index}.{${indexExt}}`);
136
- if (!input.length) {
137
- throw Error('index file is not detected');
138
- }
139
- yield logger.start('Remove build', () => fs.remove(this.buildFolder));
140
- const pkg = node && (yield this.getPackage());
141
- const options = {
142
- input,
143
- preserveEntrySignatures: 'strict',
144
- plugins: [
145
- commonjs(),
146
- json(),
147
- ts({
148
- typescript,
149
- noEmitOnError: true,
150
- compilerOptions: {
151
- declaration: false,
152
- },
153
- }),
154
- jsx(),
155
- ],
156
- onwarn(warning, warn) {
157
- if (warning.code === 'THIS_IS_UNDEFINED' || warning.code === 'SOURCEMAP_ERROR')
158
- return;
159
- warn(warning);
160
- },
161
- };
162
- this.withLint(options, true);
163
- const outputOptions = {
164
- dir: this.buildFolder,
165
- sourcemap: this.sourcemap,
166
- };
167
- if (node) {
168
- outputOptions.format = 'cjs';
169
- options.external = Object.keys((pkg === null || pkg === void 0 ? void 0 : pkg.dependencies) || {});
170
- options.plugins.push(nodeResolve(), string({
171
- include: '**/*.*',
172
- exclude: stringExcludeNode,
173
- }));
174
- }
175
- else {
176
- options.plugins.push(nodeResolve({
177
- browser: true,
178
- }), polyfill(), importAssets({
179
- include: imageInclude.map(img => `src/${img}`),
180
- publicPath: this.baseUrl,
181
- }), styles({
182
- mode: this.cssInJs ? 'inject' : 'extract',
183
- url: {
184
- inline: false,
185
- publicPath: `${this.baseUrl}assets`,
186
- },
187
- plugins: [autoprefixer()],
188
- autoModules: this.cssModules ? (id) => !id.includes('.global.') : true,
189
- sourceMap: this.sourcemap,
190
- minimize: true,
191
- }), string({
192
- include: '**/*.*',
193
- exclude: stringExcludeDom,
194
- }));
195
- outputOptions.format = 'es';
196
- outputOptions.plugins = [
197
- terser(),
198
- filesize({
199
- reporter,
200
- }),
201
- ];
202
- }
203
- this.withEnv(options, true);
204
- yield logger.start('Build production bundle', () => __awaiter(this, void 0, void 0, function* () {
205
- const bundle = yield rollup.rollup(options);
206
- yield bundle.write(outputOptions);
207
- yield bundle.close();
208
- if (!node) {
209
- yield copyFiles(this.publicFolder, this.buildFolder);
210
- const data = yield promises.readFile(this.publicIndexFile);
211
- const pkg = yield this.getPackage();
212
- yield promises.writeFile(this.buildIndexFile, yield convertIndexFile(data, pkg.version, this.baseUrl, path.parse(input[0]).name, inject));
213
- }
214
- }));
215
- if (pkg) {
216
- yield logger.start('Copy package.json', () => __awaiter(this, void 0, void 0, function* () {
217
- const data = Object.assign({}, pkg);
218
- delete data.private;
219
- delete data.devDependencies;
220
- yield fs.writeFile(path.resolve(this.buildFolder, 'package.json'), JSON.stringify(data, undefined, 2), 'UTF-8');
221
- }));
222
- const pkgLockPath = path.resolve(this.projectFolder, 'package-lock.json');
223
- if (fs.existsSync(pkgLockPath)) {
224
- yield logger.start('Copy package-lock.json', () => {
225
- return fs.copy(pkgLockPath, path.resolve(this.buildFolder, 'package-lock.json'));
226
- });
227
- }
228
- }
229
- });
230
- }
231
- start({ node = false, inject = false, error = false, index = 'index' } = {}) {
232
- return __awaiter(this, void 0, void 0, function* () {
233
- const pkg = yield this.getPackage();
234
- const input = glob.sync(`src/${index}.{${indexExt}}`);
235
- if (!input.length) {
236
- throw Error('index file is not detected');
237
- }
238
- yield logger.start('Remove build', () => fs.remove(this.devBuildFolder));
239
- const options = {
240
- input,
241
- preserveEntrySignatures: 'strict',
242
- output: {
243
- dir: this.devBuildFolder,
244
- sourcemap: true,
245
- },
246
- plugins: [
247
- commonjs(),
248
- json(),
249
- ts({
250
- typescript,
251
- compilerOptions: {
252
- declaration: false,
253
- sourceMap: true,
254
- },
255
- }),
256
- jsx(),
257
- ],
258
- onwarn(warning, warn) {
259
- if (warning.code === 'THIS_IS_UNDEFINED' || warning.code === 'SOURCEMAP_ERROR')
260
- return;
261
- if (warning.plugin === 'typescript') {
262
- const { loc: { line, column, file }, frame, message } = warning;
263
- console.log(`ERROR in ${file}:${line}:${column}`);
264
- console.log(message);
265
- console.log(frame);
266
- return;
267
- }
268
- warn(warning);
269
- },
270
- };
271
- this.withLint(options);
272
- if (node) {
273
- // @ts-expect-error
274
- options.output.format = 'cjs';
275
- options.external = Object.keys((pkg === null || pkg === void 0 ? void 0 : pkg.dependencies) || {});
276
- options.plugins.push(nodeResolve(), string({
277
- include: '**/*.*',
278
- exclude: stringExcludeNode,
279
- }), this.createServer());
280
- }
281
- else {
282
- const key = path.basename(this.sslKey) !== this.sslKey
283
- ? this.sslKey
284
- : fs.existsSync(this.sslKey)
285
- ? fs.readFileSync(this.sslKey)
286
- : undefined;
287
- const cert = path.basename(this.sslCrt) !== this.sslCrt
288
- ? this.sslCrt
289
- : fs.existsSync(this.sslCrt)
290
- ? fs.readFileSync(this.sslCrt)
291
- : undefined;
292
- // @ts-expect-error
293
- options.output.format = 'es';
294
- options.plugins.push(nodeResolve({
295
- browser: true,
296
- }), polyfill(), importAssets({
297
- include: imageInclude.map(img => `src/${img}`),
298
- publicPath: this.baseUrl,
299
- }), styles({
300
- mode: this.cssInJs ? 'inject' : 'extract',
301
- url: {
302
- inline: false,
303
- publicPath: `${this.baseUrl}assets`,
304
- },
305
- plugins: [autoprefixer()],
306
- autoModules: this.cssModules ? (id) => !id.includes('.global.') : true,
307
- sourceMap: true,
308
- }), string({
309
- include: '**/*.*',
310
- exclude: stringExcludeDom,
311
- }), this.createClient(key, cert, pkg, path.parse(input[0]).name, inject), livereload(Object.assign({ exts: ['html', 'css', 'js', 'png', 'svg', 'webp', 'gif', 'jpg', 'json'], watch: [this.devBuildFolder, this.publicFolder], verbose: false }, (key && cert ? { https: { key, cert } } : {}))));
312
- }
313
- this.withEnv(options, true);
314
- const watcher = rollup.watch(options);
315
- watcher.on('event', (e) => __awaiter(this, void 0, void 0, function* () {
316
- if (e.code === 'ERROR') {
317
- if (e.error.code === 'UNRESOLVED_IMPORT') {
318
- const [, importer, file] = e.error.message.match(/^Could not resolve '(.+)' from (.+)$/) || [];
319
- const text = (yield fs.readFile(file)).toString();
320
- const lines = new LinesAndColumns(text);
321
- const { line, column } = lines.locationForIndex(text.indexOf(importer));
322
- logger.end('Bundling', e.error.message);
323
- console.log(`ERROR in ${file}:${line + 1}:${column + 1}`);
324
- }
325
- else if (e.error.code === 'PLUGIN_ERROR' && ['rpt2', 'commonjs', 'typescript'].includes(e.error.plugin)) {
326
- const [, file, line, column] = e.error.message
327
- .replace(REG_CLEAR_TEXT, '')
328
- .match(REG_RPT_ERROR_FILE) || [];
329
- logger.end('Bundling', e.error.message);
330
- if (file) {
331
- console.log(`ERROR in ${file}:${line}:${column}`);
332
- }
333
- else if (e.error.loc) {
334
- console.log(`ERROR in ${e.error.loc.file}:${e.error.loc.line}:${e.error.loc.column}`);
335
- console.log(e.error.frame);
336
- }
337
- }
338
- else {
339
- logger.end('Bundling', error ? e.error.stack : e.error.message);
340
- }
341
- }
342
- else if (e.code === 'BUNDLE_START') {
343
- logger.start('Bundling');
344
- }
345
- else if (e.code === 'BUNDLE_END') {
346
- logger.end('Bundling');
347
- }
348
- }));
349
- });
350
- }
351
- run(file) {
352
- return __awaiter(this, void 0, void 0, function* () {
353
- const input = yield logger.start('Check file', () => getFile(file));
354
- const folder = yield new Promise((resolve, reject) => {
355
- tmp.dir((err, folder) => {
356
- if (err) {
357
- reject(err);
358
- }
359
- else {
360
- resolve(folder);
361
- }
362
- });
363
- });
364
- const jsFilePath = `${folder}/index.js`;
365
- yield logger.start('Build bundle', () => __awaiter(this, void 0, void 0, function* () {
366
- const inputOptions = {
367
- input,
368
- plugins: [
369
- commonjs(),
370
- nodeResolve(),
371
- json(),
372
- ts({
373
- typescript,
374
- tsconfigOverride: {
375
- compilerOptions: {
376
- sourceMap: true,
377
- },
378
- },
379
- }),
380
- ],
381
- };
382
- const outputOptions = {
383
- format: 'cjs',
384
- file: jsFilePath,
385
- sourcemap: true,
386
- };
387
- const bundle = yield rollup.rollup(inputOptions);
388
- yield bundle.write(outputOptions);
389
- yield bundle.close();
390
- }));
391
- yield logger.start('Running of the script', () => __awaiter(this, void 0, void 0, function* () {
392
- spawn('node', ['-r', 'source-map-support/register', jsFilePath], { stdio: 'inherit' });
393
- }));
394
- });
395
- }
396
- release({ index = 'index', pub } = {}) {
397
- return __awaiter(this, void 0, void 0, function* () {
398
- const { releaseFolder, cssModules } = this;
399
- yield logger.start('Remove previous release', () => fs.remove(releaseFolder));
400
- const pkg = yield this.getPackage();
401
- const build = (format) => __awaiter(this, void 0, void 0, function* () {
402
- var _a, _b;
403
- const ext = format === 'es'
404
- ? ((_a = (pkg.module || pkg.esnext || pkg['jsnext:main'])) === null || _a === void 0 ? void 0 : _a.replace('index', '')) || '.mjs'
405
- : ((_b = pkg.main) === null || _b === void 0 ? void 0 : _b.replace('index', '')) || '.js';
406
- const input = glob.sync(`src/${index}.{${indexExt}}`);
407
- if (!input.length) {
408
- throw Error('index file is not detected');
409
- }
410
- const options = {
411
- input,
412
- external: ['tslib'],
413
- treeshake: false,
414
- output: {
415
- dir: releaseFolder,
416
- entryFileNames: ({ name, facadeModuleId }) => {
417
- if (REG_TJSX.test(facadeModuleId)) {
418
- return `${name}${ext}`;
419
- }
420
- const match = facadeModuleId.match(REG_EXT);
421
- return match ? `${name}${match[0]}${ext}` : `${name}${ext}`;
422
- },
423
- format,
424
- preserveModules: true,
425
- exports: 'named',
426
- },
427
- plugins: [
428
- json(),
429
- ts({
430
- typescript,
431
- clean: true,
432
- tsconfigOverride: {
433
- compilerOptions: {
434
- sourceMap: false,
435
- },
436
- include: [...input, 'src/declaration.d.ts'],
437
- },
438
- }),
439
- jsx(),
440
- externals(),
441
- string({
442
- include: '**/*.*',
443
- exclude: stringExcludeDom,
444
- }),
445
- image(),
446
- styles({
447
- mode: this.cssInJs ? 'inject' : 'extract',
448
- plugins: [autoprefixer()],
449
- autoModules: cssModules ? (id) => !id.includes('.global.') : true,
450
- minimize: true,
451
- }),
452
- nodeResolve(),
453
- external(),
454
- ],
455
- };
456
- this.withLint(options);
457
- this.withEnv(options, true);
458
- const bundle = yield rollup.rollup(options);
459
- yield bundle.write(options.output);
460
- yield bundle.close();
461
- });
462
- yield logger.start('Build cjs bundle', () => __awaiter(this, void 0, void 0, function* () {
463
- yield build('cjs');
464
- }));
465
- yield logger.start('Build es6 bundle', () => __awaiter(this, void 0, void 0, function* () {
466
- yield build('es');
467
- }));
468
- yield logger.start('Copy package.json', () => __awaiter(this, void 0, void 0, function* () {
469
- const data = Object.assign({}, pkg);
470
- delete data.private;
471
- delete data.devDependencies;
472
- yield fs.writeFile(path.resolve(this.releaseFolder, 'package.json'), JSON.stringify(data, undefined, 2), 'UTF-8');
473
- }));
474
- if (pkg.bin) {
475
- yield logger.start('Build bin', () => __awaiter(this, void 0, void 0, function* () {
476
- const { bin } = pkg;
477
- for (const name in bin) {
478
- const value = bin[name];
479
- const input = glob.sync(`src/${value}.{${indexExt}}`);
480
- const file = path.join(this.releaseFolder, value);
481
- const options = {
482
- input,
483
- external: [...Object.keys(pkg.dependencies), 'tslib'],
484
- output: {
485
- file,
486
- format: 'cjs',
487
- },
488
- plugins: [
489
- preserveShebangs(),
490
- json(),
491
- ts({
492
- typescript,
493
- clean: true,
494
- tsconfigOverride: {
495
- compilerOptions: {
496
- declaration: false,
497
- },
498
- },
499
- }),
500
- externals(),
501
- jsx(),
502
- ],
503
- };
504
- this.withLint(options);
505
- this.withEnv(options);
506
- const bundle = yield rollup.rollup(options);
507
- yield bundle.write(options.output);
508
- yield bundle.close();
509
- }
510
- }));
511
- }
512
- if (fs.existsSync(this.licenseFile)) {
513
- yield logger.start('Copy license', () => __awaiter(this, void 0, void 0, function* () {
514
- yield promises.copyFile(this.licenseFile, this.licenseReleaseFile);
515
- }));
516
- }
517
- if (fs.existsSync(this.readmeFile)) {
518
- yield logger.start('Copy readme', () => __awaiter(this, void 0, void 0, function* () {
519
- yield promises.copyFile(this.readmeFile, this.readmeReleaseFile);
520
- }));
521
- }
522
- if (fs.existsSync(this.declarationFile)) {
523
- yield logger.start('Copy declaration', () => __awaiter(this, void 0, void 0, function* () {
524
- yield promises.copyFile(this.declarationFile, this.declarationReleaseFile);
525
- }));
526
- }
527
- if (pub) {
528
- const date = (Date.now() / 1000) | 0;
529
- yield logger.start(`publishing v${pkg.version} ${date}`, () => __awaiter(this, void 0, void 0, function* () {
530
- yield execAsync(`npm publish ${this.releaseFolder}`);
531
- }));
532
- }
533
- });
534
- }
535
- withLint(options, prod = false) {
536
- if (this._lintUsage === undefined) {
537
- this._lintUsage = fs.existsSync(path.join(this.projectFolder, '.eslintrc'));
538
- }
539
- if (this._lintUsage) {
540
- options.plugins.push(eslint({
541
- include: lintInclude,
542
- throwOnError: prod,
543
- }));
544
- }
545
- }
546
- withEnv(options, virtual) {
547
- options.plugins.push(env(this.envPrefix, {
548
- include: options.input,
549
- virtual,
550
- }));
551
- }
552
- increaseVersion(release) {
553
- return __awaiter(this, void 0, void 0, function* () {
554
- const pkg = yield this.getPackage();
555
- yield logger.start('Prepare package.json', () => __awaiter(this, void 0, void 0, function* () {
556
- const version = pkg.version.split('.');
557
- switch (release) {
558
- case 'patch': {
559
- version[2]++;
560
- break;
561
- }
562
- case 'minor': {
563
- version[1]++;
564
- version[2] = 0;
565
- break;
566
- }
567
- case 'major': {
568
- version[1] = 0;
569
- version[2] = 0;
570
- version[0]++;
571
- break;
572
- }
573
- default: return;
574
- }
575
- pkg.version = version.join('.');
576
- yield fs.writeFile(path.resolve(this.projectFolder, 'package.json'), JSON.stringify(pkg, undefined, 2), 'UTF-8');
577
- }));
578
- });
579
- }
580
- getPackage() {
581
- return __awaiter(this, void 0, void 0, function* () {
582
- if (this.package) {
583
- return this.package;
584
- }
585
- const packageFolder = path.resolve(this.projectFolder, 'package.json');
586
- yield logger.start('Check package.json', () => __awaiter(this, void 0, void 0, function* () {
587
- if (fs.existsSync(packageFolder)) {
588
- this.package = yield fs.readJson(packageFolder);
589
- }
590
- }));
591
- return this.package;
592
- });
593
- }
594
- createClient(key, cert, pkg, index, inject) {
595
- let app;
596
- return {
597
- name: 'client',
598
- writeBundle: () => __awaiter(this, void 0, void 0, function* () {
599
- var _a;
600
- if (!app) {
601
- app = express();
602
- const update = () => __awaiter(this, void 0, void 0, function* () {
603
- const data = yield promises.readFile(this.publicIndexFile);
604
- yield promises.writeFile(this.devBuildIndexFile, yield convertIndexFile(data, pkg.version, this.baseUrl, index, inject));
605
- });
606
- fs.watch(this.publicIndexFile, update);
607
- yield update();
608
- const httpsUsing = !!(cert && key);
609
- app.use(this.baseUrl, express.static(this.devBuildFolder));
610
- app.use(this.baseUrl, express.static(this.publicFolder));
611
- if ((_a = this.proxy) === null || _a === void 0 ? void 0 : _a.startsWith('http')) {
612
- if (this.simulateIP) {
613
- app.use((req, res, next) => {
614
- req.headers['X-Real-IP'] = this.simulateIP;
615
- next();
616
- });
617
- }
618
- app.use(this.api, proxy(this.proxy, {
619
- https: httpsUsing,
620
- limit: '1000mb',
621
- proxyReqPathResolver: req => req.originalUrl,
622
- }));
623
- }
624
- app.use(/^([^.]*|.*\.[^.]{5,})$/, (req, res) => {
625
- res.sendFile(this.devBuildFolder + '/index.html');
626
- });
627
- const server = httpsUsing ? https.createServer({ key, cert }, app) : http.createServer(app);
628
- let port = this.port;
629
- const listener = () => {
630
- const baseUrl = this.baseUrl === '/' ? '' : this.baseUrl;
631
- console.log(`${chalk.green('➤')} Started on http${httpsUsing ? 's' : ''}://localhost:${port}${baseUrl} and http${httpsUsing ? 's' : ''}://${address.ip()}:${port}${baseUrl}`);
632
- };
633
- server.listen(port, listener);
634
- server.on('error', (e) => __awaiter(this, void 0, void 0, function* () {
635
- if (e.code === 'EADDRINUSE') {
636
- port++;
637
- const { userPort } = yield prompt({
638
- name: 'userPort',
639
- type: 'number',
640
- message: `Port ${e.port} is reserved, please enter another one [${port}]:`,
641
- });
642
- if (userPort) {
643
- port = userPort;
644
- }
645
- server.listen(port);
646
- }
647
- else {
648
- throw e;
649
- }
650
- }));
651
- }
652
- }),
653
- };
654
- }
655
- createServer() {
656
- let app;
657
- return {
658
- name: 'server',
659
- writeBundle: () => __awaiter(this, void 0, void 0, function* () {
660
- app === null || app === void 0 ? void 0 : app.kill();
661
- const filePath = path.resolve(this.devBuildFolder, 'index.js');
662
- app = spawn('node', ['-r', 'source-map-support/register', filePath], { stdio: 'inherit' });
663
- }),
664
- };
665
- }
42
+ const livereload = require('rollup-plugin-livereload');
43
+ const { string } = require('rollup-plugin-string');
44
+ const { exec, spawn } = require('child_process');
45
+ const readline = require('readline');
46
+ const importAssets = require('rollup-plugin-import-assets');
47
+ const execAsync = promisify(exec);
48
+ const copyFiles = promisify(fs.copy);
49
+ const pipeline = promisify(stream.pipeline);
50
+ updateDotenv();
51
+ const REG_CLEAR_TEXT = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
52
+ const REG_RPT_ERROR_FILE = /(src[^:]+):(\d+):(\d+)/;
53
+ const REG_TJSX = /\.[tj]sx?$/;
54
+ const REG_EXT = /\.([^.]+)$/;
55
+ const scriptExtensions = ['ts', 'js', 'tsx', 'jsx'];
56
+ const indexExt = scriptExtensions.join(',');
57
+ class InnetJS {
58
+ constructor({ envPrefix = process.env.INNETJS_ENV_PREFIX || 'INNETJS_', projectFolder = process.env.PROJECT_FOLDER || '', baseUrl = process.env.BASE_URL || '', publicFolder = process.env.PUBLIC_FOLDER || 'public', releaseFolder = process.env.RELEASE_FOLDER || 'release', buildFolder = process.env.BUILD_FOLDER || 'build', srcFolder = process.env.SRC_FOLDER || 'src', sourcemap = process.env.SOURCEMAP ? process.env.SOURCEMAP === 'true' : false, cssModules = process.env.CSS_MODULES ? process.env.CSS_MODULES === 'true' : true, cssInJs = process.env.CSS_IN_JS ? process.env.CSS_IN_JS === 'true' : true, sslKey = process.env.SSL_KEY || 'localhost.key', sslCrt = process.env.SSL_CRT || 'localhost.crt', proxy = process.env.PROXY || '', simulateIP = process.env.IP, port = process.env.PORT ? +process.env.PORT : 3000, api = process.env.API || '/api/?*', } = {}) {
59
+ this.projectFolder = path.resolve(projectFolder);
60
+ this.publicFolder = path.resolve(publicFolder);
61
+ this.releaseFolder = path.resolve(releaseFolder);
62
+ this.buildFolder = path.resolve(buildFolder);
63
+ this.srcFolder = path.resolve(srcFolder);
64
+ this.licenseFile = path.join(projectFolder, 'LICENSE');
65
+ this.licenseReleaseFile = path.join(releaseFolder, 'LICENSE');
66
+ this.readmeFile = path.join(projectFolder, 'README.md');
67
+ this.readmeReleaseFile = path.join(releaseFolder, 'README.md');
68
+ this.declarationFile = path.join(srcFolder, 'declaration.d.ts');
69
+ this.declarationReleaseFile = path.join(releaseFolder, 'declaration.d.ts');
70
+ this.publicIndexFile = path.join(publicFolder, 'index.html');
71
+ this.buildIndexFile = path.join(buildFolder, 'index.html');
72
+ this.devBuildFolder = path.resolve(projectFolder, 'node_modules', '.cache', 'innetjs', 'build');
73
+ this.devBuildIndexFile = path.join(this.devBuildFolder, 'index.html');
74
+ this.sourcemap = sourcemap;
75
+ this.cssModules = cssModules;
76
+ this.cssInJs = cssInJs;
77
+ this.sslKey = sslKey;
78
+ this.sslCrt = sslCrt;
79
+ this.port = port;
80
+ this.proxy = proxy;
81
+ this.api = api;
82
+ this.baseUrl = baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`;
83
+ this.envPrefix = envPrefix;
84
+ this.simulateIP = simulateIP;
85
+ }
86
+ // Methods
87
+ init(appName, { template, force = false } = {}) {
88
+ return __awaiter(this, void 0, void 0, function* () {
89
+ const appPath = path.resolve(appName);
90
+ const { data } = yield logger.start('Get templates list', () => __awaiter(this, void 0, void 0, function* () { return yield axios.get('https://api.github.com/repos/d8corp/innetjs-templates/branches'); }));
91
+ const templates = data.map(({ name }) => name).filter(name => name !== 'main');
92
+ if (!template || !templates.includes(template)) {
93
+ logger.log(chalk.green('Select one of those templates'));
94
+ const { value } = yield selector({
95
+ values: templates,
96
+ });
97
+ template = value;
98
+ readline.moveCursor(process.stdout, 0, -1);
99
+ const text = `Selected template: ${chalk.white(value)}`;
100
+ logger.start(text);
101
+ logger.end(text);
102
+ }
103
+ if (!force) {
104
+ yield logger.start('Check if app folder is available', () => __awaiter(this, void 0, void 0, function* () {
105
+ if (fs.existsSync(appPath)) {
106
+ logger.log(chalk.red(`'${appPath}' already exist, what do you want?`));
107
+ const { id: result, value } = yield selector({
108
+ values: ['Stop the process', 'Remove the folder', 'Merge with template'],
109
+ });
110
+ readline.moveCursor(process.stdout, 0, -1);
111
+ logger.log(`Already exist, selected: ${value}`);
112
+ if (!result) {
113
+ throw Error(`'${appPath}' already exist`);
114
+ }
115
+ if (result === 1) {
116
+ yield fs.remove(appPath);
117
+ }
118
+ }
119
+ }));
120
+ }
121
+ yield logger.start('Download template', () => __awaiter(this, void 0, void 0, function* () {
122
+ if (!fs.existsSync(appPath)) {
123
+ fs.mkdirSync(appPath);
124
+ }
125
+ const zipPath = path.join(appPath, 'template.zip');
126
+ const unzipPath = path.join(appPath, `innetjs-templates-${template}`);
127
+ const { data } = yield axios.get(`https://github.com/d8corp/innetjs-templates/archive/refs/heads/${template}.zip`, {
128
+ responseType: 'stream',
129
+ });
130
+ yield pipeline(data, fs.createWriteStream(zipPath));
131
+ yield new Promise((resolve, reject) => {
132
+ fs.createReadStream(zipPath)
133
+ .pipe(Extract({ path: appPath }))
134
+ .on('finish', resolve).on('error', reject);
135
+ });
136
+ yield fs.remove(zipPath);
137
+ yield fs.move(unzipPath, appPath);
138
+ }));
139
+ yield logger.start('Install packages', () => execAsync(`cd ${appPath} && npm i`));
140
+ });
141
+ }
142
+ build({ node = false, inject = false, index = 'index' } = {}) {
143
+ return __awaiter(this, void 0, void 0, function* () {
144
+ const input = glob.sync(`src/${index}.{${indexExt}}`);
145
+ if (!input.length) {
146
+ throw Error('index file is not detected');
147
+ }
148
+ yield logger.start('Remove build', () => fs.remove(this.buildFolder));
149
+ const pkg = node && (yield this.getPackage());
150
+ const options = {
151
+ input,
152
+ preserveEntrySignatures: 'strict',
153
+ plugins: [
154
+ commonjs(),
155
+ json(),
156
+ ts({
157
+ noEmitOnError: true,
158
+ compilerOptions: {
159
+ declaration: false,
160
+ },
161
+ }),
162
+ jsx(),
163
+ ],
164
+ onwarn(warning, warn) {
165
+ if (warning.code === 'THIS_IS_UNDEFINED' || warning.code === 'SOURCEMAP_ERROR')
166
+ return;
167
+ warn(warning);
168
+ },
169
+ };
170
+ this.withLint(options, true);
171
+ const outputOptions = {
172
+ dir: this.buildFolder,
173
+ sourcemap: this.sourcemap,
174
+ };
175
+ if (node) {
176
+ outputOptions.format = 'cjs';
177
+ options.external = Object.keys((pkg === null || pkg === void 0 ? void 0 : pkg.dependencies) || {});
178
+ options.plugins.push(nodeResolve(), string({
179
+ include: '**/*.*',
180
+ exclude: stringExcludeNode,
181
+ }));
182
+ }
183
+ else {
184
+ options.plugins.push(nodeResolve({
185
+ browser: true,
186
+ }), polyfill(), importAssets({
187
+ include: imageInclude.map(img => `src/${img}`),
188
+ publicPath: this.baseUrl,
189
+ }), styles({
190
+ mode: this.cssInJs ? 'inject' : 'extract',
191
+ url: {
192
+ inline: false,
193
+ publicPath: `${this.baseUrl}assets`,
194
+ },
195
+ plugins: [autoprefixer()],
196
+ autoModules: this.cssModules ? (id) => !id.includes('.global.') : true,
197
+ sourceMap: this.sourcemap,
198
+ minimize: true,
199
+ }), string({
200
+ include: '**/*.*',
201
+ exclude: stringExcludeDom,
202
+ }));
203
+ outputOptions.format = 'es';
204
+ outputOptions.plugins = [
205
+ terser(),
206
+ filesize({
207
+ reporter,
208
+ }),
209
+ ];
210
+ }
211
+ this.withEnv(options, true);
212
+ yield logger.start('Build production bundle', () => __awaiter(this, void 0, void 0, function* () {
213
+ const bundle = yield rollup.rollup(options);
214
+ yield bundle.write(outputOptions);
215
+ yield bundle.close();
216
+ if (!node) {
217
+ yield copyFiles(this.publicFolder, this.buildFolder);
218
+ const data = yield promises.readFile(this.publicIndexFile);
219
+ const pkg = yield this.getPackage();
220
+ yield promises.writeFile(this.buildIndexFile, yield convertIndexFile(data, pkg.version, this.baseUrl, path.parse(input[0]).name, inject));
221
+ }
222
+ }));
223
+ if (pkg) {
224
+ yield logger.start('Copy package.json', () => __awaiter(this, void 0, void 0, function* () {
225
+ const data = Object.assign({}, pkg);
226
+ delete data.private;
227
+ delete data.devDependencies;
228
+ yield fs.writeFile(path.resolve(this.buildFolder, 'package.json'), JSON.stringify(data, undefined, 2), 'UTF-8');
229
+ }));
230
+ const pkgLockPath = path.resolve(this.projectFolder, 'package-lock.json');
231
+ if (fs.existsSync(pkgLockPath)) {
232
+ yield logger.start('Copy package-lock.json', () => {
233
+ return fs.copy(pkgLockPath, path.resolve(this.buildFolder, 'package-lock.json'));
234
+ });
235
+ }
236
+ }
237
+ });
238
+ }
239
+ start({ node = false, inject = false, error = false, index = 'index' } = {}) {
240
+ return __awaiter(this, void 0, void 0, function* () {
241
+ const pkg = yield this.getPackage();
242
+ const input = glob.sync(`src/${index}.{${indexExt}}`);
243
+ if (!input.length) {
244
+ throw Error('index file is not detected');
245
+ }
246
+ yield logger.start('Remove build', () => fs.remove(this.devBuildFolder));
247
+ const options = {
248
+ input,
249
+ preserveEntrySignatures: 'strict',
250
+ output: {
251
+ dir: this.devBuildFolder,
252
+ sourcemap: true,
253
+ },
254
+ plugins: [
255
+ commonjs(),
256
+ json(),
257
+ ts({
258
+ compilerOptions: {
259
+ declaration: false,
260
+ sourceMap: true,
261
+ },
262
+ }),
263
+ jsx(),
264
+ ],
265
+ onwarn(warning, warn) {
266
+ if (warning.code === 'THIS_IS_UNDEFINED' || warning.code === 'SOURCEMAP_ERROR')
267
+ return;
268
+ if (warning.plugin === 'typescript') {
269
+ const { loc: { line, column, file }, frame, message } = warning;
270
+ console.log(`ERROR in ${file}:${line}:${column}`);
271
+ console.log(message);
272
+ console.log(frame);
273
+ return;
274
+ }
275
+ warn(warning);
276
+ },
277
+ };
278
+ this.withLint(options);
279
+ if (node) {
280
+ // @ts-expect-error
281
+ options.output.format = 'cjs';
282
+ options.external = Object.keys((pkg === null || pkg === void 0 ? void 0 : pkg.dependencies) || {});
283
+ options.plugins.push(nodeResolve(), string({
284
+ include: '**/*.*',
285
+ exclude: stringExcludeNode,
286
+ }), this.createServer(input));
287
+ }
288
+ else {
289
+ const key = path.basename(this.sslKey) !== this.sslKey
290
+ ? this.sslKey
291
+ : fs.existsSync(this.sslKey)
292
+ ? fs.readFileSync(this.sslKey)
293
+ : undefined;
294
+ const cert = path.basename(this.sslCrt) !== this.sslCrt
295
+ ? this.sslCrt
296
+ : fs.existsSync(this.sslCrt)
297
+ ? fs.readFileSync(this.sslCrt)
298
+ : undefined;
299
+ // @ts-expect-error
300
+ options.output.format = 'es';
301
+ options.plugins.push(nodeResolve({
302
+ browser: true,
303
+ }), polyfill(), importAssets({
304
+ include: imageInclude.map(img => `src/${img}`),
305
+ publicPath: this.baseUrl,
306
+ }), styles({
307
+ mode: this.cssInJs ? 'inject' : 'extract',
308
+ url: {
309
+ inline: false,
310
+ publicPath: `${this.baseUrl}assets`,
311
+ },
312
+ plugins: [autoprefixer()],
313
+ autoModules: this.cssModules ? (id) => !id.includes('.global.') : true,
314
+ sourceMap: true,
315
+ }), string({
316
+ include: '**/*.*',
317
+ exclude: stringExcludeDom,
318
+ }), this.createClient(key, cert, pkg, path.parse(input[0]).name, inject), livereload(Object.assign({ exts: ['html', 'css', 'js', 'png', 'svg', 'webp', 'gif', 'jpg', 'json'], watch: [this.devBuildFolder, this.publicFolder], verbose: false }, (key && cert ? { https: { key, cert } } : {}))));
319
+ }
320
+ this.withEnv(options, true);
321
+ const watcher = rollup.watch(options);
322
+ watcher.on('event', (e) => __awaiter(this, void 0, void 0, function* () {
323
+ if (e.code === 'ERROR') {
324
+ if (e.error.code === 'UNRESOLVED_IMPORT') {
325
+ const [, importer, file] = e.error.message.match(/^Could not resolve '(.+)' from (.+)$/) || [];
326
+ const text = (yield fs.readFile(file)).toString();
327
+ const lines = new LinesAndColumns(text);
328
+ const { line, column } = lines.locationForIndex(text.indexOf(importer));
329
+ logger.end('Bundling', e.error.message);
330
+ console.log(`ERROR in ${file}:${line + 1}:${column + 1}`);
331
+ }
332
+ else if (e.error.code === 'PLUGIN_ERROR' && ['rpt2', 'commonjs', 'typescript'].includes(e.error.plugin)) {
333
+ const [, file, line, column] = e.error.message
334
+ .replace(REG_CLEAR_TEXT, '')
335
+ .match(REG_RPT_ERROR_FILE) || [];
336
+ logger.end('Bundling', e.error.message);
337
+ if (file) {
338
+ console.log(`ERROR in ${file}:${line}:${column}`);
339
+ }
340
+ else if (e.error.loc) {
341
+ console.log(`ERROR in ${e.error.loc.file}:${e.error.loc.line}:${e.error.loc.column}`);
342
+ console.log(e.error.frame);
343
+ }
344
+ }
345
+ else {
346
+ logger.end('Bundling', error ? e.error.stack : e.error.message);
347
+ }
348
+ }
349
+ else if (e.code === 'BUNDLE_START') {
350
+ logger.start('Bundling');
351
+ }
352
+ else if (e.code === 'BUNDLE_END') {
353
+ logger.end('Bundling');
354
+ }
355
+ }));
356
+ });
357
+ }
358
+ run(file) {
359
+ return __awaiter(this, void 0, void 0, function* () {
360
+ const input = yield logger.start('Check file', () => getFile(file));
361
+ const folder = yield new Promise((resolve, reject) => {
362
+ tmp.dir((err, folder) => {
363
+ if (err) {
364
+ reject(err);
365
+ }
366
+ else {
367
+ resolve(folder);
368
+ }
369
+ });
370
+ });
371
+ const jsFilePath = `${folder}/index.js`;
372
+ yield logger.start('Build bundle', () => __awaiter(this, void 0, void 0, function* () {
373
+ const inputOptions = {
374
+ input,
375
+ plugins: [
376
+ commonjs(),
377
+ nodeResolve(),
378
+ json(),
379
+ ts({
380
+ compilerOptions: {
381
+ sourceMap: true,
382
+ },
383
+ }),
384
+ ],
385
+ };
386
+ const outputOptions = {
387
+ format: 'cjs',
388
+ file: jsFilePath,
389
+ sourcemap: true,
390
+ };
391
+ const bundle = yield rollup.rollup(inputOptions);
392
+ yield bundle.write(outputOptions);
393
+ yield bundle.close();
394
+ }));
395
+ yield logger.start('Running of the script', () => __awaiter(this, void 0, void 0, function* () {
396
+ spawn('node', ['-r', 'source-map-support/register', jsFilePath], { stdio: 'inherit' });
397
+ }));
398
+ });
399
+ }
400
+ release({ index = 'index', pub } = {}) {
401
+ return __awaiter(this, void 0, void 0, function* () {
402
+ const { releaseFolder, cssModules } = this;
403
+ yield logger.start('Remove previous release', () => fs.remove(releaseFolder));
404
+ const pkg = yield this.getPackage();
405
+ const build = (format) => __awaiter(this, void 0, void 0, function* () {
406
+ var _a, _b;
407
+ const ext = format === 'es'
408
+ ? ((_a = (pkg.module || pkg.esnext || pkg['jsnext:main'])) === null || _a === void 0 ? void 0 : _a.replace('index', '')) || '.mjs'
409
+ : ((_b = pkg.main) === null || _b === void 0 ? void 0 : _b.replace('index', '')) || '.js';
410
+ const input = glob.sync(`src/${index}.{${indexExt}}`);
411
+ if (!input.length) {
412
+ throw Error('index file is not detected');
413
+ }
414
+ const options = {
415
+ input,
416
+ external: ['tslib'],
417
+ treeshake: false,
418
+ output: {
419
+ dir: releaseFolder,
420
+ entryFileNames: ({ name, facadeModuleId }) => {
421
+ if (REG_TJSX.test(facadeModuleId)) {
422
+ return `${name}${ext}`;
423
+ }
424
+ const match = facadeModuleId.match(REG_EXT);
425
+ return match ? `${name}${match[0]}${ext}` : `${name}${ext}`;
426
+ },
427
+ format,
428
+ preserveModules: true,
429
+ exports: 'named',
430
+ },
431
+ plugins: [
432
+ json(),
433
+ ts({
434
+ compilerOptions: {
435
+ sourceMap: false,
436
+ outDir: releaseFolder,
437
+ },
438
+ }),
439
+ jsx(),
440
+ externals(),
441
+ string({
442
+ include: '**/*.*',
443
+ exclude: stringExcludeDom,
444
+ }),
445
+ image(),
446
+ styles({
447
+ mode: this.cssInJs ? 'inject' : 'extract',
448
+ plugins: [autoprefixer()],
449
+ autoModules: cssModules ? (id) => !id.includes('.global.') : true,
450
+ minimize: true,
451
+ }),
452
+ nodeResolve(),
453
+ external(),
454
+ ],
455
+ };
456
+ this.withLint(options);
457
+ this.withEnv(options, true);
458
+ const bundle = yield rollup.rollup(options);
459
+ yield bundle.write(options.output);
460
+ yield bundle.close();
461
+ });
462
+ yield logger.start('Build cjs bundle', () => __awaiter(this, void 0, void 0, function* () {
463
+ yield build('cjs');
464
+ }));
465
+ yield logger.start('Build es6 bundle', () => __awaiter(this, void 0, void 0, function* () {
466
+ yield build('es');
467
+ }));
468
+ yield logger.start('Copy package.json', () => __awaiter(this, void 0, void 0, function* () {
469
+ const data = Object.assign({}, pkg);
470
+ delete data.private;
471
+ delete data.devDependencies;
472
+ yield fs.writeFile(path.resolve(this.releaseFolder, 'package.json'), JSON.stringify(data, undefined, 2), 'UTF-8');
473
+ }));
474
+ if (pkg.bin) {
475
+ yield logger.start('Build bin', () => __awaiter(this, void 0, void 0, function* () {
476
+ const { bin } = pkg;
477
+ for (const name in bin) {
478
+ const value = bin[name];
479
+ const input = glob.sync(`src/${value}.{${indexExt}}`);
480
+ const file = path.join(this.releaseFolder, value);
481
+ const options = {
482
+ input,
483
+ external: [...Object.keys(pkg.dependencies), 'tslib'],
484
+ output: {
485
+ file,
486
+ format: 'cjs',
487
+ },
488
+ plugins: [
489
+ preserveShebangs(),
490
+ json(),
491
+ ts({
492
+ compilerOptions: {
493
+ declaration: false,
494
+ },
495
+ }),
496
+ externals(),
497
+ jsx(),
498
+ ],
499
+ };
500
+ this.withLint(options);
501
+ this.withEnv(options);
502
+ const bundle = yield rollup.rollup(options);
503
+ yield bundle.write(options.output);
504
+ yield bundle.close();
505
+ }
506
+ }));
507
+ }
508
+ if (fs.existsSync(this.licenseFile)) {
509
+ yield logger.start('Copy license', () => __awaiter(this, void 0, void 0, function* () {
510
+ yield promises.copyFile(this.licenseFile, this.licenseReleaseFile);
511
+ }));
512
+ }
513
+ if (fs.existsSync(this.readmeFile)) {
514
+ yield logger.start('Copy readme', () => __awaiter(this, void 0, void 0, function* () {
515
+ yield promises.copyFile(this.readmeFile, this.readmeReleaseFile);
516
+ }));
517
+ }
518
+ if (fs.existsSync(this.declarationFile)) {
519
+ yield logger.start('Copy declaration', () => __awaiter(this, void 0, void 0, function* () {
520
+ yield promises.copyFile(this.declarationFile, this.declarationReleaseFile);
521
+ }));
522
+ }
523
+ if (pub) {
524
+ const date = (Date.now() / 1000) | 0;
525
+ yield logger.start(`publishing v${pkg.version} ${date}`, () => __awaiter(this, void 0, void 0, function* () {
526
+ yield execAsync(`npm publish ${this.releaseFolder}`);
527
+ }));
528
+ }
529
+ });
530
+ }
531
+ withLint(options, prod = false) {
532
+ if (this._lintUsage === undefined) {
533
+ this._lintUsage = fs.existsSync(path.join(this.projectFolder, '.eslintrc'));
534
+ }
535
+ if (this._lintUsage) {
536
+ options.plugins.push(eslint({
537
+ include: lintInclude,
538
+ throwOnError: prod,
539
+ }));
540
+ }
541
+ }
542
+ withEnv(options, virtual) {
543
+ options.plugins.push(env(this.envPrefix, {
544
+ include: options.input,
545
+ virtual,
546
+ }));
547
+ }
548
+ increaseVersion(release) {
549
+ return __awaiter(this, void 0, void 0, function* () {
550
+ const pkg = yield this.getPackage();
551
+ yield logger.start('Prepare package.json', () => __awaiter(this, void 0, void 0, function* () {
552
+ const version = pkg.version.split('.');
553
+ switch (release) {
554
+ case 'patch': {
555
+ version[2]++;
556
+ break;
557
+ }
558
+ case 'minor': {
559
+ version[1]++;
560
+ version[2] = 0;
561
+ break;
562
+ }
563
+ case 'major': {
564
+ version[1] = 0;
565
+ version[2] = 0;
566
+ version[0]++;
567
+ break;
568
+ }
569
+ default: return;
570
+ }
571
+ pkg.version = version.join('.');
572
+ yield fs.writeFile(path.resolve(this.projectFolder, 'package.json'), JSON.stringify(pkg, undefined, 2), 'UTF-8');
573
+ }));
574
+ });
575
+ }
576
+ getPackage() {
577
+ return __awaiter(this, void 0, void 0, function* () {
578
+ if (this.package) {
579
+ return this.package;
580
+ }
581
+ const packageFolder = path.resolve(this.projectFolder, 'package.json');
582
+ yield logger.start('Check package.json', () => __awaiter(this, void 0, void 0, function* () {
583
+ if (fs.existsSync(packageFolder)) {
584
+ this.package = yield fs.readJson(packageFolder);
585
+ }
586
+ }));
587
+ return this.package;
588
+ });
589
+ }
590
+ createClient(key, cert, pkg, index, inject) {
591
+ let app;
592
+ return {
593
+ name: 'client',
594
+ writeBundle: () => __awaiter(this, void 0, void 0, function* () {
595
+ var _a;
596
+ if (!app) {
597
+ app = express();
598
+ const update = () => __awaiter(this, void 0, void 0, function* () {
599
+ const data = yield promises.readFile(this.publicIndexFile);
600
+ yield promises.writeFile(this.devBuildIndexFile, yield convertIndexFile(data, pkg.version, this.baseUrl, index, inject));
601
+ });
602
+ fs.watch(this.publicIndexFile, update);
603
+ yield update();
604
+ const httpsUsing = !!(cert && key);
605
+ app.use(this.baseUrl, express.static(this.devBuildFolder));
606
+ app.use(this.baseUrl, express.static(this.publicFolder));
607
+ if ((_a = this.proxy) === null || _a === void 0 ? void 0 : _a.startsWith('http')) {
608
+ if (this.simulateIP) {
609
+ app.use((req, res, next) => {
610
+ req.headers['X-Real-IP'] = this.simulateIP;
611
+ next();
612
+ });
613
+ }
614
+ app.use(this.api, proxy(this.proxy, {
615
+ https: httpsUsing,
616
+ limit: '1000mb',
617
+ proxyReqPathResolver: req => req.originalUrl,
618
+ }));
619
+ }
620
+ app.use(/^([^.]*|.*\.[^.]{5,})$/, (req, res) => {
621
+ res.sendFile(this.devBuildFolder + '/index.html');
622
+ });
623
+ const server = httpsUsing ? https.createServer({ key, cert }, app) : http.createServer(app);
624
+ let port = this.port;
625
+ const listener = () => {
626
+ const baseUrl = this.baseUrl === '/' ? '' : this.baseUrl;
627
+ console.log(`${chalk.green('➤')} Started on http${httpsUsing ? 's' : ''}://localhost:${port}${baseUrl} and http${httpsUsing ? 's' : ''}://${address.ip()}:${port}${baseUrl}`);
628
+ };
629
+ server.listen(port, listener);
630
+ server.on('error', (e) => __awaiter(this, void 0, void 0, function* () {
631
+ if (e.code === 'EADDRINUSE') {
632
+ port++;
633
+ const { userPort } = yield prompt({
634
+ name: 'userPort',
635
+ type: 'number',
636
+ message: `Port ${e.port} is reserved, please enter another one [${port}]:`,
637
+ });
638
+ if (userPort) {
639
+ port = userPort;
640
+ }
641
+ server.listen(port);
642
+ }
643
+ else {
644
+ throw e;
645
+ }
646
+ }));
647
+ }
648
+ }),
649
+ };
650
+ }
651
+ createServer(input) {
652
+ const apps = {};
653
+ return {
654
+ name: 'server',
655
+ writeBundle: () => __awaiter(this, void 0, void 0, function* () {
656
+ var _a;
657
+ for (const file of input) {
658
+ const { name } = path.parse(file);
659
+ (_a = apps[name]) === null || _a === void 0 ? void 0 : _a.kill();
660
+ const filePath = path.resolve(this.devBuildFolder, `${name}.js`);
661
+ apps[name] = spawn('node', ['-r', 'source-map-support/register', filePath], { stdio: 'inherit' });
662
+ }
663
+ }),
664
+ };
665
+ }
666
666
  }
667
667
 
668
668
  export { InnetJS, indexExt, scriptExtensions };