underpost 3.1.2 → 3.1.3
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/.github/workflows/npmpkg.ci.yml +15 -1
- package/CHANGELOG.md +42 -1
- package/CLI-HELP.md +8 -2
- package/README.md +6 -3
- package/bin/deploy.js +29 -102
- package/conf.js +1 -8
- package/jsdoc.json +1 -1
- package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +1 -1
- package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +1 -1
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/manifests/deployment/dd-test-development/deployment.yaml +2 -2
- package/package.json +2 -2
- package/scripts/ports-ls.sh +2 -0
- package/src/cli/index.js +8 -0
- package/src/cli/repository.js +37 -37
- package/src/cli/run.js +99 -40
- package/src/client/components/core/Alert.js +2 -2
- package/src/client/components/core/Docs.js +9 -2
- package/src/client/components/core/RichText.js +1 -2
- package/src/client/ssr/body/404.js +15 -11
- package/src/client/ssr/body/500.js +15 -11
- package/src/client/ssr/body/SwaggerDarkMode.js +285 -0
- package/src/client/ssr/offline/NoNetworkConnection.js +11 -10
- package/src/client/ssr/pages/Test.js +11 -10
- package/src/index.js +1 -1
- package/src/runtime/express/Express.js +8 -8
- package/src/server/auth.js +6 -5
- package/src/server/client-build-docs.js +44 -110
- package/src/server/client-build.js +29 -38
- package/src/server/conf.js +19 -15
- package/src/server/start.js +15 -8
package/src/index.js
CHANGED
|
@@ -165,14 +165,7 @@ class ExpressService {
|
|
|
165
165
|
});
|
|
166
166
|
}
|
|
167
167
|
|
|
168
|
-
//
|
|
169
|
-
if (fs.existsSync(swaggerJsonPath)) {
|
|
170
|
-
const swaggerDoc = JSON.parse(fs.readFileSync(swaggerJsonPath, 'utf8'));
|
|
171
|
-
const swaggerUiOptions = await buildSwaggerUiOptions();
|
|
172
|
-
app.use(swaggerPath, swaggerUi.serve, swaggerUi.setup(swaggerDoc, swaggerUiOptions));
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// Security and CORS
|
|
168
|
+
// Security and CORS — must run before swagger-ui so CSP headers are included in swagger responses
|
|
176
169
|
if (process.env.NODE_ENV === 'development' && useLocalSsl)
|
|
177
170
|
origins = origins.map((origin) => origin.replace('http', 'https'));
|
|
178
171
|
|
|
@@ -180,6 +173,13 @@ class ExpressService {
|
|
|
180
173
|
origin: origins,
|
|
181
174
|
});
|
|
182
175
|
|
|
176
|
+
// Swagger UI setup (after security middleware so responses carry correct CSP headers)
|
|
177
|
+
if (fs.existsSync(swaggerJsonPath)) {
|
|
178
|
+
const swaggerDoc = JSON.parse(fs.readFileSync(swaggerJsonPath, 'utf8'));
|
|
179
|
+
const swaggerUiOptions = await buildSwaggerUiOptions();
|
|
180
|
+
app.use(swaggerPath, swaggerUi.serve, swaggerUi.setup(swaggerDoc, swaggerUiOptions));
|
|
181
|
+
}
|
|
182
|
+
|
|
183
183
|
// Database and Valkey connections
|
|
184
184
|
if (db && apis) await DataBaseProvider.load({ apis, host, path, db });
|
|
185
185
|
|
package/src/server/auth.js
CHANGED
|
@@ -613,13 +613,13 @@ function applySecurity(app, opts = {}) {
|
|
|
613
613
|
frameAncestors: frameAncestors,
|
|
614
614
|
imgSrc: ["'self'", 'data:', httpDirective, 'https:', 'blob:'],
|
|
615
615
|
objectSrc: ["'none'"],
|
|
616
|
-
// script-src and script-src-elem
|
|
617
|
-
|
|
616
|
+
// script-src and script-src-elem: use 'unsafe-inline' for swagger (no nonce, otherwise
|
|
617
|
+
// the nonce causes 'unsafe-inline' to be ignored per CSP3 spec), nonce for everything else.
|
|
618
|
+
scriptSrc: ["'self'", (req, res) => (res.locals.isSwagger ? "'unsafe-inline'" : `'nonce-${res.locals.nonce}'`)],
|
|
619
|
+
scriptSrcElem: [
|
|
618
620
|
"'self'",
|
|
619
|
-
(req, res) => `'nonce-${res.locals.nonce}'
|
|
620
|
-
(req, res) => (res.locals.isSwagger ? "'unsafe-inline'" : ''),
|
|
621
|
+
(req, res) => (res.locals.isSwagger ? "'unsafe-inline'" : `'nonce-${res.locals.nonce}'`),
|
|
621
622
|
],
|
|
622
|
-
scriptSrcElem: ["'self'", (req, res) => `'nonce-${res.locals.nonce}'`],
|
|
623
623
|
// style-src: avoid 'unsafe-inline' when possible; if you must inline styles,
|
|
624
624
|
// use a nonce for them too (or hash).
|
|
625
625
|
styleSrc: [
|
|
@@ -627,6 +627,7 @@ function applySecurity(app, opts = {}) {
|
|
|
627
627
|
httpDirective,
|
|
628
628
|
(req, res) => (res.locals.isSwagger ? "'unsafe-inline'" : `'nonce-${res.locals.nonce}'`),
|
|
629
629
|
],
|
|
630
|
+
styleSrcAttr: [(req, res) => (res.locals.isSwagger ? "'unsafe-inline'" : "'none'")],
|
|
630
631
|
// deny plugins
|
|
631
632
|
objectSrc: ["'none'"],
|
|
632
633
|
},
|
|
@@ -332,56 +332,17 @@ const buildApiDocs = async ({
|
|
|
332
332
|
* @param {string} options.path - The base path for the documentation
|
|
333
333
|
* @param {Object} options.metadata - Metadata for the documentation
|
|
334
334
|
* @param {string} options.publicClientId - Client ID used to resolve the tutorials/references directory
|
|
335
|
+
* @param {Object} options.docs - Documentation config from server conf
|
|
336
|
+
* @param {string} options.docs.jsJsonPath - Path to the JSDoc JSON config file
|
|
335
337
|
*/
|
|
336
|
-
const buildJsDocs = async ({ host, path, metadata = {}, publicClientId }) => {
|
|
338
|
+
const buildJsDocs = async ({ host, path, metadata = {}, publicClientId, docs }) => {
|
|
337
339
|
const logger = loggerFactory(import.meta);
|
|
338
340
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
for (const deployId of fs.readdirSync(privateConfBase)) {
|
|
344
|
-
const candidatePath = `./jsdoc.${deployId}.json`;
|
|
345
|
-
if (!fs.existsSync(candidatePath)) continue;
|
|
346
|
-
|
|
347
|
-
// Check if this deployId's server config contains the current host
|
|
348
|
-
const serverConfPath = `${privateConfBase}/${deployId}/conf.server.json`;
|
|
349
|
-
if (fs.existsSync(serverConfPath)) {
|
|
350
|
-
try {
|
|
351
|
-
const serverConf = JSON.parse(fs.readFileSync(serverConfPath, 'utf8'));
|
|
352
|
-
if (serverConf[host]) {
|
|
353
|
-
customJsDocPath = candidatePath;
|
|
354
|
-
logger.info('detected custom jsdoc config', { deployId, host, path: candidatePath });
|
|
355
|
-
break;
|
|
356
|
-
}
|
|
357
|
-
} catch (e) {
|
|
358
|
-
// skip invalid JSON
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
// Fallback: also check dev server configs
|
|
363
|
-
if (!customJsDocPath) {
|
|
364
|
-
const devConfFiles = fs
|
|
365
|
-
.readdirSync(`${privateConfBase}/${deployId}`)
|
|
366
|
-
.filter((f) => f.match(/^conf\.server\.dev\..*\.json$/));
|
|
367
|
-
for (const devFile of devConfFiles) {
|
|
368
|
-
try {
|
|
369
|
-
const devConf = JSON.parse(fs.readFileSync(`${privateConfBase}/${deployId}/${devFile}`, 'utf8'));
|
|
370
|
-
if (devConf[host]) {
|
|
371
|
-
customJsDocPath = candidatePath;
|
|
372
|
-
logger.info('detected custom jsdoc config (dev)', { deployId, host, path: candidatePath });
|
|
373
|
-
break;
|
|
374
|
-
}
|
|
375
|
-
} catch (e) {
|
|
376
|
-
// skip invalid JSON
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
if (customJsDocPath) break;
|
|
381
|
-
}
|
|
341
|
+
const jsDocSourcePath = docs.jsJsonPath;
|
|
342
|
+
if (!fs.existsSync(jsDocSourcePath)) {
|
|
343
|
+
logger.warn('jsdoc config not found, skipping', jsDocSourcePath);
|
|
344
|
+
return;
|
|
382
345
|
}
|
|
383
|
-
|
|
384
|
-
const jsDocSourcePath = customJsDocPath || `./jsdoc.json`;
|
|
385
346
|
const jsDocsConfig = JSON.parse(fs.readFileSync(jsDocSourcePath, 'utf8'));
|
|
386
347
|
logger.info('using jsdoc config', jsDocSourcePath);
|
|
387
348
|
|
|
@@ -391,22 +352,14 @@ const buildJsDocs = async ({ host, path, metadata = {}, publicClientId }) => {
|
|
|
391
352
|
|
|
392
353
|
const tutorialsPath = `./src/client/public/${publicClientId}/docs/references`;
|
|
393
354
|
|
|
394
|
-
|
|
395
|
-
const includesHardhat =
|
|
396
|
-
jsDocsConfig.source &&
|
|
397
|
-
Array.isArray(jsDocsConfig.source.include) &&
|
|
398
|
-
jsDocsConfig.source.include.some((p) => p.includes('hardhat/'));
|
|
399
|
-
if (includesHardhat && fs.existsSync(`./hardhat`)) {
|
|
355
|
+
if (Array.isArray(docs.references) && docs.references.length > 0) {
|
|
400
356
|
fs.mkdirSync(tutorialsPath, { recursive: true });
|
|
401
|
-
const
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
if (fs.existsSync(hardhatWhitePaperPath)) {
|
|
408
|
-
fs.copySync(hardhatWhitePaperPath, `${tutorialsPath}/White Paper.md`);
|
|
409
|
-
logger.info('copied hardhat WHITE-PAPER.md to tutorials references');
|
|
357
|
+
for (const refPath of docs.references) {
|
|
358
|
+
if (fs.existsSync(refPath)) {
|
|
359
|
+
const fileName = refPath.split('/').pop();
|
|
360
|
+
fs.copySync(refPath, `${tutorialsPath}/${fileName}`);
|
|
361
|
+
logger.info('copied reference to tutorials', refPath);
|
|
362
|
+
}
|
|
410
363
|
}
|
|
411
364
|
}
|
|
412
365
|
|
|
@@ -420,10 +373,10 @@ const buildJsDocs = async ({ host, path, metadata = {}, publicClientId }) => {
|
|
|
420
373
|
delete jsDocsConfig.opts.tutorials;
|
|
421
374
|
}
|
|
422
375
|
|
|
423
|
-
fs.writeFileSync(
|
|
376
|
+
fs.writeFileSync(jsDocSourcePath, JSON.stringify(jsDocsConfig, null, 4), 'utf8');
|
|
424
377
|
logger.warn('build jsdoc view', jsDocsConfig.opts.destination);
|
|
425
378
|
|
|
426
|
-
shellExec(`
|
|
379
|
+
shellExec(`npx jsdoc -c ${jsDocSourcePath}`, { silent: true });
|
|
427
380
|
};
|
|
428
381
|
|
|
429
382
|
/**
|
|
@@ -433,58 +386,37 @@ const buildJsDocs = async ({ host, path, metadata = {}, publicClientId }) => {
|
|
|
433
386
|
* @param {Object} options - Coverage build options
|
|
434
387
|
* @param {string} options.host - The hostname for the coverage
|
|
435
388
|
* @param {string} options.path - The base path for the coverage
|
|
389
|
+
* @param {Object} options.docs - Documentation config from server conf
|
|
390
|
+
* @param {string} options.docs.coveragePath - Directory where to run npm run coverage
|
|
436
391
|
*/
|
|
437
|
-
const buildCoverage = async ({ host, path }) => {
|
|
392
|
+
const buildCoverage = async ({ host, path, docs }) => {
|
|
438
393
|
const logger = loggerFactory(import.meta);
|
|
439
|
-
const
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
shellExec(`npm test`);
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
const coverageBuildPath = `${jsDocsConfig.opts.destination}coverage`;
|
|
446
|
-
fs.mkdirSync(coverageBuildPath, { recursive: true });
|
|
447
|
-
fs.copySync(`./coverage`, coverageBuildPath);
|
|
448
|
-
|
|
449
|
-
logger.warn('build coverage', coverageBuildPath);
|
|
394
|
+
const jsDocSourcePath = docs.jsJsonPath;
|
|
395
|
+
const jsDocsConfig = JSON.parse(fs.readFileSync(jsDocSourcePath, 'utf8'));
|
|
396
|
+
const coveragePath = docs.coveragePath;
|
|
450
397
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
if (hardhatPkg.scripts && hardhatPkg.scripts.coverage) {
|
|
463
|
-
logger.info('generating hardhat coverage report');
|
|
464
|
-
shellExec(`cd ./hardhat && npx hardhat coverage`, { silent: true });
|
|
465
|
-
if (fs.existsSync(hardhatCoveragePath) && fs.readdirSync(hardhatCoveragePath).length > 0) {
|
|
466
|
-
const hardhatCoverageBuildPath = `${jsDocsConfig.opts.destination}hardhat-coverage`;
|
|
467
|
-
fs.mkdirSync(hardhatCoverageBuildPath, { recursive: true });
|
|
468
|
-
fs.copySync(hardhatCoveragePath, hardhatCoverageBuildPath);
|
|
469
|
-
logger.warn('build hardhat coverage (generated)', hardhatCoverageBuildPath);
|
|
470
|
-
}
|
|
398
|
+
const coverageOutputPath = `${coveragePath}/coverage`;
|
|
399
|
+
if (!fs.existsSync(coverageOutputPath)) {
|
|
400
|
+
const pkgPath = `${coveragePath}/package.json`;
|
|
401
|
+
if (fs.existsSync(pkgPath)) {
|
|
402
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
403
|
+
if (pkg.scripts && pkg.scripts.coverage) {
|
|
404
|
+
logger.info('generating coverage report', coveragePath);
|
|
405
|
+
shellExec(`cd ${coveragePath} && npm run coverage`, { silent: true });
|
|
406
|
+
} else if (pkg.scripts && pkg.scripts.test) {
|
|
407
|
+
logger.info('generating coverage via test', coveragePath);
|
|
408
|
+
shellExec(`cd ${coveragePath} && npm test`, { silent: true });
|
|
471
409
|
}
|
|
472
|
-
} catch (e) {
|
|
473
|
-
logger.warn('hardhat coverage generation skipped', e.message);
|
|
474
410
|
}
|
|
475
411
|
}
|
|
476
412
|
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
logger.
|
|
484
|
-
}
|
|
485
|
-
if (fs.existsSync(hardhatWhitePaperPath)) {
|
|
486
|
-
fs.copySync(hardhatWhitePaperPath, `${docsDestBase}hardhat-WHITE-PAPER.md`);
|
|
487
|
-
logger.info('copied hardhat WHITE-PAPER.md to docs');
|
|
413
|
+
if (fs.existsSync(coverageOutputPath) && fs.readdirSync(coverageOutputPath).length > 0) {
|
|
414
|
+
const coverageBuildPath = `${jsDocsConfig.opts.destination}coverage`;
|
|
415
|
+
fs.mkdirSync(coverageBuildPath, { recursive: true });
|
|
416
|
+
fs.copySync(coverageOutputPath, coverageBuildPath);
|
|
417
|
+
logger.warn('build coverage', coverageBuildPath);
|
|
418
|
+
} else {
|
|
419
|
+
logger.warn('no coverage output found, skipping', coverageOutputPath);
|
|
488
420
|
}
|
|
489
421
|
};
|
|
490
422
|
|
|
@@ -501,6 +433,7 @@ const buildCoverage = async ({ host, path }) => {
|
|
|
501
433
|
* @param {string} options.publicClientId - Client ID for the public documentation
|
|
502
434
|
* @param {string} options.rootClientPath - Root path for client files
|
|
503
435
|
* @param {Object} options.packageData - Package.json data
|
|
436
|
+
* @param {Object} options.docs - Documentation config from server conf
|
|
504
437
|
*/
|
|
505
438
|
const buildDocs = async ({
|
|
506
439
|
host,
|
|
@@ -511,9 +444,10 @@ const buildDocs = async ({
|
|
|
511
444
|
publicClientId,
|
|
512
445
|
rootClientPath,
|
|
513
446
|
packageData,
|
|
447
|
+
docs,
|
|
514
448
|
}) => {
|
|
515
|
-
await buildJsDocs({ host, path, metadata, publicClientId });
|
|
516
|
-
await buildCoverage({ host, path });
|
|
449
|
+
await buildJsDocs({ host, path, metadata, publicClientId, docs });
|
|
450
|
+
await buildCoverage({ host, path, docs });
|
|
517
451
|
await buildApiDocs({
|
|
518
452
|
host,
|
|
519
453
|
path,
|
|
@@ -230,16 +230,28 @@ const defaultSitemapXsl = `<?xml version="1.0" encoding="UTF-8"?>
|
|
|
230
230
|
* @function buildClient
|
|
231
231
|
* @memberof clientBuild
|
|
232
232
|
* @param {Object} options - Options for the build process.
|
|
233
|
+
* @param {string} options.deployId - The deployment ID for which to build the client.
|
|
233
234
|
* @param {Array} options.liveClientBuildPaths - List of paths to build incrementally.
|
|
234
235
|
* @param {Array} options.instances - List of instances to build.
|
|
235
236
|
* @param {boolean} options.buildZip - Whether to create zip files of the builds.
|
|
237
|
+
* @param {boolean} options.fullBuild - Whether to perform a full build.
|
|
238
|
+
* @param {boolean} options.iconsBuild - Whether to build icons.
|
|
236
239
|
* @returns {Promise<void>} - Promise that resolves when the build is complete.
|
|
237
240
|
* @throws {Error} - If the build fails.
|
|
238
241
|
* @memberof clientBuild
|
|
239
242
|
*/
|
|
240
|
-
const buildClient = async (
|
|
243
|
+
const buildClient = async (
|
|
244
|
+
options = {
|
|
245
|
+
deployId: '',
|
|
246
|
+
liveClientBuildPaths: [],
|
|
247
|
+
instances: [],
|
|
248
|
+
buildZip: false,
|
|
249
|
+
fullBuild: false,
|
|
250
|
+
iconsBuild: false,
|
|
251
|
+
},
|
|
252
|
+
) => {
|
|
241
253
|
const logger = loggerFactory(import.meta);
|
|
242
|
-
const deployId = process.env.DEPLOY_ID;
|
|
254
|
+
const deployId = options.deployId || process.env.DEPLOY_ID;
|
|
243
255
|
const confClient = readConfJson(deployId, 'client');
|
|
244
256
|
const confServer = readConfJson(deployId, 'server', { loadReplicas: true });
|
|
245
257
|
const confSSR = readConfJson(deployId, 'ssr');
|
|
@@ -373,17 +385,14 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [],
|
|
|
373
385
|
client,
|
|
374
386
|
directory,
|
|
375
387
|
disabledRebuild,
|
|
376
|
-
minifyBuild,
|
|
377
388
|
db,
|
|
378
389
|
redirect,
|
|
379
390
|
apis,
|
|
380
|
-
iconsBuild,
|
|
381
|
-
docsBuild,
|
|
382
391
|
apiBaseProxyPath,
|
|
383
392
|
apiBaseHost,
|
|
384
393
|
ttiLoadTimeLimit,
|
|
385
394
|
singleReplica,
|
|
386
|
-
|
|
395
|
+
docs,
|
|
387
396
|
} = confServer[host][path];
|
|
388
397
|
if (singleReplica) continue;
|
|
389
398
|
if (!confClient[client]) confClient[client] = {};
|
|
@@ -397,9 +406,10 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [],
|
|
|
397
406
|
const rootClientPath = directory ? directory : `${publicPath}/${host}${path}`;
|
|
398
407
|
const port = newInstance(currentPort);
|
|
399
408
|
const publicClientId = publicRef ? publicRef : client;
|
|
400
|
-
const fullBuildEnabled =
|
|
409
|
+
const fullBuildEnabled = options.fullBuild && !enableLiveRebuild;
|
|
401
410
|
// const baseHost = process.env.NODE_ENV === 'production' ? `https://${host}` : `http://localhost:${port}`;
|
|
402
411
|
const baseHost = process.env.NODE_ENV === 'production' ? `https://${host}` : ``;
|
|
412
|
+
const minifyBuild = process.env.NODE_ENV === 'production';
|
|
403
413
|
// ''; // process.env.NODE_ENV === 'production' ? `https://${host}` : ``;
|
|
404
414
|
currentPort++;
|
|
405
415
|
|
|
@@ -421,7 +431,7 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [],
|
|
|
421
431
|
rootClientPath,
|
|
422
432
|
acmeChallengeFullPath,
|
|
423
433
|
publicClientId,
|
|
424
|
-
iconsBuild,
|
|
434
|
+
iconsBuild: options.iconsBuild,
|
|
425
435
|
metadata,
|
|
426
436
|
publicCopyNonExistingFiles,
|
|
427
437
|
});
|
|
@@ -445,11 +455,7 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [],
|
|
|
445
455
|
'components',
|
|
446
456
|
baseHost,
|
|
447
457
|
);
|
|
448
|
-
fs.writeFileSync(
|
|
449
|
-
jsPublicPath,
|
|
450
|
-
minifyBuild || process.env.NODE_ENV === 'production' ? UglifyJS.minify(jsSrc).code : jsSrc,
|
|
451
|
-
'utf8',
|
|
452
|
-
);
|
|
458
|
+
fs.writeFileSync(jsPublicPath, minifyBuild ? UglifyJS.minify(jsSrc).code : jsSrc, 'utf8');
|
|
453
459
|
}
|
|
454
460
|
}
|
|
455
461
|
|
|
@@ -471,11 +477,7 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [],
|
|
|
471
477
|
'services',
|
|
472
478
|
baseHost,
|
|
473
479
|
);
|
|
474
|
-
fs.writeFileSync(
|
|
475
|
-
jsPublicPath,
|
|
476
|
-
minifyBuild || process.env.NODE_ENV === 'production' ? UglifyJS.minify(jsSrc).code : jsSrc,
|
|
477
|
-
'utf8',
|
|
478
|
-
);
|
|
480
|
+
fs.writeFileSync(jsPublicPath, minifyBuild ? UglifyJS.minify(jsSrc).code : jsSrc, 'utf8');
|
|
479
481
|
}
|
|
480
482
|
}
|
|
481
483
|
|
|
@@ -493,11 +495,7 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [],
|
|
|
493
495
|
'services',
|
|
494
496
|
baseHost,
|
|
495
497
|
);
|
|
496
|
-
fs.writeFileSync(
|
|
497
|
-
jsPublicPath,
|
|
498
|
-
minifyBuild || process.env.NODE_ENV === 'production' ? UglifyJS.minify(jsSrc).code : jsSrc,
|
|
499
|
-
'utf8',
|
|
500
|
-
);
|
|
498
|
+
fs.writeFileSync(jsPublicPath, minifyBuild ? UglifyJS.minify(jsSrc).code : jsSrc, 'utf8');
|
|
501
499
|
}
|
|
502
500
|
}
|
|
503
501
|
}
|
|
@@ -517,11 +515,7 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [],
|
|
|
517
515
|
if (!(enableLiveRebuild && !options.liveClientBuildPaths.find((p) => p.srcBuildPath === jsSrcPath))) {
|
|
518
516
|
const jsSrc = viewFormatted(await srcFormatted(fs.readFileSync(jsSrcPath, 'utf8')), dists, path, baseHost);
|
|
519
517
|
|
|
520
|
-
fs.writeFileSync(
|
|
521
|
-
jsPublicPath,
|
|
522
|
-
minifyBuild || process.env.NODE_ENV === 'production' ? UglifyJS.minify(jsSrc).code : jsSrc,
|
|
523
|
-
'utf8',
|
|
524
|
-
);
|
|
518
|
+
fs.writeFileSync(jsPublicPath, minifyBuild ? UglifyJS.minify(jsSrc).code : jsSrc, 'utf8');
|
|
525
519
|
}
|
|
526
520
|
|
|
527
521
|
if (
|
|
@@ -548,11 +542,7 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [],
|
|
|
548
542
|
baseHost,
|
|
549
543
|
);
|
|
550
544
|
|
|
551
|
-
fs.writeFileSync(
|
|
552
|
-
`${buildPath}${buildId}.js`,
|
|
553
|
-
minifyBuild || process.env.NODE_ENV === 'production' ? UglifyJS.minify(jsSrc).code : jsSrc,
|
|
554
|
-
'utf8',
|
|
555
|
-
);
|
|
545
|
+
fs.writeFileSync(`${buildPath}${buildId}.js`, minifyBuild ? UglifyJS.minify(jsSrc).code : jsSrc, 'utf8');
|
|
556
546
|
const title = metadata.title ? metadata.title : title;
|
|
557
547
|
|
|
558
548
|
const canonicalURL = `https://${host}${path}${
|
|
@@ -689,7 +679,7 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [],
|
|
|
689
679
|
|
|
690
680
|
fs.writeFileSync(
|
|
691
681
|
`${buildPath}index.html`,
|
|
692
|
-
minifyBuild
|
|
682
|
+
minifyBuild
|
|
693
683
|
? await minify(htmlSrc, {
|
|
694
684
|
minifyCSS: true,
|
|
695
685
|
minifyJS: true,
|
|
@@ -739,7 +729,7 @@ Sitemap: ${sitemapBaseUrl}/sitemap.xml`,
|
|
|
739
729
|
);
|
|
740
730
|
}
|
|
741
731
|
|
|
742
|
-
if (fullBuildEnabled &&
|
|
732
|
+
if (fullBuildEnabled && docs) {
|
|
743
733
|
await buildDocs({
|
|
744
734
|
host,
|
|
745
735
|
path,
|
|
@@ -749,13 +739,14 @@ Sitemap: ${sitemapBaseUrl}/sitemap.xml`,
|
|
|
749
739
|
publicClientId,
|
|
750
740
|
rootClientPath,
|
|
751
741
|
packageData,
|
|
742
|
+
docs,
|
|
752
743
|
});
|
|
753
744
|
}
|
|
754
745
|
|
|
755
746
|
if (client) {
|
|
756
747
|
let PRE_CACHED_RESOURCES = [];
|
|
757
748
|
|
|
758
|
-
if (views &&
|
|
749
|
+
if (views && fs.existsSync(`${rootClientPath}/sw.js`)) {
|
|
759
750
|
PRE_CACHED_RESOURCES = await fs.readdir(rootClientPath, { recursive: true });
|
|
760
751
|
PRE_CACHED_RESOURCES = views
|
|
761
752
|
.map((view) => `${path === '/' ? '' : path}${view.path}`)
|
|
@@ -774,7 +765,7 @@ Sitemap: ${sitemapBaseUrl}/sitemap.xml`,
|
|
|
774
765
|
const htmlSrc = Render({
|
|
775
766
|
title: page.title,
|
|
776
767
|
ssrPath,
|
|
777
|
-
ssrHeadComponents: '',
|
|
768
|
+
ssrHeadComponents: '<base target="_top">',
|
|
778
769
|
ssrBodyComponents: SsrComponent(),
|
|
779
770
|
renderPayload: {
|
|
780
771
|
apiBaseProxyPath,
|
|
@@ -802,7 +793,7 @@ Sitemap: ${sitemapBaseUrl}/sitemap.xml`,
|
|
|
802
793
|
|
|
803
794
|
fs.writeFileSync(
|
|
804
795
|
buildHtmlPath,
|
|
805
|
-
minifyBuild
|
|
796
|
+
minifyBuild
|
|
806
797
|
? await minify(htmlSrc, {
|
|
807
798
|
minifyCSS: true,
|
|
808
799
|
minifyJS: true,
|
package/src/server/conf.js
CHANGED
|
@@ -1275,18 +1275,6 @@ const awaitDeployMonitor = async (init = false, deltaMs = 1000) => {
|
|
|
1275
1275
|
if (Underpost.env.get('await-deploy')) return await awaitDeployMonitor();
|
|
1276
1276
|
};
|
|
1277
1277
|
|
|
1278
|
-
/**
|
|
1279
|
-
* @method getCronBackUpFolder
|
|
1280
|
-
* @description Gets the cron back up folder.
|
|
1281
|
-
* @param {string} host - The host.
|
|
1282
|
-
* @param {string} path - The path.
|
|
1283
|
-
* @returns {string} - The cron back up folder.
|
|
1284
|
-
* @memberof ServerConfBuilder
|
|
1285
|
-
*/
|
|
1286
|
-
const getCronBackUpFolder = (host = '', path = '') => {
|
|
1287
|
-
return `${host}${path.replace(/\\/g, '/').replace(`/`, '-')}`;
|
|
1288
|
-
};
|
|
1289
|
-
|
|
1290
1278
|
/**
|
|
1291
1279
|
* @method mergeFile
|
|
1292
1280
|
* @description Merges the file.
|
|
@@ -1499,8 +1487,25 @@ const buildCliDoc = (program, oldVersion, newVersion) => {
|
|
|
1499
1487
|
md = md.replaceAll(oldVersion, newVersion);
|
|
1500
1488
|
fs.writeFileSync(`./src/client/public/nexodev/docs/references/Command Line Interface.md`, md, 'utf8');
|
|
1501
1489
|
fs.writeFileSync(`./CLI-HELP.md`, md, 'utf8');
|
|
1502
|
-
|
|
1503
|
-
|
|
1490
|
+
|
|
1491
|
+
// Update README.md: replace version and CLI index section between comment tags
|
|
1492
|
+
let readme = fs.readFileSync(`./README.md`, 'utf8');
|
|
1493
|
+
readme = readme.replaceAll(oldVersion, newVersion);
|
|
1494
|
+
const cliStartTag = '<!-- cli-index-start -->';
|
|
1495
|
+
const cliEndTag = '<!-- cli-index-end -->';
|
|
1496
|
+
const startIdx = readme.indexOf(cliStartTag);
|
|
1497
|
+
const endIdx = readme.indexOf(cliEndTag);
|
|
1498
|
+
if (startIdx !== -1 && endIdx !== -1) {
|
|
1499
|
+
readme =
|
|
1500
|
+
readme.substring(0, startIdx) +
|
|
1501
|
+
cliStartTag +
|
|
1502
|
+
'\n' +
|
|
1503
|
+
baseOptions +
|
|
1504
|
+
'\n' +
|
|
1505
|
+
cliEndTag +
|
|
1506
|
+
readme.substring(endIdx + cliEndTag.length);
|
|
1507
|
+
}
|
|
1508
|
+
fs.writeFileSync('./README.md', readme, 'utf8');
|
|
1504
1509
|
};
|
|
1505
1510
|
|
|
1506
1511
|
/**
|
|
@@ -1743,7 +1748,6 @@ export {
|
|
|
1743
1748
|
getDataDeploy,
|
|
1744
1749
|
validateTemplatePath,
|
|
1745
1750
|
buildReplicaId,
|
|
1746
|
-
getCronBackUpFolder,
|
|
1747
1751
|
mergeFile,
|
|
1748
1752
|
getPathsSSR,
|
|
1749
1753
|
buildKindPorts,
|
package/src/server/start.js
CHANGED
|
@@ -147,18 +147,25 @@ class UnderpostStartUp {
|
|
|
147
147
|
* @param {string} deployId - The ID of the deployment.
|
|
148
148
|
* @param {string} env - The environment of the deployment.
|
|
149
149
|
* @param {Object} options - Options for the build.
|
|
150
|
+
* @param {boolean} options.skipPullBase - Whether to skip pulling the base code and use the current workspace code directly.
|
|
150
151
|
* @param {boolean} options.underpostQuicklyInstall - Whether to use underpost quickly install.
|
|
151
152
|
* @memberof UnderpostStartUp
|
|
152
153
|
*/
|
|
153
|
-
async build(
|
|
154
|
+
async build(
|
|
155
|
+
deployId = 'dd-default',
|
|
156
|
+
env = 'development',
|
|
157
|
+
options = { underpostQuicklyInstall: false, skipPullBase: false },
|
|
158
|
+
) {
|
|
154
159
|
const buildBasePath = `/home/dd`;
|
|
155
160
|
const repoName = `engine-${deployId.split('-')[1]}`;
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
161
|
+
if (!options.skipPullBase) {
|
|
162
|
+
shellExec(`cd ${buildBasePath} && underpost clone ${process.env.GITHUB_USERNAME}/${repoName}`);
|
|
163
|
+
shellExec(`mkdir -p ${buildBasePath}/engine`);
|
|
164
|
+
shellExec(`cd ${buildBasePath} && sudo cp -a ./${repoName}/. ./engine`);
|
|
165
|
+
shellExec(`cd ${buildBasePath} && sudo rm -rf ./${repoName}`);
|
|
166
|
+
shellExec(`cd ${buildBasePath}/engine && underpost clone ${process.env.GITHUB_USERNAME}/${repoName}-private`);
|
|
167
|
+
shellExec(`cd ${buildBasePath}/engine && sudo mv ./${repoName}-private ./engine-private`);
|
|
168
|
+
}
|
|
162
169
|
shellCd(`${buildBasePath}/engine`);
|
|
163
170
|
shellExec(options?.underpostQuicklyInstall ? `underpost install` : `npm install`);
|
|
164
171
|
shellExec(`node bin env ${deployId} ${env}`);
|
|
@@ -167,7 +174,7 @@ class UnderpostStartUp {
|
|
|
167
174
|
for (const itcScript of itcScripts)
|
|
168
175
|
if (itcScript.match(deployId)) shellExec(`node ./engine-private/itc-scripts/${itcScript}`);
|
|
169
176
|
}
|
|
170
|
-
|
|
177
|
+
shellExec(`node bin client ${deployId}`);
|
|
171
178
|
},
|
|
172
179
|
/**
|
|
173
180
|
* Runs a deployment.
|