@metricinsights/pp-dev 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -41
- package/bin/pp-dev.js +4 -10
- package/dist/cjs/cli.js +589 -0
- package/dist/cjs/cli.js.map +1 -0
- package/dist/cjs/helpers.js +29 -0
- package/dist/cjs/helpers.js.map +1 -0
- package/dist/cjs/index-ab672d81.js +292 -0
- package/dist/cjs/index-ab672d81.js.map +1 -0
- package/dist/cjs/index.js +27 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/package.json +113 -0
- package/dist/cjs/plugin-24dd0a43.js +878 -0
- package/dist/cjs/plugin-24dd0a43.js.map +1 -0
- package/dist/cjs/plugin.js +20 -0
- package/dist/cjs/plugin.js.map +1 -0
- package/dist/{cli.js → esm/cli.js} +210 -23
- package/dist/esm/cli.js.map +1 -0
- package/dist/esm/helpers.js +25 -0
- package/dist/esm/helpers.js.map +1 -0
- package/dist/{index.js → esm/index-d2c8ad2e.js} +98 -12
- package/dist/esm/index-d2c8ad2e.js.map +1 -0
- package/dist/esm/index.js +19 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/package.json +113 -0
- package/dist/esm/plugin-ecb1c54a.js +843 -0
- package/dist/esm/plugin-ecb1c54a.js.map +1 -0
- package/dist/esm/plugin.js +14 -0
- package/dist/esm/plugin.js.map +1 -0
- package/dist/types/cli.d.ts +3 -0
- package/dist/types/helpers.d.ts +24 -0
- package/dist/types/index.d.ts +18 -0
- package/dist/{plugin.d.ts → types/plugin.d.ts} +4 -2
- package/package.json +23 -8
- package/pp-dev.d.ts +1 -1
- package/dist/api/assets.d.ts +0 -15
- package/dist/api/assets.js +0 -58
- package/dist/api/assets.js.map +0 -1
- package/dist/api/base.d.ts +0 -5
- package/dist/api/base.js +0 -7
- package/dist/api/base.js.map +0 -1
- package/dist/api/constants.d.ts +0 -1
- package/dist/api/constants.js +0 -2
- package/dist/api/constants.js.map +0 -1
- package/dist/api/index.d.ts +0 -2
- package/dist/api/index.js +0 -3
- package/dist/api/index.js.map +0 -1
- package/dist/api/page.d.ts +0 -16
- package/dist/api/page.js +0 -43
- package/dist/api/page.js.map +0 -1
- package/dist/banner/header.d.ts +0 -2
- package/dist/banner/header.js +0 -10
- package/dist/banner/header.js.map +0 -1
- package/dist/cli.d.ts +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/client/rollup.config.d.ts +0 -2
- package/dist/constants.d.ts +0 -6
- package/dist/constants.js +0 -18
- package/dist/constants.js.map +0 -1
- package/dist/index.d.ts +0 -13
- package/dist/index.js.map +0 -1
- package/dist/lib/client.service.d.ts +0 -16
- package/dist/lib/client.service.js +0 -59
- package/dist/lib/client.service.js.map +0 -1
- package/dist/lib/dist.service.d.ts +0 -31
- package/dist/lib/dist.service.js +0 -148
- package/dist/lib/dist.service.js.map +0 -1
- package/dist/lib/helpers/content-encoding.helper.d.ts +0 -3
- package/dist/lib/helpers/content-encoding.helper.js +0 -26
- package/dist/lib/helpers/content-encoding.helper.js.map +0 -1
- package/dist/lib/helpers/server.d.ts +0 -14
- package/dist/lib/helpers/server.js +0 -40
- package/dist/lib/helpers/server.js.map +0 -1
- package/dist/lib/helpers/url.helper.d.ts +0 -7
- package/dist/lib/helpers/url.helper.js +0 -40
- package/dist/lib/helpers/url.helper.js.map +0 -1
- package/dist/lib/load-pp-data.middleware.d.ts +0 -5
- package/dist/lib/load-pp-data.middleware.js +0 -28
- package/dist/lib/load-pp-data.middleware.js.map +0 -1
- package/dist/lib/pp-redirect.middleware.d.ts +0 -3
- package/dist/lib/pp-redirect.middleware.js +0 -21
- package/dist/lib/pp-redirect.middleware.js.map +0 -1
- package/dist/lib/pp.middleware.d.ts +0 -27
- package/dist/lib/pp.middleware.js +0 -155
- package/dist/lib/pp.middleware.js.map +0 -1
- package/dist/lib/proxy-cache.middleware.d.ts +0 -18
- package/dist/lib/proxy-cache.middleware.js +0 -51
- package/dist/lib/proxy-cache.middleware.js.map +0 -1
- package/dist/lib/proxy-pass.middleware.d.ts +0 -11
- package/dist/lib/proxy-pass.middleware.js +0 -90
- package/dist/lib/proxy-pass.middleware.js.map +0 -1
- package/dist/lib/rewrite-response.middleware.d.ts +0 -6
- package/dist/lib/rewrite-response.middleware.js +0 -23
- package/dist/lib/rewrite-response.middleware.js.map +0 -1
- package/dist/plugin.js +0 -76
- package/dist/plugin.js.map +0 -1
- package/dist/plugins/client-injection-plugin.d.ts +0 -12
- package/dist/plugins/client-injection-plugin.js +0 -57
- package/dist/plugins/client-injection-plugin.js.map +0 -1
- package/dist/shortcuts.d.ts +0 -12
- package/dist/shortcuts.js +0 -93
- package/dist/shortcuts.js.map +0 -1
|
@@ -0,0 +1,878 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var httpProxyMiddleware = require('http-proxy-middleware');
|
|
4
|
+
var url = require('url');
|
|
5
|
+
var axios = require('axios');
|
|
6
|
+
var jsdom = require('jsdom');
|
|
7
|
+
var memoryCache = require('memory-cache');
|
|
8
|
+
var path = require('path');
|
|
9
|
+
var fs = require('fs');
|
|
10
|
+
var crypto = require('crypto');
|
|
11
|
+
var process = require('process');
|
|
12
|
+
var child_process = require('child_process');
|
|
13
|
+
var console = require('console');
|
|
14
|
+
var zlib = require('zlib');
|
|
15
|
+
|
|
16
|
+
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
17
|
+
function _interopNamespaceDefault(e) {
|
|
18
|
+
var n = Object.create(null);
|
|
19
|
+
if (e) {
|
|
20
|
+
Object.keys(e).forEach(function (k) {
|
|
21
|
+
if (k !== 'default') {
|
|
22
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
23
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
24
|
+
enumerable: true,
|
|
25
|
+
get: function () { return e[k]; }
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
n.default = e;
|
|
31
|
+
return Object.freeze(n);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
var memoryCache__namespace = /*#__PURE__*/_interopNamespaceDefault(memoryCache);
|
|
35
|
+
var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
|
|
36
|
+
var crypto__namespace = /*#__PURE__*/_interopNamespaceDefault(crypto);
|
|
37
|
+
var process__namespace = /*#__PURE__*/_interopNamespaceDefault(process);
|
|
38
|
+
var child_process__namespace = /*#__PURE__*/_interopNamespaceDefault(child_process);
|
|
39
|
+
var console__namespace = /*#__PURE__*/_interopNamespaceDefault(console);
|
|
40
|
+
|
|
41
|
+
const urlReplacer = (originalHost, destinationHost, content) => {
|
|
42
|
+
const urlReplaceRegExp = new RegExp(`(!!)?(https?(:(\\\\)?/(\\\\)?/)${originalHost})`, 'gi');
|
|
43
|
+
return content.replace(urlReplaceRegExp, (substring, ...args) => {
|
|
44
|
+
if (substring.startsWith('!!')) {
|
|
45
|
+
return args[1];
|
|
46
|
+
}
|
|
47
|
+
return `http${args[2]}${destinationHost}`;
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
const urlPathReplacer = (urlPath, destinationPath, content) => {
|
|
51
|
+
const urlReplaceRegExp = new RegExp(`${urlPath.replace(/\\*\//gi, '\\\\/')}`, 'gi');
|
|
52
|
+
return content.replace(urlReplaceRegExp, destinationPath);
|
|
53
|
+
};
|
|
54
|
+
const redirect = (res, url, statusCode) => {
|
|
55
|
+
res.setHeader('location', url);
|
|
56
|
+
res.statusCode = statusCode || 302;
|
|
57
|
+
res.end();
|
|
58
|
+
};
|
|
59
|
+
function cutUrlParams(url) {
|
|
60
|
+
const urlParts = url.split('?');
|
|
61
|
+
return urlParts[0];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const hostOriginRegExp = /^(https?:\/\/)([^/]+)(\/.*)?$/i;
|
|
65
|
+
const PROXY_HEADER = 'X-PP-Proxy';
|
|
66
|
+
function initProxy(opts) {
|
|
67
|
+
const { rewritePath = /^\/(?!pt).*/i, baseURL = '', devServer } = opts;
|
|
68
|
+
if (!baseURL) {
|
|
69
|
+
throw new Error('Base url is required');
|
|
70
|
+
}
|
|
71
|
+
const host = baseURL.replace(hostOriginRegExp, '$2');
|
|
72
|
+
const origin = baseURL.replace(hostOriginRegExp, '$1$2');
|
|
73
|
+
const fileType = import('file-type');
|
|
74
|
+
return httpProxyMiddleware.createProxyMiddleware((pathname) => {
|
|
75
|
+
if ((opts.proxyIgnore || []).some((value) => {
|
|
76
|
+
if (typeof value === 'string') {
|
|
77
|
+
return pathname.startsWith(value);
|
|
78
|
+
}
|
|
79
|
+
else if (typeof value.test === 'function') {
|
|
80
|
+
return value.test(pathname);
|
|
81
|
+
}
|
|
82
|
+
return true;
|
|
83
|
+
})) {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
if (typeof rewritePath === 'string') {
|
|
87
|
+
return pathname.startsWith(rewritePath);
|
|
88
|
+
}
|
|
89
|
+
else if (Array.isArray(rewritePath)) {
|
|
90
|
+
return rewritePath.some((rP) => pathname.startsWith(rP));
|
|
91
|
+
}
|
|
92
|
+
else if (typeof rewritePath.test === 'function') {
|
|
93
|
+
return rewritePath.test(pathname);
|
|
94
|
+
}
|
|
95
|
+
return false;
|
|
96
|
+
}, {
|
|
97
|
+
/**
|
|
98
|
+
* IMPORTANT: avoid res.end being called automatically
|
|
99
|
+
**/
|
|
100
|
+
selfHandleResponse: true,
|
|
101
|
+
target: baseURL,
|
|
102
|
+
changeOrigin: true,
|
|
103
|
+
autoRewrite: true,
|
|
104
|
+
logLevel: 'silent',
|
|
105
|
+
headers: {
|
|
106
|
+
host,
|
|
107
|
+
origin,
|
|
108
|
+
},
|
|
109
|
+
onProxyReq(proxyReq, req, res) {
|
|
110
|
+
const host = req.headers.host;
|
|
111
|
+
const referer = proxyReq.getHeader('referer');
|
|
112
|
+
devServer.config.logger.info(`Proxies request: ${req.method} ${req.url} -> ${proxyReq.method} ${proxyReq.protocol}//${proxyReq.host}${proxyReq.path}`);
|
|
113
|
+
if (host && referer && typeof referer === 'string') {
|
|
114
|
+
proxyReq.setHeader('referer', referer.replace(new RegExp(`https?://${host}`), baseURL));
|
|
115
|
+
}
|
|
116
|
+
req.socket.on('close', () => {
|
|
117
|
+
setTimeout(() => {
|
|
118
|
+
if (!proxyReq.destroyed) {
|
|
119
|
+
proxyReq.destroy();
|
|
120
|
+
}
|
|
121
|
+
}, 200);
|
|
122
|
+
});
|
|
123
|
+
return proxyReq;
|
|
124
|
+
},
|
|
125
|
+
onProxyRes: httpProxyMiddleware.responseInterceptor(async (responseBuffer, proxyRes, req, res) => {
|
|
126
|
+
res.setHeader(PROXY_HEADER, 1);
|
|
127
|
+
const type = await (await fileType).fileTypeFromBuffer(responseBuffer);
|
|
128
|
+
if (type) {
|
|
129
|
+
return responseBuffer;
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
let response = responseBuffer.toString('utf8'); // convert buffer to string
|
|
133
|
+
try {
|
|
134
|
+
const reqUrl = new URL(req.url ?? '', `http://${host}`);
|
|
135
|
+
if (reqUrl.searchParams && reqUrl.searchParams.has('proxyRedirect')) {
|
|
136
|
+
response +=
|
|
137
|
+
'<script>' +
|
|
138
|
+
'const params = new URLSearchParams(window.location.search);' +
|
|
139
|
+
"if (params.has('proxyRedirect')) {" +
|
|
140
|
+
" setTimeout(() => { window.location = params.get('proxyRedirect'); }, 50);" +
|
|
141
|
+
'}' +
|
|
142
|
+
'</script>';
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
//
|
|
147
|
+
}
|
|
148
|
+
const reqHost = req.headers.host ?? '';
|
|
149
|
+
// manipulate response and return the result
|
|
150
|
+
return urlPathReplacer('/auth/saml/login', '/login', urlReplacer(host, reqHost, response));
|
|
151
|
+
}
|
|
152
|
+
}),
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
class BaseAPI {
|
|
157
|
+
axios;
|
|
158
|
+
constructor(axios) {
|
|
159
|
+
this.axios = axios;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
class AssetsAPI extends BaseAPI {
|
|
164
|
+
// Import for CJS and ESM
|
|
165
|
+
formdataModulePromise = import('formdata-node');
|
|
166
|
+
constructor(axios) {
|
|
167
|
+
super(axios);
|
|
168
|
+
}
|
|
169
|
+
async downloadPageAssets(portalPageId, headers) {
|
|
170
|
+
return this.axios
|
|
171
|
+
.get(`/admin/page/downloadassets/id/${portalPageId}`, {
|
|
172
|
+
withCredentials: true,
|
|
173
|
+
headers: Object.assign({}, headers, { accept: '*/*' }),
|
|
174
|
+
responseType: 'arraybuffer',
|
|
175
|
+
})
|
|
176
|
+
.then((res) => res.data);
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Upload page assets.
|
|
180
|
+
* @param portalPageId
|
|
181
|
+
* @param file - Zip file with assets
|
|
182
|
+
* @param headers
|
|
183
|
+
*/
|
|
184
|
+
async uploadPageAssets(portalPageId, file, headers) {
|
|
185
|
+
const formData = new (await this.formdataModulePromise).FormData();
|
|
186
|
+
const assetFile = new File([file.buffer], 'file.zip', { type: 'application/zip' });
|
|
187
|
+
formData.append('file', assetFile);
|
|
188
|
+
const url = `/admin/page/uploadassets/id/${portalPageId}`;
|
|
189
|
+
return this.axios
|
|
190
|
+
.post(`/admin/page/uploadassets/id/${portalPageId}`, formData, {
|
|
191
|
+
withCredentials: true,
|
|
192
|
+
headers: Object.assign({}, headers, {
|
|
193
|
+
accept: 'application/json',
|
|
194
|
+
'Content-Type': 'multipart/form-data',
|
|
195
|
+
Referer: this.axios.getUri({ url }),
|
|
196
|
+
}),
|
|
197
|
+
})
|
|
198
|
+
.then((res) => res.data);
|
|
199
|
+
}
|
|
200
|
+
async downloadTemplateAssets(templateId, headers) {
|
|
201
|
+
return this.axios
|
|
202
|
+
.get(`/admin/pagetemplate/downloadassets/id/${templateId}`, {
|
|
203
|
+
withCredentials: true,
|
|
204
|
+
headers: Object.assign({}, headers, { accept: '*/*' }),
|
|
205
|
+
responseType: 'arraybuffer',
|
|
206
|
+
})
|
|
207
|
+
.then((res) => res.data);
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Upload template assets.
|
|
211
|
+
* @param templateId
|
|
212
|
+
* @param file - Zip file with assets
|
|
213
|
+
* @param headers
|
|
214
|
+
*/
|
|
215
|
+
async uploadTemplateAssets(templateId, file, headers) {
|
|
216
|
+
const formData = new (await this.formdataModulePromise).FormData();
|
|
217
|
+
const assetFile = new (await this.formdataModulePromise).File([file.buffer], 'file.zip', {
|
|
218
|
+
type: 'application/zip',
|
|
219
|
+
});
|
|
220
|
+
formData.append('file', assetFile, 'file.zip');
|
|
221
|
+
const url = `/admin/pagetemplate/uploadassets/id/${templateId}`;
|
|
222
|
+
return this.axios
|
|
223
|
+
.post(url, formData, {
|
|
224
|
+
withCredentials: true,
|
|
225
|
+
headers: Object.assign({}, headers, {
|
|
226
|
+
accept: 'application/json',
|
|
227
|
+
'Content-Type': 'multipart/form-data',
|
|
228
|
+
Referer: this.axios.getUri({ url }),
|
|
229
|
+
}),
|
|
230
|
+
})
|
|
231
|
+
.then((res) => res.data);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
class PageAPI extends BaseAPI {
|
|
236
|
+
async getAll(headers) {
|
|
237
|
+
return (await this.axios.get('/api/page', {
|
|
238
|
+
withCredentials: true,
|
|
239
|
+
headers: Object.assign({}, headers, {
|
|
240
|
+
Accept: 'application/json',
|
|
241
|
+
'Content-Type': 'application/json',
|
|
242
|
+
'Cache-Control': 'no-cache',
|
|
243
|
+
Pragma: 'no-cache',
|
|
244
|
+
Expires: '0',
|
|
245
|
+
}),
|
|
246
|
+
})).data.pages;
|
|
247
|
+
}
|
|
248
|
+
async get(id, headers) {
|
|
249
|
+
return (await this.axios.get(`/api/page/id/${id}`, {
|
|
250
|
+
withCredentials: true,
|
|
251
|
+
headers: Object.assign({}, headers, {
|
|
252
|
+
accept: 'application/json',
|
|
253
|
+
'content-type': 'application/json',
|
|
254
|
+
}),
|
|
255
|
+
})).data.page;
|
|
256
|
+
}
|
|
257
|
+
async getPageContent(internalPageName, headers) {
|
|
258
|
+
return (await this.axios.get(`/p/${internalPageName}`, {
|
|
259
|
+
withCredentials: true,
|
|
260
|
+
headers: Object.assign({}, headers, {
|
|
261
|
+
accept: 'text/html',
|
|
262
|
+
'content-type': 'application/json',
|
|
263
|
+
}),
|
|
264
|
+
})).data;
|
|
265
|
+
}
|
|
266
|
+
async create(page, headers) {
|
|
267
|
+
return (await this.axios.post('/api/page', page, {
|
|
268
|
+
withCredentials: true,
|
|
269
|
+
headers: Object.assign({}, headers, {
|
|
270
|
+
accept: 'application/json',
|
|
271
|
+
'content-type': 'application/json',
|
|
272
|
+
}),
|
|
273
|
+
})).data.page;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
class MiAPI {
|
|
278
|
+
#headers;
|
|
279
|
+
#axios;
|
|
280
|
+
#pageTemplate = null;
|
|
281
|
+
#pageTitle;
|
|
282
|
+
#pageVars;
|
|
283
|
+
#templateLoaded;
|
|
284
|
+
#templateLoadedResolve;
|
|
285
|
+
portalPageId;
|
|
286
|
+
templateLess;
|
|
287
|
+
assetsApi;
|
|
288
|
+
pageApi;
|
|
289
|
+
constructor(baseURL, opts) {
|
|
290
|
+
const { headers = {}, portalPageId, templateLess = true } = opts || {};
|
|
291
|
+
this.#headers = headers;
|
|
292
|
+
this.#pageVars = [];
|
|
293
|
+
this.#pageTitle = '';
|
|
294
|
+
this.#templateLoaded = new Promise((resolve) => {
|
|
295
|
+
this.#templateLoadedResolve = resolve;
|
|
296
|
+
});
|
|
297
|
+
this.#axios = axios.create({ baseURL, headers });
|
|
298
|
+
this.portalPageId = portalPageId;
|
|
299
|
+
this.templateLess = templateLess;
|
|
300
|
+
this.assetsApi = new AssetsAPI(this.#axios);
|
|
301
|
+
this.pageApi = new PageAPI(this.#axios);
|
|
302
|
+
}
|
|
303
|
+
async isTemplateLoaded() {
|
|
304
|
+
return this.#templateLoaded;
|
|
305
|
+
}
|
|
306
|
+
#clearHeaders(headers) {
|
|
307
|
+
const obj = Object.assign({}, headers, { host: undefined });
|
|
308
|
+
Object.keys(obj).forEach((key) => obj[key] === undefined && delete obj[key]);
|
|
309
|
+
this.#headers = obj;
|
|
310
|
+
return obj;
|
|
311
|
+
}
|
|
312
|
+
updateHeaders(headers) {
|
|
313
|
+
this.#clearHeaders(headers);
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Get page template
|
|
317
|
+
* @param headers
|
|
318
|
+
*/
|
|
319
|
+
async getPageTemplate(headers) {
|
|
320
|
+
if (this.#pageTemplate) {
|
|
321
|
+
return Promise.resolve(this.#pageTemplate);
|
|
322
|
+
}
|
|
323
|
+
if (typeof this.templateLess === 'undefined') {
|
|
324
|
+
this.templateLess = false;
|
|
325
|
+
}
|
|
326
|
+
const pageList = await this.pageApi.getAll(this.#clearHeaders(headers));
|
|
327
|
+
let page = pageList.find((p) => p.name === '[DEV PAGE. DO NOT DELETE]');
|
|
328
|
+
if (!page) {
|
|
329
|
+
page = await this.pageApi.create({
|
|
330
|
+
enabled: 'Y',
|
|
331
|
+
name: '[DEV PAGE. DO NOT DELETE]',
|
|
332
|
+
internal_name: 'dev-page-template',
|
|
333
|
+
visible_in_homepage: 'Y',
|
|
334
|
+
}, this.#clearHeaders(headers));
|
|
335
|
+
}
|
|
336
|
+
return await this.pageApi
|
|
337
|
+
.getPageContent(page.internal_name, this.#clearHeaders(headers))
|
|
338
|
+
.then((response) => {
|
|
339
|
+
this.#pageTemplate = response;
|
|
340
|
+
return response;
|
|
341
|
+
})
|
|
342
|
+
.finally(() => {
|
|
343
|
+
this.#templateLoadedResolve(true);
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Get page template variables
|
|
348
|
+
*
|
|
349
|
+
* @param pageId
|
|
350
|
+
* @param headers
|
|
351
|
+
*/
|
|
352
|
+
async getPageVariables(pageId, headers) {
|
|
353
|
+
this.#pageTemplate = await this.getPageTemplate(headers);
|
|
354
|
+
if (!this.portalPageId) {
|
|
355
|
+
this.portalPageId = pageId;
|
|
356
|
+
this.templateLess = false;
|
|
357
|
+
}
|
|
358
|
+
return await this.pageApi
|
|
359
|
+
.get(pageId, this.#clearHeaders(headers))
|
|
360
|
+
.then((response) => {
|
|
361
|
+
const { tags = '[]', name, template } = response;
|
|
362
|
+
if (template && tags) {
|
|
363
|
+
const parsed = JSON.parse(tags);
|
|
364
|
+
this.#pageVars = parsed;
|
|
365
|
+
this.#pageTitle = name;
|
|
366
|
+
return parsed;
|
|
367
|
+
}
|
|
368
|
+
this.#pageVars = [];
|
|
369
|
+
this.#pageTitle = name;
|
|
370
|
+
return [];
|
|
371
|
+
})
|
|
372
|
+
.catch((reason) => {
|
|
373
|
+
if (reason.response?.status === 404) {
|
|
374
|
+
throw new Error(`Portal Page with id "${pageId}" not found on instance ${this.#axios.getUri()}`);
|
|
375
|
+
}
|
|
376
|
+
throw reason;
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* Build page with variables
|
|
381
|
+
*
|
|
382
|
+
* @param content
|
|
383
|
+
* @param miHudLess
|
|
384
|
+
*/
|
|
385
|
+
buildPage(content, miHudLess = false) {
|
|
386
|
+
let result = typeof content === 'string' ? content : content.toString('utf-8');
|
|
387
|
+
for (const v of this.#pageVars) {
|
|
388
|
+
result = result.replace(new RegExp(`\\[${v.name}\\]`, 'g'), v.value);
|
|
389
|
+
}
|
|
390
|
+
const dom = new jsdom.JSDOM(miHudLess ? result : this.#pageTemplate);
|
|
391
|
+
const placeholderText = '%%PLACEHOLDER%%';
|
|
392
|
+
if (!miHudLess) {
|
|
393
|
+
const placeholder = dom.window.document.createElement('div');
|
|
394
|
+
placeholder.innerHTML = placeholderText;
|
|
395
|
+
const container = dom.window.document.querySelector('.main-side');
|
|
396
|
+
if (container) {
|
|
397
|
+
const scripts = container.querySelectorAll('script');
|
|
398
|
+
if (scripts.length) {
|
|
399
|
+
container.insertBefore(placeholder, scripts.item(scripts.length - 1));
|
|
400
|
+
}
|
|
401
|
+
else {
|
|
402
|
+
container.append(placeholder);
|
|
403
|
+
}
|
|
404
|
+
const head = dom.window.document.querySelector('head');
|
|
405
|
+
const title = head.querySelector('title');
|
|
406
|
+
if (title) {
|
|
407
|
+
title.text = this.#pageTitle;
|
|
408
|
+
}
|
|
409
|
+
else {
|
|
410
|
+
head.innerHTML += `<title>${this.#pageTitle}</title>`;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
const serializedDom = dom.serialize();
|
|
415
|
+
return serializedDom.replace(new RegExp(`<div>\\s*${placeholderText}\\s*<\\/div>`, 'i'), result);
|
|
416
|
+
}
|
|
417
|
+
async getAssets() {
|
|
418
|
+
if (this.portalPageId) {
|
|
419
|
+
if (this.templateLess) {
|
|
420
|
+
return await this.assetsApi.downloadPageAssets(this.portalPageId, this.#headers);
|
|
421
|
+
}
|
|
422
|
+
else {
|
|
423
|
+
const pageInfo = await this.pageApi.get(this.portalPageId, this.#headers);
|
|
424
|
+
if (pageInfo.template) {
|
|
425
|
+
return await this.assetsApi.downloadTemplateAssets(pageInfo.template, this.#headers);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
async updateAssets(assets) {
|
|
431
|
+
if (this.portalPageId) {
|
|
432
|
+
if (this.templateLess) {
|
|
433
|
+
return await this.assetsApi.uploadPageAssets(this.portalPageId, assets, this.#headers);
|
|
434
|
+
}
|
|
435
|
+
else {
|
|
436
|
+
const pageInfo = await this.pageApi.get(this.portalPageId, this.#headers);
|
|
437
|
+
if (pageInfo.template) {
|
|
438
|
+
return await this.assetsApi.uploadTemplateAssets(pageInfo.template, assets, this.#headers);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
class ClientService {
|
|
446
|
+
server;
|
|
447
|
+
opts;
|
|
448
|
+
eventMap;
|
|
449
|
+
constructor(server, opts) {
|
|
450
|
+
this.server = server;
|
|
451
|
+
this.opts = opts || {};
|
|
452
|
+
this.eventMap = new Map();
|
|
453
|
+
this.eventMap.set('info-data:request', this.onInfoDataRequest.bind(this));
|
|
454
|
+
this.eventMap.set('template:sync', this.onTemplateSync.bind(this));
|
|
455
|
+
this.init();
|
|
456
|
+
}
|
|
457
|
+
init() {
|
|
458
|
+
const { ws } = this.server;
|
|
459
|
+
for (const [event, handler] of this.eventMap) {
|
|
460
|
+
ws.on(event, handler);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
onInfoDataRequest() {
|
|
464
|
+
this.server.ws.send({
|
|
465
|
+
type: 'custom',
|
|
466
|
+
event: 'info-data:response',
|
|
467
|
+
data: {},
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
async onTemplateSync() {
|
|
471
|
+
if (this.opts.distService && this.opts.miAPI) {
|
|
472
|
+
const { distService, miAPI } = this.opts;
|
|
473
|
+
const currentAssets = await miAPI?.getAssets();
|
|
474
|
+
const newAssets = currentAssets
|
|
475
|
+
? await distService?.saveBackupAndBuild(currentAssets)
|
|
476
|
+
: await distService?.buildNewAssets();
|
|
477
|
+
if (newAssets) {
|
|
478
|
+
const updateResult = await miAPI?.updateAssets(newAssets);
|
|
479
|
+
if (updateResult?.status === 'OK') {
|
|
480
|
+
const backupMeta = distService?.getBackupMeta();
|
|
481
|
+
const { lastBackupName: backupFilename, lastBackupHash: currentHash, lastBackupDate: backupDate, } = backupMeta || { lastBackupName: '', lastBackupHash: '', lastBackupDate: new Date().toISOString() };
|
|
482
|
+
this.server.ws.send('template:sync:response', {
|
|
483
|
+
syncedAt: new Date(backupDate),
|
|
484
|
+
currentHash,
|
|
485
|
+
backupFilename,
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
else {
|
|
489
|
+
this.server.ws.send('template:sync:response', { error: 'Failed to update assets' });
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
else {
|
|
493
|
+
this.server.ws.send('template:sync:response', { error: 'Failed to build new assets' });
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
else {
|
|
498
|
+
this.server.ws.send('template:sync:response', { error: 'Dist service or MiAPI is not defined' });
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
const cache = new memoryCache__namespace.Cache();
|
|
505
|
+
const testCacheUrlRegExp = /\.[a-z0-9]+$/i;
|
|
506
|
+
function initProxyCache(opts) {
|
|
507
|
+
const { devServer, ttl = 10 * 60 * 1000 } = opts;
|
|
508
|
+
devServer.cache = cache;
|
|
509
|
+
return (req, res, next) => {
|
|
510
|
+
const url = req.originalUrl || req.url || '';
|
|
511
|
+
if (testCacheUrlRegExp.test(url.split('?')[0] || '')) {
|
|
512
|
+
const cacheItem = cache.get(url);
|
|
513
|
+
if (cacheItem && devServer.config) {
|
|
514
|
+
devServer.config.logger.info(`Proxies request: ${req.method} ${url} -> Cache ${url}`);
|
|
515
|
+
for (const [header, value] of Object.entries(cacheItem.headers)) {
|
|
516
|
+
res.setHeader(header, value);
|
|
517
|
+
}
|
|
518
|
+
res.write(cacheItem.content);
|
|
519
|
+
res.end();
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
const end = res.end;
|
|
523
|
+
const write = res.write;
|
|
524
|
+
let buffer = Buffer.from('', 'utf8');
|
|
525
|
+
// Rewrite response method and get the content.
|
|
526
|
+
res.write = function (data, encoding, callback) {
|
|
527
|
+
if (!res.hasHeader(PROXY_HEADER)) {
|
|
528
|
+
return write.call(this, data, encoding, callback);
|
|
529
|
+
}
|
|
530
|
+
buffer = Buffer.concat([buffer, data]);
|
|
531
|
+
return true;
|
|
532
|
+
};
|
|
533
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
534
|
+
// @ts-ignore
|
|
535
|
+
res.end = function (chunk, encoding, cb) {
|
|
536
|
+
if (!res.hasHeader(PROXY_HEADER)) {
|
|
537
|
+
return end.call(this, chunk, encoding, cb);
|
|
538
|
+
}
|
|
539
|
+
if (typeof chunk === 'string') {
|
|
540
|
+
buffer = Buffer.concat([buffer, Buffer.from(chunk, encoding)]);
|
|
541
|
+
}
|
|
542
|
+
if (Buffer.isBuffer(chunk)) {
|
|
543
|
+
buffer = Buffer.concat([buffer, chunk]);
|
|
544
|
+
}
|
|
545
|
+
if (res.hasHeader(PROXY_HEADER)) {
|
|
546
|
+
devServer.config.logger?.info(`[Cached] ${url}`);
|
|
547
|
+
cache.put(url, { headers: res.getHeaders(), content: buffer }, ttl);
|
|
548
|
+
}
|
|
549
|
+
end.call(this, buffer, encoding, cb);
|
|
550
|
+
};
|
|
551
|
+
}
|
|
552
|
+
next();
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
const TEMPLATE_PART_PAGE_NAME = 'pageName';
|
|
557
|
+
const TEMPLATE_PART_DATE = 'date';
|
|
558
|
+
const DIRNAME = path__namespace.dirname((typeof __filename !== 'undefined' && __filename) || url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.src || new URL('plugin-24dd0a43.js', document.baseURI).href))));
|
|
559
|
+
const pluginPath = path__namespace.resolve(DIRNAME, '..', '..');
|
|
560
|
+
const node_modules_path = path__namespace.resolve(pluginPath, '..', '..');
|
|
561
|
+
const metaDirName = '.pp-dev-meta';
|
|
562
|
+
const metaDirPath = path__namespace.resolve(node_modules_path, metaDirName);
|
|
563
|
+
const metaFilePath = path__namespace.resolve(metaDirPath, 'sync-service.meta.json');
|
|
564
|
+
class DistService {
|
|
565
|
+
backupFolder;
|
|
566
|
+
backupNameTemplate;
|
|
567
|
+
dateFormat;
|
|
568
|
+
pageName;
|
|
569
|
+
currentMeta = null;
|
|
570
|
+
constructor(pageName, syncOptions) {
|
|
571
|
+
const { backupFolder = path__namespace.resolve(process__namespace.cwd(), 'backups'), backupNameTemplate = `{${TEMPLATE_PART_PAGE_NAME}}-{${TEMPLATE_PART_DATE}}.zip`, dateFormat = (date) => date.toISOString().replace(/:/g, '-').replace(/\..*$/, ''), } = syncOptions || {};
|
|
572
|
+
this.backupFolder = backupFolder;
|
|
573
|
+
this.backupNameTemplate = backupNameTemplate;
|
|
574
|
+
this.dateFormat = dateFormat;
|
|
575
|
+
this.pageName = pageName;
|
|
576
|
+
this.syncMeta();
|
|
577
|
+
}
|
|
578
|
+
async checkMeta() {
|
|
579
|
+
try {
|
|
580
|
+
await fs.promises.stat(metaDirPath);
|
|
581
|
+
}
|
|
582
|
+
catch {
|
|
583
|
+
await fs.promises.mkdir(metaDirPath);
|
|
584
|
+
}
|
|
585
|
+
try {
|
|
586
|
+
await fs.promises.stat(this.backupFolder);
|
|
587
|
+
}
|
|
588
|
+
catch {
|
|
589
|
+
await fs.promises.mkdir(this.backupFolder);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
async readMetaFile() {
|
|
593
|
+
await this.checkMeta();
|
|
594
|
+
return await fs.promises
|
|
595
|
+
.readFile(metaFilePath, {
|
|
596
|
+
encoding: 'utf-8',
|
|
597
|
+
})
|
|
598
|
+
.catch(() => '{}');
|
|
599
|
+
}
|
|
600
|
+
async writeMetaFile(meta) {
|
|
601
|
+
await this.checkMeta();
|
|
602
|
+
return await fs.promises.writeFile(metaFilePath, JSON.stringify(meta, null, 2), {
|
|
603
|
+
encoding: 'utf-8',
|
|
604
|
+
});
|
|
605
|
+
}
|
|
606
|
+
async syncMeta() {
|
|
607
|
+
if (!this.currentMeta) {
|
|
608
|
+
this.currentMeta = JSON.parse(await this.readMetaFile());
|
|
609
|
+
}
|
|
610
|
+
else {
|
|
611
|
+
await this.writeMetaFile(this.currentMeta);
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
async getLatestSavedBackup() {
|
|
615
|
+
const { lastBackupName } = this.currentMeta;
|
|
616
|
+
if (!lastBackupName) {
|
|
617
|
+
return null;
|
|
618
|
+
}
|
|
619
|
+
const backupPath = path__namespace.resolve(this.backupFolder, lastBackupName);
|
|
620
|
+
try {
|
|
621
|
+
await fs.promises.stat(backupPath);
|
|
622
|
+
return backupPath;
|
|
623
|
+
}
|
|
624
|
+
catch {
|
|
625
|
+
return null;
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
backupName(pageName, date = new Date()) {
|
|
629
|
+
return this.backupNameTemplate
|
|
630
|
+
.replace(`{${TEMPLATE_PART_PAGE_NAME}}`, pageName)
|
|
631
|
+
.replace(`{${TEMPLATE_PART_DATE}}`, this.dateFormat(date));
|
|
632
|
+
}
|
|
633
|
+
getBackupMeta() {
|
|
634
|
+
return this.currentMeta;
|
|
635
|
+
}
|
|
636
|
+
async saveBackup(backupFile) {
|
|
637
|
+
const backupFileHash = crypto__namespace.createHash('md5').update(backupFile).digest('hex');
|
|
638
|
+
const lastSavedBackup = await this.getLatestSavedBackup();
|
|
639
|
+
if (lastSavedBackup) {
|
|
640
|
+
const { lastBackupHash } = this.currentMeta;
|
|
641
|
+
if (lastBackupHash === backupFileHash) {
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
const backupDate = new Date();
|
|
646
|
+
const filename = this.backupName(this.pageName, backupDate);
|
|
647
|
+
this.currentMeta.lastBackupName = filename;
|
|
648
|
+
this.currentMeta.lastBackupHash = backupFileHash;
|
|
649
|
+
this.currentMeta.lastBackupDate = backupDate.toISOString();
|
|
650
|
+
await this.syncMeta();
|
|
651
|
+
return await fs.promises.writeFile(path__namespace.resolve(this.backupFolder, filename), backupFile);
|
|
652
|
+
}
|
|
653
|
+
async buildNewAssets() {
|
|
654
|
+
const buildCommand = new Promise(function (resolve, reject) {
|
|
655
|
+
let data = '';
|
|
656
|
+
// Colorized log output with message about build start
|
|
657
|
+
console__namespace.log('\x1b[36m%s\x1b[0m', '[DistService] Build started');
|
|
658
|
+
const proc = child_process__namespace.spawn('node', [path__namespace.resolve(pluginPath, './bin/pp-dev.js'), 'build'], {
|
|
659
|
+
cwd: process__namespace.cwd(),
|
|
660
|
+
env: process__namespace.env,
|
|
661
|
+
stdio: 'inherit',
|
|
662
|
+
});
|
|
663
|
+
proc.on('message', (msg) => {
|
|
664
|
+
data += msg;
|
|
665
|
+
});
|
|
666
|
+
proc.on('close', (code) => {
|
|
667
|
+
if (code !== 0) {
|
|
668
|
+
reject(new Error(`build command exited with code ${code}`));
|
|
669
|
+
return;
|
|
670
|
+
}
|
|
671
|
+
resolve(data);
|
|
672
|
+
});
|
|
673
|
+
proc.on('error', (err) => {
|
|
674
|
+
reject(err);
|
|
675
|
+
});
|
|
676
|
+
});
|
|
677
|
+
try {
|
|
678
|
+
await buildCommand.finally(() => {
|
|
679
|
+
// Colorized log output with message about build end
|
|
680
|
+
console__namespace.log('\x1b[36m%s\x1b[0m', '[DistService] Build finished');
|
|
681
|
+
});
|
|
682
|
+
const assetFile = path__namespace.resolve(process__namespace.cwd(), `./dist-zip/${this.pageName}.zip`);
|
|
683
|
+
if (!(await fs.promises.stat(assetFile))) {
|
|
684
|
+
throw new Error(`File ${assetFile} not found`);
|
|
685
|
+
}
|
|
686
|
+
return await fs.promises.readFile(assetFile);
|
|
687
|
+
}
|
|
688
|
+
catch (e) {
|
|
689
|
+
console__namespace.log(e);
|
|
690
|
+
throw e;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
async saveBackupAndBuild(backupFile) {
|
|
694
|
+
await this.saveBackup(backupFile);
|
|
695
|
+
return await this.buildNewAssets();
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
function decodeContent(content, contentEncoding) {
|
|
700
|
+
switch (contentEncoding) {
|
|
701
|
+
case 'gzip':
|
|
702
|
+
return zlib.unzipSync(content);
|
|
703
|
+
case 'br':
|
|
704
|
+
return zlib.brotliDecompressSync(content);
|
|
705
|
+
case 'deflate':
|
|
706
|
+
return zlib.deflateSync(content);
|
|
707
|
+
default:
|
|
708
|
+
return content;
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
function encodeContent(content, contentEncoding) {
|
|
712
|
+
switch (contentEncoding) {
|
|
713
|
+
case 'gzip':
|
|
714
|
+
return zlib.gzipSync(content);
|
|
715
|
+
case 'br':
|
|
716
|
+
return zlib.brotliCompressSync(content);
|
|
717
|
+
case 'deflate':
|
|
718
|
+
return zlib.inflateSync(content);
|
|
719
|
+
default:
|
|
720
|
+
return content;
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
/**
|
|
725
|
+
* Rewrite response middleware
|
|
726
|
+
*
|
|
727
|
+
* @param predicate Check if need to rewrite response data
|
|
728
|
+
* @param rewrite Rewrite response content handler
|
|
729
|
+
*/
|
|
730
|
+
function initRewriteResponse(predicate, rewrite) {
|
|
731
|
+
return (req, res, next) => {
|
|
732
|
+
if (predicate(req.url ?? '', req, res)) {
|
|
733
|
+
const end = res.end;
|
|
734
|
+
const buffers = [];
|
|
735
|
+
res.write = function (body) {
|
|
736
|
+
buffers.push(body);
|
|
737
|
+
return true;
|
|
738
|
+
};
|
|
739
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
740
|
+
// @ts-ignore
|
|
741
|
+
res.end = function (chunk, encoding, cb) {
|
|
742
|
+
if (typeof chunk === 'string') {
|
|
743
|
+
buffers.push(Buffer.from(chunk));
|
|
744
|
+
}
|
|
745
|
+
const contentEncoding = res.getHeader('content-encoding');
|
|
746
|
+
const content = decodeContent(Buffer.from(Buffer.concat(buffers)), contentEncoding);
|
|
747
|
+
end.call(this, encodeContent(rewrite(content, req, res), contentEncoding), encoding, cb);
|
|
748
|
+
};
|
|
749
|
+
}
|
|
750
|
+
next();
|
|
751
|
+
};
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
function initPPRedirect(base, templateName) {
|
|
755
|
+
base = base.startsWith('/') ? base : `/${base}`;
|
|
756
|
+
base = base.endsWith('/') ? base : `${base}/`;
|
|
757
|
+
const baseWithoutTrailingSlash = base.endsWith('/') ? base.slice(0, -1) : base;
|
|
758
|
+
return (req, res, next) => {
|
|
759
|
+
const parsedUrl = new url.URL(req.url ?? '', 'http://localhost');
|
|
760
|
+
const { pathname, search } = parsedUrl;
|
|
761
|
+
const findPaths = ['/', baseWithoutTrailingSlash];
|
|
762
|
+
if (templateName) {
|
|
763
|
+
findPaths.push(`/pt/${templateName}`);
|
|
764
|
+
}
|
|
765
|
+
// Redirect from `/` and `/pt/${templateName}` and `${base}` (without a training slash) to portal page address
|
|
766
|
+
if (findPaths.includes(pathname)) {
|
|
767
|
+
const redirectUrl = `${base}${search}`;
|
|
768
|
+
return redirect(res, redirectUrl, 302);
|
|
769
|
+
}
|
|
770
|
+
next();
|
|
771
|
+
};
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
function initLoadPPData(applyUrlRegExp, mi, opts) {
|
|
775
|
+
const { templateLess = false, miHudLess = false, portalPageId } = opts;
|
|
776
|
+
return (req, res, next) => {
|
|
777
|
+
const isNeedTemplateLoad = !(templateLess && miHudLess);
|
|
778
|
+
const isApplyRequest = applyUrlRegExp.test(cutUrlParams(req.url ?? ''));
|
|
779
|
+
if (isNeedTemplateLoad && isApplyRequest) {
|
|
780
|
+
const headers = (req.headers ?? {});
|
|
781
|
+
const loadPageData = !templateLess && typeof portalPageId !== 'undefined'
|
|
782
|
+
? mi.getPageVariables(portalPageId, headers)
|
|
783
|
+
: mi.getPageTemplate(headers);
|
|
784
|
+
loadPageData
|
|
785
|
+
.then(() => {
|
|
786
|
+
next();
|
|
787
|
+
})
|
|
788
|
+
.catch((reason) => {
|
|
789
|
+
if (reason.response) {
|
|
790
|
+
return redirect(res, `/home?proxyRedirect=${encodeURIComponent('/')}`, 302);
|
|
791
|
+
}
|
|
792
|
+
next(reason);
|
|
793
|
+
});
|
|
794
|
+
}
|
|
795
|
+
else {
|
|
796
|
+
next();
|
|
797
|
+
}
|
|
798
|
+
};
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
function vitePPDev(options) {
|
|
802
|
+
const { templateName, templateLess = false, backendBaseURL, miHudLess = false, portalPageId, enableProxyCache = true, proxyCacheTTL = 10 * 60 * 1000, } = options || {};
|
|
803
|
+
// Avoid server caching for index.html file when first loading
|
|
804
|
+
let isFirstRequest = true;
|
|
805
|
+
return {
|
|
806
|
+
name: 'vite-pp-dev',
|
|
807
|
+
apply: 'serve',
|
|
808
|
+
config: (config) => {
|
|
809
|
+
config.clientInjectionPlugin = { backendBaseURL, portalPageId, templateLess };
|
|
810
|
+
return config;
|
|
811
|
+
},
|
|
812
|
+
transformIndexHtml: async (html, ctx) => {
|
|
813
|
+
const result = { html, tags: [] };
|
|
814
|
+
if (isFirstRequest) {
|
|
815
|
+
isFirstRequest = false;
|
|
816
|
+
result.tags.push({
|
|
817
|
+
tag: 'script',
|
|
818
|
+
injectTo: 'body',
|
|
819
|
+
children: `${Math.random()}`,
|
|
820
|
+
});
|
|
821
|
+
}
|
|
822
|
+
return result;
|
|
823
|
+
},
|
|
824
|
+
configureServer: (server) => {
|
|
825
|
+
let base = server.config.base;
|
|
826
|
+
if (!base.endsWith('/')) {
|
|
827
|
+
base += '/';
|
|
828
|
+
}
|
|
829
|
+
const baseWithoutTrailingSlash = base.substring(0, base.lastIndexOf('/'));
|
|
830
|
+
server.middlewares.use(initPPRedirect(base, templateName));
|
|
831
|
+
if (backendBaseURL) {
|
|
832
|
+
const baseUrlHost = new URL(backendBaseURL).host;
|
|
833
|
+
const mi = new MiAPI(backendBaseURL, {
|
|
834
|
+
headers: {
|
|
835
|
+
host: baseUrlHost,
|
|
836
|
+
referer: backendBaseURL,
|
|
837
|
+
origin: backendBaseURL.replace(/^(https?:\/\/)([^/]+)(\/.*)?$/i, '$1$2'),
|
|
838
|
+
},
|
|
839
|
+
portalPageId,
|
|
840
|
+
templateLess,
|
|
841
|
+
});
|
|
842
|
+
if (enableProxyCache) {
|
|
843
|
+
let ttl = +proxyCacheTTL;
|
|
844
|
+
if (!ttl || Number.isNaN(ttl) || ttl < 0) {
|
|
845
|
+
ttl = 10 * 60 * 1000; // 10 minutes
|
|
846
|
+
}
|
|
847
|
+
server.middlewares.use(initProxyCache({ devServer: server, ttl }));
|
|
848
|
+
}
|
|
849
|
+
server.middlewares.use(initProxy({
|
|
850
|
+
devServer: server,
|
|
851
|
+
baseURL: backendBaseURL,
|
|
852
|
+
proxyIgnore: ['/@vite', '/@metricinsights', '/@', baseWithoutTrailingSlash],
|
|
853
|
+
}));
|
|
854
|
+
const isIndexRegExp = new RegExp(`^((${base})|/)$`);
|
|
855
|
+
// Get portal page variables from the backend (also, redirect magic)
|
|
856
|
+
server.middlewares.use(initLoadPPData(isIndexRegExp, mi, options));
|
|
857
|
+
server.middlewares.use(initRewriteResponse((url) => {
|
|
858
|
+
return isIndexRegExp.test(cutUrlParams(url));
|
|
859
|
+
}, (response, req) => {
|
|
860
|
+
return Buffer.from(urlReplacer(baseUrlHost, req.headers.host ?? '', mi.buildPage(response, miHudLess)));
|
|
861
|
+
}));
|
|
862
|
+
const distService = new DistService(templateName);
|
|
863
|
+
new ClientService(server, { distService, miAPI: mi });
|
|
864
|
+
}
|
|
865
|
+
},
|
|
866
|
+
};
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
exports.MiAPI = MiAPI;
|
|
870
|
+
exports.cutUrlParams = cutUrlParams;
|
|
871
|
+
exports.initLoadPPData = initLoadPPData;
|
|
872
|
+
exports.initPPRedirect = initPPRedirect;
|
|
873
|
+
exports.initProxy = initProxy;
|
|
874
|
+
exports.initProxyCache = initProxyCache;
|
|
875
|
+
exports.initRewriteResponse = initRewriteResponse;
|
|
876
|
+
exports.urlReplacer = urlReplacer;
|
|
877
|
+
exports.vitePPDev = vitePPDev;
|
|
878
|
+
//# sourceMappingURL=plugin-24dd0a43.js.map
|