@metricinsights/pp-dev 0.9.0 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +144 -0
- package/README.md +152 -232
- package/dist/cjs/cli.js +1 -1200
- package/dist/cjs/cli.js.map +1 -1
- package/dist/cjs/helpers.js +1 -28
- package/dist/cjs/helpers.js.map +1 -1
- package/dist/cjs/index-DRre2UkM.js +2 -0
- package/dist/cjs/index-DRre2UkM.js.map +1 -0
- package/dist/cjs/index.js +1 -26
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/package.json +19 -14
- package/dist/cjs/plugin-Dx9CDaej.js +2 -0
- package/dist/cjs/plugin-Dx9CDaej.js.map +1 -0
- package/dist/cjs/plugin.js +1 -25
- package/dist/cjs/plugin.js.map +1 -1
- package/dist/client/client.css +3 -287
- package/dist/client/client.css.map +1 -0
- package/dist/client/client.js +110 -14
- package/dist/client/client.js.map +1 -1
- package/dist/client/index.html +39 -26
- package/dist/esm/cli.js +1 -1173
- package/dist/esm/cli.js.map +1 -1
- package/dist/esm/helpers.js +1 -24
- package/dist/esm/helpers.js.map +1 -1
- package/dist/esm/index-kmS_-y6Z.js +2 -0
- package/dist/esm/index-kmS_-y6Z.js.map +1 -0
- package/dist/esm/index.js +1 -19
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/package.json +19 -14
- package/dist/esm/plugin-H4ccpQoX.js +2 -0
- package/dist/esm/plugin-H4ccpQoX.js.map +1 -0
- package/dist/esm/plugin.js +1 -16
- package/dist/esm/plugin.js.map +1 -1
- package/dist/types/index.d.ts +104 -3
- package/package.json +19 -14
- package/dist/cjs/index-BE4YF5iw.js +0 -331
- package/dist/cjs/index-BE4YF5iw.js.map +0 -1
- package/dist/cjs/plugin-DZS4Taov.js +0 -1315
- package/dist/cjs/plugin-DZS4Taov.js.map +0 -1
- package/dist/client/index.d.ts +0 -2
- package/dist/esm/index-7YgmP5z7.js +0 -308
- package/dist/esm/index-7YgmP5z7.js.map +0 -1
- package/dist/esm/plugin-BeHiwpzF.js +0 -1277
- package/dist/esm/plugin-BeHiwpzF.js.map +0 -1
- package/dist/types/cli.d.ts +0 -3
- package/dist/types/helpers.d.ts +0 -24
- package/dist/types/plugin.d.ts +0 -86
package/dist/esm/cli.js
CHANGED
|
@@ -1,1174 +1,2 @@
|
|
|
1
|
-
import * as path from 'path';
|
|
2
|
-
import * as fs from 'fs';
|
|
3
|
-
import { performance } from 'node:perf_hooks';
|
|
4
|
-
import { cac } from 'cac';
|
|
5
|
-
import { g as getViteConfig, V as VERSION } from './index-7YgmP5z7.js';
|
|
6
|
-
import { c as createLogger, a as colors, i as initPPRedirect, M as MiAPI, b as initProxyCache, d as initProxy, e as initLoadPPData, f as initRewriteResponse, u as urlReplacer, g as cutUrlParams } from './plugin-BeHiwpzF.js';
|
|
7
|
-
import { loadConfigFromFile, mergeConfig, build, resolveConfig, optimizeDeps, preview } from 'vite';
|
|
8
|
-
import { URL as URL$1, parse } from 'url';
|
|
9
|
-
import * as express from 'express';
|
|
10
|
-
import * as winston from 'winston';
|
|
11
|
-
import * as dirCompare from 'dir-compare';
|
|
12
|
-
import DiffMatchPatch from 'diff-match-patch';
|
|
13
|
-
import { isBinaryFile } from 'isbinaryfile';
|
|
14
|
-
import * as os from 'os';
|
|
15
|
-
import * as crypto from 'crypto';
|
|
16
|
-
import extractZip from 'extract-zip';
|
|
17
|
-
import svgToFont from 'svgtofont';
|
|
18
|
-
import 'ejs';
|
|
19
|
-
import 'esbuild';
|
|
20
|
-
import 'http-proxy-middleware';
|
|
21
|
-
import 'picocolors';
|
|
22
|
-
import 'axios';
|
|
23
|
-
import 'jsdom';
|
|
24
|
-
import 'https';
|
|
25
|
-
import 'memory-cache';
|
|
26
|
-
import 'process';
|
|
27
|
-
import 'child_process';
|
|
28
|
-
import 'console';
|
|
29
|
-
import 'zlib';
|
|
30
|
-
|
|
31
|
-
function isDefined(value) {
|
|
32
|
-
return value != null;
|
|
33
|
-
}
|
|
34
|
-
function bindShortcuts(server, opts) {
|
|
35
|
-
if (!server.httpServer || !process.stdin.isTTY || process.env.CI) {
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
server._shortcutsOptions = opts;
|
|
39
|
-
const logger = createLogger();
|
|
40
|
-
if (opts.print) {
|
|
41
|
-
logger.info(colors.dim(colors.green(' ➜')) + colors.dim(' press ') + colors.bold('h') + colors.dim(' to show help'));
|
|
42
|
-
}
|
|
43
|
-
const shortcuts = (opts.customShortcuts ?? []).filter(isDefined).concat(BASE_SHORTCUTS);
|
|
44
|
-
let actionRunning = false;
|
|
45
|
-
const onInput = async (input) => {
|
|
46
|
-
// ctrl+c or ctrl+d
|
|
47
|
-
if (input === '\x03' || input === '\x04') {
|
|
48
|
-
await server.close().finally(() => process.exit(1));
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
if (actionRunning) {
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
if (input === 'h') {
|
|
55
|
-
logger.info([
|
|
56
|
-
'',
|
|
57
|
-
colors.bold(' Shortcuts'),
|
|
58
|
-
...shortcuts.map((shortcut) => colors.dim(' press ') + colors.bold(shortcut.key) + colors.dim(` to ${shortcut.description}`)),
|
|
59
|
-
].join('\n'));
|
|
60
|
-
}
|
|
61
|
-
const shortcut = shortcuts.find((shortcut) => shortcut.key === input);
|
|
62
|
-
if (!shortcut) {
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
actionRunning = true;
|
|
66
|
-
await shortcut.action(server);
|
|
67
|
-
actionRunning = false;
|
|
68
|
-
};
|
|
69
|
-
process.stdin.setRawMode(true);
|
|
70
|
-
process.stdin.on('data', onInput).setEncoding('utf8').resume();
|
|
71
|
-
server.httpServer.on('close', () => {
|
|
72
|
-
process.stdin.off('data', onInput).pause();
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
const BASE_SHORTCUTS = [
|
|
76
|
-
{
|
|
77
|
-
key: 'r',
|
|
78
|
-
description: 'restart the server',
|
|
79
|
-
async action(server) {
|
|
80
|
-
await server.restart();
|
|
81
|
-
},
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
key: 'u',
|
|
85
|
-
description: 'show server url',
|
|
86
|
-
action(server) {
|
|
87
|
-
server.config.logger.info('');
|
|
88
|
-
server.printUrls();
|
|
89
|
-
},
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
key: 'o',
|
|
93
|
-
description: 'open in browser',
|
|
94
|
-
action(server) {
|
|
95
|
-
server.openBrowser();
|
|
96
|
-
},
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
key: 'c',
|
|
100
|
-
description: 'clear console',
|
|
101
|
-
action(server) {
|
|
102
|
-
server.config.logger.clearScreen('error');
|
|
103
|
-
},
|
|
104
|
-
},
|
|
105
|
-
{
|
|
106
|
-
key: 'q',
|
|
107
|
-
description: 'quit',
|
|
108
|
-
async action(server) {
|
|
109
|
-
await server.close().finally(() => process.exit());
|
|
110
|
-
},
|
|
111
|
-
},
|
|
112
|
-
{
|
|
113
|
-
key: 'C',
|
|
114
|
-
description: 'clear proxy cache',
|
|
115
|
-
action(server) {
|
|
116
|
-
if (server.cache) {
|
|
117
|
-
server.cache.clear();
|
|
118
|
-
server.config.logger.info('Proxy cache cleared');
|
|
119
|
-
}
|
|
120
|
-
},
|
|
121
|
-
},
|
|
122
|
-
];
|
|
123
|
-
|
|
124
|
-
function createDevServer(logLevel = 'info') {
|
|
125
|
-
const server = express.default();
|
|
126
|
-
const logger = winston.createLogger({
|
|
127
|
-
level: logLevel,
|
|
128
|
-
format: winston.format.cli({ level: true }),
|
|
129
|
-
transports: [new winston.transports.Console()],
|
|
130
|
-
});
|
|
131
|
-
server.config = {
|
|
132
|
-
logger,
|
|
133
|
-
};
|
|
134
|
-
const originalListen = server.listen;
|
|
135
|
-
let listener;
|
|
136
|
-
server.listen = function (...args) {
|
|
137
|
-
listener = originalListen.apply(this, args);
|
|
138
|
-
};
|
|
139
|
-
server.printUrls = function (base) {
|
|
140
|
-
if (!listener) {
|
|
141
|
-
throw new Error('Server is not listening');
|
|
142
|
-
}
|
|
143
|
-
const colorUrl = (url) => colors.cyan(url.replace(/:(\d+)\//, (_, port) => `:${colors.bold(port)}/`));
|
|
144
|
-
const address = listener.address();
|
|
145
|
-
if (address && typeof address === 'object') {
|
|
146
|
-
if (address.address === '::') {
|
|
147
|
-
const url = new URL$1(base || '', `http://localhost:${address.port}`);
|
|
148
|
-
logger.info(` ${colors.green('➜')} ${colors.bold('Local')}: ${colorUrl(url.toString())}`);
|
|
149
|
-
}
|
|
150
|
-
else {
|
|
151
|
-
const url = new URL$1(base || '', `http://[${address.address}]:${address.port}`);
|
|
152
|
-
logger.info(` ${colors.green('➜')} ${colors.bold('Local')}: ${colorUrl(url.toString())}`);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
};
|
|
156
|
-
return server;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
const changelogTemplate = /* HTML */ `<!DOCTYPE html>
|
|
160
|
-
<html lang="en">
|
|
161
|
-
<head>
|
|
162
|
-
<meta charset="UTF-8" />
|
|
163
|
-
<title>Changelog Diff</title>
|
|
164
|
-
<style>
|
|
165
|
-
tr,
|
|
166
|
-
td {
|
|
167
|
-
padding: 0;
|
|
168
|
-
}
|
|
169
|
-
.diff-file {
|
|
170
|
-
margin-top: 20px;
|
|
171
|
-
border: 1px solid #e1e4e8;
|
|
172
|
-
border-radius: 6px;
|
|
173
|
-
}
|
|
174
|
-
.diff-file-title {
|
|
175
|
-
padding: 10px 20px;
|
|
176
|
-
background-color: #f6f8fa;
|
|
177
|
-
border-bottom: 1px solid #e1e4e8;
|
|
178
|
-
border-radius: 6px 6px 0 0;
|
|
179
|
-
font-weight: bold;
|
|
180
|
-
}
|
|
181
|
-
.diff-file-title .renamed {
|
|
182
|
-
font-weight: normal;
|
|
183
|
-
}
|
|
184
|
-
.diff-file-title .renamed .from {
|
|
185
|
-
color: #cb2431;
|
|
186
|
-
}
|
|
187
|
-
.diff-file-title .renamed .to {
|
|
188
|
-
color: #22863a;
|
|
189
|
-
}
|
|
190
|
-
.diff-file-title .added {
|
|
191
|
-
color: #22863a;
|
|
192
|
-
}
|
|
193
|
-
.diff-file-title .deleted {
|
|
194
|
-
color: #cb2431;
|
|
195
|
-
}
|
|
196
|
-
.diff-file-content {
|
|
197
|
-
}
|
|
198
|
-
.diff-table {
|
|
199
|
-
tab-size: 8;
|
|
200
|
-
width: 100%;
|
|
201
|
-
border-collapse: separate;
|
|
202
|
-
border-spacing: 0;
|
|
203
|
-
}
|
|
204
|
-
.blob-num {
|
|
205
|
-
position: relative;
|
|
206
|
-
color: #1f2328;
|
|
207
|
-
width: 1%;
|
|
208
|
-
min-width: 50px;
|
|
209
|
-
padding: 0 10px;
|
|
210
|
-
font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;
|
|
211
|
-
font-size: 12px;
|
|
212
|
-
line-height: 20px;
|
|
213
|
-
text-align: right;
|
|
214
|
-
white-space: nowrap;
|
|
215
|
-
vertical-align: top;
|
|
216
|
-
cursor: pointer;
|
|
217
|
-
-webkit-user-select: none;
|
|
218
|
-
user-select: none;
|
|
219
|
-
}
|
|
220
|
-
.blob-num.addition {
|
|
221
|
-
background-color: #ccffd8;
|
|
222
|
-
border-color: #1f883e;
|
|
223
|
-
}
|
|
224
|
-
.blob-num.deletion {
|
|
225
|
-
background-color: #ffd7d5;
|
|
226
|
-
border-color: #cf222e;
|
|
227
|
-
}
|
|
228
|
-
.blob-num::before {
|
|
229
|
-
content: attr(data-line-number);
|
|
230
|
-
}
|
|
231
|
-
.blob-code {
|
|
232
|
-
position: relative;
|
|
233
|
-
padding: 0 10px 0 22px;
|
|
234
|
-
vertical-align: top;
|
|
235
|
-
color: #1f2329;
|
|
236
|
-
}
|
|
237
|
-
.blob-code.code-addition {
|
|
238
|
-
background-color: #e6ffec;
|
|
239
|
-
}
|
|
240
|
-
.blob-code.code-deletion {
|
|
241
|
-
background-color: #ffebe9;
|
|
242
|
-
}
|
|
243
|
-
.blob-code.skip,
|
|
244
|
-
.blob-code.message {
|
|
245
|
-
text-align: center;
|
|
246
|
-
}
|
|
247
|
-
.blob-code.skip .blob-code-inner,
|
|
248
|
-
.blob-code.message .blob-code-inner {
|
|
249
|
-
font-weight: bold;
|
|
250
|
-
color: #6a737d;
|
|
251
|
-
padding: 10px 0;
|
|
252
|
-
}
|
|
253
|
-
.blob-code-inner {
|
|
254
|
-
display: table-cell;
|
|
255
|
-
overflow: visible;
|
|
256
|
-
font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;
|
|
257
|
-
font-size: 12px;
|
|
258
|
-
word-wrap: anywhere;
|
|
259
|
-
white-space: pre-wrap;
|
|
260
|
-
}
|
|
261
|
-
.blob-code-inner::before {
|
|
262
|
-
content: attr(data-code-prefix);
|
|
263
|
-
position: absolute;
|
|
264
|
-
top: 1px;
|
|
265
|
-
left: 8px;
|
|
266
|
-
padding-right: 8px;
|
|
267
|
-
}
|
|
268
|
-
</style>
|
|
269
|
-
</head>
|
|
270
|
-
<body>
|
|
271
|
-
<h1>Changelog Diff</h1>
|
|
272
|
-
|
|
273
|
-
%FILES%
|
|
274
|
-
</body>
|
|
275
|
-
</html>`;
|
|
276
|
-
const LINE_ADDED = 1;
|
|
277
|
-
const LINE_REMOVED = -1;
|
|
278
|
-
const LINE_CONTEXT = 0;
|
|
279
|
-
/**
|
|
280
|
-
* Escape HTML sequence
|
|
281
|
-
* @param str
|
|
282
|
-
*/
|
|
283
|
-
function escapeHTMLSequence(str) {
|
|
284
|
-
return str.replace(/[\u00A0-\u9999<>&]/g, (i) => '&#' + i.charCodeAt(0) + ';');
|
|
285
|
-
}
|
|
286
|
-
const fileNameWithHashRegEx = /(.+)(-[a-f0-9]{6,20})(\.[a-z0-9]+)$/i;
|
|
287
|
-
/**
|
|
288
|
-
* Changelog generator class
|
|
289
|
-
* @class
|
|
290
|
-
* @classdesc
|
|
291
|
-
* Generates a changelog file based on the differences between two asset folders or zip files
|
|
292
|
-
* @example
|
|
293
|
-
* const changelogGenerator = new ChangelogGenerator({
|
|
294
|
-
* previousAssetsPath: './dist-zip/previous',
|
|
295
|
-
* currentAssetsPath: './dist-zip/current',
|
|
296
|
-
* destinationPath: './dist-zip',
|
|
297
|
-
* changelogFilename: 'CHANGELOG.html',
|
|
298
|
-
* });
|
|
299
|
-
* changelogGenerator.generateChangelog();
|
|
300
|
-
*/
|
|
301
|
-
class ChangelogGenerator {
|
|
302
|
-
oldAssetsPath;
|
|
303
|
-
newAssetsPath;
|
|
304
|
-
destinationPath;
|
|
305
|
-
changelogFilename;
|
|
306
|
-
changelogTemplate = changelogTemplate;
|
|
307
|
-
diffFileTemplateHandler;
|
|
308
|
-
diffLineTemplateHandler;
|
|
309
|
-
contextLines = 3;
|
|
310
|
-
logger;
|
|
311
|
-
/**
|
|
312
|
-
* Changelog generator class constructor
|
|
313
|
-
* @param opts
|
|
314
|
-
*/
|
|
315
|
-
constructor(opts) {
|
|
316
|
-
const { oldAssetsPath, newAssetsPath, destinationPath, changelogTemplate, diffFileTemplateHandler, diffLineTemplateHandler, changelogFilename, contextLines, } = opts;
|
|
317
|
-
this.logger = createLogger();
|
|
318
|
-
if (!oldAssetsPath || !newAssetsPath || !destinationPath) {
|
|
319
|
-
throw new Error('Previous assets path, current assets path and destination path are required');
|
|
320
|
-
}
|
|
321
|
-
if (oldAssetsPath === newAssetsPath) {
|
|
322
|
-
throw new Error('Previous and current assets paths must be different');
|
|
323
|
-
}
|
|
324
|
-
if (!this.isExists(oldAssetsPath)) {
|
|
325
|
-
throw new Error(`Previous assets path ${oldAssetsPath} does not exist`);
|
|
326
|
-
}
|
|
327
|
-
if (!this.isExists(newAssetsPath)) {
|
|
328
|
-
throw new Error(`Current assets path ${newAssetsPath} does not exist`);
|
|
329
|
-
}
|
|
330
|
-
if (this.isZipFile(oldAssetsPath)) {
|
|
331
|
-
const unzipDestinationPath = path.resolve(os.tmpdir(), crypto.createHash('md5').update(oldAssetsPath).digest('hex'));
|
|
332
|
-
this.oldAssetsPath = this.unzipFile(oldAssetsPath, unzipDestinationPath)
|
|
333
|
-
.then(() => {
|
|
334
|
-
return this.normalizeAssetFolderPath(unzipDestinationPath);
|
|
335
|
-
})
|
|
336
|
-
.then((path) => {
|
|
337
|
-
if (this.isEmptyFolder(path)) {
|
|
338
|
-
throw new Error(`Previous assets path ${path} is empty`);
|
|
339
|
-
}
|
|
340
|
-
return path;
|
|
341
|
-
});
|
|
342
|
-
}
|
|
343
|
-
else if (this.isFolder(oldAssetsPath)) {
|
|
344
|
-
const path = this.normalizeAssetFolderPath(oldAssetsPath);
|
|
345
|
-
if (this.isEmptyFolder(path)) {
|
|
346
|
-
throw new Error(`Previous assets path ${path} is empty`);
|
|
347
|
-
}
|
|
348
|
-
this.oldAssetsPath = Promise.resolve(path);
|
|
349
|
-
}
|
|
350
|
-
else {
|
|
351
|
-
throw new Error(`Invalid previous assets path ${oldAssetsPath}. It must be a folder or a zip file`);
|
|
352
|
-
}
|
|
353
|
-
if (this.isZipFile(newAssetsPath)) {
|
|
354
|
-
const unzipDestinationPath = path.resolve(os.tmpdir(), crypto.createHash('md5').update(newAssetsPath).digest('hex'));
|
|
355
|
-
this.newAssetsPath = this.unzipFile(newAssetsPath, unzipDestinationPath)
|
|
356
|
-
.then(() => {
|
|
357
|
-
return this.normalizeAssetFolderPath(unzipDestinationPath);
|
|
358
|
-
})
|
|
359
|
-
.then((path) => {
|
|
360
|
-
if (this.isEmptyFolder(path)) {
|
|
361
|
-
throw new Error(`Current assets path ${path} is empty`);
|
|
362
|
-
}
|
|
363
|
-
return path;
|
|
364
|
-
});
|
|
365
|
-
}
|
|
366
|
-
else if (this.isFolder(newAssetsPath)) {
|
|
367
|
-
const path = this.normalizeAssetFolderPath(newAssetsPath);
|
|
368
|
-
if (this.isEmptyFolder(path)) {
|
|
369
|
-
throw new Error(`Current assets path ${newAssetsPath} is empty`);
|
|
370
|
-
}
|
|
371
|
-
this.newAssetsPath = Promise.resolve(path);
|
|
372
|
-
}
|
|
373
|
-
else {
|
|
374
|
-
throw new Error(`Invalid current assets path ${newAssetsPath}. It must be a folder or a zip file`);
|
|
375
|
-
}
|
|
376
|
-
this.destinationPath = destinationPath;
|
|
377
|
-
this.mkdirpSync(this.destinationPath);
|
|
378
|
-
if (changelogFilename) {
|
|
379
|
-
this.changelogFilename = changelogFilename;
|
|
380
|
-
}
|
|
381
|
-
else {
|
|
382
|
-
this.changelogFilename = 'CHANGELOG.html';
|
|
383
|
-
}
|
|
384
|
-
if (changelogTemplate) {
|
|
385
|
-
if (this.templateIsValid(changelogTemplate)) {
|
|
386
|
-
this.changelogTemplate = changelogTemplate;
|
|
387
|
-
}
|
|
388
|
-
else {
|
|
389
|
-
this.logger.warn(colors.yellow('Invalid changelog template, using default'));
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
if (typeof diffFileTemplateHandler === 'function') {
|
|
393
|
-
this.diffFileTemplateHandler = diffFileTemplateHandler;
|
|
394
|
-
}
|
|
395
|
-
if (typeof diffLineTemplateHandler === 'function') {
|
|
396
|
-
this.diffLineTemplateHandler = diffLineTemplateHandler;
|
|
397
|
-
}
|
|
398
|
-
if (contextLines) {
|
|
399
|
-
this.contextLines = contextLines;
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
templateIsValid(template) {
|
|
403
|
-
return template.includes('%FILES%');
|
|
404
|
-
}
|
|
405
|
-
isExists(assetPath) {
|
|
406
|
-
return fs.existsSync(assetPath);
|
|
407
|
-
}
|
|
408
|
-
isZipFile(assetPath) {
|
|
409
|
-
return assetPath.endsWith('.zip');
|
|
410
|
-
}
|
|
411
|
-
isFolder(assetPath) {
|
|
412
|
-
return fs.lstatSync(assetPath).isDirectory();
|
|
413
|
-
}
|
|
414
|
-
isEmptyFolder(assetPath) {
|
|
415
|
-
return fs.readdirSync(assetPath, { withFileTypes: true }).length === 0;
|
|
416
|
-
}
|
|
417
|
-
mkdirpSync(dir) {
|
|
418
|
-
if (!fs.existsSync(dir)) {
|
|
419
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
async unzipFile(assetPath, destinationPath) {
|
|
423
|
-
fs.rmSync(destinationPath, { force: true, recursive: true });
|
|
424
|
-
return extractZip(assetPath, { dir: destinationPath });
|
|
425
|
-
}
|
|
426
|
-
normalizeAssetFolderPath(assetPath) {
|
|
427
|
-
const folderContent = fs.readdirSync(assetPath);
|
|
428
|
-
if (folderContent.length === 1 && fs.lstatSync(path.join(assetPath, folderContent[0])).isDirectory()) {
|
|
429
|
-
return this.normalizeAssetFolderPath(path.join(assetPath, folderContent[0]));
|
|
430
|
-
}
|
|
431
|
-
return assetPath;
|
|
432
|
-
}
|
|
433
|
-
pathToPosix(path) {
|
|
434
|
-
return path.replace(/\\/g, '/');
|
|
435
|
-
}
|
|
436
|
-
diffTableTemplate(diffLinesHTML) {
|
|
437
|
-
return /* HTML */ `<table class="diff-table">
|
|
438
|
-
<tbody>
|
|
439
|
-
${diffLinesHTML}
|
|
440
|
-
</tbody>
|
|
441
|
-
</table>`;
|
|
442
|
-
}
|
|
443
|
-
getDiffTableHTML(diffLines) {
|
|
444
|
-
const diffLinesHTML = diffLines
|
|
445
|
-
.filter((value, index, array) => {
|
|
446
|
-
if (value.lineType === LINE_CONTEXT) {
|
|
447
|
-
return ((index >= 0 && index < this.contextLines) ||
|
|
448
|
-
(index > array.length - (this.contextLines + 1) && index <= array.length - 1) ||
|
|
449
|
-
array
|
|
450
|
-
.slice(index - this.contextLines, index + this.contextLines + 1)
|
|
451
|
-
.some((line) => line.lineType !== LINE_CONTEXT));
|
|
452
|
-
}
|
|
453
|
-
return true;
|
|
454
|
-
})
|
|
455
|
-
.map((line, index, array) => {
|
|
456
|
-
if (index > 0) {
|
|
457
|
-
const prevLine = array[index - 1];
|
|
458
|
-
if (line.lineNumber - prevLine.lineNumber > 1) {
|
|
459
|
-
return [{ lineNumber: -1, lineContent: '', lineType: LINE_CONTEXT }, line];
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
return [line];
|
|
463
|
-
})
|
|
464
|
-
.flat()
|
|
465
|
-
.map((line) => this.diffLineHTML(line))
|
|
466
|
-
.join('');
|
|
467
|
-
return this.diffTableTemplate(diffLinesHTML);
|
|
468
|
-
}
|
|
469
|
-
diffLineMessageTemplate(message) {
|
|
470
|
-
return /* HTML */ `<tr>
|
|
471
|
-
<td class="blob-num"></td>
|
|
472
|
-
<td class="blob-num"></td>
|
|
473
|
-
<td class="blob-code message">
|
|
474
|
-
<span class="blob-code-inner">${message}</span>
|
|
475
|
-
</td>
|
|
476
|
-
</tr>`;
|
|
477
|
-
}
|
|
478
|
-
diffLineSkipTemplate() {
|
|
479
|
-
return /* HTML */ `<tr>
|
|
480
|
-
<td class="blob-num"></td>
|
|
481
|
-
<td class="blob-num"></td>
|
|
482
|
-
<td class="blob-code skip">
|
|
483
|
-
<span class="blob-code-inner">Skip</span>
|
|
484
|
-
</td>
|
|
485
|
-
</tr>`;
|
|
486
|
-
}
|
|
487
|
-
diffLineTemplate(diffLine) {
|
|
488
|
-
const { lineNumber, lineContent, lineType } = diffLine;
|
|
489
|
-
const numClass = lineType === LINE_ADDED ? 'addition' : lineType === LINE_REMOVED ? 'deletion' : '';
|
|
490
|
-
const codeClass = lineType === LINE_ADDED ? 'code-addition' : lineType === LINE_REMOVED ? 'code-deletion' : '';
|
|
491
|
-
const prefix = lineType === LINE_ADDED ? '+' : lineType === LINE_REMOVED ? '-' : ' ';
|
|
492
|
-
return /* HTML */ `<tr>
|
|
493
|
-
<td
|
|
494
|
-
class="blob-num ${numClass}${numClass === 'addition' ? ' empty' : ''}"
|
|
495
|
-
${numClass !== 'addition' ? ` data-line-number="${lineNumber}"` : ''}
|
|
496
|
-
></td>
|
|
497
|
-
<td
|
|
498
|
-
class="blob-num ${numClass}${numClass === 'deletion' ? ' empty' : ''}"
|
|
499
|
-
${numClass !== 'deletion' ? ` data-line-number="${lineNumber}"` : ''}
|
|
500
|
-
></td>
|
|
501
|
-
<td class="blob-code ${codeClass}">
|
|
502
|
-
<span class="blob-code-inner" data-code-prefix="${prefix}">${escapeHTMLSequence(lineContent ?? '')}</span>
|
|
503
|
-
</td>
|
|
504
|
-
</tr>`;
|
|
505
|
-
}
|
|
506
|
-
diffLineHTML(diffLine) {
|
|
507
|
-
if (this.diffLineTemplateHandler) {
|
|
508
|
-
return this.diffLineTemplateHandler(diffLine);
|
|
509
|
-
}
|
|
510
|
-
const { lineNumber } = diffLine;
|
|
511
|
-
if (lineNumber === -1) {
|
|
512
|
-
return this.diffLineSkipTemplate();
|
|
513
|
-
}
|
|
514
|
-
return this.diffLineTemplate(diffLine);
|
|
515
|
-
}
|
|
516
|
-
diffFileTemplate(filename, htmlDiff) {
|
|
517
|
-
if (this.diffFileTemplateHandler) {
|
|
518
|
-
return this.diffFileTemplateHandler(filename, htmlDiff);
|
|
519
|
-
}
|
|
520
|
-
return /* HTML */ `<div class="diff-file">
|
|
521
|
-
<div class="diff-file-title">${filename}</div>
|
|
522
|
-
<div class="diff-file-content">${htmlDiff}</div>
|
|
523
|
-
</div>`;
|
|
524
|
-
}
|
|
525
|
-
async generateAssetFoldersDiff() {
|
|
526
|
-
this.logger.info(colors.blue(`Comparing asset folders ${await this.oldAssetsPath} and ${await this.newAssetsPath}`));
|
|
527
|
-
const dirDiff = await dirCompare.compare(await this.oldAssetsPath, await this.newAssetsPath, {
|
|
528
|
-
compareContent: true,
|
|
529
|
-
skipSymlinks: true,
|
|
530
|
-
compareSize: true,
|
|
531
|
-
compareDate: false,
|
|
532
|
-
compareNameHandler: (name1, name2) => {
|
|
533
|
-
if (fileNameWithHashRegEx.test(name1)) {
|
|
534
|
-
name1 = name1.replace(fileNameWithHashRegEx, '$1$3');
|
|
535
|
-
}
|
|
536
|
-
if (fileNameWithHashRegEx.test(name2)) {
|
|
537
|
-
name2 = name2.replace(fileNameWithHashRegEx, '$1$3');
|
|
538
|
-
}
|
|
539
|
-
if (name1.localeCompare(name2) === 0) {
|
|
540
|
-
return 0;
|
|
541
|
-
}
|
|
542
|
-
return name1.localeCompare(name2) > 0 ? 1 : -1;
|
|
543
|
-
},
|
|
544
|
-
});
|
|
545
|
-
return dirDiff.diffSet?.filter((d) => d.state !== 'equal' || d.name1 !== d.name2) || [];
|
|
546
|
-
}
|
|
547
|
-
async generateAssetFilesDiff(oldFileString, newFileString) {
|
|
548
|
-
const dmp = new DiffMatchPatch();
|
|
549
|
-
const linesChars = dmp.diff_linesToChars_(oldFileString, newFileString);
|
|
550
|
-
const linesDiff = dmp.diff_main(linesChars.chars1, linesChars.chars2, false);
|
|
551
|
-
dmp.diff_charsToLines_(linesDiff, linesChars.lineArray);
|
|
552
|
-
let lineNumber = 0;
|
|
553
|
-
return linesDiff
|
|
554
|
-
.map((diffLine) => {
|
|
555
|
-
const [lineType, lineContent] = diffLine;
|
|
556
|
-
const linesCount = lineContent.endsWith('\n')
|
|
557
|
-
? lineContent.split('\n').length - 1
|
|
558
|
-
: lineContent.split('\n').length;
|
|
559
|
-
const lines = lineContent
|
|
560
|
-
.split('\n')
|
|
561
|
-
.map((line, index) => {
|
|
562
|
-
return { lineContent: line, lineNumber: lineNumber + index + 1, lineType };
|
|
563
|
-
})
|
|
564
|
-
.slice(0, linesCount);
|
|
565
|
-
if (lineType !== LINE_REMOVED) {
|
|
566
|
-
lineNumber += linesCount;
|
|
567
|
-
}
|
|
568
|
-
return lines;
|
|
569
|
-
})
|
|
570
|
-
.flat();
|
|
571
|
-
}
|
|
572
|
-
/**
|
|
573
|
-
* Generate diff for a file
|
|
574
|
-
* @param difference
|
|
575
|
-
* @private
|
|
576
|
-
*/
|
|
577
|
-
async generateFilesDiff(difference) {
|
|
578
|
-
if (difference.state === 'equal') {
|
|
579
|
-
const filepath1 = this.pathToPosix(path.join('.', difference.relativePath, difference.name1 ?? ''));
|
|
580
|
-
const filepath2 = this.pathToPosix(path.join('.', difference.relativePath, difference.name2 ?? ''));
|
|
581
|
-
return this.diffFileTemplate(
|
|
582
|
-
/* HTML */ `<span class="renamed"
|
|
583
|
-
>Renamed <span class="from">${filepath1}</span> -> <span class="to">${filepath2}</span></span
|
|
584
|
-
>`, this.diffTableTemplate(this.diffLineMessageTemplate('No changes')));
|
|
585
|
-
}
|
|
586
|
-
const assetFile1Path = difference.path1 && difference.name1 ? path.join(difference.path1, difference.name1) : null;
|
|
587
|
-
const assetFile2Path = difference.path2 && difference.name2 ? path.join(difference.path2, difference.name2) : null;
|
|
588
|
-
const filepath = this.pathToPosix(path.join('.', difference.relativePath, (difference.name1 || difference.name2) ?? ''));
|
|
589
|
-
if (difference.state === 'left' && assetFile1Path) {
|
|
590
|
-
return this.diffFileTemplate(
|
|
591
|
-
/* HTML */ `<span class="removed">Removed ${filepath}</span>`, this.diffTableTemplate(this.diffLineMessageTemplate('File removed')));
|
|
592
|
-
}
|
|
593
|
-
if (difference.state === 'right' && assetFile2Path) {
|
|
594
|
-
return this.diffFileTemplate(
|
|
595
|
-
/* HTML */ `<span class="added">Added ${filepath}</span>`, this.diffTableTemplate(this.diffLineMessageTemplate('File added')));
|
|
596
|
-
}
|
|
597
|
-
if (difference.state === 'distinct' && assetFile1Path && assetFile2Path) {
|
|
598
|
-
const filepath1 = this.pathToPosix(path.join('.', difference.relativePath, difference.name1 ?? ''));
|
|
599
|
-
const filepath2 = this.pathToPosix(path.join('.', difference.relativePath, difference.name2 ?? ''));
|
|
600
|
-
const filenameTitle = difference.name1 !== difference.name2
|
|
601
|
-
? /* HTML */ `<span class="renamed"
|
|
602
|
-
>Renamed <span class="from">${filepath1}</span> -> <span class="to">${filepath2}</span></span
|
|
603
|
-
>`
|
|
604
|
-
: filepath;
|
|
605
|
-
return this.diffFileTemplate(filenameTitle, (await isBinaryFile(assetFile1Path)) || (await isBinaryFile(assetFile2Path))
|
|
606
|
-
? this.diffTableTemplate(this.diffLineMessageTemplate('Binary file'))
|
|
607
|
-
: this.getDiffTableHTML(await this.generateAssetFilesDiff(fs.readFileSync(assetFile1Path, 'utf-8'), fs.readFileSync(assetFile2Path, 'utf-8'))));
|
|
608
|
-
}
|
|
609
|
-
return '';
|
|
610
|
-
}
|
|
611
|
-
/**
|
|
612
|
-
* Generate changelog file based on the differences between two asset folders or zip files
|
|
613
|
-
* and write it to the destination folder
|
|
614
|
-
*/
|
|
615
|
-
async generateChangelog() {
|
|
616
|
-
this.logger.info(colors.green('Generating changelog'));
|
|
617
|
-
const diffSet = await this.generateAssetFoldersDiff();
|
|
618
|
-
const htmlDiff = (await Promise.all(diffSet.map((difference) => this.generateFilesDiff(difference)))).join('');
|
|
619
|
-
this.logger.info(colors.green('Writing changelog file'));
|
|
620
|
-
const templateArray = this.changelogTemplate.split('%FILES%');
|
|
621
|
-
templateArray.splice(1, 0, htmlDiff);
|
|
622
|
-
const changelogHTML = templateArray.join('');
|
|
623
|
-
fs.writeFileSync(path.join(this.destinationPath, this.changelogFilename), changelogHTML);
|
|
624
|
-
this.logger.info(colors.green(`Changelog file written to ${path.join(this.destinationPath, this.changelogFilename)}`));
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
class IconFontGenerator {
|
|
629
|
-
sourceDir;
|
|
630
|
-
outputDir;
|
|
631
|
-
fontName;
|
|
632
|
-
constructor(options) {
|
|
633
|
-
this.sourceDir = options.sourceDir;
|
|
634
|
-
this.outputDir = options.outputDir;
|
|
635
|
-
this.fontName = options.fontName;
|
|
636
|
-
}
|
|
637
|
-
async generate() {
|
|
638
|
-
await svgToFont({
|
|
639
|
-
src: this.sourceDir,
|
|
640
|
-
dist: this.outputDir,
|
|
641
|
-
fontName: this.fontName,
|
|
642
|
-
css: true,
|
|
643
|
-
typescript: true,
|
|
644
|
-
startUnicode: 0xea01,
|
|
645
|
-
svgicons2svgfont: {
|
|
646
|
-
fontHeight: 1024,
|
|
647
|
-
},
|
|
648
|
-
});
|
|
649
|
-
}
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
const cli = cac('pp-dev');
|
|
653
|
-
let profileSession = global.__pp_dev_profile_session;
|
|
654
|
-
let profileCount = 0;
|
|
655
|
-
const stopProfiler = (log) => {
|
|
656
|
-
if (!profileSession) {
|
|
657
|
-
return;
|
|
658
|
-
}
|
|
659
|
-
return new Promise((res, rej) => {
|
|
660
|
-
profileSession.post('Profiler.stop', (err, { profile }) => {
|
|
661
|
-
// Write profile to disk, upload, etc.
|
|
662
|
-
if (!err) {
|
|
663
|
-
const outPath = path.resolve(`./pp-dev-profile-${profileCount++}.cpuprofile`);
|
|
664
|
-
fs.writeFileSync(outPath, JSON.stringify(profile));
|
|
665
|
-
log(colors.yellow(`CPU profile written to ${colors.white(colors.dim(outPath))}`));
|
|
666
|
-
profileSession = undefined;
|
|
667
|
-
res();
|
|
668
|
-
}
|
|
669
|
-
else {
|
|
670
|
-
rej(err);
|
|
671
|
-
}
|
|
672
|
-
});
|
|
673
|
-
});
|
|
674
|
-
};
|
|
675
|
-
const filterDuplicateOptions = (options) => {
|
|
676
|
-
for (const [key, value] of Object.entries(options)) {
|
|
677
|
-
if (Array.isArray(value)) {
|
|
678
|
-
options[key] = value[value.length - 1];
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
};
|
|
682
|
-
/**
|
|
683
|
-
* removing global flags before passing as command specific sub-configs
|
|
684
|
-
*/
|
|
685
|
-
function cleanOptions(options) {
|
|
686
|
-
const ret = { ...options };
|
|
687
|
-
delete ret['--'];
|
|
688
|
-
delete ret.c;
|
|
689
|
-
delete ret.config;
|
|
690
|
-
delete ret.base;
|
|
691
|
-
delete ret.l;
|
|
692
|
-
delete ret.logLevel;
|
|
693
|
-
delete ret.clearScreen;
|
|
694
|
-
delete ret.d;
|
|
695
|
-
delete ret.debug;
|
|
696
|
-
delete ret.f;
|
|
697
|
-
delete ret.filter;
|
|
698
|
-
delete ret.m;
|
|
699
|
-
delete ret.mode;
|
|
700
|
-
return ret;
|
|
701
|
-
}
|
|
702
|
-
cli
|
|
703
|
-
.option('-c, --config <file>', `[string] use specified config file`)
|
|
704
|
-
.option('--base <path>', `[string] public base path (default: /)`)
|
|
705
|
-
.option('-l, --logLevel <level>', `[string] info | warn | error | silent`)
|
|
706
|
-
.option('--clearScreen', `[boolean] allow/disable clear screen when logging`)
|
|
707
|
-
.option('-d, --debug [feat]', `[string | boolean] show debug logs`)
|
|
708
|
-
.option('-f, --filter <filter>', `[string] filter debug logs`)
|
|
709
|
-
.option('-m, --mode <mode>', `[string] set env mode`);
|
|
710
|
-
// dev
|
|
711
|
-
cli
|
|
712
|
-
.command('[root]', 'start dev server') // default command
|
|
713
|
-
.alias('serve') // the command is called 'serve' in Vite's API
|
|
714
|
-
.alias('dev') // alias to align with the script name
|
|
715
|
-
.option('--host [host]', `[string] specify hostname`)
|
|
716
|
-
.option('--port <port>', `[number] specify port`)
|
|
717
|
-
.option('--https', `[boolean] use TLS + HTTP/2`)
|
|
718
|
-
.option('--open [path]', `[boolean | string] open browser on startup`)
|
|
719
|
-
.option('--cors', `[boolean] enable CORS`)
|
|
720
|
-
.option('--strictPort', `[boolean] exit if specified port is already in use`)
|
|
721
|
-
.option('--force', `[boolean] force the optimizer to ignore the cache and re-bundle`)
|
|
722
|
-
.action(async (root, options) => {
|
|
723
|
-
filterDuplicateOptions(options);
|
|
724
|
-
// output structure is preserved even after bundling so require()
|
|
725
|
-
// is ok here
|
|
726
|
-
const { createServer } = await import('vite');
|
|
727
|
-
try {
|
|
728
|
-
const configFromFile = await loadConfigFromFile({ mode: options.mode || 'development', command: 'serve' }, options.config, root, options.logLevel);
|
|
729
|
-
let config = await getViteConfig();
|
|
730
|
-
if (configFromFile) {
|
|
731
|
-
const { plugins, ...fileConfig } = configFromFile.config;
|
|
732
|
-
config = mergeConfig(config, fileConfig);
|
|
733
|
-
}
|
|
734
|
-
const server = await createServer(mergeConfig(config, {
|
|
735
|
-
root,
|
|
736
|
-
base: options.base,
|
|
737
|
-
mode: options.mode,
|
|
738
|
-
configFile: options.config,
|
|
739
|
-
logLevel: options.logLevel,
|
|
740
|
-
clearScreen: options.clearScreen,
|
|
741
|
-
optimizeDeps: { force: options.force },
|
|
742
|
-
server: cleanOptions(options),
|
|
743
|
-
customLogger: createLogger(options.logLevel),
|
|
744
|
-
}, true));
|
|
745
|
-
if (!server.config.base || server.config.base === '/') {
|
|
746
|
-
throw new Error('base cannot be equal to "/" or empty string');
|
|
747
|
-
}
|
|
748
|
-
if (!server.httpServer) {
|
|
749
|
-
throw new Error('HTTP server not available');
|
|
750
|
-
}
|
|
751
|
-
await server.listen();
|
|
752
|
-
const logger = createLogger(options.logLevel);
|
|
753
|
-
const ppDevStartTime = global.__pp_dev_start_time ?? false;
|
|
754
|
-
const startupDurationString = ppDevStartTime
|
|
755
|
-
? colors.dim(`ready in ${colors.reset(colors.bold(Math.ceil(performance.now() - ppDevStartTime)))} ms`)
|
|
756
|
-
: '';
|
|
757
|
-
logger.info(`\n ${colors.green(`${colors.bold('PP-DEV')} v${VERSION}`)} ${startupDurationString}\n`);
|
|
758
|
-
server.printUrls();
|
|
759
|
-
bindShortcuts(server, {
|
|
760
|
-
print: true,
|
|
761
|
-
customShortcuts: [
|
|
762
|
-
profileSession && {
|
|
763
|
-
key: 'p',
|
|
764
|
-
description: 'start/stop the profiler',
|
|
765
|
-
async action(server) {
|
|
766
|
-
if (profileSession) {
|
|
767
|
-
await stopProfiler(logger.info);
|
|
768
|
-
}
|
|
769
|
-
else {
|
|
770
|
-
const inspector = await import('node:inspector').then((r) => r.default);
|
|
771
|
-
await new Promise((res) => {
|
|
772
|
-
profileSession = new inspector.Session();
|
|
773
|
-
profileSession.connect();
|
|
774
|
-
profileSession.post('Profiler.enable', () => {
|
|
775
|
-
profileSession?.post('Profiler.start', () => {
|
|
776
|
-
logger.info('Profiler started');
|
|
777
|
-
res();
|
|
778
|
-
});
|
|
779
|
-
});
|
|
780
|
-
});
|
|
781
|
-
}
|
|
782
|
-
},
|
|
783
|
-
},
|
|
784
|
-
{
|
|
785
|
-
key: 'l',
|
|
786
|
-
description: 'proxy re-login',
|
|
787
|
-
action(server) {
|
|
788
|
-
server.ws.send({
|
|
789
|
-
type: 'custom',
|
|
790
|
-
event: 'redirect',
|
|
791
|
-
data: { url: `/auth/index/logout?proxyRedirect=${encodeURIComponent('/')}` },
|
|
792
|
-
});
|
|
793
|
-
},
|
|
794
|
-
},
|
|
795
|
-
],
|
|
796
|
-
});
|
|
797
|
-
}
|
|
798
|
-
catch (e) {
|
|
799
|
-
const logger = createLogger(options.logLevel);
|
|
800
|
-
logger.error(colors.red(`error when starting dev server:\n${e.stack}`), {
|
|
801
|
-
error: e,
|
|
802
|
-
});
|
|
803
|
-
stopProfiler(logger.info);
|
|
804
|
-
process.exit(1);
|
|
805
|
-
}
|
|
806
|
-
});
|
|
807
|
-
// dev
|
|
808
|
-
cli
|
|
809
|
-
.command('next [root]', 'start dev server') // default command
|
|
810
|
-
.alias('next-serve') // the command is called 'serve' in Vite's API
|
|
811
|
-
.alias('next-dev') // alias to align with the script name
|
|
812
|
-
.option('--host [host]', `[string] specify hostname`)
|
|
813
|
-
.option('--port <port>', `[number] specify port`, { default: 3000 })
|
|
814
|
-
.option('--https', `[boolean] use TLS + HTTP/2`)
|
|
815
|
-
.option('--open [path]', `[boolean | string] open browser on startup`)
|
|
816
|
-
.option('--cors', `[boolean] enable CORS`)
|
|
817
|
-
.option('--strictPort', `[boolean] exit if specified port is already in use`)
|
|
818
|
-
.option('--force', `[boolean] force the optimizer to ignore the cache and re-bundle`)
|
|
819
|
-
.action(async (root, options) => {
|
|
820
|
-
filterDuplicateOptions(options);
|
|
821
|
-
const { default: next } = await import('next');
|
|
822
|
-
const logger = createLogger();
|
|
823
|
-
const server = createDevServer(options.logLevel);
|
|
824
|
-
const opts = cleanOptions(options);
|
|
825
|
-
const app = next({ dev: true, hostname: opts.host, port: opts.port });
|
|
826
|
-
await app.prepare();
|
|
827
|
-
const nextServer = (await app.getServer());
|
|
828
|
-
let base = nextServer.nextConfig.basePath;
|
|
829
|
-
const { assetPrefix } = nextServer.nextConfig;
|
|
830
|
-
if (!base.endsWith('/')) {
|
|
831
|
-
base += '/';
|
|
832
|
-
}
|
|
833
|
-
if (base === '/') {
|
|
834
|
-
throw new Error('basePath cannot be equal to "/" or empty string');
|
|
835
|
-
}
|
|
836
|
-
const baseWithoutTrailingSlash = base.substring(0, base.lastIndexOf('/'));
|
|
837
|
-
const templateName = nextServer.nextConfig.serverRuntimeConfig.templateName;
|
|
838
|
-
const ppDevConfig = nextServer.nextConfig.serverRuntimeConfig.ppDevConfig;
|
|
839
|
-
const { backendBaseURL, portalPageId, templateLess = true, enableProxyCache = true, miHudLess = true, proxyCacheTTL = 10 * 60 * 1000, disableSSLValidation = false, } = ppDevConfig;
|
|
840
|
-
server.use(initPPRedirect(base, templateName));
|
|
841
|
-
if (backendBaseURL) {
|
|
842
|
-
const baseUrlHost = new URL(backendBaseURL).host;
|
|
843
|
-
const mi = new MiAPI(backendBaseURL, {
|
|
844
|
-
headers: {
|
|
845
|
-
host: baseUrlHost,
|
|
846
|
-
referer: backendBaseURL,
|
|
847
|
-
origin: backendBaseURL.replace(/^(https?:\/\/)([^/]+)(\/.*)?$/i, '$1$2'),
|
|
848
|
-
},
|
|
849
|
-
portalPageId,
|
|
850
|
-
templateLess,
|
|
851
|
-
disableSSLValidation,
|
|
852
|
-
});
|
|
853
|
-
if (enableProxyCache) {
|
|
854
|
-
let ttl = +proxyCacheTTL;
|
|
855
|
-
if (!ttl || Number.isNaN(ttl) || ttl < 0) {
|
|
856
|
-
ttl = 10 * 60 * 1000; // 10 minutes
|
|
857
|
-
}
|
|
858
|
-
server.use(initProxyCache({ devServer: server, ttl }));
|
|
859
|
-
}
|
|
860
|
-
const proxyIgnore = ['/@vite', '/@metricinsights', '/@', baseWithoutTrailingSlash];
|
|
861
|
-
if (assetPrefix) {
|
|
862
|
-
proxyIgnore.push(assetPrefix);
|
|
863
|
-
}
|
|
864
|
-
server.use(initProxy({
|
|
865
|
-
devServer: server,
|
|
866
|
-
baseURL: backendBaseURL,
|
|
867
|
-
proxyIgnore,
|
|
868
|
-
disableSSLValidation,
|
|
869
|
-
}));
|
|
870
|
-
const isIndexRegExp = new RegExp(`^((${base})|/)$`);
|
|
871
|
-
// Get portal page variables from the backend (also, redirect magic)
|
|
872
|
-
server.use(initLoadPPData(isIndexRegExp, mi, ppDevConfig));
|
|
873
|
-
server.use(initRewriteResponse((url) => {
|
|
874
|
-
return isIndexRegExp.test(cutUrlParams(url));
|
|
875
|
-
}, (response, req) => {
|
|
876
|
-
return Buffer.from(urlReplacer(baseUrlHost, req.headers.host ?? '', mi.buildPage(response, miHudLess)));
|
|
877
|
-
}));
|
|
878
|
-
}
|
|
879
|
-
const handle = app.getRequestHandler();
|
|
880
|
-
server.all('*', (req, res) => {
|
|
881
|
-
if (req.url.startsWith(assetPrefix) && assetPrefix !== baseWithoutTrailingSlash) {
|
|
882
|
-
const parsedUrl = parse(req.url.replace(assetPrefix, baseWithoutTrailingSlash), true);
|
|
883
|
-
return handle(req, res, parsedUrl);
|
|
884
|
-
}
|
|
885
|
-
const parsedUrl = parse(req.url, true);
|
|
886
|
-
handle(req, res, parsedUrl);
|
|
887
|
-
});
|
|
888
|
-
try {
|
|
889
|
-
await new Promise((resolve) => {
|
|
890
|
-
if (opts.host) {
|
|
891
|
-
resolve(server.listen(opts.port, opts.host, () => {
|
|
892
|
-
//
|
|
893
|
-
}));
|
|
894
|
-
}
|
|
895
|
-
else {
|
|
896
|
-
resolve(server.listen(opts.port, () => {
|
|
897
|
-
//
|
|
898
|
-
}));
|
|
899
|
-
}
|
|
900
|
-
});
|
|
901
|
-
const ppDevStartTime = global.__pp_dev_start_time ?? false;
|
|
902
|
-
const startupDurationString = ppDevStartTime
|
|
903
|
-
? colors.dim(`ready in ${colors.reset(colors.bold(Math.ceil(performance.now() - ppDevStartTime)))} ms`)
|
|
904
|
-
: '';
|
|
905
|
-
logger.info(`\n ${colors.green(`${colors.bold('PP-DEV')} v${VERSION}`)} ${startupDurationString}\n`, {
|
|
906
|
-
clear: true,
|
|
907
|
-
});
|
|
908
|
-
server.printUrls(base);
|
|
909
|
-
// bindShortcuts(server, {
|
|
910
|
-
// print: true,
|
|
911
|
-
// customShortcuts: [
|
|
912
|
-
// profileSession && {
|
|
913
|
-
// key: 'p',
|
|
914
|
-
// description: 'start/stop the profiler',
|
|
915
|
-
// async action(server) {
|
|
916
|
-
// if (profileSession) {
|
|
917
|
-
// await stopProfiler(server.config.logger.info);
|
|
918
|
-
// } else {
|
|
919
|
-
// const inspector = await import('node:inspector').then((r) => (r as any).default);
|
|
920
|
-
// await new Promise<void>((res) => {
|
|
921
|
-
// profileSession = new inspector.Session();
|
|
922
|
-
// profileSession.connect();
|
|
923
|
-
// profileSession.post('Profiler.enable', () => {
|
|
924
|
-
// profileSession?.post('Profiler.start', () => {
|
|
925
|
-
// server.config.logger.info('Profiler started');
|
|
926
|
-
// res();
|
|
927
|
-
// });
|
|
928
|
-
// });
|
|
929
|
-
// });
|
|
930
|
-
// }
|
|
931
|
-
// },
|
|
932
|
-
// },
|
|
933
|
-
// {
|
|
934
|
-
// key: 'l',
|
|
935
|
-
// description: 'proxy re-login',
|
|
936
|
-
// action(server: ViteDevServer): void | Promise<void> {
|
|
937
|
-
// server.ws.send({
|
|
938
|
-
// type: 'custom',
|
|
939
|
-
// event: 'redirect',
|
|
940
|
-
// data: { url: `/auth/index/logout?proxyRedirect=${encodeURIComponent('/')}` },
|
|
941
|
-
// });
|
|
942
|
-
// },
|
|
943
|
-
// },
|
|
944
|
-
// ],
|
|
945
|
-
// });
|
|
946
|
-
}
|
|
947
|
-
catch (e) {
|
|
948
|
-
const logger = createLogger(options.logLevel);
|
|
949
|
-
logger.error(colors.red(`error when starting dev server:\n${e.stack}`), {
|
|
950
|
-
error: e,
|
|
951
|
-
});
|
|
952
|
-
stopProfiler(logger.info);
|
|
953
|
-
process.exit(1);
|
|
954
|
-
}
|
|
955
|
-
});
|
|
956
|
-
// build
|
|
957
|
-
cli
|
|
958
|
-
.command('build [root]', 'build for production')
|
|
959
|
-
.option('--target <target>', `[string] transpile target (default: 'modules')`)
|
|
960
|
-
.option('--outDir <dir>', `[string] output directory (default: dist)`)
|
|
961
|
-
.option('--assetsDir <dir>', `[string] directory under outDir to place assets in (default: assets)`)
|
|
962
|
-
.option('--assetsInlineLimit <number>', `[number] static asset base64 inline threshold in bytes (default: 4096)`)
|
|
963
|
-
.option('--ssr [entry]', `[string] build specified entry for server-side rendering`)
|
|
964
|
-
.option('--sourcemap [output]', `[boolean | "inline" | "hidden"] output source maps for build (default: false)`)
|
|
965
|
-
.option('--minify [minifier]', `[boolean | "terser" | "esbuild"] enable/disable minification, ` + `or specify minifier to use (default: esbuild)`)
|
|
966
|
-
.option('--manifest [name]', `[boolean | string] emit build manifest json`)
|
|
967
|
-
.option('--ssrManifest [name]', `[boolean | string] emit ssr manifest json`)
|
|
968
|
-
.option('--force', `[boolean] force the optimizer to ignore the cache and re-bundle (experimental)`)
|
|
969
|
-
.option('--emptyOutDir', `[boolean] force empty outDir when it's outside of root`)
|
|
970
|
-
.option('-w, --watch', `[boolean] rebuilds when modules have changed on disk`)
|
|
971
|
-
.option('--changelog [assetsFile]', `[boolean | string] generate changelog between assetsFile and current build (default: false)`)
|
|
972
|
-
.action(async (root, options) => {
|
|
973
|
-
filterDuplicateOptions(options);
|
|
974
|
-
const buildOptions = cleanOptions(options);
|
|
975
|
-
try {
|
|
976
|
-
const configFromFile = await loadConfigFromFile({ mode: options.mode || 'production', command: 'build' }, options.config, root, options.logLevel);
|
|
977
|
-
let config = await getViteConfig();
|
|
978
|
-
if (configFromFile) {
|
|
979
|
-
const { plugins, ...fileConfig } = configFromFile.config;
|
|
980
|
-
config = mergeConfig(config, fileConfig);
|
|
981
|
-
}
|
|
982
|
-
const buildConfig = mergeConfig(config, {
|
|
983
|
-
root,
|
|
984
|
-
base: options.base,
|
|
985
|
-
mode: options.mode,
|
|
986
|
-
configFile: options.config,
|
|
987
|
-
logLevel: options.logLevel,
|
|
988
|
-
clearScreen: options.clearScreen,
|
|
989
|
-
optimizeDeps: { force: options.force },
|
|
990
|
-
build: buildOptions,
|
|
991
|
-
}, true);
|
|
992
|
-
await build(buildConfig);
|
|
993
|
-
if (buildOptions.changelog) {
|
|
994
|
-
const executionRoot = root || process.cwd();
|
|
995
|
-
const outDir = buildConfig.build?.outDir || 'dist';
|
|
996
|
-
let oldAssetsPath = '';
|
|
997
|
-
if (typeof buildOptions.changelog === 'string') {
|
|
998
|
-
oldAssetsPath = path.resolve(executionRoot, buildOptions.changelog);
|
|
999
|
-
}
|
|
1000
|
-
else {
|
|
1001
|
-
const backupsDirPath = path.resolve(executionRoot, buildConfig.ppDevConfig?.syncBackupsDir || 'backups');
|
|
1002
|
-
if (!fs.existsSync(backupsDirPath)) {
|
|
1003
|
-
createLogger(options.logLevel).warn(colors.yellow(`backups directory not found, skipping changelog generation`));
|
|
1004
|
-
return;
|
|
1005
|
-
}
|
|
1006
|
-
const backups = fs.readdirSync(backupsDirPath, { withFileTypes: true });
|
|
1007
|
-
if (!backups.length) {
|
|
1008
|
-
createLogger(options.logLevel).warn(colors.yellow(`no backups found, skipping changelog generation`));
|
|
1009
|
-
return;
|
|
1010
|
-
}
|
|
1011
|
-
const latestBackup = backups
|
|
1012
|
-
.filter((value) => {
|
|
1013
|
-
return value.isFile() && value.name.endsWith('.zip');
|
|
1014
|
-
})
|
|
1015
|
-
.reduce((latest, current) => {
|
|
1016
|
-
const latestTime = fs.statSync(path.resolve(backupsDirPath, latest.name)).mtimeMs;
|
|
1017
|
-
const currentTime = fs.statSync(path.resolve(backupsDirPath, current.name)).mtimeMs;
|
|
1018
|
-
return latestTime > currentTime ? latest : current;
|
|
1019
|
-
}, backups[0]).name;
|
|
1020
|
-
oldAssetsPath = path.resolve(backupsDirPath, latestBackup);
|
|
1021
|
-
}
|
|
1022
|
-
const currentAssetFilePath = path.resolve(executionRoot, outDir);
|
|
1023
|
-
let changelogDestination = 'dist-zip';
|
|
1024
|
-
if (buildConfig.ppDevConfig) {
|
|
1025
|
-
if (buildConfig.ppDevConfig.distZip === false) {
|
|
1026
|
-
changelogDestination = buildConfig.build?.outDir || 'dist';
|
|
1027
|
-
}
|
|
1028
|
-
else if (typeof buildConfig.ppDevConfig.distZip === 'object' &&
|
|
1029
|
-
typeof buildConfig.ppDevConfig.distZip.outDir === 'string') {
|
|
1030
|
-
changelogDestination = buildConfig.ppDevConfig.distZip.outDir;
|
|
1031
|
-
}
|
|
1032
|
-
}
|
|
1033
|
-
const changelogGenerator = new ChangelogGenerator({
|
|
1034
|
-
oldAssetsPath,
|
|
1035
|
-
newAssetsPath: currentAssetFilePath,
|
|
1036
|
-
destinationPath: path.resolve(executionRoot, changelogDestination),
|
|
1037
|
-
});
|
|
1038
|
-
await changelogGenerator.generateChangelog();
|
|
1039
|
-
}
|
|
1040
|
-
}
|
|
1041
|
-
catch (e) {
|
|
1042
|
-
createLogger(options.logLevel).error(colors.red(`error during build:\n${e.stack}`), { error: e });
|
|
1043
|
-
process.exit(1);
|
|
1044
|
-
}
|
|
1045
|
-
finally {
|
|
1046
|
-
stopProfiler((message) => createLogger(options.logLevel).info(message));
|
|
1047
|
-
}
|
|
1048
|
-
});
|
|
1049
|
-
// changelog
|
|
1050
|
-
cli
|
|
1051
|
-
.command('changelog [oldAssetPath] [newAssetPath]', 'generate changelog between two assets files/folders')
|
|
1052
|
-
.option('--oldAssetsPath <oldAssetsPath>', `[string] path to the old assets zip file or folder`)
|
|
1053
|
-
.option('--newAssetsPath <newAssetsPath>', `[string] path to the new assets zip file or folder`)
|
|
1054
|
-
.option('--destination <destination>', `[string] destination folder for the changelog (default: .)`)
|
|
1055
|
-
.option('--filename <filename>', `[string] filename for the changelog (default: CHANGELOG.html)`)
|
|
1056
|
-
.action(async (oldAssetPath, newAssetPath, options) => {
|
|
1057
|
-
filterDuplicateOptions(options);
|
|
1058
|
-
const { oldAssetsPath: oldPath = oldAssetPath, newAssetsPath: newPath = newAssetPath, destination = '.', filename = 'CHANGELOG.html', logLevel, } = options;
|
|
1059
|
-
const root = process.cwd();
|
|
1060
|
-
if (!oldPath || !newPath) {
|
|
1061
|
-
createLogger(logLevel).error(colors.red(`error during changelog generation: oldAssetPath and newAssetPath are required`));
|
|
1062
|
-
process.exit(1);
|
|
1063
|
-
}
|
|
1064
|
-
const fullOldPath = path.resolve(root, oldPath);
|
|
1065
|
-
const fullNewPath = path.resolve(root, newPath);
|
|
1066
|
-
const fullDestination = path.resolve(root, destination);
|
|
1067
|
-
const changelogGenerator = new ChangelogGenerator({
|
|
1068
|
-
oldAssetsPath: fullOldPath,
|
|
1069
|
-
newAssetsPath: fullNewPath,
|
|
1070
|
-
destinationPath: fullDestination,
|
|
1071
|
-
changelogFilename: filename,
|
|
1072
|
-
});
|
|
1073
|
-
await changelogGenerator.generateChangelog();
|
|
1074
|
-
});
|
|
1075
|
-
cli
|
|
1076
|
-
.command('generate-icon-font [source] [destination]', 'generate icon font from SVG files')
|
|
1077
|
-
.option('--source <source>', `[string] path to the source directory with SVG files`)
|
|
1078
|
-
.option('--destination <destination>', `[string] path to the destination directory to save the generated font files`)
|
|
1079
|
-
.option('--font-name, -n <fontName>', `[string] name of the font to generate (default: 'icon-font')`)
|
|
1080
|
-
.action(async (source, destination, options) => {
|
|
1081
|
-
filterDuplicateOptions(options);
|
|
1082
|
-
const { source: sourceDir = source, destination: destDir = destination, fontName = 'icon-font' } = options;
|
|
1083
|
-
const root = process.cwd();
|
|
1084
|
-
const fullSourceDir = path.resolve(root, sourceDir);
|
|
1085
|
-
const fullDestDir = path.resolve(root, destDir);
|
|
1086
|
-
const iconFontGenerator = new IconFontGenerator({
|
|
1087
|
-
sourceDir: fullSourceDir,
|
|
1088
|
-
outputDir: fullDestDir,
|
|
1089
|
-
fontName,
|
|
1090
|
-
});
|
|
1091
|
-
const logger = createLogger(options.logLevel);
|
|
1092
|
-
logger.info(`Generating icon font from SVG files in ${colors.dim(fullSourceDir)}`);
|
|
1093
|
-
await iconFontGenerator.generate();
|
|
1094
|
-
logger.info(`Icon font generated and saved to ${colors.dim(fullDestDir)}`);
|
|
1095
|
-
});
|
|
1096
|
-
// optimize
|
|
1097
|
-
cli
|
|
1098
|
-
.command('optimize [root]', 'pre-bundle dependencies')
|
|
1099
|
-
.option('--force', `[boolean] force the optimizer to ignore the cache and re-bundle`)
|
|
1100
|
-
.action(async (root, options) => {
|
|
1101
|
-
filterDuplicateOptions(options);
|
|
1102
|
-
try {
|
|
1103
|
-
const configFromFile = await loadConfigFromFile({ mode: options.mode || 'production', command: 'build' }, options.config, root, options.logLevel);
|
|
1104
|
-
let config = await getViteConfig();
|
|
1105
|
-
if (configFromFile) {
|
|
1106
|
-
const { plugins, ...fileConfig } = configFromFile.config;
|
|
1107
|
-
config = mergeConfig(config, fileConfig);
|
|
1108
|
-
}
|
|
1109
|
-
const optimizeConfig = await resolveConfig(mergeConfig(config, {
|
|
1110
|
-
root,
|
|
1111
|
-
base: options.base,
|
|
1112
|
-
configFile: options.config,
|
|
1113
|
-
logLevel: options.logLevel,
|
|
1114
|
-
mode: options.mode,
|
|
1115
|
-
}), 'serve');
|
|
1116
|
-
await optimizeDeps(optimizeConfig, options.force, true);
|
|
1117
|
-
}
|
|
1118
|
-
catch (e) {
|
|
1119
|
-
createLogger(options.logLevel).error(colors.red(`error when optimizing deps:\n${e.stack}`), { error: e });
|
|
1120
|
-
process.exit(1);
|
|
1121
|
-
}
|
|
1122
|
-
});
|
|
1123
|
-
cli
|
|
1124
|
-
.command('preview [root]', 'locally preview production build')
|
|
1125
|
-
.option('--host [host]', `[string] specify hostname`)
|
|
1126
|
-
.option('--port <port>', `[number] specify port`)
|
|
1127
|
-
.option('--strictPort', `[boolean] exit if specified port is already in use`)
|
|
1128
|
-
.option('--https', `[boolean] use TLS + HTTP/2`)
|
|
1129
|
-
.option('--open [path]', `[boolean | string] open browser on startup`)
|
|
1130
|
-
.option('--outDir <dir>', `[string] output directory (default: dist)`)
|
|
1131
|
-
.action(async (root, options) => {
|
|
1132
|
-
filterDuplicateOptions(options);
|
|
1133
|
-
try {
|
|
1134
|
-
const configFromFile = await loadConfigFromFile({ mode: options.mode || 'production', command: 'build' }, options.config, root, options.logLevel);
|
|
1135
|
-
let config = await getViteConfig();
|
|
1136
|
-
if (configFromFile) {
|
|
1137
|
-
const { plugins, ...fileConfig } = configFromFile.config;
|
|
1138
|
-
config = mergeConfig(config, fileConfig);
|
|
1139
|
-
}
|
|
1140
|
-
const server = await preview(mergeConfig(config, {
|
|
1141
|
-
root,
|
|
1142
|
-
base: options.base,
|
|
1143
|
-
configFile: options.config,
|
|
1144
|
-
logLevel: options.logLevel,
|
|
1145
|
-
mode: options.mode,
|
|
1146
|
-
build: {
|
|
1147
|
-
outDir: options.outDir,
|
|
1148
|
-
},
|
|
1149
|
-
preview: {
|
|
1150
|
-
port: options.port,
|
|
1151
|
-
strictPort: options.strictPort,
|
|
1152
|
-
host: options.host,
|
|
1153
|
-
https: options.https,
|
|
1154
|
-
open: options.open,
|
|
1155
|
-
},
|
|
1156
|
-
}));
|
|
1157
|
-
server.printUrls();
|
|
1158
|
-
}
|
|
1159
|
-
catch (e) {
|
|
1160
|
-
createLogger(options.logLevel).error(colors.red(`error when starting preview server:\n${e.stack}`), {
|
|
1161
|
-
error: e,
|
|
1162
|
-
});
|
|
1163
|
-
process.exit(1);
|
|
1164
|
-
}
|
|
1165
|
-
finally {
|
|
1166
|
-
stopProfiler((message) => createLogger(options.logLevel).info(message));
|
|
1167
|
-
}
|
|
1168
|
-
});
|
|
1169
|
-
cli.help();
|
|
1170
|
-
cli.version(VERSION);
|
|
1171
|
-
cli.parse();
|
|
1172
|
-
|
|
1173
|
-
export { stopProfiler };
|
|
1
|
+
import*as e from"path";import*as t from"fs";import{performance as o}from"node:perf_hooks";import{cac as n}from"cac";import{loadConfigFromFile as i,loadEnv as s,mergeConfig as r,build as a,resolveConfig as l,optimizeDeps as d,preview as c}from"vite";import{g as p,V as f}from"./index-kmS_-y6Z.js";import{c as h,a as m,i as g,M as u,b,d as v,e as w,f as y,g as P,r as T,u as x,h as L}from"./plugin-H4ccpQoX.js";import{URL as $,parse as S}from"url";import*as F from"express";import*as k from"winston";import*as A from"dir-compare";import C from"diff-match-patch";import{isBinaryFile as D}from"isbinaryfile";import*as E from"os";import*as j from"crypto";import z from"extract-zip";import H from"svgtofont";import*as _ from"node:process";import"ejs";import"esbuild";import"http-proxy-middleware";import"picocolors";import"axios";import"jsdom";import"https";import"memory-cache";import"process";import"child_process";import"console";import"zlib";function I(e){return null!==e||void 0!==e}const M=[{key:"r",description:"restart the server",async action(e){await e.restart()}},{key:"u",description:"show server url",action(e){e.config.logger.info(""),e.printUrls()}},{key:"o",description:"open in browser",action(e){e.openBrowser()}},{key:"c",description:"clear console",action(e){e.config.logger.clearScreen("error")}},{key:"q",description:"quit",async action(e){await e.close().finally((()=>process.exit()))}},{key:"C",description:"clear proxy cache",action(e){e.cache&&(e.cache.clear(),e.config.logger.info("Proxy cache cleared"))}}];const N=/(.+)(-[a-f0-9]{6,20})(\.[a-z0-9]+)$/i;class R{oldAssetsPath;newAssetsPath;destinationPath;changelogFilename;changelogTemplate='<!DOCTYPE html>\n <html lang="en">\n <head>\n <meta charset="UTF-8" />\n <title>Changelog Diff</title>\n <style>\n tr,\n td {\n padding: 0;\n }\n .diff-file {\n margin-top: 20px;\n border: 1px solid #e1e4e8;\n border-radius: 6px;\n }\n .diff-file-title {\n padding: 10px 20px;\n background-color: #f6f8fa;\n border-bottom: 1px solid #e1e4e8;\n border-radius: 6px 6px 0 0;\n font-weight: bold;\n }\n .diff-file-title .renamed {\n font-weight: normal;\n }\n .diff-file-title .renamed .from {\n color: #cb2431;\n }\n .diff-file-title .renamed .to {\n color: #22863a;\n }\n .diff-file-title .added {\n color: #22863a;\n }\n .diff-file-title .deleted {\n color: #cb2431;\n }\n .diff-file-content {\n }\n .diff-table {\n tab-size: 8;\n width: 100%;\n border-collapse: separate;\n border-spacing: 0;\n }\n .blob-num {\n position: relative;\n color: #1f2328;\n width: 1%;\n min-width: 50px;\n padding: 0 10px;\n font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;\n font-size: 12px;\n line-height: 20px;\n text-align: right;\n white-space: nowrap;\n vertical-align: top;\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n }\n .blob-num.addition {\n background-color: #ccffd8;\n border-color: #1f883e;\n }\n .blob-num.deletion {\n background-color: #ffd7d5;\n border-color: #cf222e;\n }\n .blob-num::before {\n content: attr(data-line-number);\n }\n .blob-code {\n position: relative;\n padding: 0 10px 0 22px;\n vertical-align: top;\n color: #1f2329;\n }\n .blob-code.code-addition {\n background-color: #e6ffec;\n }\n .blob-code.code-deletion {\n background-color: #ffebe9;\n }\n .blob-code.skip,\n .blob-code.message {\n text-align: center;\n }\n .blob-code.skip .blob-code-inner,\n .blob-code.message .blob-code-inner {\n font-weight: bold;\n color: #6a737d;\n padding: 10px 0;\n }\n .blob-code-inner {\n display: table-cell;\n overflow: visible;\n font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;\n font-size: 12px;\n word-wrap: anywhere;\n white-space: pre-wrap;\n }\n .blob-code-inner::before {\n content: attr(data-code-prefix);\n position: absolute;\n top: 1px;\n left: 8px;\n padding-right: 8px;\n }\n </style>\n </head>\n <body>\n <h1>Changelog Diff</h1>\n\n %FILES%\n </body>\n </html>';diffFileTemplateHandler;diffLineTemplateHandler;contextLines=3;logger;constructor(t){const{oldAssetsPath:o,newAssetsPath:n,destinationPath:i,changelogTemplate:s,diffFileTemplateHandler:r,diffLineTemplateHandler:a,changelogFilename:l,contextLines:d}=t;if(this.logger=h(),!o||!n||!i)throw new Error("Previous assets path, current assets path and destination path are required");if(o===n)throw new Error("Previous and current assets paths must be different");if(!this.isExists(o))throw new Error(`Previous assets path ${o} does not exist`);if(!this.isExists(n))throw new Error(`Current assets path ${n} does not exist`);if(this.isZipFile(o)){const t=e.resolve(E.tmpdir(),j.createHash("md5").update(o).digest("hex"));this.oldAssetsPath=this.unzipFile(o,t).then((()=>this.normalizeAssetFolderPath(t))).then((e=>{if(this.isEmptyFolder(e))throw new Error(`Previous assets path ${e} is empty`);return e}))}else{if(!this.isFolder(o))throw new Error(`Invalid previous assets path ${o}. It must be a folder or a zip file`);{const e=this.normalizeAssetFolderPath(o);if(this.isEmptyFolder(e))throw new Error(`Previous assets path ${e} is empty`);this.oldAssetsPath=Promise.resolve(e)}}if(this.isZipFile(n)){const t=e.resolve(E.tmpdir(),j.createHash("md5").update(n).digest("hex"));this.newAssetsPath=this.unzipFile(n,t).then((()=>this.normalizeAssetFolderPath(t))).then((e=>{if(this.isEmptyFolder(e))throw new Error(`Current assets path ${e} is empty`);return e}))}else{if(!this.isFolder(n))throw new Error(`Invalid current assets path ${n}. It must be a folder or a zip file`);{const e=this.normalizeAssetFolderPath(n);if(this.isEmptyFolder(e))throw new Error(`Current assets path ${n} is empty`);this.newAssetsPath=Promise.resolve(e)}}this.destinationPath=i,this.mkdirpSync(this.destinationPath),this.changelogFilename=l||"CHANGELOG.html",s&&(this.templateIsValid(s)?this.changelogTemplate=s:this.logger.warn(m.yellow("Invalid changelog template, using default"))),"function"==typeof r&&(this.diffFileTemplateHandler=r),"function"==typeof a&&(this.diffLineTemplateHandler=a),d&&(this.contextLines=d)}templateIsValid(e){return e.includes("%FILES%")}isExists(e){return t.existsSync(e)}isZipFile(e){return e.endsWith(".zip")}isFolder(e){return t.lstatSync(e).isDirectory()}isEmptyFolder(e){return 0===t.readdirSync(e,{withFileTypes:!0}).length}mkdirpSync(e){t.existsSync(e)||t.mkdirSync(e,{recursive:!0})}async unzipFile(e,o){return t.rmSync(o,{force:!0,recursive:!0}),z(e,{dir:o})}normalizeAssetFolderPath(o){const n=t.readdirSync(o);return 1===n.length&&t.lstatSync(e.join(o,n[0])).isDirectory()?this.normalizeAssetFolderPath(e.join(o,n[0])):o}pathToPosix(e){return e.replace(/\\/g,"/")}diffTableTemplate(e){return`<table class="diff-table">\n <tbody>\n ${e}\n </tbody>\n </table>`}getDiffTableHTML(e){const t=e.filter(((e,t,o)=>0!==e.lineType||(t>=0&&t<this.contextLines||t>o.length-(this.contextLines+1)&&t<=o.length-1||o.slice(t-this.contextLines,t+this.contextLines+1).some((e=>0!==e.lineType))))).map(((e,t,o)=>{if(t>0){const n=o[t-1];if(e.lineNumber-n.lineNumber>1)return[{lineNumber:-1,lineContent:"",lineType:0},e]}return[e]})).flat().map((e=>this.diffLineHTML(e))).join("");return this.diffTableTemplate(t)}diffLineMessageTemplate(e){return`<tr>\n <td class="blob-num"></td>\n <td class="blob-num"></td>\n <td class="blob-code message">\n <span class="blob-code-inner">${e}</span>\n </td>\n </tr>`}diffLineSkipTemplate(){return'<tr>\n <td class="blob-num"></td>\n <td class="blob-num"></td>\n <td class="blob-code skip">\n <span class="blob-code-inner">Skip</span>\n </td>\n </tr>'}diffLineTemplate(e){const{lineNumber:t,lineContent:o,lineType:n}=e,i=1===n?"addition":-1===n?"deletion":"";return`<tr>\n <td\n class="blob-num ${i}${"addition"===i?" empty":""}"\n ${"addition"!==i?` data-line-number="${t}"`:""}\n ></td>\n <td\n class="blob-num ${i}${"deletion"===i?" empty":""}"\n ${"deletion"!==i?` data-line-number="${t}"`:""}\n ></td>\n <td class="blob-code ${1===n?"code-addition":-1===n?"code-deletion":""}">\n <span class="blob-code-inner" data-code-prefix="${1===n?"+":-1===n?"-":" "}">${s=o??"",s.replace(/[\u00A0-\u9999<>&]/g,(e=>"&#"+e.charCodeAt(0)+";"))}</span>\n </td>\n </tr>`;var s}diffLineHTML(e){if(this.diffLineTemplateHandler)return this.diffLineTemplateHandler(e);const{lineNumber:t}=e;return-1===t?this.diffLineSkipTemplate():this.diffLineTemplate(e)}diffFileTemplate(e,t){return this.diffFileTemplateHandler?this.diffFileTemplateHandler(e,t):`<div class="diff-file">\n <div class="diff-file-title">${e}</div>\n <div class="diff-file-content">${t}</div>\n </div>`}async generateAssetFoldersDiff(){this.logger.info(m.blue(`Comparing asset folders ${await this.oldAssetsPath} and ${await this.newAssetsPath}`));const e=await A.compare(await this.oldAssetsPath,await this.newAssetsPath,{compareContent:!0,skipSymlinks:!0,compareSize:!0,compareDate:!1,compareNameHandler:(e,t)=>(N.test(e)&&(e=e.replace(N,"$1$3")),N.test(t)&&(t=t.replace(N,"$1$3")),0===e.localeCompare(t)?0:e.localeCompare(t)>0?1:-1)});return e.diffSet?.filter((e=>"equal"!==e.state||e.name1!==e.name2))||[]}async generateAssetFilesDiff(e,t){const o=new C,n=o.diff_linesToChars_(e,t),i=o.diff_main(n.chars1,n.chars2,!1);o.diff_charsToLines_(i,n.lineArray);let s=0;return i.map((e=>{const[t,o]=e,n=o.endsWith("\n")?o.split("\n").length-1:o.split("\n").length,i=o.split("\n").map(((e,o)=>({lineContent:e,lineNumber:s+o+1,lineType:t}))).slice(0,n);return-1!==t&&(s+=n),i})).flat()}async generateFilesDiff(o){if("equal"===o.state){const t=this.pathToPosix(e.join(".",o.relativePath,o.name1??"")),n=this.pathToPosix(e.join(".",o.relativePath,o.name2??""));return this.diffFileTemplate(`<span class="renamed"\n >Renamed <span class="from">${t}</span> -> <span class="to">${n}</span></span\n >`,this.diffTableTemplate(this.diffLineMessageTemplate("No changes")))}const n=o.path1&&o.name1?e.join(o.path1,o.name1):null,i=o.path2&&o.name2?e.join(o.path2,o.name2):null,s=this.pathToPosix(e.join(".",o.relativePath,(o.name1||o.name2)??""));if("left"===o.state&&n)return this.diffFileTemplate(`<span class="removed">Removed ${s}</span>`,this.diffTableTemplate(this.diffLineMessageTemplate("File removed")));if("right"===o.state&&i)return this.diffFileTemplate(`<span class="added">Added ${s}</span>`,this.diffTableTemplate(this.diffLineMessageTemplate("File added")));if("distinct"===o.state&&n&&i){const r=this.pathToPosix(e.join(".",o.relativePath,o.name1??"")),a=this.pathToPosix(e.join(".",o.relativePath,o.name2??"")),l=o.name1!==o.name2?`<span class="renamed"\n >Renamed <span class="from">${r}</span> -> <span class="to">${a}</span></span\n >`:s;return this.diffFileTemplate(l,await D(n)||await D(i)?this.diffTableTemplate(this.diffLineMessageTemplate("Binary file")):this.getDiffTableHTML(await this.generateAssetFilesDiff(t.readFileSync(n,"utf-8"),t.readFileSync(i,"utf-8"))))}return""}async generateChangelog(){this.logger.info(m.green("Generating changelog"));const o=await this.generateAssetFoldersDiff(),n=(await Promise.all(o.map((e=>this.generateFilesDiff(e))))).join("");this.logger.info(m.green("Writing changelog file"));const i=this.changelogTemplate.split("%FILES%");i.splice(1,0,n);const s=i.join("");t.writeFileSync(e.join(this.destinationPath,this.changelogFilename),s),this.logger.info(m.green(`Changelog file written to ${e.join(this.destinationPath,this.changelogFilename)}`))}}class U{sourceDir;outputDir;fontName;constructor(e){this.sourceDir=e.sourceDir,this.outputDir=e.outputDir,this.fontName=e.fontName}async generate(){await H({src:this.sourceDir,dist:this.outputDir,fontName:this.fontName,css:!0,typescript:!0,startUnicode:59905,svgicons2svgfont:{fontHeight:1024}})}}const O=n("pp-dev");let q=global.__pp_dev_profile_session,G=0;const V=o=>{if(q)return new Promise(((n,i)=>{q.post("Profiler.stop",((s,{profile:r})=>{if(s)i(s);else{const i=e.resolve(`./pp-dev-profile-${G++}.cpuprofile`);t.writeFileSync(i,JSON.stringify(r)),o(m.yellow(`CPU profile written to ${m.white(m.dim(i))}`)),q=void 0,n()}}))}))},W=e=>{for(const[t,o]of Object.entries(e))Array.isArray(o)&&(e[t]=o[o.length-1])};function B(e){const t={...e};return delete t["--"],delete t.c,delete t.config,delete t.base,delete t.l,delete t.logLevel,delete t.clearScreen,delete t.d,delete t.debug,delete t.f,delete t.filter,delete t.m,delete t.mode,t}O.option("-c, --config <file>","[string] use specified config file").option("--base <path>","[string] public base path (default: /)").option("-l, --logLevel <level>","[string] info | warn | error | silent").option("--clearScreen","[boolean] allow/disable clear screen when logging").option("-d, --debug [feat]","[string | boolean] show debug logs").option("-f, --filter <filter>","[string] filter debug logs").option("-m, --mode <mode>","[string] set env mode"),O.command("[root]","start dev server").alias("serve").alias("dev").option("--host [host]","[string] specify hostname").option("--port <port>","[number] specify port").option("--https","[boolean] use TLS + HTTP/2").option("--open [path]","[boolean | string] open browser on startup").option("--cors","[boolean] enable CORS").option("--strictPort","[boolean] exit if specified port is already in use").option("--force","[boolean] force the optimizer to ignore the cache and re-bundle").action((async(e,t)=>{W(t);const{createServer:n}=await import("vite");try{const a=await i({mode:t.mode||"development",command:"serve"},t.config,e,t.logLevel);let l=await p();const d=s(t.mode||"development",e??_.cwd(),"");if(d&&Object.keys(d).forEach((e=>{e.startsWith("MI_")&&(_.env[e]=d[e])})),a){const{plugins:e,...t}=a.config;l=r(l,t)}const c=await n(r(l,{root:e,base:t.base,mode:t.mode,configFile:t.config,logLevel:t.logLevel,clearScreen:t.clearScreen,optimizeDeps:{force:t.force},server:B(t),customLogger:h(t.logLevel)},!0));if(!c.config.base||"/"===c.config.base)throw new Error('base cannot be equal to "/" or empty string');if(!c.httpServer)throw new Error("HTTP server not available");await c.listen();const g=h(t.logLevel),u=global.__pp_dev_start_time??!1,b=u?m.dim(`ready in ${m.reset(m.bold(Math.ceil(o.now()-u)))} ms`):"";g.info(`\n ${m.green(`${m.bold("PP-DEV")} v${f}`)} ${b}\n`),c.printUrls(),function(e,t){if(!e.httpServer||!process.stdin.isTTY||process.env.CI)return;e._shortcutsOptions=t;const o=h();t.print&&o.info(m.dim(m.green(" ➜"))+m.dim(" press ")+m.bold("h")+m.dim(" to show help"));const n=(t.customShortcuts??[]).filter(I).concat(M);let i=!1;const s=async t=>{if(""===t||""===t)return void await e.close().finally((()=>process.exit(1)));if(i)return;"h"===t&&o.info(["",m.bold(" Shortcuts"),...n.map((e=>m.dim(" press ")+m.bold(e.key)+m.dim(` to ${e.description}`)))].join("\n"));const s=n.find((e=>e.key===t));s&&(i=!0,await s.action(e),i=!1)};process.stdin.setRawMode(!0),process.stdin.on("data",s).setEncoding("utf8").resume(),e.httpServer.on("close",(()=>{process.stdin.off("data",s).pause()}))}(c,{print:!0,customShortcuts:[q&&{key:"p",description:"start/stop the profiler",async action(e){if(q)await V(g.info);else{const e=await import("node:inspector").then((e=>e.default));await new Promise((t=>{q=new e.Session,q.connect(),q.post("Profiler.enable",(()=>{q?.post("Profiler.start",(()=>{g.info("Profiler started"),t()}))}))}))}}},{key:"l",description:"proxy re-login",action(e){e.ws.send({type:"custom",event:"redirect",data:{url:`/auth/index/logout?proxyRedirect=${encodeURIComponent("/")}`}})}}]})}catch(e){const o=h(t.logLevel);o.error(m.red(`error when starting dev server:\n${e.stack}`),{error:e}),V(o.info),_.exit(1)}})),O.command("next [root]","start dev server").alias("next-serve").alias("next-dev").option("--host [host]","[string] specify hostname").option("--port <port>","[number] specify port",{default:3e3}).option("--https","[boolean] use TLS + HTTP/2").option("--open [path]","[boolean | string] open browser on startup").option("--cors","[boolean] enable CORS").option("--strictPort","[boolean] exit if specified port is already in use").option("--force","[boolean] force the optimizer to ignore the cache and re-bundle").action((async(e,t)=>{W(t);const{default:n}=await import("next"),i=h(),r=function(e="info"){const t=F.default(),o=k.createLogger({level:e,format:k.format.cli({level:!0}),transports:[new k.transports.Console]});t.config={logger:o};const n=t.listen;let i;return t.listen=function(...e){i=n.apply(this,e)},t.printUrls=function(e){if(!i)throw new Error("Server is not listening");const t=e=>m.cyan(e.replace(/:(\d+)\//,((e,t)=>`:${m.bold(t)}/`))),n=i.address();if(n&&"object"==typeof n)if("::"===n.address){const i=new $(e||"",`http://localhost:${n.port}`);o.info(` ${m.green("➜")} ${m.bold("Local")}: ${t(i.toString())}`)}else{const i=new $(e||"",`http://[${n.address}]:${n.port}`);o.info(` ${m.green("➜")} ${m.bold("Local")}: ${t(i.toString())}`)}},t}(t.logLevel),a=B(t),l=s(t.mode||"development",e??_.cwd(),"");l&&Object.keys(l).forEach((e=>{e.startsWith("MI_")&&(_.env[e]=l[e])}));const d=n({dev:!0,hostname:a.host,port:a.port});await d.prepare();const c=await d.getServer();let p=c.nextConfig.basePath;const{assetPrefix:A}=c.nextConfig;if(p.endsWith("/")||(p+="/"),"/"===p)throw new Error('basePath cannot be equal to "/" or empty string');const C=p.substring(0,p.lastIndexOf("/")),D=c.nextConfig.serverRuntimeConfig.templateName,E=c.nextConfig.serverRuntimeConfig.ppDevConfig,{backendBaseURL:j,portalPageId:z,appId:H,templateLess:I=!0,enableProxyCache:M=!0,miHudLess:N=!0,proxyCacheTTL:R=6e5,disableSSLValidation:U=!1,v7Features:O=!1,personalAccessToken:q=_.env.MI_ACCESS_TOKEN}=E,G=H??z;if(r.use(g(p,D)),j){let e;try{e=new URL(j).host}catch(e){i.error(m.red(`Invalid backendBaseURL: ${j}`)),_.exit(1)}const t=new u(j,{headers:{host:e,referer:j,origin:j.replace(/^(https?:\/\/)([^/]+)(\/.*)?$/i,"$1$2")},portalPageId:G,templateLess:I,disableSSLValidation:U,v7Features:O,personalAccessToken:q});if(M){let e=+R;(!e||Number.isNaN(e)||e<0)&&(e=6e5),r.use(b({devServer:r,ttl:e}))}const o=["/@vite","/@metricinsights","/@",C];A&&o.push(A),r.use(v({devServer:r,baseURL:j,proxyIgnore:o,disableSSLValidation:U,miAPI:t}));const n=new RegExp(`^((${p})|/)$`);r.use(w(n,t,E)),r.use(y((e=>n.test(L(e))),((o,n)=>Buffer.from(x(e,n.headers.host??"",t.buildPage(o,N)))))),P.post("/@api/login",(async(e,o,n)=>{const{token:s,tokenType:r}=e.body;if(!s)return void o.status(400).json({error:"Token is required"}).end();const a=e=>(i.error(e),n(e),null);if("personal"===r){if(!await t.get("/data/page/index/auth/info",{"Content-Type":"application/json",Accept:"application/json",Authorization:`Bearer ${s}`},!0).then((async e=>{if("number"==typeof e.data?.user?.user_id)return t.personalAccessToken=s,e;o.status(400).json({error:"Token expired or invalid"}).end()})).catch(a))return;T(o,"/",302)}else if("regular"===r){if(!await t.get("/api/user",{"Content-Type":"application/json",Accept:"application/json",Token:s},!0).then((e=>{if(e.data?.users?.length)return t.personalAccessToken=void 0,o.setHeader("set-cookie",e.headers["set-cookie"]??""),e;o.status(400).json({error:"Token expired or invalid"}).end()})).catch(a))return;T(o,"/",302)}})),r.use(P)}const Z=d.getRequestHandler();r.all("*",((e,t)=>{try{if(e.url?.startsWith(A)&&A!==C){const o=e.url.replace(A,C),n=S(o,!0);return n.pathname?Z(e,t,n):(t.statusCode=400,void t.end("Invalid URL"))}const o=S(e.url||"/",!0);if(!o.pathname)return t.statusCode=400,void t.end("Invalid URL");Z(e,t,o)}catch(e){const o=e instanceof Error?e.message:"Unknown error";i.error(m.red(`Error handling request: ${o}`)),t.statusCode=500,t.end("Internal Server Error")}}));try{await new Promise((e=>{a.host?e(r.listen(a.port,a.host,(()=>{}))):e(r.listen(a.port,(()=>{})))}));const e=global.__pp_dev_start_time??!1,t=e?m.dim(`ready in ${m.reset(m.bold(Math.ceil(o.now()-e)))} ms`):"";i.info(`\n ${m.green(`${m.bold("PP-DEV")} v${f}`)} ${t}\n`,{clear:!0}),r.printUrls(p)}catch(e){const o=h(t.logLevel);o.error(m.red(`error when starting dev server:\n${e.stack}`),{error:e}),V(o.info),_.exit(1)}})),O.command("build [root]","build for production").option("--target <target>","[string] transpile target (default: 'modules')").option("--outDir <dir>","[string] output directory (default: dist)").option("--assetsDir <dir>","[string] directory under outDir to place assets in (default: assets)").option("--assetsInlineLimit <number>","[number] static asset base64 inline threshold in bytes (default: 4096)").option("--ssr [entry]","[string] build specified entry for server-side rendering").option("--sourcemap [output]",'[boolean | "inline" | "hidden"] output source maps for build (default: false)').option("--minify [minifier]",'[boolean | "terser" | "esbuild"] enable/disable minification, or specify minifier to use (default: esbuild)').option("--manifest [name]","[boolean | string] emit build manifest json").option("--ssrManifest [name]","[boolean | string] emit ssr manifest json").option("--force","[boolean] force the optimizer to ignore the cache and re-bundle (experimental)").option("--emptyOutDir","[boolean] force empty outDir when it's outside of root").option("-w, --watch","[boolean] rebuilds when modules have changed on disk").option("--changelog [assetsFile]","[boolean | string] generate changelog between assetsFile and current build (default: false)").action((async(o,n)=>{W(n);const s=B(n);try{const l=await i({mode:n.mode||"production",command:"build"},n.config,o,n.logLevel);let d=await p();if(l){const{plugins:e,...t}=l.config;d=r(d,t)}const c=r(d,{root:o,base:n.base,mode:n.mode,configFile:n.config,logLevel:n.logLevel,clearScreen:n.clearScreen,optimizeDeps:{force:n.force},build:s},!0);if(await a(c),s.changelog){const i=o||_.cwd(),r=c.build?.outDir||"dist";let a="";if("string"==typeof s.changelog)a=e.resolve(i,s.changelog);else{const o=e.resolve(i,c.ppDevConfig?.syncBackupsDir||"backups");if(!t.existsSync(o))return void h(n.logLevel).warn(m.yellow("backups directory not found, skipping changelog generation"));const s=t.readdirSync(o,{withFileTypes:!0});if(!s.length)return void h(n.logLevel).warn(m.yellow("no backups found, skipping changelog generation"));const r=s.filter((e=>e.isFile()&&e.name.endsWith(".zip"))).reduce(((n,i)=>t.statSync(e.resolve(o,n.name)).mtimeMs>t.statSync(e.resolve(o,i.name)).mtimeMs?n:i),s[0]).name;a=e.resolve(o,r)}const l=e.resolve(i,r);let d="dist-zip";c.ppDevConfig&&(!1===c.ppDevConfig.distZip?d=c.build?.outDir||"dist":"object"==typeof c.ppDevConfig.distZip&&"string"==typeof c.ppDevConfig.distZip.outDir&&(d=c.ppDevConfig.distZip.outDir));const p=new R({oldAssetsPath:a,newAssetsPath:l,destinationPath:e.resolve(i,d)});await p.generateChangelog()}}catch(e){h(n.logLevel).error(m.red(`error during build:\n${e.stack}`),{error:e}),_.exit(1)}finally{V((e=>h(n.logLevel).info(e)))}})),O.command("changelog [oldAssetPath] [newAssetPath]","generate changelog between two assets files/folders").option("--oldAssetsPath <oldAssetsPath>","[string] path to the old assets zip file or folder").option("--newAssetsPath <newAssetsPath>","[string] path to the new assets zip file or folder").option("--destination <destination>","[string] destination folder for the changelog (default: .)").option("--filename <filename>","[string] filename for the changelog (default: CHANGELOG.html)").action((async(t,o,n)=>{W(n);const{oldAssetsPath:i=t,newAssetsPath:s=o,destination:r=".",filename:a="CHANGELOG.html",logLevel:l}=n,d=_.cwd();i&&s||(h(l).error(m.red("error during changelog generation: oldAssetPath and newAssetPath are required")),_.exit(1));const c=e.resolve(d,i),p=e.resolve(d,s),f=e.resolve(d,r),g=new R({oldAssetsPath:c,newAssetsPath:p,destinationPath:f,changelogFilename:a});await g.generateChangelog()})),O.command("generate-icon-font [source] [destination]","generate icon font from SVG files").option("--source <source>","[string] path to the source directory with SVG files").option("--destination <destination>","[string] path to the destination directory to save the generated font files").option("--font-name, -n <fontName>","[string] name of the font to generate (default: 'icon-font')").action((async(t,o,n)=>{W(n);const{source:i=t,destination:s=o,fontName:r="icon-font"}=n,a=_.cwd(),l=e.resolve(a,i),d=e.resolve(a,s),c=new U({sourceDir:l,outputDir:d,fontName:r}),p=h(n.logLevel);p.info(`Generating icon font from SVG files in ${m.dim(l)}`),await c.generate(),p.info(`Icon font generated and saved to ${m.dim(d)}`)})),O.command("optimize [root]","pre-bundle dependencies").option("--force","[boolean] force the optimizer to ignore the cache and re-bundle").action((async(e,t)=>{W(t);try{const o=await i({mode:t.mode||"production",command:"build"},t.config,e,t.logLevel);let n=await p();if(o){const{plugins:e,...t}=o.config;n=r(n,t)}const s=await l(r(n,{root:e,base:t.base,configFile:t.config,logLevel:t.logLevel,mode:t.mode}),"serve");await d(s,t.force,!0)}catch(e){h(t.logLevel).error(m.red(`error when optimizing deps:\n${e.stack}`),{error:e}),_.exit(1)}})),O.command("preview [root]","locally preview production build").option("--host [host]","[string] specify hostname").option("--port <port>","[number] specify port").option("--strictPort","[boolean] exit if specified port is already in use").option("--https","[boolean] use TLS + HTTP/2").option("--open [path]","[boolean | string] open browser on startup").option("--outDir <dir>","[string] output directory (default: dist)").action((async(e,t)=>{W(t);try{const o=await i({mode:t.mode||"production",command:"build"},t.config,e,t.logLevel);let n=await p();if(o){const{plugins:e,...t}=o.config;n=r(n,t)}(await c(r(n,{root:e,base:t.base,configFile:t.config,logLevel:t.logLevel,mode:t.mode,build:{outDir:t.outDir},preview:{port:t.port,strictPort:t.strictPort,host:t.host,https:t.https,open:t.open}}))).printUrls()}catch(e){h(t.logLevel).error(m.red(`error when starting preview server:\n${e.stack}`),{error:e}),_.exit(1)}finally{V((e=>h(t.logLevel).info(e)))}})),O.help(),O.version(f),O.parse();export{V as stopProfiler};
|
|
1174
2
|
//# sourceMappingURL=cli.js.map
|