@bluealba/platform-cli 0.3.0-feature-platform-cli-222 → 0.3.1-feature-platform-cli-prefix-221
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +311 -224
- package/package.json +1 -1
- package/templates/customization-ui-module-template/Dockerfile +4 -4
- package/templates/customization-ui-module-template/Dockerfile.development +1 -1
- package/templates/customization-ui-module-template/package.json +3 -3
- package/templates/customization-ui-module-template/tsconfig.json +1 -1
- package/templates/customization-ui-module-template/webpack.config.js +2 -2
- package/templates/platform-init-template/{core → {{platformName}}-core}/local/.env.example +1 -1
- package/templates/platform-init-template/{core/local/core-docker-compose.yml → {{platformName}}-core/local/{{platformName}}-core-docker-compose.yml} +5 -5
- package/templates/react-ui-module-template/Dockerfile +3 -3
- package/templates/react-ui-module-template/Dockerfile.development +1 -1
- package/templates/react-ui-module-template/package.json +1 -1
- package/templates/react-ui-module-template/src/Icon.tsx +1 -1
- /package/templates/customization-ui-module-template/src/{platform-customization-ui.tsx → {{platformName}}-customization-ui.tsx} +0 -0
- /package/templates/platform-init-template/{core → {{platformName}}-core}/.changeset/config.json +0 -0
- /package/templates/platform-init-template/{core → {{platformName}}-core}/.nvmrc +0 -0
- /package/templates/platform-init-template/{core → {{platformName}}-core}/.syncpackrc +0 -0
- /package/templates/platform-init-template/{core → {{platformName}}-core}/local/environment/pae-nestjs-gateway-service.env +0 -0
- /package/templates/platform-init-template/{core → {{platformName}}-core}/local/nginx.conf +0 -0
- /package/templates/platform-init-template/{core → {{platformName}}-core}/local/platform-docker-compose.yml +0 -0
- /package/templates/platform-init-template/{core → {{platformName}}-core}/local/ssl/cert.pem +0 -0
- /package/templates/platform-init-template/{core → {{platformName}}-core}/local/ssl/key.pem +0 -0
- /package/templates/platform-init-template/{core → {{platformName}}-core}/package.json +0 -0
- /package/templates/platform-init-template/{core → {{platformName}}-core}/packages-versions.json +0 -0
- /package/templates/platform-init-template/{core → {{platformName}}-core}/scripts/preinstall.mjs +0 -0
- /package/templates/platform-init-template/{core → {{platformName}}-core}/services/.gitkeep +0 -0
- /package/templates/platform-init-template/{core → {{platformName}}-core}/turbo.json +0 -0
- /package/templates/platform-init-template/{core → {{platformName}}-core}/ui/.gitkeep +0 -0
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { render } from "ink";
|
|
|
6
6
|
// src/app.tsx
|
|
7
7
|
import { createRequire } from "module";
|
|
8
8
|
import { useState as useState3, useCallback as useCallback2 } from "react";
|
|
9
|
-
import { Box as Box4, Text as
|
|
9
|
+
import { Box as Box4, Text as Text7, useApp, useInput } from "ink";
|
|
10
10
|
|
|
11
11
|
// src/components/prompt.tsx
|
|
12
12
|
import { Box, Text } from "ink";
|
|
@@ -54,53 +54,76 @@ var CommandPalette = React.memo(function CommandPalette2({ commands, selectedInd
|
|
|
54
54
|
});
|
|
55
55
|
|
|
56
56
|
// src/components/scrollback-history.tsx
|
|
57
|
-
import { Static, Text as
|
|
57
|
+
import { Static, Text as Text5 } from "ink";
|
|
58
58
|
|
|
59
59
|
// src/components/welcome-banner.tsx
|
|
60
|
+
import React3 from "react";
|
|
61
|
+
import { Box as Box3, Text as Text4 } from "ink";
|
|
62
|
+
|
|
63
|
+
// src/components/working-directory.tsx
|
|
60
64
|
import React2 from "react";
|
|
61
|
-
import {
|
|
65
|
+
import { Text as Text3 } from "ink";
|
|
66
|
+
import { cwd } from "process";
|
|
67
|
+
import { homedir } from "os";
|
|
62
68
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
69
|
+
function shortenPath(fullPath) {
|
|
70
|
+
const home = homedir();
|
|
71
|
+
return fullPath.startsWith(home) ? `~${fullPath.slice(home.length)}` : fullPath;
|
|
72
|
+
}
|
|
73
|
+
var WorkingDirectory = React2.memo(function WorkingDirectory2() {
|
|
74
|
+
const dir = shortenPath(cwd());
|
|
75
|
+
return /* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
|
|
76
|
+
" ",
|
|
77
|
+
/* @__PURE__ */ jsx3(Text3, { color: "cyan", children: "cwd:" }),
|
|
78
|
+
" ",
|
|
79
|
+
dir
|
|
80
|
+
] });
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// src/components/welcome-banner.tsx
|
|
84
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
63
85
|
var ASCII_ART = [
|
|
64
86
|
"|---. .---|",
|
|
65
87
|
"| \\/ |",
|
|
66
88
|
"| /\\ |",
|
|
67
89
|
"|---' '---|"
|
|
68
90
|
];
|
|
69
|
-
var WelcomeBanner =
|
|
70
|
-
return /* @__PURE__ */
|
|
71
|
-
/* @__PURE__ */
|
|
91
|
+
var WelcomeBanner = React3.memo(function WelcomeBanner2({ version: version2 }) {
|
|
92
|
+
return /* @__PURE__ */ jsxs4(Box3, { borderStyle: "round", flexDirection: "column", paddingX: 1, paddingY: 1, children: [
|
|
93
|
+
/* @__PURE__ */ jsxs4(Text4, { bold: true, color: "cyan", children: [
|
|
72
94
|
"Blue Alba Platform CLI v",
|
|
73
95
|
version2
|
|
74
96
|
] }),
|
|
75
|
-
/* @__PURE__ */
|
|
76
|
-
/* @__PURE__ */
|
|
77
|
-
/* @__PURE__ */
|
|
78
|
-
/* @__PURE__ */
|
|
79
|
-
/* @__PURE__ */
|
|
97
|
+
/* @__PURE__ */ jsxs4(Box3, { marginTop: 1, children: [
|
|
98
|
+
/* @__PURE__ */ jsx4(Box3, { flexDirection: "column", marginRight: 2, children: ASCII_ART.map((line, i) => /* @__PURE__ */ jsx4(Text4, { color: "yellow", children: line }, i)) }),
|
|
99
|
+
/* @__PURE__ */ jsxs4(Box3, { flexDirection: "column", justifyContent: "center", marginRight: 2, children: [
|
|
100
|
+
/* @__PURE__ */ jsx4(Text4, { bold: true, children: "Welcome to the" }),
|
|
101
|
+
/* @__PURE__ */ jsx4(Text4, { bold: true, children: "Blue Alba Platform!" })
|
|
80
102
|
] }),
|
|
81
|
-
/* @__PURE__ */
|
|
82
|
-
/* @__PURE__ */
|
|
83
|
-
/* @__PURE__ */
|
|
84
|
-
/* @__PURE__ */
|
|
103
|
+
/* @__PURE__ */ jsx4(Box3, { flexDirection: "column", children: ASCII_ART.map((_, i) => /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "\u2502" }, i)) }),
|
|
104
|
+
/* @__PURE__ */ jsxs4(Box3, { flexDirection: "column", marginLeft: 2, children: [
|
|
105
|
+
/* @__PURE__ */ jsx4(Text4, { bold: true, color: "cyan", children: "Tips for getting started" }),
|
|
106
|
+
/* @__PURE__ */ jsxs4(Text4, { children: [
|
|
85
107
|
"Run ",
|
|
86
|
-
/* @__PURE__ */
|
|
108
|
+
/* @__PURE__ */ jsx4(Text4, { color: "green", children: "/init" }),
|
|
87
109
|
" to start building a platform"
|
|
88
110
|
] })
|
|
89
111
|
] })
|
|
90
|
-
] })
|
|
112
|
+
] }),
|
|
113
|
+
/* @__PURE__ */ jsx4(WorkingDirectory, {})
|
|
91
114
|
] });
|
|
92
115
|
});
|
|
93
116
|
|
|
94
117
|
// src/components/scrollback-history.tsx
|
|
95
|
-
import { jsx as
|
|
118
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
96
119
|
function ScrollbackHistory({ items, version: version2 }) {
|
|
97
|
-
return /* @__PURE__ */
|
|
120
|
+
return /* @__PURE__ */ jsx5(Static, { items, children: (item) => item.kind === "banner" ? /* @__PURE__ */ jsx5(WelcomeBanner, { version: version2 }, item.id) : /* @__PURE__ */ jsx5(Text5, { children: item.line }, item.id) });
|
|
98
121
|
}
|
|
99
122
|
|
|
100
123
|
// src/components/spinner.tsx
|
|
101
124
|
import { useState, useEffect } from "react";
|
|
102
|
-
import { Text as
|
|
103
|
-
import { jsx as
|
|
125
|
+
import { Text as Text6 } from "ink";
|
|
126
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
104
127
|
var FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
105
128
|
var INTERVAL_MS = 80;
|
|
106
129
|
function Spinner({ label }) {
|
|
@@ -111,12 +134,12 @@ function Spinner({ label }) {
|
|
|
111
134
|
}, INTERVAL_MS);
|
|
112
135
|
return () => clearInterval(id);
|
|
113
136
|
}, []);
|
|
114
|
-
return /* @__PURE__ */
|
|
115
|
-
/* @__PURE__ */
|
|
137
|
+
return /* @__PURE__ */ jsxs5(Text6, { children: [
|
|
138
|
+
/* @__PURE__ */ jsxs5(Text6, { color: "cyan", children: [
|
|
116
139
|
FRAMES[frame],
|
|
117
140
|
" "
|
|
118
141
|
] }),
|
|
119
|
-
label && /* @__PURE__ */
|
|
142
|
+
label && /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: label })
|
|
120
143
|
] });
|
|
121
144
|
}
|
|
122
145
|
|
|
@@ -124,7 +147,7 @@ function Spinner({ label }) {
|
|
|
124
147
|
import { Fzf } from "fzf";
|
|
125
148
|
|
|
126
149
|
// src/commands/create-application/create-application.command.ts
|
|
127
|
-
import { join as
|
|
150
|
+
import { join as join11, resolve } from "path";
|
|
128
151
|
import { mkdir as mkdir2 } from "fs/promises";
|
|
129
152
|
|
|
130
153
|
// src/commands/create-application/scaffold-application-monorepo.ts
|
|
@@ -289,8 +312,8 @@ var nestjsServiceModuleTemplateDir = join6(
|
|
|
289
312
|
"templates",
|
|
290
313
|
"nestjs-service-module-template"
|
|
291
314
|
);
|
|
292
|
-
async function scaffoldNestjsService(serviceDir, organizationName, applicationName, applicationDisplayName, serviceBaseDir, logger) {
|
|
293
|
-
const serviceName = `${applicationName}-service`;
|
|
315
|
+
async function scaffoldNestjsService(serviceDir, organizationName, platformName, applicationName, applicationDisplayName, serviceBaseDir, logger) {
|
|
316
|
+
const serviceName = `${platformName}-${applicationName}-service`;
|
|
294
317
|
const serviceDisplayName = `${applicationDisplayName} Service`;
|
|
295
318
|
logger.log(`Creating NestJS service "${serviceName}"...`);
|
|
296
319
|
await applyTemplate(
|
|
@@ -321,33 +344,35 @@ async function addModuleEntry(bootstrapServiceDir, applicationName, entry, logge
|
|
|
321
344
|
}
|
|
322
345
|
|
|
323
346
|
// src/commands/create-application/module-entry-builders.ts
|
|
324
|
-
function buildServiceModuleEntry(organizationName, applicationName, applicationDisplayName) {
|
|
347
|
+
function buildServiceModuleEntry(organizationName, platformName, applicationName, applicationDisplayName) {
|
|
348
|
+
const serviceName = `${platformName}-${applicationName}-service`;
|
|
325
349
|
return {
|
|
326
|
-
name: `@${organizationName}/${
|
|
350
|
+
name: `@${organizationName}/${serviceName}`,
|
|
327
351
|
displayName: `${applicationDisplayName} Service`,
|
|
328
352
|
type: "service",
|
|
329
|
-
baseUrl: `/${
|
|
353
|
+
baseUrl: `/${serviceName}`,
|
|
330
354
|
service: {
|
|
331
|
-
host:
|
|
355
|
+
host: serviceName,
|
|
332
356
|
port: 80
|
|
333
357
|
},
|
|
334
358
|
dependsOn: []
|
|
335
359
|
};
|
|
336
360
|
}
|
|
337
|
-
function buildUiModuleEntry(organizationName, applicationName, applicationDisplayName) {
|
|
361
|
+
function buildUiModuleEntry(organizationName, platformName, applicationName, applicationDisplayName) {
|
|
362
|
+
const uiName = `${platformName}-${applicationName}-ui`;
|
|
338
363
|
return {
|
|
339
|
-
name: `@${organizationName}/${
|
|
364
|
+
name: `@${organizationName}/${uiName}`,
|
|
340
365
|
displayName: applicationDisplayName,
|
|
341
366
|
type: "app",
|
|
342
|
-
baseUrl: `/${
|
|
367
|
+
baseUrl: `/${uiName}`,
|
|
343
368
|
service: {
|
|
344
|
-
host:
|
|
369
|
+
host: uiName,
|
|
345
370
|
port: 80
|
|
346
371
|
},
|
|
347
372
|
ui: {
|
|
348
373
|
route: `/${applicationName}`,
|
|
349
374
|
mountAtSelector: "#pae-shell-ui-content",
|
|
350
|
-
bundleFile: `${organizationName}-${
|
|
375
|
+
bundleFile: `${organizationName}-${uiName}.js`,
|
|
351
376
|
customProps: {}
|
|
352
377
|
},
|
|
353
378
|
dependsOn: [`@bluealba/pae-shell-ui`]
|
|
@@ -357,9 +382,10 @@ function buildUiModuleEntry(organizationName, applicationName, applicationDispla
|
|
|
357
382
|
// src/commands/create-application/create-docker-compose.ts
|
|
358
383
|
import { writeFile as writeFile3 } from "fs/promises";
|
|
359
384
|
function buildBootstrapBlock(platformName, applicationName) {
|
|
360
|
-
|
|
385
|
+
const bootstrapName = `${platformName}-${applicationName}-bootstrap-service`;
|
|
386
|
+
return ` ${bootstrapName}:
|
|
361
387
|
build:
|
|
362
|
-
context: ../../${platformName}-${applicationName}/services/${
|
|
388
|
+
context: ../../${platformName}-${applicationName}/services/${bootstrapName}
|
|
363
389
|
dockerfile: Dockerfile.development
|
|
364
390
|
environment:
|
|
365
391
|
- NODE_TLS_REJECT_UNAUTHORIZED=0
|
|
@@ -376,9 +402,10 @@ function buildBootstrapBlock(platformName, applicationName) {
|
|
|
376
402
|
`;
|
|
377
403
|
}
|
|
378
404
|
function buildUiBlock(platformName, applicationName, uiPort) {
|
|
379
|
-
|
|
405
|
+
const uiName = `${platformName}-${applicationName}-ui`;
|
|
406
|
+
return ` ${uiName}:
|
|
380
407
|
build:
|
|
381
|
-
context: ../../${platformName}-${applicationName}/ui/${
|
|
408
|
+
context: ../../${platformName}-${applicationName}/ui/${uiName}
|
|
382
409
|
dockerfile: Dockerfile.development
|
|
383
410
|
ports:
|
|
384
411
|
- ${uiPort}:80
|
|
@@ -387,9 +414,10 @@ function buildUiBlock(platformName, applicationName, uiPort) {
|
|
|
387
414
|
`;
|
|
388
415
|
}
|
|
389
416
|
function buildBackendBlock(platformName, applicationName, servicePort) {
|
|
390
|
-
|
|
417
|
+
const serviceName = `${platformName}-${applicationName}-service`;
|
|
418
|
+
return ` ${serviceName}:
|
|
391
419
|
build:
|
|
392
|
-
context: ../../${platformName}-${applicationName}/services/${
|
|
420
|
+
context: ../../${platformName}-${applicationName}/services/${serviceName}
|
|
393
421
|
dockerfile: Dockerfile.development
|
|
394
422
|
args:
|
|
395
423
|
- BA_NPM_AUTH_TOKEN=$BA_NPM_AUTH_TOKEN
|
|
@@ -422,9 +450,8 @@ async function createDockerCompose(dockerComposePath, applicationName, platformN
|
|
|
422
450
|
// src/commands/create-application/port-allocator.ts
|
|
423
451
|
import { join as join8 } from "path";
|
|
424
452
|
import { readdir as readdir2, readFile as readFile3 } from "fs/promises";
|
|
425
|
-
async function getNextAvailablePort(
|
|
453
|
+
async function getNextAvailablePort(localDir) {
|
|
426
454
|
const allPorts = [];
|
|
427
|
-
const localDir = join8(rootDir, "core", "local");
|
|
428
455
|
try {
|
|
429
456
|
const files = await readdir2(localDir);
|
|
430
457
|
const ymlFiles = files.filter((f) => f.endsWith(".yml") || f.endsWith(".yaml"));
|
|
@@ -449,32 +476,76 @@ function formatError(err) {
|
|
|
449
476
|
return err instanceof Error ? err.message : String(err);
|
|
450
477
|
}
|
|
451
478
|
|
|
452
|
-
// src/utils/platform-
|
|
479
|
+
// src/utils/platform-layout.ts
|
|
480
|
+
import { access, readdir as readdir3 } from "fs/promises";
|
|
481
|
+
import { join as join9, dirname as dirname7 } from "path";
|
|
453
482
|
import { cwd as cwd2 } from "process";
|
|
454
|
-
|
|
483
|
+
async function findCoreDirIn(dir) {
|
|
484
|
+
let entries;
|
|
485
|
+
try {
|
|
486
|
+
entries = await readdir3(dir, { withFileTypes: true });
|
|
487
|
+
} catch {
|
|
488
|
+
return null;
|
|
489
|
+
}
|
|
490
|
+
const dirs = entries.filter((e) => e.isDirectory());
|
|
491
|
+
for (const entry of dirs) {
|
|
492
|
+
if (entry.name.endsWith("-core")) {
|
|
493
|
+
try {
|
|
494
|
+
await access(join9(dir, entry.name, "product.manifest.json"));
|
|
495
|
+
return entry.name;
|
|
496
|
+
} catch {
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
const coreEntry = dirs.find((e) => e.name === "core");
|
|
501
|
+
if (coreEntry) {
|
|
502
|
+
try {
|
|
503
|
+
await access(join9(dir, "core", "product.manifest.json"));
|
|
504
|
+
return "core";
|
|
505
|
+
} catch {
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
return null;
|
|
509
|
+
}
|
|
510
|
+
async function findPlatformLayout(startDir = cwd2()) {
|
|
511
|
+
let dir = startDir;
|
|
512
|
+
while (true) {
|
|
513
|
+
const coreDirName = await findCoreDirIn(dir);
|
|
514
|
+
if (coreDirName) {
|
|
515
|
+
const coreDir = join9(dir, coreDirName);
|
|
516
|
+
return {
|
|
517
|
+
rootDir: dir,
|
|
518
|
+
coreDir,
|
|
519
|
+
coreDirName,
|
|
520
|
+
localDir: join9(coreDir, "local")
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
const parent = dirname7(dir);
|
|
524
|
+
if (parent === dir) {
|
|
525
|
+
return null;
|
|
526
|
+
}
|
|
527
|
+
dir = parent;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
// src/utils/platform-check.ts
|
|
532
|
+
async function isPlatformInitialized() {
|
|
533
|
+
return await findPlatformLayout() !== null;
|
|
534
|
+
}
|
|
455
535
|
|
|
456
536
|
// src/utils/manifest.ts
|
|
457
|
-
import { readFile as readFile4, writeFile as writeFile4, access } from "fs/promises";
|
|
458
|
-
import { join as
|
|
459
|
-
import { cwd } from "process";
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
return join9(rootDir, MANIFEST_RELATIVE_PATH);
|
|
537
|
+
import { readFile as readFile4, writeFile as writeFile4, access as access2 } from "fs/promises";
|
|
538
|
+
import { join as join10 } from "path";
|
|
539
|
+
import { cwd as cwd3 } from "process";
|
|
540
|
+
function manifestPath(rootDir, coreDirName = "core") {
|
|
541
|
+
return join10(rootDir, coreDirName, "product.manifest.json");
|
|
463
542
|
}
|
|
464
|
-
async function readManifest(rootDir =
|
|
465
|
-
const content = await readFile4(manifestPath(rootDir), "utf-8");
|
|
543
|
+
async function readManifest(rootDir = cwd3(), coreDirName = "core") {
|
|
544
|
+
const content = await readFile4(manifestPath(rootDir, coreDirName), "utf-8");
|
|
466
545
|
return JSON.parse(content);
|
|
467
546
|
}
|
|
468
|
-
async function writeManifest(manifest, rootDir =
|
|
469
|
-
await writeFile4(manifestPath(rootDir), JSON.stringify(manifest, null, 2), "utf-8");
|
|
470
|
-
}
|
|
471
|
-
async function manifestExists(rootDir = cwd()) {
|
|
472
|
-
try {
|
|
473
|
-
await access(manifestPath(rootDir));
|
|
474
|
-
return true;
|
|
475
|
-
} catch {
|
|
476
|
-
return false;
|
|
477
|
-
}
|
|
547
|
+
async function writeManifest(manifest, rootDir = cwd3(), coreDirName = "core") {
|
|
548
|
+
await writeFile4(manifestPath(rootDir, coreDirName), JSON.stringify(manifest, null, 2), "utf-8");
|
|
478
549
|
}
|
|
479
550
|
function createInitialManifest(params) {
|
|
480
551
|
const { organizationName, platformName, platformDisplayName } = params;
|
|
@@ -496,24 +567,6 @@ function addApplicationToManifest(manifest, app) {
|
|
|
496
567
|
};
|
|
497
568
|
}
|
|
498
569
|
|
|
499
|
-
// src/utils/platform-check.ts
|
|
500
|
-
async function findRootDir(startDir = cwd2()) {
|
|
501
|
-
let dir = startDir;
|
|
502
|
-
while (true) {
|
|
503
|
-
if (await manifestExists(dir)) {
|
|
504
|
-
return dir;
|
|
505
|
-
}
|
|
506
|
-
const parent = dirname7(dir);
|
|
507
|
-
if (parent === dir) {
|
|
508
|
-
return null;
|
|
509
|
-
}
|
|
510
|
-
dir = parent;
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
async function isPlatformInitialized() {
|
|
514
|
-
return await findRootDir() !== null;
|
|
515
|
-
}
|
|
516
|
-
|
|
517
570
|
// src/commands/create-application/create-application.command.ts
|
|
518
571
|
var CREATE_APPLICATION_COMMAND_NAME = "create-application";
|
|
519
572
|
var createApplicationCommand = {
|
|
@@ -528,22 +581,24 @@ async function createApplication(params, logger) {
|
|
|
528
581
|
hasUserInterface,
|
|
529
582
|
hasBackendService
|
|
530
583
|
} = params;
|
|
531
|
-
const
|
|
532
|
-
if (!
|
|
584
|
+
const layout = await findPlatformLayout();
|
|
585
|
+
if (!layout) {
|
|
533
586
|
logger.log("Error: Cannot create an application \u2014 no platform initialized in this directory.");
|
|
534
587
|
return;
|
|
535
588
|
}
|
|
589
|
+
const { rootDir, coreDirName, localDir } = layout;
|
|
536
590
|
let manifest;
|
|
537
591
|
try {
|
|
538
|
-
manifest = await readManifest(rootDir);
|
|
592
|
+
manifest = await readManifest(rootDir, coreDirName);
|
|
539
593
|
} catch (err) {
|
|
540
594
|
logger.log(`Error: Could not read product manifest \u2014 ${formatError(err)}`);
|
|
541
595
|
return;
|
|
542
596
|
}
|
|
543
597
|
const { organization: organizationName, name: platformName } = manifest.product;
|
|
544
598
|
const localPath = `../${platformName}-${applicationName}`;
|
|
545
|
-
const applicationDir = resolve(
|
|
546
|
-
const
|
|
599
|
+
const applicationDir = resolve(join11(rootDir, coreDirName), localPath);
|
|
600
|
+
const bootstrapServiceName = `${platformName}-${applicationName}-bootstrap-service`;
|
|
601
|
+
const bootstrapServiceDir = join11(applicationDir, "services", bootstrapServiceName);
|
|
547
602
|
logger.log(`Creating application monorepo "${applicationName}"...`);
|
|
548
603
|
try {
|
|
549
604
|
await scaffoldApplicationMonorepo(applicationDir, organizationName, platformName, applicationName, logger);
|
|
@@ -551,12 +606,12 @@ async function createApplication(params, logger) {
|
|
|
551
606
|
logger.log(`Error: Could not scaffold application monorepo \u2014 ${formatError(err)}`);
|
|
552
607
|
return;
|
|
553
608
|
}
|
|
554
|
-
await mkdir2(
|
|
555
|
-
await mkdir2(
|
|
556
|
-
logger.log(`Creating bootstrap service "${
|
|
557
|
-
const
|
|
609
|
+
await mkdir2(join11(applicationDir, "services"), { recursive: true });
|
|
610
|
+
await mkdir2(join11(applicationDir, "ui"), { recursive: true });
|
|
611
|
+
logger.log(`Creating bootstrap service "${bootstrapServiceName}"...`);
|
|
612
|
+
const bootstrapServiceBaseDir = `${platformName}-${applicationName}/services`;
|
|
558
613
|
try {
|
|
559
|
-
await scaffoldBootstrap(bootstrapServiceDir, organizationName, applicationName
|
|
614
|
+
await scaffoldBootstrap(bootstrapServiceDir, organizationName, `${platformName}-${applicationName}`, bootstrapServiceBaseDir, logger);
|
|
560
615
|
} catch (err) {
|
|
561
616
|
logger.log(`Error: Could not scaffold bootstrap service \u2014 ${formatError(err)}`);
|
|
562
617
|
return;
|
|
@@ -572,7 +627,7 @@ async function createApplication(params, logger) {
|
|
|
572
627
|
await addModuleEntry(
|
|
573
628
|
bootstrapServiceDir,
|
|
574
629
|
applicationName,
|
|
575
|
-
buildUiModuleEntry(organizationName, applicationName, applicationDisplayName),
|
|
630
|
+
buildUiModuleEntry(organizationName, platformName, applicationName, applicationDisplayName),
|
|
576
631
|
logger
|
|
577
632
|
);
|
|
578
633
|
}
|
|
@@ -580,12 +635,13 @@ async function createApplication(params, logger) {
|
|
|
580
635
|
await addModuleEntry(
|
|
581
636
|
bootstrapServiceDir,
|
|
582
637
|
applicationName,
|
|
583
|
-
buildServiceModuleEntry(organizationName, applicationName, applicationDisplayName),
|
|
638
|
+
buildServiceModuleEntry(organizationName, platformName, applicationName, applicationDisplayName),
|
|
584
639
|
logger
|
|
585
640
|
);
|
|
586
641
|
}
|
|
587
642
|
if (hasUserInterface) {
|
|
588
|
-
const
|
|
643
|
+
const uiName = `${platformName}-${applicationName}-ui`;
|
|
644
|
+
const uiDir = join11(applicationDir, "ui", uiName);
|
|
589
645
|
const uiBaseDir = `${platformName}-${applicationName}/ui`;
|
|
590
646
|
try {
|
|
591
647
|
await scaffoldUiModule(uiDir, organizationName, platformName, applicationName, applicationDisplayName, uiBaseDir, logger);
|
|
@@ -595,17 +651,18 @@ async function createApplication(params, logger) {
|
|
|
595
651
|
}
|
|
596
652
|
}
|
|
597
653
|
if (hasBackendService) {
|
|
598
|
-
const
|
|
654
|
+
const serviceName = `${platformName}-${applicationName}-service`;
|
|
655
|
+
const serviceDir = join11(applicationDir, "services", serviceName);
|
|
599
656
|
const serviceBaseDir = `${platformName}-${applicationName}/services`;
|
|
600
657
|
try {
|
|
601
|
-
await scaffoldNestjsService(serviceDir, organizationName, applicationName, applicationDisplayName, serviceBaseDir, logger);
|
|
658
|
+
await scaffoldNestjsService(serviceDir, organizationName, platformName, applicationName, applicationDisplayName, serviceBaseDir, logger);
|
|
602
659
|
} catch (err) {
|
|
603
660
|
logger.log(`Error: Could not scaffold NestJS service \u2014 ${formatError(err)}`);
|
|
604
661
|
return;
|
|
605
662
|
}
|
|
606
663
|
}
|
|
607
|
-
const dockerComposePath =
|
|
608
|
-
const basePort = await getNextAvailablePort(
|
|
664
|
+
const dockerComposePath = join11(localDir, `${platformName}-${applicationName}-docker-compose.yml`);
|
|
665
|
+
const basePort = await getNextAvailablePort(localDir);
|
|
609
666
|
const uiPort = hasUserInterface ? basePort : 0;
|
|
610
667
|
const servicePort = hasBackendService ? hasUserInterface ? basePort + 1 : basePort : 0;
|
|
611
668
|
await createDockerCompose(
|
|
@@ -626,7 +683,7 @@ async function createApplication(params, logger) {
|
|
|
626
683
|
repository: null
|
|
627
684
|
});
|
|
628
685
|
try {
|
|
629
|
-
await writeManifest(updatedManifest, rootDir);
|
|
686
|
+
await writeManifest(updatedManifest, rootDir, coreDirName);
|
|
630
687
|
logger.log(`Updated product manifest with application "${applicationName}".`);
|
|
631
688
|
} catch (err) {
|
|
632
689
|
logger.log(`Warning: Could not update product manifest \u2014 ${formatError(err)}`);
|
|
@@ -635,8 +692,8 @@ async function createApplication(params, logger) {
|
|
|
635
692
|
}
|
|
636
693
|
|
|
637
694
|
// src/commands/init/init.command.ts
|
|
638
|
-
import { join as
|
|
639
|
-
import { cwd as
|
|
695
|
+
import { join as join17 } from "path";
|
|
696
|
+
import { cwd as cwd4 } from "process";
|
|
640
697
|
|
|
641
698
|
// src/utils/string.ts
|
|
642
699
|
function camelize(name) {
|
|
@@ -645,8 +702,8 @@ function camelize(name) {
|
|
|
645
702
|
|
|
646
703
|
// src/commands/init/scaffold-platform.ts
|
|
647
704
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
648
|
-
import { join as
|
|
649
|
-
var templateDir =
|
|
705
|
+
import { join as join12, dirname as dirname8 } from "path";
|
|
706
|
+
var templateDir = join12(
|
|
650
707
|
dirname8(fileURLToPath6(import.meta.url)),
|
|
651
708
|
"..",
|
|
652
709
|
"templates",
|
|
@@ -658,8 +715,8 @@ async function scaffoldPlatform(outputDir, variables, logger) {
|
|
|
658
715
|
|
|
659
716
|
// src/commands/init/scaffold-platform-bootstrap.ts
|
|
660
717
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
661
|
-
import { join as
|
|
662
|
-
var templateDir2 =
|
|
718
|
+
import { join as join13, dirname as dirname9 } from "path";
|
|
719
|
+
var templateDir2 = join13(
|
|
663
720
|
dirname9(fileURLToPath7(import.meta.url)),
|
|
664
721
|
"..",
|
|
665
722
|
"templates",
|
|
@@ -671,8 +728,8 @@ async function scaffoldPlatformBootstrap(outputDir, variables, logger) {
|
|
|
671
728
|
|
|
672
729
|
// src/commands/init/scaffold-customization-ui.ts
|
|
673
730
|
import { fileURLToPath as fileURLToPath8 } from "url";
|
|
674
|
-
import { join as
|
|
675
|
-
var templateDir3 =
|
|
731
|
+
import { join as join14, dirname as dirname10 } from "path";
|
|
732
|
+
var templateDir3 = join14(
|
|
676
733
|
dirname10(fileURLToPath8(import.meta.url)),
|
|
677
734
|
"..",
|
|
678
735
|
"templates",
|
|
@@ -683,19 +740,20 @@ async function scaffoldCustomizationUi(outputDir, variables, logger) {
|
|
|
683
740
|
}
|
|
684
741
|
|
|
685
742
|
// src/commands/init/register-customization-module.ts
|
|
686
|
-
import { join as
|
|
743
|
+
import { join as join15 } from "path";
|
|
687
744
|
import { readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
|
|
688
|
-
async function registerCustomizationModule(bootstrapServiceDir, organizationName, logger) {
|
|
689
|
-
const modulesJsonPath =
|
|
745
|
+
async function registerCustomizationModule(bootstrapServiceDir, organizationName, logger, platformName = "platform") {
|
|
746
|
+
const modulesJsonPath = join15(bootstrapServiceDir, "src", "data", "platform", "modules.json");
|
|
747
|
+
const customizationUiName = `${platformName}-customization-ui`;
|
|
690
748
|
const entry = {
|
|
691
|
-
name: `@${organizationName}
|
|
749
|
+
name: `@${organizationName}/${customizationUiName}`,
|
|
692
750
|
displayName: "Platform Customization UI",
|
|
693
751
|
type: "app",
|
|
694
|
-
baseUrl:
|
|
695
|
-
service: { host:
|
|
752
|
+
baseUrl: `/${customizationUiName}`,
|
|
753
|
+
service: { host: customizationUiName, port: 80 },
|
|
696
754
|
ui: {
|
|
697
755
|
route: "/",
|
|
698
|
-
bundleFile:
|
|
756
|
+
bundleFile: `${customizationUiName}.js`,
|
|
699
757
|
isPlatformCustomization: true,
|
|
700
758
|
customProps: {}
|
|
701
759
|
},
|
|
@@ -709,7 +767,7 @@ async function registerCustomizationModule(bootstrapServiceDir, organizationName
|
|
|
709
767
|
|
|
710
768
|
// src/commands/init/generate-local-env.ts
|
|
711
769
|
import { readFile as readFile6, writeFile as writeFile6 } from "fs/promises";
|
|
712
|
-
import { join as
|
|
770
|
+
import { join as join16 } from "path";
|
|
713
771
|
|
|
714
772
|
// src/utils/random.ts
|
|
715
773
|
import { randomBytes } from "crypto";
|
|
@@ -718,10 +776,10 @@ function generateRandomSecret() {
|
|
|
718
776
|
}
|
|
719
777
|
|
|
720
778
|
// src/commands/init/generate-local-env.ts
|
|
721
|
-
async function generateLocalEnv(outputDir, logger) {
|
|
722
|
-
const examplePath =
|
|
723
|
-
const envPath =
|
|
724
|
-
logger.log(
|
|
779
|
+
async function generateLocalEnv(outputDir, logger, coreDirName = "core") {
|
|
780
|
+
const examplePath = join16(outputDir, coreDirName, "local", ".env.example");
|
|
781
|
+
const envPath = join16(outputDir, coreDirName, "local", ".env");
|
|
782
|
+
logger.log(`Generating ${coreDirName}/local/.env with random secrets...`);
|
|
725
783
|
const content = await readFile6(examplePath, "utf-8");
|
|
726
784
|
const result = content.replace(/^(PAE_AUTH_JWT_SECRET|PAE_GATEWAY_SERVICE_ACCESS_SECRET|PAE_DB_PASSWORD)=$/gm, (_, key) => {
|
|
727
785
|
return `${key}=${generateRandomSecret()}`;
|
|
@@ -742,15 +800,18 @@ async function init(params, logger) {
|
|
|
742
800
|
}
|
|
743
801
|
const { organizationName, platformName, platformDisplayName } = params;
|
|
744
802
|
const platformTitle = camelize(platformName);
|
|
745
|
-
const outputDir =
|
|
803
|
+
const outputDir = cwd4();
|
|
746
804
|
logger.log(`Initializing ${platformTitle} platform for @${organizationName}...`);
|
|
805
|
+
const coreDirName = `${platformName}-core`;
|
|
806
|
+
const bootstrapServiceName = `${platformName}-bootstrap-service`;
|
|
807
|
+
const customizationUiName = `${platformName}-customization-ui`;
|
|
747
808
|
const variables = {
|
|
748
809
|
organizationName,
|
|
749
810
|
platformName,
|
|
750
811
|
platformTitle,
|
|
751
812
|
platformDisplayName,
|
|
752
|
-
bootstrapName:
|
|
753
|
-
bootstrapServiceDir:
|
|
813
|
+
bootstrapName: platformName,
|
|
814
|
+
bootstrapServiceDir: `${coreDirName}/services`
|
|
754
815
|
};
|
|
755
816
|
try {
|
|
756
817
|
await scaffoldPlatform(outputDir, variables, logger);
|
|
@@ -759,22 +820,22 @@ async function init(params, logger) {
|
|
|
759
820
|
return;
|
|
760
821
|
}
|
|
761
822
|
try {
|
|
762
|
-
await generateLocalEnv(outputDir, logger);
|
|
823
|
+
await generateLocalEnv(outputDir, logger, coreDirName);
|
|
763
824
|
} catch (err) {
|
|
764
|
-
logger.log(`Error: Could not generate
|
|
825
|
+
logger.log(`Error: Could not generate ${coreDirName}/local/.env \u2014 ${formatError(err)}`);
|
|
765
826
|
return;
|
|
766
827
|
}
|
|
767
828
|
try {
|
|
768
829
|
const manifest = createInitialManifest({ organizationName, platformName, platformDisplayName });
|
|
769
|
-
await writeManifest(manifest, outputDir);
|
|
770
|
-
logger.log(
|
|
830
|
+
await writeManifest(manifest, outputDir, coreDirName);
|
|
831
|
+
logger.log(`Created product manifest: ${coreDirName}/product.manifest.json`);
|
|
771
832
|
} catch (err) {
|
|
772
833
|
logger.log(`Error: Could not write product manifest \u2014 ${formatError(err)}`);
|
|
773
834
|
return;
|
|
774
835
|
}
|
|
775
836
|
try {
|
|
776
837
|
await scaffoldPlatformBootstrap(
|
|
777
|
-
|
|
838
|
+
join17(outputDir, coreDirName, "services", bootstrapServiceName),
|
|
778
839
|
variables,
|
|
779
840
|
logger
|
|
780
841
|
);
|
|
@@ -784,7 +845,7 @@ async function init(params, logger) {
|
|
|
784
845
|
}
|
|
785
846
|
try {
|
|
786
847
|
await scaffoldCustomizationUi(
|
|
787
|
-
|
|
848
|
+
join17(outputDir, coreDirName, "ui", customizationUiName),
|
|
788
849
|
variables,
|
|
789
850
|
logger
|
|
790
851
|
);
|
|
@@ -794,9 +855,10 @@ async function init(params, logger) {
|
|
|
794
855
|
}
|
|
795
856
|
try {
|
|
796
857
|
await registerCustomizationModule(
|
|
797
|
-
|
|
858
|
+
join17(outputDir, coreDirName, "services", bootstrapServiceName),
|
|
798
859
|
organizationName,
|
|
799
|
-
logger
|
|
860
|
+
logger,
|
|
861
|
+
platformName
|
|
800
862
|
);
|
|
801
863
|
} catch (err) {
|
|
802
864
|
logger.log(`Error: Could not register customization module \u2014 ${formatError(err)}`);
|
|
@@ -806,7 +868,7 @@ async function init(params, logger) {
|
|
|
806
868
|
}
|
|
807
869
|
|
|
808
870
|
// src/commands/configure-idp/configure-idp.command.ts
|
|
809
|
-
import { join as
|
|
871
|
+
import { join as join18 } from "path";
|
|
810
872
|
import { fetch as undiciFetch, Agent } from "undici";
|
|
811
873
|
|
|
812
874
|
// src/utils/env-reader.ts
|
|
@@ -884,12 +946,12 @@ var configureIdpCommand = {
|
|
|
884
946
|
description: "Configure an Identity Provider (IDP) in the gateway"
|
|
885
947
|
};
|
|
886
948
|
async function configureIdp(params, logger) {
|
|
887
|
-
const
|
|
888
|
-
if (!
|
|
949
|
+
const layout = await findPlatformLayout();
|
|
950
|
+
if (!layout) {
|
|
889
951
|
logger.log("Error: Cannot configure an IDP \u2014 no platform initialized in this directory.");
|
|
890
952
|
return;
|
|
891
953
|
}
|
|
892
|
-
const envPath =
|
|
954
|
+
const envPath = join18(layout.localDir, ".env");
|
|
893
955
|
let env;
|
|
894
956
|
try {
|
|
895
957
|
env = await readEnvFile(envPath);
|
|
@@ -941,13 +1003,13 @@ async function configureIdp(params, logger) {
|
|
|
941
1003
|
}
|
|
942
1004
|
|
|
943
1005
|
// src/commands/create-service-module/create-service-module.command.ts
|
|
944
|
-
import { join as
|
|
945
|
-
import { access as
|
|
1006
|
+
import { join as join20, resolve as resolve2 } from "path";
|
|
1007
|
+
import { access as access3 } from "fs/promises";
|
|
946
1008
|
|
|
947
1009
|
// src/commands/create-service-module/scaffold-service-module.ts
|
|
948
1010
|
import { fileURLToPath as fileURLToPath9 } from "url";
|
|
949
|
-
import { join as
|
|
950
|
-
var nestjsServiceModuleTemplateDir2 =
|
|
1011
|
+
import { join as join19, dirname as dirname11 } from "path";
|
|
1012
|
+
var nestjsServiceModuleTemplateDir2 = join19(
|
|
951
1013
|
dirname11(fileURLToPath9(import.meta.url)),
|
|
952
1014
|
"..",
|
|
953
1015
|
"templates",
|
|
@@ -1016,14 +1078,15 @@ var createServiceModuleCommand = {
|
|
|
1016
1078
|
};
|
|
1017
1079
|
async function createServiceModule(params, logger) {
|
|
1018
1080
|
const { applicationName, serviceName, serviceDisplayName } = params;
|
|
1019
|
-
const
|
|
1020
|
-
if (!
|
|
1081
|
+
const layout = await findPlatformLayout();
|
|
1082
|
+
if (!layout) {
|
|
1021
1083
|
logger.log("Error: Cannot create a service module \u2014 no platform initialized in this directory.");
|
|
1022
1084
|
return;
|
|
1023
1085
|
}
|
|
1086
|
+
const { rootDir, coreDirName, localDir } = layout;
|
|
1024
1087
|
let manifest;
|
|
1025
1088
|
try {
|
|
1026
|
-
manifest = await readManifest(rootDir);
|
|
1089
|
+
manifest = await readManifest(rootDir, coreDirName);
|
|
1027
1090
|
} catch (err) {
|
|
1028
1091
|
logger.log(`Error: Could not read product manifest \u2014 ${formatError(err)}`);
|
|
1029
1092
|
return;
|
|
@@ -1034,17 +1097,17 @@ async function createServiceModule(params, logger) {
|
|
|
1034
1097
|
logger.log(`Error: The specified application "${applicationName}" is not registered in the product manifest.`);
|
|
1035
1098
|
return;
|
|
1036
1099
|
}
|
|
1037
|
-
const applicationDir = resolve2(
|
|
1100
|
+
const applicationDir = resolve2(join20(rootDir, coreDirName), appEntry.localPath);
|
|
1038
1101
|
try {
|
|
1039
|
-
await
|
|
1102
|
+
await access3(applicationDir);
|
|
1040
1103
|
} catch {
|
|
1041
1104
|
logger.log(`Error: The specified application "${applicationName}" does not exist in the platform.`);
|
|
1042
1105
|
return;
|
|
1043
1106
|
}
|
|
1044
|
-
const fullServiceName = `${serviceName}-service`;
|
|
1045
|
-
const serviceDir =
|
|
1107
|
+
const fullServiceName = `${platformName}-${serviceName}-service`;
|
|
1108
|
+
const serviceDir = join20(applicationDir, "services", fullServiceName);
|
|
1046
1109
|
try {
|
|
1047
|
-
await
|
|
1110
|
+
await access3(serviceDir);
|
|
1048
1111
|
logger.log(`Error: A service named "${fullServiceName}" already exists in application "${applicationName}".`);
|
|
1049
1112
|
return;
|
|
1050
1113
|
} catch {
|
|
@@ -1063,26 +1126,27 @@ async function createServiceModule(params, logger) {
|
|
|
1063
1126
|
logger.log(`Error: Could not scaffold NestJS service \u2014 ${formatError(err)}`);
|
|
1064
1127
|
return;
|
|
1065
1128
|
}
|
|
1066
|
-
const bootstrapServiceDir =
|
|
1129
|
+
const bootstrapServiceDir = join20(applicationDir, "services", `${platformName}-${applicationName}-bootstrap-service`);
|
|
1067
1130
|
const moduleEntry = buildCustomServiceModuleEntry(organizationName, fullServiceName, serviceDisplayName);
|
|
1068
1131
|
await addModuleEntry(bootstrapServiceDir, applicationName, moduleEntry, logger);
|
|
1069
|
-
const dockerComposePath =
|
|
1070
|
-
const port = await getNextAvailablePort(
|
|
1132
|
+
const dockerComposePath = join20(localDir, `${platformName}-${applicationName}-docker-compose.yml`);
|
|
1133
|
+
const port = await getNextAvailablePort(localDir);
|
|
1071
1134
|
await appendServiceToDockerCompose(dockerComposePath, fullServiceName, platformName, applicationName, port, logger);
|
|
1072
1135
|
logger.log(`Done! Service module "${fullServiceName}" added to application "${applicationName}".`);
|
|
1073
1136
|
}
|
|
1074
1137
|
|
|
1075
1138
|
// src/commands/create-ui-module/create-ui-module.command.ts
|
|
1076
|
-
import { join as
|
|
1077
|
-
import { access as
|
|
1139
|
+
import { join as join21, resolve as resolve3 } from "path";
|
|
1140
|
+
import { access as access4, readdir as readdir4 } from "fs/promises";
|
|
1078
1141
|
|
|
1079
1142
|
// src/commands/create-ui-module/append-ui-docker-compose.ts
|
|
1080
1143
|
import { readFile as readFile9, writeFile as writeFile8 } from "fs/promises";
|
|
1081
1144
|
async function appendUiToDockerCompose(dockerComposePath, platformName, applicationName, port, logger) {
|
|
1145
|
+
const uiName = `${platformName}-${applicationName}-ui`;
|
|
1082
1146
|
const block = `
|
|
1083
|
-
${
|
|
1147
|
+
${uiName}:
|
|
1084
1148
|
build:
|
|
1085
|
-
context: ../../${platformName}-${applicationName}/ui/${
|
|
1149
|
+
context: ../../${platformName}-${applicationName}/ui/${uiName}
|
|
1086
1150
|
dockerfile: Dockerfile.development
|
|
1087
1151
|
ports:
|
|
1088
1152
|
- ${port}:80
|
|
@@ -1107,14 +1171,15 @@ var createUiModuleCommand = {
|
|
|
1107
1171
|
};
|
|
1108
1172
|
async function createUiModule(params, logger) {
|
|
1109
1173
|
const { applicationName, applicationDisplayName } = params;
|
|
1110
|
-
const
|
|
1111
|
-
if (!
|
|
1174
|
+
const layout = await findPlatformLayout();
|
|
1175
|
+
if (!layout) {
|
|
1112
1176
|
logger.log("Error: Cannot create a UI module \u2014 no platform initialized in this directory.");
|
|
1113
1177
|
return;
|
|
1114
1178
|
}
|
|
1179
|
+
const { rootDir, coreDirName, localDir } = layout;
|
|
1115
1180
|
let manifest;
|
|
1116
1181
|
try {
|
|
1117
|
-
manifest = await readManifest(rootDir);
|
|
1182
|
+
manifest = await readManifest(rootDir, coreDirName);
|
|
1118
1183
|
} catch (err) {
|
|
1119
1184
|
logger.log(`Error: Could not read product manifest \u2014 ${formatError(err)}`);
|
|
1120
1185
|
return;
|
|
@@ -1125,16 +1190,16 @@ async function createUiModule(params, logger) {
|
|
|
1125
1190
|
logger.log(`Error: The specified application "${applicationName}" is not registered in the product manifest.`);
|
|
1126
1191
|
return;
|
|
1127
1192
|
}
|
|
1128
|
-
const applicationDir = resolve3(
|
|
1193
|
+
const applicationDir = resolve3(join21(rootDir, coreDirName), appEntry.localPath);
|
|
1129
1194
|
try {
|
|
1130
|
-
await
|
|
1195
|
+
await access4(applicationDir);
|
|
1131
1196
|
} catch {
|
|
1132
1197
|
logger.log(`Error: The specified application "${applicationName}" does not exist in the platform.`);
|
|
1133
1198
|
return;
|
|
1134
1199
|
}
|
|
1135
|
-
const uiDir =
|
|
1200
|
+
const uiDir = join21(applicationDir, "ui");
|
|
1136
1201
|
try {
|
|
1137
|
-
const uiEntries = await
|
|
1202
|
+
const uiEntries = await readdir4(uiDir);
|
|
1138
1203
|
const existingUiModules = uiEntries.filter((e) => e !== ".gitkeep");
|
|
1139
1204
|
if (existingUiModules.length > 0) {
|
|
1140
1205
|
logger.log(`Error: Currently we support only one UI module per application. Application "${applicationName}" already has a UI module.`);
|
|
@@ -1142,7 +1207,8 @@ async function createUiModule(params, logger) {
|
|
|
1142
1207
|
}
|
|
1143
1208
|
} catch {
|
|
1144
1209
|
}
|
|
1145
|
-
const
|
|
1210
|
+
const uiName = `${platformName}-${applicationName}-ui`;
|
|
1211
|
+
const uiOutputDir = join21(uiDir, uiName);
|
|
1146
1212
|
const uiBaseDir = `${platformName}-${applicationName}/ui`;
|
|
1147
1213
|
try {
|
|
1148
1214
|
await scaffoldUiModule(uiOutputDir, organizationName, platformName, applicationName, applicationDisplayName, uiBaseDir, logger);
|
|
@@ -1150,13 +1216,13 @@ async function createUiModule(params, logger) {
|
|
|
1150
1216
|
logger.log(`Error: Could not scaffold UI module \u2014 ${formatError(err)}`);
|
|
1151
1217
|
return;
|
|
1152
1218
|
}
|
|
1153
|
-
const bootstrapServiceDir =
|
|
1154
|
-
const moduleEntry = buildUiModuleEntry(organizationName, applicationName, applicationDisplayName);
|
|
1219
|
+
const bootstrapServiceDir = join21(applicationDir, "services", `${platformName}-${applicationName}-bootstrap-service`);
|
|
1220
|
+
const moduleEntry = buildUiModuleEntry(organizationName, platformName, applicationName, applicationDisplayName);
|
|
1155
1221
|
await addModuleEntry(bootstrapServiceDir, applicationName, moduleEntry, logger);
|
|
1156
|
-
const dockerComposePath =
|
|
1157
|
-
const port = await getNextAvailablePort(
|
|
1222
|
+
const dockerComposePath = join21(localDir, `${platformName}-${applicationName}-docker-compose.yml`);
|
|
1223
|
+
const port = await getNextAvailablePort(localDir);
|
|
1158
1224
|
await appendUiToDockerCompose(dockerComposePath, platformName, applicationName, port, logger);
|
|
1159
|
-
logger.log(`Done! UI module "${
|
|
1225
|
+
logger.log(`Done! UI module "${uiName}" added to application "${applicationName}".`);
|
|
1160
1226
|
}
|
|
1161
1227
|
|
|
1162
1228
|
// src/commands/registry.ts
|
|
@@ -1432,7 +1498,7 @@ function useCommandRunner({ appendStaticItem, setState }) {
|
|
|
1432
1498
|
}
|
|
1433
1499
|
|
|
1434
1500
|
// src/app.tsx
|
|
1435
|
-
import { jsx as
|
|
1501
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1436
1502
|
var require2 = createRequire(import.meta.url);
|
|
1437
1503
|
var { version } = require2("../package.json");
|
|
1438
1504
|
function App() {
|
|
@@ -1519,17 +1585,17 @@ function App() {
|
|
|
1519
1585
|
function renderActiveArea() {
|
|
1520
1586
|
switch (state) {
|
|
1521
1587
|
case APP_STATE.EXECUTING:
|
|
1522
|
-
return /* @__PURE__ */
|
|
1523
|
-
/* @__PURE__ */
|
|
1524
|
-
/* @__PURE__ */
|
|
1588
|
+
return /* @__PURE__ */ jsxs6(Box4, { flexDirection: "row", gap: 1, children: [
|
|
1589
|
+
/* @__PURE__ */ jsx7(Spinner, { label: "Running\u2026" }),
|
|
1590
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "(esc to cancel)" })
|
|
1525
1591
|
] });
|
|
1526
1592
|
case APP_STATE.PROMPTING:
|
|
1527
|
-
return /* @__PURE__ */
|
|
1528
|
-
/* @__PURE__ */
|
|
1529
|
-
/* @__PURE__ */
|
|
1593
|
+
return /* @__PURE__ */ jsxs6(Box4, { flexDirection: "column", children: [
|
|
1594
|
+
/* @__PURE__ */ jsx7(Text7, { color: "cyan", children: promptMessage }),
|
|
1595
|
+
/* @__PURE__ */ jsx7(Prompt, { value: promptValue, onChange: setPromptValue, onSubmit: handlePromptSubmit })
|
|
1530
1596
|
] });
|
|
1531
1597
|
default:
|
|
1532
|
-
return /* @__PURE__ */
|
|
1598
|
+
return /* @__PURE__ */ jsx7(
|
|
1533
1599
|
Prompt,
|
|
1534
1600
|
{
|
|
1535
1601
|
value: inputValue,
|
|
@@ -1542,10 +1608,10 @@ function App() {
|
|
|
1542
1608
|
);
|
|
1543
1609
|
}
|
|
1544
1610
|
}
|
|
1545
|
-
return /* @__PURE__ */
|
|
1546
|
-
/* @__PURE__ */
|
|
1611
|
+
return /* @__PURE__ */ jsxs6(Box4, { flexDirection: "column", children: [
|
|
1612
|
+
/* @__PURE__ */ jsx7(ScrollbackHistory, { items: staticItems, version }),
|
|
1547
1613
|
renderActiveArea(),
|
|
1548
|
-
state === APP_STATE.PALETTE && /* @__PURE__ */
|
|
1614
|
+
state === APP_STATE.PALETTE && /* @__PURE__ */ jsx7(CommandPalette, { commands: filteredCommands, selectedIndex })
|
|
1549
1615
|
] });
|
|
1550
1616
|
}
|
|
1551
1617
|
|
|
@@ -1630,8 +1696,8 @@ async function configureIdpCliController(args2) {
|
|
|
1630
1696
|
|
|
1631
1697
|
// src/commands/local-scripts/docker-compose-orchestrator.ts
|
|
1632
1698
|
import { spawn } from "child_process";
|
|
1633
|
-
import { access as
|
|
1634
|
-
import { join as
|
|
1699
|
+
import { access as access5 } from "fs/promises";
|
|
1700
|
+
import { join as join22 } from "path";
|
|
1635
1701
|
function runDockerCompose(args2, logger, rootDir, signal) {
|
|
1636
1702
|
return new Promise((resolvePromise) => {
|
|
1637
1703
|
const child = spawn("docker", ["compose", ...args2], {
|
|
@@ -1676,42 +1742,62 @@ function runDockerCompose(args2, logger, rootDir, signal) {
|
|
|
1676
1742
|
});
|
|
1677
1743
|
});
|
|
1678
1744
|
}
|
|
1679
|
-
async function getAppComposePaths(
|
|
1745
|
+
async function getAppComposePaths(localDir, platformName, manifest) {
|
|
1680
1746
|
const results = [];
|
|
1681
1747
|
for (const app of manifest.applications) {
|
|
1682
|
-
const
|
|
1748
|
+
const prefixedPath = join22(localDir, `${platformName}-${app.name}-docker-compose.yml`);
|
|
1749
|
+
const unprefixedPath = join22(localDir, `${app.name}-docker-compose.yml`);
|
|
1750
|
+
let resolved = null;
|
|
1683
1751
|
try {
|
|
1684
|
-
await
|
|
1685
|
-
|
|
1752
|
+
await access5(prefixedPath);
|
|
1753
|
+
resolved = prefixedPath;
|
|
1686
1754
|
} catch {
|
|
1755
|
+
try {
|
|
1756
|
+
await access5(unprefixedPath);
|
|
1757
|
+
resolved = unprefixedPath;
|
|
1758
|
+
} catch {
|
|
1759
|
+
}
|
|
1760
|
+
}
|
|
1761
|
+
if (resolved) {
|
|
1762
|
+
results.push({ composePath: resolved, appName: app.name });
|
|
1687
1763
|
}
|
|
1688
1764
|
}
|
|
1689
1765
|
return results;
|
|
1690
1766
|
}
|
|
1691
|
-
async function buildAllComposeArgs(
|
|
1692
|
-
const
|
|
1767
|
+
async function buildAllComposeArgs(layout, manifest, logger) {
|
|
1768
|
+
const { rootDir, coreDirName, localDir } = layout;
|
|
1769
|
+
const platformName = manifest.product.name;
|
|
1770
|
+
const prefixedCoreCompose = join22(localDir, `${coreDirName}-docker-compose.yml`);
|
|
1771
|
+
const unprefixedCoreCompose = join22(localDir, "core-docker-compose.yml");
|
|
1772
|
+
let coreComposePath;
|
|
1773
|
+
try {
|
|
1774
|
+
await access5(prefixedCoreCompose);
|
|
1775
|
+
coreComposePath = prefixedCoreCompose;
|
|
1776
|
+
} catch {
|
|
1777
|
+
coreComposePath = unprefixedCoreCompose;
|
|
1778
|
+
}
|
|
1693
1779
|
const fileArgs = [
|
|
1694
1780
|
"-f",
|
|
1695
|
-
|
|
1781
|
+
join22(localDir, "platform-docker-compose.yml"),
|
|
1696
1782
|
"-f",
|
|
1697
|
-
|
|
1783
|
+
coreComposePath
|
|
1698
1784
|
];
|
|
1699
|
-
const appEntries = await getAppComposePaths(
|
|
1700
|
-
for (const { composePath
|
|
1785
|
+
const appEntries = await getAppComposePaths(localDir, platformName, manifest);
|
|
1786
|
+
for (const { composePath } of appEntries) {
|
|
1701
1787
|
fileArgs.push("-f", composePath);
|
|
1702
1788
|
}
|
|
1703
1789
|
for (const app of manifest.applications) {
|
|
1704
1790
|
if (!appEntries.find((e) => e.appName === app.name)) {
|
|
1705
|
-
logger.log(`Warning: No docker-compose found for application "${app.name}" in
|
|
1791
|
+
logger.log(`Warning: No docker-compose found for application "${app.name}" in ${coreDirName}/local/ \u2014 skipping.`);
|
|
1706
1792
|
}
|
|
1707
1793
|
}
|
|
1708
1794
|
return fileArgs;
|
|
1709
1795
|
}
|
|
1710
|
-
async function startEnvironment(
|
|
1796
|
+
async function startEnvironment(layout, manifest, logger, signal) {
|
|
1797
|
+
const { rootDir, localDir } = layout;
|
|
1711
1798
|
const platformName = manifest.product.name;
|
|
1712
|
-
const envFile =
|
|
1713
|
-
const fileArgs = await buildAllComposeArgs(
|
|
1714
|
-
const localDir = join21(rootDir, "core", "local");
|
|
1799
|
+
const envFile = join22(localDir, ".env");
|
|
1800
|
+
const fileArgs = await buildAllComposeArgs(layout, manifest, logger);
|
|
1715
1801
|
logger.log("Starting environment...");
|
|
1716
1802
|
await runDockerCompose(
|
|
1717
1803
|
[
|
|
@@ -1732,11 +1818,11 @@ async function startEnvironment(rootDir, manifest, logger, signal) {
|
|
|
1732
1818
|
signal
|
|
1733
1819
|
);
|
|
1734
1820
|
}
|
|
1735
|
-
async function stopEnvironment(
|
|
1821
|
+
async function stopEnvironment(layout, manifest, logger, signal) {
|
|
1822
|
+
const { rootDir, localDir } = layout;
|
|
1736
1823
|
const platformName = manifest.product.name;
|
|
1737
|
-
const envFile =
|
|
1738
|
-
const fileArgs = await buildAllComposeArgs(
|
|
1739
|
-
const localDir = join21(rootDir, "core", "local");
|
|
1824
|
+
const envFile = join22(localDir, ".env");
|
|
1825
|
+
const fileArgs = await buildAllComposeArgs(layout, manifest, logger);
|
|
1740
1826
|
logger.log("Stopping environment...");
|
|
1741
1827
|
await runDockerCompose(
|
|
1742
1828
|
[
|
|
@@ -1754,11 +1840,11 @@ async function stopEnvironment(rootDir, manifest, logger, signal) {
|
|
|
1754
1840
|
signal
|
|
1755
1841
|
);
|
|
1756
1842
|
}
|
|
1757
|
-
async function destroyEnvironment(
|
|
1843
|
+
async function destroyEnvironment(layout, manifest, logger, signal) {
|
|
1844
|
+
const { rootDir, localDir } = layout;
|
|
1758
1845
|
const platformName = manifest.product.name;
|
|
1759
|
-
const envFile =
|
|
1760
|
-
const fileArgs = await buildAllComposeArgs(
|
|
1761
|
-
const localDir = join21(rootDir, "core", "local");
|
|
1846
|
+
const envFile = join22(localDir, ".env");
|
|
1847
|
+
const fileArgs = await buildAllComposeArgs(layout, manifest, logger);
|
|
1762
1848
|
logger.log("Destroying environment...");
|
|
1763
1849
|
await runDockerCompose(
|
|
1764
1850
|
[
|
|
@@ -1782,8 +1868,8 @@ async function destroyEnvironment(rootDir, manifest, logger, signal) {
|
|
|
1782
1868
|
|
|
1783
1869
|
// src/commands/local-scripts/npm-orchestrator.ts
|
|
1784
1870
|
import { spawn as spawn2 } from "child_process";
|
|
1785
|
-
import { access as
|
|
1786
|
-
import {
|
|
1871
|
+
import { access as access6 } from "fs/promises";
|
|
1872
|
+
import { resolve as resolve4, join as join23 } from "path";
|
|
1787
1873
|
function runCommand(command, args2, workDir, logger, signal) {
|
|
1788
1874
|
return new Promise((resolvePromise) => {
|
|
1789
1875
|
const child = spawn2(command, args2, {
|
|
@@ -1830,24 +1916,24 @@ function runCommand(command, args2, workDir, logger, signal) {
|
|
|
1830
1916
|
}
|
|
1831
1917
|
async function dirExists(dirPath) {
|
|
1832
1918
|
try {
|
|
1833
|
-
await
|
|
1919
|
+
await access6(dirPath);
|
|
1834
1920
|
return true;
|
|
1835
1921
|
} catch {
|
|
1836
1922
|
return false;
|
|
1837
1923
|
}
|
|
1838
1924
|
}
|
|
1839
|
-
async function installDependencies(
|
|
1840
|
-
const coreDir =
|
|
1925
|
+
async function installDependencies(layout, manifest, logger, signal) {
|
|
1926
|
+
const { coreDir, coreDirName } = layout;
|
|
1841
1927
|
const appDirs = [];
|
|
1842
1928
|
for (const app of manifest.applications) {
|
|
1843
|
-
const appDir = resolve4(
|
|
1929
|
+
const appDir = resolve4(join23(coreDir), app.localPath);
|
|
1844
1930
|
if (!await dirExists(appDir)) {
|
|
1845
1931
|
logger.log(`Warning: Application directory "${app.name}" not found at ${appDir} \u2014 skipping install.`);
|
|
1846
1932
|
continue;
|
|
1847
1933
|
}
|
|
1848
1934
|
appDirs.push({ name: app.name, dir: appDir });
|
|
1849
1935
|
}
|
|
1850
|
-
const targets = [{ name:
|
|
1936
|
+
const targets = [{ name: coreDirName, dir: coreDir }, ...appDirs];
|
|
1851
1937
|
logger.log(`Installing dependencies in parallel: ${targets.map((t) => t.name).join(", ")}...`);
|
|
1852
1938
|
await Promise.all(
|
|
1853
1939
|
targets.map(
|
|
@@ -1857,14 +1943,14 @@ async function installDependencies(rootDir, manifest, logger, signal) {
|
|
|
1857
1943
|
)
|
|
1858
1944
|
);
|
|
1859
1945
|
}
|
|
1860
|
-
async function buildAll(
|
|
1861
|
-
const coreDir =
|
|
1862
|
-
logger.log(
|
|
1946
|
+
async function buildAll(layout, manifest, logger, signal) {
|
|
1947
|
+
const { coreDir, coreDirName } = layout;
|
|
1948
|
+
logger.log(`Building ${coreDirName}/...`);
|
|
1863
1949
|
await runCommand("npx", ["turbo", "build"], coreDir, logger, signal);
|
|
1864
1950
|
if (signal?.aborted) return;
|
|
1865
1951
|
const appDirs = [];
|
|
1866
1952
|
for (const app of manifest.applications) {
|
|
1867
|
-
const appDir = resolve4(
|
|
1953
|
+
const appDir = resolve4(join23(coreDir), app.localPath);
|
|
1868
1954
|
if (!await dirExists(appDir)) {
|
|
1869
1955
|
logger.log(`Warning: Application directory "${app.name}" not found at ${appDir} \u2014 skipping build.`);
|
|
1870
1956
|
continue;
|
|
@@ -1889,33 +1975,34 @@ var START_COMMAND_NAME = "start";
|
|
|
1889
1975
|
var STOP_COMMAND_NAME = "stop";
|
|
1890
1976
|
var DESTROY_COMMAND_NAME = "destroy";
|
|
1891
1977
|
async function runLocalScript(scriptName, logger, signal) {
|
|
1892
|
-
const
|
|
1893
|
-
if (!
|
|
1978
|
+
const layout = await findPlatformLayout();
|
|
1979
|
+
if (!layout) {
|
|
1894
1980
|
logger.log(`Error: Cannot run "${scriptName}" \u2014 no platform initialized in this directory.`);
|
|
1895
1981
|
return;
|
|
1896
1982
|
}
|
|
1983
|
+
const { rootDir, coreDirName } = layout;
|
|
1897
1984
|
let manifest;
|
|
1898
1985
|
try {
|
|
1899
|
-
manifest = await readManifest(rootDir);
|
|
1986
|
+
manifest = await readManifest(rootDir, coreDirName);
|
|
1900
1987
|
} catch (err) {
|
|
1901
1988
|
logger.log(`Error: Could not read product manifest \u2014 ${formatError(err)}`);
|
|
1902
1989
|
return;
|
|
1903
1990
|
}
|
|
1904
1991
|
switch (scriptName) {
|
|
1905
1992
|
case START_COMMAND_NAME:
|
|
1906
|
-
await startEnvironment(
|
|
1993
|
+
await startEnvironment(layout, manifest, logger, signal);
|
|
1907
1994
|
break;
|
|
1908
1995
|
case STOP_COMMAND_NAME:
|
|
1909
|
-
await stopEnvironment(
|
|
1996
|
+
await stopEnvironment(layout, manifest, logger, signal);
|
|
1910
1997
|
break;
|
|
1911
1998
|
case DESTROY_COMMAND_NAME:
|
|
1912
|
-
await destroyEnvironment(
|
|
1999
|
+
await destroyEnvironment(layout, manifest, logger, signal);
|
|
1913
2000
|
break;
|
|
1914
2001
|
case INSTALL_COMMAND_NAME:
|
|
1915
|
-
await installDependencies(
|
|
2002
|
+
await installDependencies(layout, manifest, logger, signal);
|
|
1916
2003
|
break;
|
|
1917
2004
|
case BUILD_COMMAND_NAME:
|
|
1918
|
-
await buildAll(
|
|
2005
|
+
await buildAll(layout, manifest, logger, signal);
|
|
1919
2006
|
break;
|
|
1920
2007
|
default:
|
|
1921
2008
|
logger.log(`Error: Unknown script "${scriptName}".`);
|
|
@@ -2045,10 +2132,10 @@ function parseKeyValueArgs(args2) {
|
|
|
2045
2132
|
}
|
|
2046
2133
|
|
|
2047
2134
|
// src/index.tsx
|
|
2048
|
-
import { jsx as
|
|
2135
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
2049
2136
|
var args = process.argv.slice(2);
|
|
2050
2137
|
if (args.length === 0) {
|
|
2051
|
-
render(/* @__PURE__ */
|
|
2138
|
+
render(/* @__PURE__ */ jsx8(App, {}));
|
|
2052
2139
|
} else {
|
|
2053
2140
|
const commandName = args[0];
|
|
2054
2141
|
const params = parseKeyValueArgs(args.slice(1));
|