@bluealba/platform-cli 0.2.1 → 0.3.0-feature-platform-cli-222
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 +716 -153
- package/package.json +5 -5
- package/templates/bootstrap-service-template/package.json +2 -2
- package/templates/customization-ui-module-template/package.json +2 -2
- package/templates/customization-ui-module-template/src/root.component.tsx +2 -11
- package/templates/platform-init-template/{local → core/local}/core-docker-compose.yml +4 -4
- package/templates/platform-init-template/{local → core/local}/platform-docker-compose.yml +1 -1
- package/templates/react-ui-module-template/package.json +1 -1
- package/templates/customization-ui-module-template/src/components/ExpandedNavbarLogo.tsx +0 -62
- package/templates/customization-ui-module-template/src/components/ExtensionPoints/index.tsx +0 -28
- package/templates/customization-ui-module-template/src/components/Logo.tsx +0 -55
- package/templates/customization-ui-module-template/src/components/SplashLogo.tsx +0 -52
- package/templates/customization-ui-module-template/src/hooks/useDynamicStyleSheet.ts +0 -18
- package/templates/platform-init-template/local/docker-compose.yml +0 -3
- package/templates/platform-init-template/local/package.json +0 -18
- package/templates/platform-init-template/local/scripts/build.sh +0 -18
- package/templates/platform-init-template/local/scripts/install.sh +0 -18
- /package/templates/platform-init-template/{local → core/local}/.env.example +0 -0
- /package/templates/platform-init-template/{local → core/local}/environment/pae-nestjs-gateway-service.env +0 -0
- /package/templates/platform-init-template/{local → core/local}/nginx.conf +0 -0
- /package/templates/platform-init-template/{local → core/local}/ssl/cert.pem +0 -0
- /package/templates/platform-init-template/{local → core/local}/ssl/key.pem +0 -0
package/dist/index.js
CHANGED
|
@@ -61,11 +61,10 @@ import React2 from "react";
|
|
|
61
61
|
import { Box as Box3, Text as Text3 } from "ink";
|
|
62
62
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
63
63
|
var ASCII_ART = [
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
" / | \\ "
|
|
64
|
+
"|---. .---|",
|
|
65
|
+
"| \\/ |",
|
|
66
|
+
"| /\\ |",
|
|
67
|
+
"|---' '---|"
|
|
69
68
|
];
|
|
70
69
|
var WelcomeBanner = React2.memo(function WelcomeBanner2({ version: version2 }) {
|
|
71
70
|
return /* @__PURE__ */ jsxs3(Box3, { borderStyle: "round", flexDirection: "column", paddingX: 1, paddingY: 1, children: [
|
|
@@ -125,8 +124,7 @@ function Spinner({ label }) {
|
|
|
125
124
|
import { Fzf } from "fzf";
|
|
126
125
|
|
|
127
126
|
// src/commands/create-application/create-application.command.ts
|
|
128
|
-
import { join as join10 } from "path";
|
|
129
|
-
import { cwd as cwd2 } from "process";
|
|
127
|
+
import { join as join10, resolve } from "path";
|
|
130
128
|
import { mkdir as mkdir2 } from "fs/promises";
|
|
131
129
|
|
|
132
130
|
// src/commands/create-application/scaffold-application-monorepo.ts
|
|
@@ -358,10 +356,10 @@ function buildUiModuleEntry(organizationName, applicationName, applicationDispla
|
|
|
358
356
|
|
|
359
357
|
// src/commands/create-application/create-docker-compose.ts
|
|
360
358
|
import { writeFile as writeFile3 } from "fs/promises";
|
|
361
|
-
function buildBootstrapBlock(applicationName) {
|
|
359
|
+
function buildBootstrapBlock(platformName, applicationName) {
|
|
362
360
|
return ` ${applicationName}-bootstrap-service:
|
|
363
361
|
build:
|
|
364
|
-
context:
|
|
362
|
+
context: ../../${platformName}-${applicationName}/services/${applicationName}-bootstrap-service
|
|
365
363
|
dockerfile: Dockerfile.development
|
|
366
364
|
environment:
|
|
367
365
|
- NODE_TLS_REJECT_UNAUTHORIZED=0
|
|
@@ -371,27 +369,27 @@ function buildBootstrapBlock(applicationName) {
|
|
|
371
369
|
- GATEWAY_SERVICE_URL=\${PAE_GATEWAY_URL}
|
|
372
370
|
- SERVICE_ACCESS_SECRET=\${PAE_GATEWAY_SERVICE_ACCESS_SECRET}
|
|
373
371
|
volumes:
|
|
374
|
-
- \${PWD}
|
|
372
|
+
- \${PWD}/:/app/out
|
|
375
373
|
depends_on:
|
|
376
374
|
pae-nestjs-gateway-service:
|
|
377
375
|
condition: service_healthy
|
|
378
376
|
`;
|
|
379
377
|
}
|
|
380
|
-
function buildUiBlock(applicationName, uiPort) {
|
|
378
|
+
function buildUiBlock(platformName, applicationName, uiPort) {
|
|
381
379
|
return ` ${applicationName}-ui:
|
|
382
380
|
build:
|
|
383
|
-
context:
|
|
381
|
+
context: ../../${platformName}-${applicationName}/ui/${applicationName}-ui
|
|
384
382
|
dockerfile: Dockerfile.development
|
|
385
383
|
ports:
|
|
386
384
|
- ${uiPort}:80
|
|
387
385
|
volumes:
|
|
388
|
-
- \${PWD}
|
|
386
|
+
- \${PWD}/:/app/out
|
|
389
387
|
`;
|
|
390
388
|
}
|
|
391
|
-
function buildBackendBlock(applicationName, servicePort) {
|
|
389
|
+
function buildBackendBlock(platformName, applicationName, servicePort) {
|
|
392
390
|
return ` ${applicationName}-service:
|
|
393
391
|
build:
|
|
394
|
-
context:
|
|
392
|
+
context: ../../${platformName}-${applicationName}/services/${applicationName}-service
|
|
395
393
|
dockerfile: Dockerfile.development
|
|
396
394
|
args:
|
|
397
395
|
- BA_NPM_AUTH_TOKEN=$BA_NPM_AUTH_TOKEN
|
|
@@ -400,18 +398,18 @@ function buildBackendBlock(applicationName, servicePort) {
|
|
|
400
398
|
environment:
|
|
401
399
|
- GATEWAY_URL=\${PAE_GATEWAY_URL}
|
|
402
400
|
volumes:
|
|
403
|
-
- \${PWD}
|
|
401
|
+
- \${PWD}/:/app/out
|
|
404
402
|
`;
|
|
405
403
|
}
|
|
406
|
-
async function createDockerCompose(dockerComposePath, applicationName, hasUserInterface, hasBackendService, uiPort, servicePort, logger) {
|
|
407
|
-
const blocks = ["services:\n", buildBootstrapBlock(applicationName)];
|
|
404
|
+
async function createDockerCompose(dockerComposePath, applicationName, platformName, hasUserInterface, hasBackendService, uiPort, servicePort, logger) {
|
|
405
|
+
const blocks = ["services:\n", buildBootstrapBlock(platformName, applicationName)];
|
|
408
406
|
if (hasUserInterface) {
|
|
409
|
-
blocks.push(buildUiBlock(applicationName, uiPort));
|
|
407
|
+
blocks.push(buildUiBlock(platformName, applicationName, uiPort));
|
|
410
408
|
}
|
|
411
409
|
if (hasBackendService) {
|
|
412
|
-
blocks.push(buildBackendBlock(applicationName, servicePort));
|
|
410
|
+
blocks.push(buildBackendBlock(platformName, applicationName, servicePort));
|
|
413
411
|
}
|
|
414
|
-
const content = blocks.join("\n");
|
|
412
|
+
const content = blocks.join("\n") + "\n";
|
|
415
413
|
try {
|
|
416
414
|
await writeFile3(dockerComposePath, content, "utf-8");
|
|
417
415
|
logger.log(`Created docker-compose: ${dockerComposePath}`);
|
|
@@ -421,32 +419,18 @@ async function createDockerCompose(dockerComposePath, applicationName, hasUserIn
|
|
|
421
419
|
}
|
|
422
420
|
}
|
|
423
421
|
|
|
424
|
-
// src/commands/create-application/update-root-docker-compose.ts
|
|
425
|
-
import { readFile as readFile3, writeFile as writeFile4 } from "fs/promises";
|
|
426
|
-
async function updateRootDockerCompose(rootDockerComposePath, applicationName, logger) {
|
|
427
|
-
try {
|
|
428
|
-
const existing = await readFile3(rootDockerComposePath, "utf-8");
|
|
429
|
-
const includeLine = ` - path: ./${applicationName}-docker-compose.yml
|
|
430
|
-
`;
|
|
431
|
-
await writeFile4(rootDockerComposePath, existing + includeLine, "utf-8");
|
|
432
|
-
logger.log(`Updated root docker-compose: ${rootDockerComposePath}`);
|
|
433
|
-
} catch (err) {
|
|
434
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
435
|
-
logger.log(`Warning: Could not update root docker-compose \u2014 ${message}`);
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
|
|
439
422
|
// src/commands/create-application/port-allocator.ts
|
|
440
423
|
import { join as join8 } from "path";
|
|
441
|
-
import { readdir as readdir2, readFile as
|
|
442
|
-
async function getNextAvailablePort(
|
|
424
|
+
import { readdir as readdir2, readFile as readFile3 } from "fs/promises";
|
|
425
|
+
async function getNextAvailablePort(rootDir) {
|
|
443
426
|
const allPorts = [];
|
|
427
|
+
const localDir = join8(rootDir, "core", "local");
|
|
444
428
|
try {
|
|
445
429
|
const files = await readdir2(localDir);
|
|
446
|
-
const
|
|
447
|
-
for (const file of
|
|
430
|
+
const ymlFiles = files.filter((f) => f.endsWith(".yml") || f.endsWith(".yaml"));
|
|
431
|
+
for (const file of ymlFiles) {
|
|
448
432
|
try {
|
|
449
|
-
const content = await
|
|
433
|
+
const content = await readFile3(join8(localDir, file), "utf-8");
|
|
450
434
|
const regex = /^\s*-\s*"?(\d+):\d+"?\s*$/gm;
|
|
451
435
|
let match;
|
|
452
436
|
while ((match = regex.exec(content)) !== null) {
|
|
@@ -466,18 +450,69 @@ function formatError(err) {
|
|
|
466
450
|
}
|
|
467
451
|
|
|
468
452
|
// src/utils/platform-check.ts
|
|
469
|
-
import {
|
|
453
|
+
import { cwd as cwd2 } from "process";
|
|
454
|
+
import { dirname as dirname7 } from "path";
|
|
455
|
+
|
|
456
|
+
// src/utils/manifest.ts
|
|
457
|
+
import { readFile as readFile4, writeFile as writeFile4, access } from "fs/promises";
|
|
470
458
|
import { join as join9 } from "path";
|
|
471
459
|
import { cwd } from "process";
|
|
472
|
-
|
|
460
|
+
var MANIFEST_RELATIVE_PATH = join9("core", "product.manifest.json");
|
|
461
|
+
function manifestPath(rootDir) {
|
|
462
|
+
return join9(rootDir, MANIFEST_RELATIVE_PATH);
|
|
463
|
+
}
|
|
464
|
+
async function readManifest(rootDir = cwd()) {
|
|
465
|
+
const content = await readFile4(manifestPath(rootDir), "utf-8");
|
|
466
|
+
return JSON.parse(content);
|
|
467
|
+
}
|
|
468
|
+
async function writeManifest(manifest, rootDir = cwd()) {
|
|
469
|
+
await writeFile4(manifestPath(rootDir), JSON.stringify(manifest, null, 2), "utf-8");
|
|
470
|
+
}
|
|
471
|
+
async function manifestExists(rootDir = cwd()) {
|
|
473
472
|
try {
|
|
474
|
-
await access(
|
|
475
|
-
await access(join9(cwd(), "local"));
|
|
473
|
+
await access(manifestPath(rootDir));
|
|
476
474
|
return true;
|
|
477
475
|
} catch {
|
|
478
476
|
return false;
|
|
479
477
|
}
|
|
480
478
|
}
|
|
479
|
+
function createInitialManifest(params) {
|
|
480
|
+
const { organizationName, platformName, platformDisplayName } = params;
|
|
481
|
+
return {
|
|
482
|
+
version: "1",
|
|
483
|
+
product: {
|
|
484
|
+
name: platformName,
|
|
485
|
+
displayName: platformDisplayName,
|
|
486
|
+
organization: organizationName,
|
|
487
|
+
scope: `@${organizationName}`
|
|
488
|
+
},
|
|
489
|
+
applications: []
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
function addApplicationToManifest(manifest, app) {
|
|
493
|
+
return {
|
|
494
|
+
...manifest,
|
|
495
|
+
applications: [...manifest.applications, app]
|
|
496
|
+
};
|
|
497
|
+
}
|
|
498
|
+
|
|
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
|
+
}
|
|
481
516
|
|
|
482
517
|
// src/commands/create-application/create-application.command.ts
|
|
483
518
|
var CREATE_APPLICATION_COMMAND_NAME = "create-application";
|
|
@@ -487,22 +522,28 @@ var createApplicationCommand = {
|
|
|
487
522
|
};
|
|
488
523
|
async function createApplication(params, logger) {
|
|
489
524
|
const {
|
|
490
|
-
organizationName,
|
|
491
|
-
platformName,
|
|
492
525
|
applicationName,
|
|
493
526
|
applicationDisplayName,
|
|
494
527
|
applicationDescription,
|
|
495
528
|
hasUserInterface,
|
|
496
529
|
hasBackendService
|
|
497
530
|
} = params;
|
|
498
|
-
|
|
531
|
+
const rootDir = await findRootDir();
|
|
532
|
+
if (!rootDir) {
|
|
499
533
|
logger.log("Error: Cannot create an application \u2014 no platform initialized in this directory.");
|
|
500
534
|
return;
|
|
501
535
|
}
|
|
502
|
-
|
|
503
|
-
|
|
536
|
+
let manifest;
|
|
537
|
+
try {
|
|
538
|
+
manifest = await readManifest(rootDir);
|
|
539
|
+
} catch (err) {
|
|
540
|
+
logger.log(`Error: Could not read product manifest \u2014 ${formatError(err)}`);
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
const { organization: organizationName, name: platformName } = manifest.product;
|
|
544
|
+
const localPath = `../${platformName}-${applicationName}`;
|
|
545
|
+
const applicationDir = resolve(join10(rootDir, "core"), localPath);
|
|
504
546
|
const bootstrapServiceDir = join10(applicationDir, "services", `${applicationName}-bootstrap-service`);
|
|
505
|
-
const localDir = join10(rootDir, "local");
|
|
506
547
|
logger.log(`Creating application monorepo "${applicationName}"...`);
|
|
507
548
|
try {
|
|
508
549
|
await scaffoldApplicationMonorepo(applicationDir, organizationName, platformName, applicationName, logger);
|
|
@@ -513,7 +554,7 @@ async function createApplication(params, logger) {
|
|
|
513
554
|
await mkdir2(join10(applicationDir, "services"), { recursive: true });
|
|
514
555
|
await mkdir2(join10(applicationDir, "ui"), { recursive: true });
|
|
515
556
|
logger.log(`Creating bootstrap service "${applicationName}-bootstrap-service"...`);
|
|
516
|
-
const bootstrapServiceDir_var = `${applicationName}/services`;
|
|
557
|
+
const bootstrapServiceDir_var = `${platformName}-${applicationName}/services`;
|
|
517
558
|
try {
|
|
518
559
|
await scaffoldBootstrap(bootstrapServiceDir, organizationName, applicationName, bootstrapServiceDir_var, logger);
|
|
519
560
|
} catch (err) {
|
|
@@ -545,7 +586,7 @@ async function createApplication(params, logger) {
|
|
|
545
586
|
}
|
|
546
587
|
if (hasUserInterface) {
|
|
547
588
|
const uiDir = join10(applicationDir, "ui", `${applicationName}-ui`);
|
|
548
|
-
const uiBaseDir = `${applicationName}/ui`;
|
|
589
|
+
const uiBaseDir = `${platformName}-${applicationName}/ui`;
|
|
549
590
|
try {
|
|
550
591
|
await scaffoldUiModule(uiDir, organizationName, platformName, applicationName, applicationDisplayName, uiBaseDir, logger);
|
|
551
592
|
} catch (err) {
|
|
@@ -555,7 +596,7 @@ async function createApplication(params, logger) {
|
|
|
555
596
|
}
|
|
556
597
|
if (hasBackendService) {
|
|
557
598
|
const serviceDir = join10(applicationDir, "services", `${applicationName}-service`);
|
|
558
|
-
const serviceBaseDir = `${applicationName}/services`;
|
|
599
|
+
const serviceBaseDir = `${platformName}-${applicationName}/services`;
|
|
559
600
|
try {
|
|
560
601
|
await scaffoldNestjsService(serviceDir, organizationName, applicationName, applicationDisplayName, serviceBaseDir, logger);
|
|
561
602
|
} catch (err) {
|
|
@@ -563,21 +604,33 @@ async function createApplication(params, logger) {
|
|
|
563
604
|
return;
|
|
564
605
|
}
|
|
565
606
|
}
|
|
566
|
-
const dockerComposePath = join10(
|
|
567
|
-
const basePort = await getNextAvailablePort(
|
|
607
|
+
const dockerComposePath = join10(rootDir, "core", "local", `${applicationName}-docker-compose.yml`);
|
|
608
|
+
const basePort = await getNextAvailablePort(rootDir);
|
|
568
609
|
const uiPort = hasUserInterface ? basePort : 0;
|
|
569
610
|
const servicePort = hasBackendService ? hasUserInterface ? basePort + 1 : basePort : 0;
|
|
570
611
|
await createDockerCompose(
|
|
571
612
|
dockerComposePath,
|
|
572
613
|
applicationName,
|
|
614
|
+
platformName,
|
|
573
615
|
hasUserInterface,
|
|
574
616
|
hasBackendService,
|
|
575
617
|
uiPort,
|
|
576
618
|
servicePort,
|
|
577
619
|
logger
|
|
578
620
|
);
|
|
579
|
-
const
|
|
580
|
-
|
|
621
|
+
const updatedManifest = addApplicationToManifest(manifest, {
|
|
622
|
+
name: applicationName,
|
|
623
|
+
displayName: applicationDisplayName,
|
|
624
|
+
description: applicationDescription,
|
|
625
|
+
localPath,
|
|
626
|
+
repository: null
|
|
627
|
+
});
|
|
628
|
+
try {
|
|
629
|
+
await writeManifest(updatedManifest, rootDir);
|
|
630
|
+
logger.log(`Updated product manifest with application "${applicationName}".`);
|
|
631
|
+
} catch (err) {
|
|
632
|
+
logger.log(`Warning: Could not update product manifest \u2014 ${formatError(err)}`);
|
|
633
|
+
}
|
|
581
634
|
logger.log(`Done! Application "${applicationName}" created at ${applicationDir}`);
|
|
582
635
|
}
|
|
583
636
|
|
|
@@ -592,9 +645,9 @@ function camelize(name) {
|
|
|
592
645
|
|
|
593
646
|
// src/commands/init/scaffold-platform.ts
|
|
594
647
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
595
|
-
import { join as join11, dirname as
|
|
648
|
+
import { join as join11, dirname as dirname8 } from "path";
|
|
596
649
|
var templateDir = join11(
|
|
597
|
-
|
|
650
|
+
dirname8(fileURLToPath6(import.meta.url)),
|
|
598
651
|
"..",
|
|
599
652
|
"templates",
|
|
600
653
|
"platform-init-template"
|
|
@@ -605,9 +658,9 @@ async function scaffoldPlatform(outputDir, variables, logger) {
|
|
|
605
658
|
|
|
606
659
|
// src/commands/init/scaffold-platform-bootstrap.ts
|
|
607
660
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
608
|
-
import { join as join12, dirname as
|
|
661
|
+
import { join as join12, dirname as dirname9 } from "path";
|
|
609
662
|
var templateDir2 = join12(
|
|
610
|
-
|
|
663
|
+
dirname9(fileURLToPath7(import.meta.url)),
|
|
611
664
|
"..",
|
|
612
665
|
"templates",
|
|
613
666
|
"bootstrap-service-template"
|
|
@@ -618,9 +671,9 @@ async function scaffoldPlatformBootstrap(outputDir, variables, logger) {
|
|
|
618
671
|
|
|
619
672
|
// src/commands/init/scaffold-customization-ui.ts
|
|
620
673
|
import { fileURLToPath as fileURLToPath8 } from "url";
|
|
621
|
-
import { join as join13, dirname as
|
|
674
|
+
import { join as join13, dirname as dirname10 } from "path";
|
|
622
675
|
var templateDir3 = join13(
|
|
623
|
-
|
|
676
|
+
dirname10(fileURLToPath8(import.meta.url)),
|
|
624
677
|
"..",
|
|
625
678
|
"templates",
|
|
626
679
|
"customization-ui-module-template"
|
|
@@ -666,9 +719,9 @@ function generateRandomSecret() {
|
|
|
666
719
|
|
|
667
720
|
// src/commands/init/generate-local-env.ts
|
|
668
721
|
async function generateLocalEnv(outputDir, logger) {
|
|
669
|
-
const examplePath = join15(outputDir, "local", ".env.example");
|
|
670
|
-
const envPath = join15(outputDir, "local", ".env");
|
|
671
|
-
logger.log("Generating local/.env with random secrets...");
|
|
722
|
+
const examplePath = join15(outputDir, "core", "local", ".env.example");
|
|
723
|
+
const envPath = join15(outputDir, "core", "local", ".env");
|
|
724
|
+
logger.log("Generating core/local/.env with random secrets...");
|
|
672
725
|
const content = await readFile6(examplePath, "utf-8");
|
|
673
726
|
const result = content.replace(/^(PAE_AUTH_JWT_SECRET|PAE_GATEWAY_SERVICE_ACCESS_SECRET|PAE_DB_PASSWORD)=$/gm, (_, key) => {
|
|
674
727
|
return `${key}=${generateRandomSecret()}`;
|
|
@@ -708,7 +761,15 @@ async function init(params, logger) {
|
|
|
708
761
|
try {
|
|
709
762
|
await generateLocalEnv(outputDir, logger);
|
|
710
763
|
} catch (err) {
|
|
711
|
-
logger.log(`Error: Could not generate local/.env \u2014 ${formatError(err)}`);
|
|
764
|
+
logger.log(`Error: Could not generate core/local/.env \u2014 ${formatError(err)}`);
|
|
765
|
+
return;
|
|
766
|
+
}
|
|
767
|
+
try {
|
|
768
|
+
const manifest = createInitialManifest({ organizationName, platformName, platformDisplayName });
|
|
769
|
+
await writeManifest(manifest, outputDir);
|
|
770
|
+
logger.log("Created product manifest: core/product.manifest.json");
|
|
771
|
+
} catch (err) {
|
|
772
|
+
logger.log(`Error: Could not write product manifest \u2014 ${formatError(err)}`);
|
|
712
773
|
return;
|
|
713
774
|
}
|
|
714
775
|
try {
|
|
@@ -746,7 +807,6 @@ async function init(params, logger) {
|
|
|
746
807
|
|
|
747
808
|
// src/commands/configure-idp/configure-idp.command.ts
|
|
748
809
|
import { join as join17 } from "path";
|
|
749
|
-
import { cwd as cwd4 } from "process";
|
|
750
810
|
import { fetch as undiciFetch, Agent } from "undici";
|
|
751
811
|
|
|
752
812
|
// src/utils/env-reader.ts
|
|
@@ -824,11 +884,12 @@ var configureIdpCommand = {
|
|
|
824
884
|
description: "Configure an Identity Provider (IDP) in the gateway"
|
|
825
885
|
};
|
|
826
886
|
async function configureIdp(params, logger) {
|
|
827
|
-
|
|
887
|
+
const rootDir = await findRootDir();
|
|
888
|
+
if (!rootDir) {
|
|
828
889
|
logger.log("Error: Cannot configure an IDP \u2014 no platform initialized in this directory.");
|
|
829
890
|
return;
|
|
830
891
|
}
|
|
831
|
-
const envPath = join17(
|
|
892
|
+
const envPath = join17(rootDir, "core", "local", ".env");
|
|
832
893
|
let env;
|
|
833
894
|
try {
|
|
834
895
|
env = await readEnvFile(envPath);
|
|
@@ -839,11 +900,11 @@ async function configureIdp(params, logger) {
|
|
|
839
900
|
const gatewayUrl = env.get("PAE_GATEWAY_HOST_URL");
|
|
840
901
|
const accessSecret = env.get("PAE_GATEWAY_SERVICE_ACCESS_SECRET");
|
|
841
902
|
if (!gatewayUrl) {
|
|
842
|
-
logger.log("Error: PAE_GATEWAY_HOST_URL is not set in local/.env");
|
|
903
|
+
logger.log("Error: PAE_GATEWAY_HOST_URL is not set in core/local/.env");
|
|
843
904
|
return;
|
|
844
905
|
}
|
|
845
906
|
if (!accessSecret) {
|
|
846
|
-
logger.log("Error: PAE_GATEWAY_SERVICE_ACCESS_SECRET is not set in local/.env");
|
|
907
|
+
logger.log("Error: PAE_GATEWAY_SERVICE_ACCESS_SECRET is not set in core/local/.env");
|
|
847
908
|
return;
|
|
848
909
|
}
|
|
849
910
|
const provider = idpProviderRegistry.get(params.providerType);
|
|
@@ -879,6 +940,225 @@ async function configureIdp(params, logger) {
|
|
|
879
940
|
logger.log(`IDP provider "${params.name}" configured successfully.`);
|
|
880
941
|
}
|
|
881
942
|
|
|
943
|
+
// src/commands/create-service-module/create-service-module.command.ts
|
|
944
|
+
import { join as join19, resolve as resolve2 } from "path";
|
|
945
|
+
import { access as access2 } from "fs/promises";
|
|
946
|
+
|
|
947
|
+
// src/commands/create-service-module/scaffold-service-module.ts
|
|
948
|
+
import { fileURLToPath as fileURLToPath9 } from "url";
|
|
949
|
+
import { join as join18, dirname as dirname11 } from "path";
|
|
950
|
+
var nestjsServiceModuleTemplateDir2 = join18(
|
|
951
|
+
dirname11(fileURLToPath9(import.meta.url)),
|
|
952
|
+
"..",
|
|
953
|
+
"templates",
|
|
954
|
+
"nestjs-service-module-template"
|
|
955
|
+
);
|
|
956
|
+
async function scaffoldServiceModule(serviceDir, organizationName, serviceName, serviceDisplayName, serviceBaseDir, logger) {
|
|
957
|
+
logger.log(`Creating NestJS service "${serviceName}"...`);
|
|
958
|
+
await applyTemplate(
|
|
959
|
+
{
|
|
960
|
+
templateDir: nestjsServiceModuleTemplateDir2,
|
|
961
|
+
outputDir: serviceDir,
|
|
962
|
+
variables: { organizationName, serviceName, serviceDisplayName, serviceBaseDir }
|
|
963
|
+
},
|
|
964
|
+
(message) => logger.log(message)
|
|
965
|
+
);
|
|
966
|
+
logger.log(`Done! Service output: ${serviceDir}`);
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
// src/commands/create-service-module/service-module-entry-builder.ts
|
|
970
|
+
function buildCustomServiceModuleEntry(organizationName, serviceName, serviceDisplayName) {
|
|
971
|
+
return {
|
|
972
|
+
name: `@${organizationName}/${serviceName}`,
|
|
973
|
+
displayName: serviceDisplayName,
|
|
974
|
+
type: "service",
|
|
975
|
+
baseUrl: `/${serviceName}`,
|
|
976
|
+
service: {
|
|
977
|
+
host: serviceName,
|
|
978
|
+
port: 80
|
|
979
|
+
},
|
|
980
|
+
dependsOn: []
|
|
981
|
+
};
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
// src/commands/create-service-module/append-docker-compose.ts
|
|
985
|
+
import { readFile as readFile8, writeFile as writeFile7 } from "fs/promises";
|
|
986
|
+
async function appendServiceToDockerCompose(dockerComposePath, serviceName, platformName, applicationName, port, logger) {
|
|
987
|
+
const block = `
|
|
988
|
+
${serviceName}:
|
|
989
|
+
build:
|
|
990
|
+
context: ../../${platformName}-${applicationName}/services/${serviceName}
|
|
991
|
+
dockerfile: Dockerfile.development
|
|
992
|
+
args:
|
|
993
|
+
- BA_NPM_AUTH_TOKEN=$BA_NPM_AUTH_TOKEN
|
|
994
|
+
ports:
|
|
995
|
+
- ${port}:80
|
|
996
|
+
environment:
|
|
997
|
+
- GATEWAY_URL=\${PAE_GATEWAY_URL}
|
|
998
|
+
volumes:
|
|
999
|
+
- \${PWD}/:/app/out
|
|
1000
|
+
`;
|
|
1001
|
+
try {
|
|
1002
|
+
const existing = await readFile8(dockerComposePath, "utf-8");
|
|
1003
|
+
await writeFile7(dockerComposePath, existing + block, "utf-8");
|
|
1004
|
+
logger.log(`Updated docker-compose: ${dockerComposePath}`);
|
|
1005
|
+
} catch (err) {
|
|
1006
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1007
|
+
logger.log(`Warning: Could not update docker-compose \u2014 ${message}`);
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
// src/commands/create-service-module/create-service-module.command.ts
|
|
1012
|
+
var CREATE_SERVICE_MODULE_COMMAND_NAME = "create-service-module";
|
|
1013
|
+
var createServiceModuleCommand = {
|
|
1014
|
+
name: CREATE_SERVICE_MODULE_COMMAND_NAME,
|
|
1015
|
+
description: "Add a new service module to an existing application"
|
|
1016
|
+
};
|
|
1017
|
+
async function createServiceModule(params, logger) {
|
|
1018
|
+
const { applicationName, serviceName, serviceDisplayName } = params;
|
|
1019
|
+
const rootDir = await findRootDir();
|
|
1020
|
+
if (!rootDir) {
|
|
1021
|
+
logger.log("Error: Cannot create a service module \u2014 no platform initialized in this directory.");
|
|
1022
|
+
return;
|
|
1023
|
+
}
|
|
1024
|
+
let manifest;
|
|
1025
|
+
try {
|
|
1026
|
+
manifest = await readManifest(rootDir);
|
|
1027
|
+
} catch (err) {
|
|
1028
|
+
logger.log(`Error: Could not read product manifest \u2014 ${formatError(err)}`);
|
|
1029
|
+
return;
|
|
1030
|
+
}
|
|
1031
|
+
const { organization: organizationName, name: platformName } = manifest.product;
|
|
1032
|
+
const appEntry = manifest.applications.find((a) => a.name === applicationName);
|
|
1033
|
+
if (!appEntry) {
|
|
1034
|
+
logger.log(`Error: The specified application "${applicationName}" is not registered in the product manifest.`);
|
|
1035
|
+
return;
|
|
1036
|
+
}
|
|
1037
|
+
const applicationDir = resolve2(join19(rootDir, "core"), appEntry.localPath);
|
|
1038
|
+
try {
|
|
1039
|
+
await access2(applicationDir);
|
|
1040
|
+
} catch {
|
|
1041
|
+
logger.log(`Error: The specified application "${applicationName}" does not exist in the platform.`);
|
|
1042
|
+
return;
|
|
1043
|
+
}
|
|
1044
|
+
const fullServiceName = `${serviceName}-service`;
|
|
1045
|
+
const serviceDir = join19(applicationDir, "services", fullServiceName);
|
|
1046
|
+
try {
|
|
1047
|
+
await access2(serviceDir);
|
|
1048
|
+
logger.log(`Error: A service named "${fullServiceName}" already exists in application "${applicationName}".`);
|
|
1049
|
+
return;
|
|
1050
|
+
} catch {
|
|
1051
|
+
}
|
|
1052
|
+
const serviceBaseDir = `${platformName}-${applicationName}/services`;
|
|
1053
|
+
try {
|
|
1054
|
+
await scaffoldServiceModule(
|
|
1055
|
+
serviceDir,
|
|
1056
|
+
organizationName,
|
|
1057
|
+
fullServiceName,
|
|
1058
|
+
serviceDisplayName,
|
|
1059
|
+
serviceBaseDir,
|
|
1060
|
+
logger
|
|
1061
|
+
);
|
|
1062
|
+
} catch (err) {
|
|
1063
|
+
logger.log(`Error: Could not scaffold NestJS service \u2014 ${formatError(err)}`);
|
|
1064
|
+
return;
|
|
1065
|
+
}
|
|
1066
|
+
const bootstrapServiceDir = join19(applicationDir, "services", `${applicationName}-bootstrap-service`);
|
|
1067
|
+
const moduleEntry = buildCustomServiceModuleEntry(organizationName, fullServiceName, serviceDisplayName);
|
|
1068
|
+
await addModuleEntry(bootstrapServiceDir, applicationName, moduleEntry, logger);
|
|
1069
|
+
const dockerComposePath = join19(rootDir, "core", "local", `${applicationName}-docker-compose.yml`);
|
|
1070
|
+
const port = await getNextAvailablePort(rootDir);
|
|
1071
|
+
await appendServiceToDockerCompose(dockerComposePath, fullServiceName, platformName, applicationName, port, logger);
|
|
1072
|
+
logger.log(`Done! Service module "${fullServiceName}" added to application "${applicationName}".`);
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
// src/commands/create-ui-module/create-ui-module.command.ts
|
|
1076
|
+
import { join as join20, resolve as resolve3 } from "path";
|
|
1077
|
+
import { access as access3, readdir as readdir3 } from "fs/promises";
|
|
1078
|
+
|
|
1079
|
+
// src/commands/create-ui-module/append-ui-docker-compose.ts
|
|
1080
|
+
import { readFile as readFile9, writeFile as writeFile8 } from "fs/promises";
|
|
1081
|
+
async function appendUiToDockerCompose(dockerComposePath, platformName, applicationName, port, logger) {
|
|
1082
|
+
const block = `
|
|
1083
|
+
${applicationName}-ui:
|
|
1084
|
+
build:
|
|
1085
|
+
context: ../../${platformName}-${applicationName}/ui/${applicationName}-ui
|
|
1086
|
+
dockerfile: Dockerfile.development
|
|
1087
|
+
ports:
|
|
1088
|
+
- ${port}:80
|
|
1089
|
+
volumes:
|
|
1090
|
+
- \${PWD}/:/app/out
|
|
1091
|
+
`;
|
|
1092
|
+
try {
|
|
1093
|
+
const existing = await readFile9(dockerComposePath, "utf-8");
|
|
1094
|
+
await writeFile8(dockerComposePath, existing + block, "utf-8");
|
|
1095
|
+
logger.log(`Updated docker-compose: ${dockerComposePath}`);
|
|
1096
|
+
} catch (err) {
|
|
1097
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1098
|
+
logger.log(`Warning: Could not update docker-compose \u2014 ${message}`);
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
// src/commands/create-ui-module/create-ui-module.command.ts
|
|
1103
|
+
var CREATE_UI_MODULE_COMMAND_NAME = "create-ui-module";
|
|
1104
|
+
var createUiModuleCommand = {
|
|
1105
|
+
name: CREATE_UI_MODULE_COMMAND_NAME,
|
|
1106
|
+
description: "Add a UI module to an existing application"
|
|
1107
|
+
};
|
|
1108
|
+
async function createUiModule(params, logger) {
|
|
1109
|
+
const { applicationName, applicationDisplayName } = params;
|
|
1110
|
+
const rootDir = await findRootDir();
|
|
1111
|
+
if (!rootDir) {
|
|
1112
|
+
logger.log("Error: Cannot create a UI module \u2014 no platform initialized in this directory.");
|
|
1113
|
+
return;
|
|
1114
|
+
}
|
|
1115
|
+
let manifest;
|
|
1116
|
+
try {
|
|
1117
|
+
manifest = await readManifest(rootDir);
|
|
1118
|
+
} catch (err) {
|
|
1119
|
+
logger.log(`Error: Could not read product manifest \u2014 ${formatError(err)}`);
|
|
1120
|
+
return;
|
|
1121
|
+
}
|
|
1122
|
+
const { organization: organizationName, name: platformName } = manifest.product;
|
|
1123
|
+
const appEntry = manifest.applications.find((a) => a.name === applicationName);
|
|
1124
|
+
if (!appEntry) {
|
|
1125
|
+
logger.log(`Error: The specified application "${applicationName}" is not registered in the product manifest.`);
|
|
1126
|
+
return;
|
|
1127
|
+
}
|
|
1128
|
+
const applicationDir = resolve3(join20(rootDir, "core"), appEntry.localPath);
|
|
1129
|
+
try {
|
|
1130
|
+
await access3(applicationDir);
|
|
1131
|
+
} catch {
|
|
1132
|
+
logger.log(`Error: The specified application "${applicationName}" does not exist in the platform.`);
|
|
1133
|
+
return;
|
|
1134
|
+
}
|
|
1135
|
+
const uiDir = join20(applicationDir, "ui");
|
|
1136
|
+
try {
|
|
1137
|
+
const uiEntries = await readdir3(uiDir);
|
|
1138
|
+
const existingUiModules = uiEntries.filter((e) => e !== ".gitkeep");
|
|
1139
|
+
if (existingUiModules.length > 0) {
|
|
1140
|
+
logger.log(`Error: Currently we support only one UI module per application. Application "${applicationName}" already has a UI module.`);
|
|
1141
|
+
return;
|
|
1142
|
+
}
|
|
1143
|
+
} catch {
|
|
1144
|
+
}
|
|
1145
|
+
const uiOutputDir = join20(uiDir, `${applicationName}-ui`);
|
|
1146
|
+
const uiBaseDir = `${platformName}-${applicationName}/ui`;
|
|
1147
|
+
try {
|
|
1148
|
+
await scaffoldUiModule(uiOutputDir, organizationName, platformName, applicationName, applicationDisplayName, uiBaseDir, logger);
|
|
1149
|
+
} catch (err) {
|
|
1150
|
+
logger.log(`Error: Could not scaffold UI module \u2014 ${formatError(err)}`);
|
|
1151
|
+
return;
|
|
1152
|
+
}
|
|
1153
|
+
const bootstrapServiceDir = join20(applicationDir, "services", `${applicationName}-bootstrap-service`);
|
|
1154
|
+
const moduleEntry = buildUiModuleEntry(organizationName, applicationName, applicationDisplayName);
|
|
1155
|
+
await addModuleEntry(bootstrapServiceDir, applicationName, moduleEntry, logger);
|
|
1156
|
+
const dockerComposePath = join20(rootDir, "core", "local", `${applicationName}-docker-compose.yml`);
|
|
1157
|
+
const port = await getNextAvailablePort(rootDir);
|
|
1158
|
+
await appendUiToDockerCompose(dockerComposePath, platformName, applicationName, port, logger);
|
|
1159
|
+
logger.log(`Done! UI module "${applicationName}-ui" added to application "${applicationName}".`);
|
|
1160
|
+
}
|
|
1161
|
+
|
|
882
1162
|
// src/commands/registry.ts
|
|
883
1163
|
var CommandRegistry = class {
|
|
884
1164
|
commands = /* @__PURE__ */ new Map();
|
|
@@ -904,6 +1184,8 @@ var registry = new CommandRegistry();
|
|
|
904
1184
|
registry.register(createApplicationCommand);
|
|
905
1185
|
registry.register(initCommand);
|
|
906
1186
|
registry.register(configureIdpCommand);
|
|
1187
|
+
registry.register(createServiceModuleCommand);
|
|
1188
|
+
registry.register(createUiModuleCommand);
|
|
907
1189
|
|
|
908
1190
|
// src/app-state.ts
|
|
909
1191
|
var APP_STATE = {
|
|
@@ -916,11 +1198,6 @@ var APP_STATE = {
|
|
|
916
1198
|
// src/hooks/use-command-runner.ts
|
|
917
1199
|
import { useState as useState2, useCallback, useRef } from "react";
|
|
918
1200
|
|
|
919
|
-
// src/controllers/ui/create-application.ui-controller.ts
|
|
920
|
-
import { readFile as readFile8 } from "fs/promises";
|
|
921
|
-
import { join as join18 } from "path";
|
|
922
|
-
import { cwd as cwd5 } from "process";
|
|
923
|
-
|
|
924
1201
|
// src/services/create-application.service.ts
|
|
925
1202
|
async function createApplicationService(params, logger) {
|
|
926
1203
|
await createApplication(params, logger);
|
|
@@ -932,24 +1209,6 @@ async function createApplicationUiController(ctx) {
|
|
|
932
1209
|
ctx.log("Error: Cannot create an application \u2014 no platform initialized in this directory.");
|
|
933
1210
|
return;
|
|
934
1211
|
}
|
|
935
|
-
let organizationName;
|
|
936
|
-
let platformName;
|
|
937
|
-
try {
|
|
938
|
-
const corePackageJson = JSON.parse(
|
|
939
|
-
await readFile8(join18(cwd5(), "core", "package.json"), "utf-8")
|
|
940
|
-
);
|
|
941
|
-
const scopeMatch = corePackageJson.name.match(/^@([^/]+)\//);
|
|
942
|
-
organizationName = scopeMatch?.[1];
|
|
943
|
-
const rawName = corePackageJson.name.replace(/^@[^/]+\//, "").replace(/-core$/, "");
|
|
944
|
-
platformName = rawName;
|
|
945
|
-
if (!organizationName || !platformName) {
|
|
946
|
-
throw new Error(`Could not parse organization/platform from package name: "${corePackageJson.name}"`);
|
|
947
|
-
}
|
|
948
|
-
} catch (err) {
|
|
949
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
950
|
-
ctx.log(`Error: Could not read core/package.json \u2014 ${message}`);
|
|
951
|
-
return;
|
|
952
|
-
}
|
|
953
1212
|
const applicationName = await ctx.prompt("Application name:");
|
|
954
1213
|
if (!/^[a-z0-9-]+$/.test(applicationName)) {
|
|
955
1214
|
ctx.log(`Error: Application name "${applicationName}" is invalid. Use only lowercase letters, numbers, and hyphens.`);
|
|
@@ -969,8 +1228,6 @@ async function createApplicationUiController(ctx) {
|
|
|
969
1228
|
}
|
|
970
1229
|
await createApplicationService(
|
|
971
1230
|
{
|
|
972
|
-
organizationName,
|
|
973
|
-
platformName,
|
|
974
1231
|
applicationName,
|
|
975
1232
|
applicationDisplayName,
|
|
976
1233
|
applicationDescription,
|
|
@@ -1032,11 +1289,64 @@ async function configureIdpUiController(ctx) {
|
|
|
1032
1289
|
);
|
|
1033
1290
|
}
|
|
1034
1291
|
|
|
1292
|
+
// src/services/create-service-module.service.ts
|
|
1293
|
+
async function createServiceModuleService(params, logger) {
|
|
1294
|
+
await createServiceModule(params, logger);
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1297
|
+
// src/controllers/ui/create-service-module.ui-controller.ts
|
|
1298
|
+
async function createServiceModuleUiController(ctx) {
|
|
1299
|
+
if (!await isPlatformInitialized()) {
|
|
1300
|
+
ctx.log("Error: Cannot create a service module \u2014 no platform initialized in this directory.");
|
|
1301
|
+
return;
|
|
1302
|
+
}
|
|
1303
|
+
const applicationName = await ctx.prompt("Application name:");
|
|
1304
|
+
if (!/^[a-z0-9-]+$/.test(applicationName)) {
|
|
1305
|
+
ctx.log(`Error: Application name "${applicationName}" is invalid. Use only lowercase letters, numbers, and hyphens.`);
|
|
1306
|
+
return;
|
|
1307
|
+
}
|
|
1308
|
+
const serviceName = await ctx.prompt("Service name:");
|
|
1309
|
+
if (!/^[a-z0-9-]+$/.test(serviceName)) {
|
|
1310
|
+
ctx.log(`Error: Service name "${serviceName}" is invalid. Use only lowercase letters, numbers, and hyphens.`);
|
|
1311
|
+
return;
|
|
1312
|
+
}
|
|
1313
|
+
const serviceDisplayName = await ctx.prompt("Service display name:");
|
|
1314
|
+
await createServiceModuleService(
|
|
1315
|
+
{ applicationName, serviceName, serviceDisplayName },
|
|
1316
|
+
ctx
|
|
1317
|
+
);
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1320
|
+
// src/services/create-ui-module.service.ts
|
|
1321
|
+
async function createUiModuleService(params, logger) {
|
|
1322
|
+
await createUiModule(params, logger);
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
// src/controllers/ui/create-ui-module.ui-controller.ts
|
|
1326
|
+
async function createUiModuleUiController(ctx) {
|
|
1327
|
+
if (!await isPlatformInitialized()) {
|
|
1328
|
+
ctx.log("Error: Cannot create a UI module \u2014 no platform initialized in this directory.");
|
|
1329
|
+
return;
|
|
1330
|
+
}
|
|
1331
|
+
const applicationName = await ctx.prompt("Application name:");
|
|
1332
|
+
if (!/^[a-z0-9-]+$/.test(applicationName)) {
|
|
1333
|
+
ctx.log(`Error: Application name "${applicationName}" is invalid. Use only lowercase letters, numbers, and hyphens.`);
|
|
1334
|
+
return;
|
|
1335
|
+
}
|
|
1336
|
+
const applicationDisplayName = await ctx.prompt("Application display name:");
|
|
1337
|
+
await createUiModuleService(
|
|
1338
|
+
{ applicationName, applicationDisplayName },
|
|
1339
|
+
ctx
|
|
1340
|
+
);
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1035
1343
|
// src/controllers/ui/registry.ts
|
|
1036
1344
|
var uiControllers = /* @__PURE__ */ new Map([
|
|
1037
1345
|
[CREATE_APPLICATION_COMMAND_NAME, createApplicationUiController],
|
|
1038
1346
|
[INIT_COMMAND_NAME, initUiController],
|
|
1039
|
-
[CONFIGURE_IDP_COMMAND_NAME, configureIdpUiController]
|
|
1347
|
+
[CONFIGURE_IDP_COMMAND_NAME, configureIdpUiController],
|
|
1348
|
+
[CREATE_SERVICE_MODULE_COMMAND_NAME, createServiceModuleUiController],
|
|
1349
|
+
[CREATE_UI_MODULE_COMMAND_NAME, createUiModuleUiController]
|
|
1040
1350
|
]);
|
|
1041
1351
|
|
|
1042
1352
|
// src/hooks/use-command-runner.ts
|
|
@@ -1051,7 +1361,7 @@ function useCommandRunner({ appendStaticItem, setState }) {
|
|
|
1051
1361
|
abortControllerRef.current = null;
|
|
1052
1362
|
promptResolveRef.current = null;
|
|
1053
1363
|
}, []);
|
|
1054
|
-
const
|
|
1364
|
+
const runCommand2 = useCallback(
|
|
1055
1365
|
(cmd) => {
|
|
1056
1366
|
const controller = new AbortController();
|
|
1057
1367
|
abortControllerRef.current = controller;
|
|
@@ -1065,14 +1375,14 @@ function useCommandRunner({ appendStaticItem, setState }) {
|
|
|
1065
1375
|
}
|
|
1066
1376
|
},
|
|
1067
1377
|
prompt(message) {
|
|
1068
|
-
return new Promise((
|
|
1378
|
+
return new Promise((resolve5, reject) => {
|
|
1069
1379
|
if (controller.signal.aborted) {
|
|
1070
1380
|
reject(new DOMException("Aborted", "AbortError"));
|
|
1071
1381
|
return;
|
|
1072
1382
|
}
|
|
1073
1383
|
setPromptMessage(message);
|
|
1074
1384
|
setPromptValue("");
|
|
1075
|
-
promptResolveRef.current =
|
|
1385
|
+
promptResolveRef.current = resolve5;
|
|
1076
1386
|
setState(APP_STATE.PROMPTING);
|
|
1077
1387
|
controller.signal.addEventListener(
|
|
1078
1388
|
"abort",
|
|
@@ -1104,15 +1414,15 @@ function useCommandRunner({ appendStaticItem, setState }) {
|
|
|
1104
1414
|
);
|
|
1105
1415
|
const handlePromptSubmit = useCallback(
|
|
1106
1416
|
(value) => {
|
|
1107
|
-
const
|
|
1417
|
+
const resolve5 = promptResolveRef.current;
|
|
1108
1418
|
promptResolveRef.current = null;
|
|
1109
1419
|
setState(APP_STATE.EXECUTING);
|
|
1110
|
-
|
|
1420
|
+
resolve5?.(value);
|
|
1111
1421
|
},
|
|
1112
1422
|
[setState]
|
|
1113
1423
|
);
|
|
1114
1424
|
return {
|
|
1115
|
-
runCommand,
|
|
1425
|
+
runCommand: runCommand2,
|
|
1116
1426
|
handlePromptSubmit,
|
|
1117
1427
|
abortExecution,
|
|
1118
1428
|
promptMessage,
|
|
@@ -1134,7 +1444,7 @@ function App() {
|
|
|
1134
1444
|
const appendStaticItem = useCallback2((item) => {
|
|
1135
1445
|
setStaticItems((prev) => [...prev, item]);
|
|
1136
1446
|
}, []);
|
|
1137
|
-
const { runCommand, handlePromptSubmit, abortExecution, promptMessage, promptValue, setPromptValue } = useCommandRunner({ appendStaticItem, setState });
|
|
1447
|
+
const { runCommand: runCommand2, handlePromptSubmit, abortExecution, promptMessage, promptValue, setPromptValue } = useCommandRunner({ appendStaticItem, setState });
|
|
1138
1448
|
const query = inputValue.startsWith("/") ? inputValue.slice(1) : "";
|
|
1139
1449
|
const filteredCommands = registry.search(query);
|
|
1140
1450
|
useInput(
|
|
@@ -1166,7 +1476,7 @@ function App() {
|
|
|
1166
1476
|
const cmd = filteredCommands[selectedIndex];
|
|
1167
1477
|
if (cmd) {
|
|
1168
1478
|
setInputValue("");
|
|
1169
|
-
|
|
1479
|
+
runCommand2(cmd);
|
|
1170
1480
|
}
|
|
1171
1481
|
return;
|
|
1172
1482
|
}
|
|
@@ -1202,9 +1512,9 @@ function App() {
|
|
|
1202
1512
|
if (!value.startsWith("/")) return;
|
|
1203
1513
|
const name = value.slice(1).trim();
|
|
1204
1514
|
const cmd = registry.get(name);
|
|
1205
|
-
if (cmd)
|
|
1515
|
+
if (cmd) runCommand2(cmd);
|
|
1206
1516
|
},
|
|
1207
|
-
[
|
|
1517
|
+
[runCommand2]
|
|
1208
1518
|
);
|
|
1209
1519
|
function renderActiveArea() {
|
|
1210
1520
|
switch (state) {
|
|
@@ -1240,9 +1550,6 @@ function App() {
|
|
|
1240
1550
|
}
|
|
1241
1551
|
|
|
1242
1552
|
// src/controllers/cli/create-application.cli-controller.ts
|
|
1243
|
-
import { readFile as readFile9 } from "fs/promises";
|
|
1244
|
-
import { join as join19 } from "path";
|
|
1245
|
-
import { cwd as cwd6 } from "process";
|
|
1246
1553
|
async function createApplicationCliController(args2) {
|
|
1247
1554
|
if (!await isPlatformInitialized()) {
|
|
1248
1555
|
console.error("Error: Cannot create an application \u2014 no platform initialized in this directory.");
|
|
@@ -1263,28 +1570,8 @@ async function createApplicationCliController(args2) {
|
|
|
1263
1570
|
console.error(`Error: Application name "${applicationName}" is invalid. Use only lowercase letters, numbers, and hyphens.`);
|
|
1264
1571
|
process.exit(1);
|
|
1265
1572
|
}
|
|
1266
|
-
let organizationName;
|
|
1267
|
-
let platformName;
|
|
1268
|
-
try {
|
|
1269
|
-
const corePackageJson = JSON.parse(
|
|
1270
|
-
await readFile9(join19(cwd6(), "core", "package.json"), "utf-8")
|
|
1271
|
-
);
|
|
1272
|
-
const scopeMatch = corePackageJson.name.match(/^@([^/]+)\//);
|
|
1273
|
-
organizationName = scopeMatch?.[1];
|
|
1274
|
-
const rawName = corePackageJson.name.replace(/^@[^/]+\//, "").replace(/-core$/, "");
|
|
1275
|
-
platformName = rawName;
|
|
1276
|
-
if (!organizationName || !platformName) {
|
|
1277
|
-
throw new Error(`Could not parse organization/platform from package name: "${corePackageJson.name}"`);
|
|
1278
|
-
}
|
|
1279
|
-
} catch (err) {
|
|
1280
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
1281
|
-
console.error(`Error: Could not read core/package.json \u2014 ${message}`);
|
|
1282
|
-
process.exit(1);
|
|
1283
|
-
}
|
|
1284
1573
|
await createApplicationService(
|
|
1285
1574
|
{
|
|
1286
|
-
organizationName,
|
|
1287
|
-
platformName,
|
|
1288
1575
|
applicationName,
|
|
1289
1576
|
applicationDisplayName,
|
|
1290
1577
|
applicationDescription,
|
|
@@ -1341,22 +1628,167 @@ async function configureIdpCliController(args2) {
|
|
|
1341
1628
|
await configureIdpService({ providerType, name, issuer, clientId, clientSecret, extras }, logger);
|
|
1342
1629
|
}
|
|
1343
1630
|
|
|
1344
|
-
// src/
|
|
1631
|
+
// src/commands/local-scripts/docker-compose-orchestrator.ts
|
|
1345
1632
|
import { spawn } from "child_process";
|
|
1346
|
-
import { access as
|
|
1347
|
-
import { join as
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1633
|
+
import { access as access4 } from "fs/promises";
|
|
1634
|
+
import { join as join21 } from "path";
|
|
1635
|
+
function runDockerCompose(args2, logger, rootDir, signal) {
|
|
1636
|
+
return new Promise((resolvePromise) => {
|
|
1637
|
+
const child = spawn("docker", ["compose", ...args2], {
|
|
1638
|
+
shell: false,
|
|
1639
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
1640
|
+
cwd: rootDir
|
|
1641
|
+
});
|
|
1642
|
+
const onAbort = () => {
|
|
1643
|
+
child.kill("SIGTERM");
|
|
1644
|
+
};
|
|
1645
|
+
if (signal) {
|
|
1646
|
+
if (signal.aborted) {
|
|
1647
|
+
child.kill("SIGTERM");
|
|
1648
|
+
resolvePromise();
|
|
1649
|
+
return;
|
|
1650
|
+
}
|
|
1651
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
1652
|
+
}
|
|
1653
|
+
child.stdout.on("data", (data) => {
|
|
1654
|
+
for (const line of data.toString().split("\n")) {
|
|
1655
|
+
if (line.trim()) logger.log(line);
|
|
1656
|
+
}
|
|
1657
|
+
});
|
|
1658
|
+
child.stderr.on("data", (data) => {
|
|
1659
|
+
for (const line of data.toString().split("\n")) {
|
|
1660
|
+
if (line.trim()) logger.log(line);
|
|
1661
|
+
}
|
|
1662
|
+
});
|
|
1663
|
+
child.on("close", (code, sig) => {
|
|
1664
|
+
signal?.removeEventListener("abort", onAbort);
|
|
1665
|
+
if (sig === "SIGTERM" || signal?.aborted) {
|
|
1666
|
+
logger.log("Command cancelled.");
|
|
1667
|
+
} else if (code !== 0) {
|
|
1668
|
+
logger.log(`docker compose exited with code ${code}.`);
|
|
1669
|
+
}
|
|
1670
|
+
resolvePromise();
|
|
1671
|
+
});
|
|
1672
|
+
child.on("error", (err) => {
|
|
1673
|
+
signal?.removeEventListener("abort", onAbort);
|
|
1674
|
+
logger.log(`Failed to run docker compose: ${err.message}`);
|
|
1675
|
+
resolvePromise();
|
|
1676
|
+
});
|
|
1677
|
+
});
|
|
1678
|
+
}
|
|
1679
|
+
async function getAppComposePaths(rootDir, manifest) {
|
|
1680
|
+
const results = [];
|
|
1681
|
+
for (const app of manifest.applications) {
|
|
1682
|
+
const composePath = join21(rootDir, "core", "local", `${app.name}-docker-compose.yml`);
|
|
1683
|
+
try {
|
|
1684
|
+
await access4(composePath);
|
|
1685
|
+
results.push({ composePath, appName: app.name });
|
|
1686
|
+
} catch {
|
|
1687
|
+
}
|
|
1688
|
+
}
|
|
1689
|
+
return results;
|
|
1690
|
+
}
|
|
1691
|
+
async function buildAllComposeArgs(rootDir, manifest, logger) {
|
|
1692
|
+
const localDir = join21(rootDir, "core", "local");
|
|
1693
|
+
const fileArgs = [
|
|
1694
|
+
"-f",
|
|
1695
|
+
join21(localDir, "platform-docker-compose.yml"),
|
|
1696
|
+
"-f",
|
|
1697
|
+
join21(localDir, "core-docker-compose.yml")
|
|
1698
|
+
];
|
|
1699
|
+
const appEntries = await getAppComposePaths(rootDir, manifest);
|
|
1700
|
+
for (const { composePath, appName } of appEntries) {
|
|
1701
|
+
fileArgs.push("-f", composePath);
|
|
1702
|
+
}
|
|
1703
|
+
for (const app of manifest.applications) {
|
|
1704
|
+
if (!appEntries.find((e) => e.appName === app.name)) {
|
|
1705
|
+
logger.log(`Warning: No docker-compose found for application "${app.name}" in core/local/ \u2014 skipping.`);
|
|
1706
|
+
}
|
|
1355
1707
|
}
|
|
1356
|
-
return
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1708
|
+
return fileArgs;
|
|
1709
|
+
}
|
|
1710
|
+
async function startEnvironment(rootDir, manifest, logger, signal) {
|
|
1711
|
+
const platformName = manifest.product.name;
|
|
1712
|
+
const envFile = join21(rootDir, "core", "local", ".env");
|
|
1713
|
+
const fileArgs = await buildAllComposeArgs(rootDir, manifest, logger);
|
|
1714
|
+
const localDir = join21(rootDir, "core", "local");
|
|
1715
|
+
logger.log("Starting environment...");
|
|
1716
|
+
await runDockerCompose(
|
|
1717
|
+
[
|
|
1718
|
+
"-p",
|
|
1719
|
+
`${platformName}-platform`,
|
|
1720
|
+
"--project-directory",
|
|
1721
|
+
localDir,
|
|
1722
|
+
"--env-file",
|
|
1723
|
+
envFile,
|
|
1724
|
+
...fileArgs,
|
|
1725
|
+
"up",
|
|
1726
|
+
"-d",
|
|
1727
|
+
"--build",
|
|
1728
|
+
"--remove-orphans"
|
|
1729
|
+
],
|
|
1730
|
+
logger,
|
|
1731
|
+
rootDir,
|
|
1732
|
+
signal
|
|
1733
|
+
);
|
|
1734
|
+
}
|
|
1735
|
+
async function stopEnvironment(rootDir, manifest, logger, signal) {
|
|
1736
|
+
const platformName = manifest.product.name;
|
|
1737
|
+
const envFile = join21(rootDir, "core", "local", ".env");
|
|
1738
|
+
const fileArgs = await buildAllComposeArgs(rootDir, manifest, logger);
|
|
1739
|
+
const localDir = join21(rootDir, "core", "local");
|
|
1740
|
+
logger.log("Stopping environment...");
|
|
1741
|
+
await runDockerCompose(
|
|
1742
|
+
[
|
|
1743
|
+
"-p",
|
|
1744
|
+
`${platformName}-platform`,
|
|
1745
|
+
"--project-directory",
|
|
1746
|
+
localDir,
|
|
1747
|
+
"--env-file",
|
|
1748
|
+
envFile,
|
|
1749
|
+
...fileArgs,
|
|
1750
|
+
"down"
|
|
1751
|
+
],
|
|
1752
|
+
logger,
|
|
1753
|
+
rootDir,
|
|
1754
|
+
signal
|
|
1755
|
+
);
|
|
1756
|
+
}
|
|
1757
|
+
async function destroyEnvironment(rootDir, manifest, logger, signal) {
|
|
1758
|
+
const platformName = manifest.product.name;
|
|
1759
|
+
const envFile = join21(rootDir, "core", "local", ".env");
|
|
1760
|
+
const fileArgs = await buildAllComposeArgs(rootDir, manifest, logger);
|
|
1761
|
+
const localDir = join21(rootDir, "core", "local");
|
|
1762
|
+
logger.log("Destroying environment...");
|
|
1763
|
+
await runDockerCompose(
|
|
1764
|
+
[
|
|
1765
|
+
"-p",
|
|
1766
|
+
`${platformName}-platform`,
|
|
1767
|
+
"--project-directory",
|
|
1768
|
+
localDir,
|
|
1769
|
+
"--env-file",
|
|
1770
|
+
envFile,
|
|
1771
|
+
...fileArgs,
|
|
1772
|
+
"down",
|
|
1773
|
+
"-v",
|
|
1774
|
+
"--rmi",
|
|
1775
|
+
"all"
|
|
1776
|
+
],
|
|
1777
|
+
logger,
|
|
1778
|
+
rootDir,
|
|
1779
|
+
signal
|
|
1780
|
+
);
|
|
1781
|
+
}
|
|
1782
|
+
|
|
1783
|
+
// src/commands/local-scripts/npm-orchestrator.ts
|
|
1784
|
+
import { spawn as spawn2 } from "child_process";
|
|
1785
|
+
import { access as access5 } from "fs/promises";
|
|
1786
|
+
import { join as join22, resolve as resolve4 } from "path";
|
|
1787
|
+
function runCommand(command, args2, workDir, logger, signal) {
|
|
1788
|
+
return new Promise((resolvePromise) => {
|
|
1789
|
+
const child = spawn2(command, args2, {
|
|
1790
|
+
cwd: workDir,
|
|
1791
|
+
shell: false,
|
|
1360
1792
|
stdio: ["ignore", "pipe", "pipe"]
|
|
1361
1793
|
});
|
|
1362
1794
|
const onAbort = () => {
|
|
@@ -1365,7 +1797,7 @@ async function runNpmScript(scriptName, logger, signal) {
|
|
|
1365
1797
|
if (signal) {
|
|
1366
1798
|
if (signal.aborted) {
|
|
1367
1799
|
child.kill("SIGTERM");
|
|
1368
|
-
|
|
1800
|
+
resolvePromise();
|
|
1369
1801
|
return;
|
|
1370
1802
|
}
|
|
1371
1803
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
@@ -1383,19 +1815,72 @@ async function runNpmScript(scriptName, logger, signal) {
|
|
|
1383
1815
|
child.on("close", (code, sig) => {
|
|
1384
1816
|
signal?.removeEventListener("abort", onAbort);
|
|
1385
1817
|
if (sig === "SIGTERM" || signal?.aborted) {
|
|
1386
|
-
logger.log(
|
|
1818
|
+
logger.log("Command cancelled.");
|
|
1387
1819
|
} else if (code !== 0) {
|
|
1388
|
-
logger.log(`Command "
|
|
1820
|
+
logger.log(`Command "${command} ${args2.join(" ")}" exited with code ${code}.`);
|
|
1389
1821
|
}
|
|
1390
|
-
|
|
1822
|
+
resolvePromise();
|
|
1391
1823
|
});
|
|
1392
1824
|
child.on("error", (err) => {
|
|
1393
1825
|
signal?.removeEventListener("abort", onAbort);
|
|
1394
|
-
logger.log(`Failed to run "
|
|
1395
|
-
|
|
1826
|
+
logger.log(`Failed to run "${command} ${args2.join(" ")}": ${err.message}`);
|
|
1827
|
+
resolvePromise();
|
|
1396
1828
|
});
|
|
1397
1829
|
});
|
|
1398
1830
|
}
|
|
1831
|
+
async function dirExists(dirPath) {
|
|
1832
|
+
try {
|
|
1833
|
+
await access5(dirPath);
|
|
1834
|
+
return true;
|
|
1835
|
+
} catch {
|
|
1836
|
+
return false;
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1839
|
+
async function installDependencies(rootDir, manifest, logger, signal) {
|
|
1840
|
+
const coreDir = join22(rootDir, "core");
|
|
1841
|
+
const appDirs = [];
|
|
1842
|
+
for (const app of manifest.applications) {
|
|
1843
|
+
const appDir = resolve4(join22(rootDir, "core"), app.localPath);
|
|
1844
|
+
if (!await dirExists(appDir)) {
|
|
1845
|
+
logger.log(`Warning: Application directory "${app.name}" not found at ${appDir} \u2014 skipping install.`);
|
|
1846
|
+
continue;
|
|
1847
|
+
}
|
|
1848
|
+
appDirs.push({ name: app.name, dir: appDir });
|
|
1849
|
+
}
|
|
1850
|
+
const targets = [{ name: "core", dir: coreDir }, ...appDirs];
|
|
1851
|
+
logger.log(`Installing dependencies in parallel: ${targets.map((t) => t.name).join(", ")}...`);
|
|
1852
|
+
await Promise.all(
|
|
1853
|
+
targets.map(
|
|
1854
|
+
({ name, dir }) => runCommand("npm", ["install"], dir, logger, signal).then(() => {
|
|
1855
|
+
logger.log(`\u2713 ${name} install done`);
|
|
1856
|
+
})
|
|
1857
|
+
)
|
|
1858
|
+
);
|
|
1859
|
+
}
|
|
1860
|
+
async function buildAll(rootDir, manifest, logger, signal) {
|
|
1861
|
+
const coreDir = join22(rootDir, "core");
|
|
1862
|
+
logger.log("Building core/...");
|
|
1863
|
+
await runCommand("npx", ["turbo", "build"], coreDir, logger, signal);
|
|
1864
|
+
if (signal?.aborted) return;
|
|
1865
|
+
const appDirs = [];
|
|
1866
|
+
for (const app of manifest.applications) {
|
|
1867
|
+
const appDir = resolve4(join22(rootDir, "core"), app.localPath);
|
|
1868
|
+
if (!await dirExists(appDir)) {
|
|
1869
|
+
logger.log(`Warning: Application directory "${app.name}" not found at ${appDir} \u2014 skipping build.`);
|
|
1870
|
+
continue;
|
|
1871
|
+
}
|
|
1872
|
+
appDirs.push({ name: app.name, dir: appDir });
|
|
1873
|
+
}
|
|
1874
|
+
if (appDirs.length === 0) return;
|
|
1875
|
+
logger.log(`Building apps in parallel: ${appDirs.map((a) => a.name).join(", ")}...`);
|
|
1876
|
+
await Promise.all(
|
|
1877
|
+
appDirs.map(
|
|
1878
|
+
({ name, dir }) => runCommand("npm", ["run", "build"], dir, logger, signal).then(() => {
|
|
1879
|
+
logger.log(`\u2713 ${name} build done`);
|
|
1880
|
+
})
|
|
1881
|
+
)
|
|
1882
|
+
);
|
|
1883
|
+
}
|
|
1399
1884
|
|
|
1400
1885
|
// src/commands/local-scripts/local-script.command.ts
|
|
1401
1886
|
var INSTALL_COMMAND_NAME = "install";
|
|
@@ -1404,7 +1889,37 @@ var START_COMMAND_NAME = "start";
|
|
|
1404
1889
|
var STOP_COMMAND_NAME = "stop";
|
|
1405
1890
|
var DESTROY_COMMAND_NAME = "destroy";
|
|
1406
1891
|
async function runLocalScript(scriptName, logger, signal) {
|
|
1407
|
-
await
|
|
1892
|
+
const rootDir = await findRootDir();
|
|
1893
|
+
if (!rootDir) {
|
|
1894
|
+
logger.log(`Error: Cannot run "${scriptName}" \u2014 no platform initialized in this directory.`);
|
|
1895
|
+
return;
|
|
1896
|
+
}
|
|
1897
|
+
let manifest;
|
|
1898
|
+
try {
|
|
1899
|
+
manifest = await readManifest(rootDir);
|
|
1900
|
+
} catch (err) {
|
|
1901
|
+
logger.log(`Error: Could not read product manifest \u2014 ${formatError(err)}`);
|
|
1902
|
+
return;
|
|
1903
|
+
}
|
|
1904
|
+
switch (scriptName) {
|
|
1905
|
+
case START_COMMAND_NAME:
|
|
1906
|
+
await startEnvironment(rootDir, manifest, logger, signal);
|
|
1907
|
+
break;
|
|
1908
|
+
case STOP_COMMAND_NAME:
|
|
1909
|
+
await stopEnvironment(rootDir, manifest, logger, signal);
|
|
1910
|
+
break;
|
|
1911
|
+
case DESTROY_COMMAND_NAME:
|
|
1912
|
+
await destroyEnvironment(rootDir, manifest, logger, signal);
|
|
1913
|
+
break;
|
|
1914
|
+
case INSTALL_COMMAND_NAME:
|
|
1915
|
+
await installDependencies(rootDir, manifest, logger, signal);
|
|
1916
|
+
break;
|
|
1917
|
+
case BUILD_COMMAND_NAME:
|
|
1918
|
+
await buildAll(rootDir, manifest, logger, signal);
|
|
1919
|
+
break;
|
|
1920
|
+
default:
|
|
1921
|
+
logger.log(`Error: Unknown script "${scriptName}".`);
|
|
1922
|
+
}
|
|
1408
1923
|
}
|
|
1409
1924
|
|
|
1410
1925
|
// src/services/local-script.service.ts
|
|
@@ -1455,11 +1970,59 @@ function createLocalScriptCliController(scriptName) {
|
|
|
1455
1970
|
};
|
|
1456
1971
|
}
|
|
1457
1972
|
|
|
1973
|
+
// src/controllers/cli/create-service-module.cli-controller.ts
|
|
1974
|
+
async function createServiceModuleCliController(args2) {
|
|
1975
|
+
if (!await isPlatformInitialized()) {
|
|
1976
|
+
console.error("Error: Cannot create a service module \u2014 no platform initialized in this directory.");
|
|
1977
|
+
process.exit(1);
|
|
1978
|
+
}
|
|
1979
|
+
const { applicationName, serviceName, serviceDisplayName } = args2;
|
|
1980
|
+
if (!applicationName || !serviceName || !serviceDisplayName) {
|
|
1981
|
+
console.error("Error: applicationName, serviceName, and serviceDisplayName are required.");
|
|
1982
|
+
process.exit(1);
|
|
1983
|
+
}
|
|
1984
|
+
if (!/^[a-z0-9-]+$/.test(applicationName)) {
|
|
1985
|
+
console.error(`Error: Application name "${applicationName}" is invalid. Use only lowercase letters, numbers, and hyphens.`);
|
|
1986
|
+
process.exit(1);
|
|
1987
|
+
}
|
|
1988
|
+
if (!/^[a-z0-9-]+$/.test(serviceName)) {
|
|
1989
|
+
console.error(`Error: Service name "${serviceName}" is invalid. Use only lowercase letters, numbers, and hyphens.`);
|
|
1990
|
+
process.exit(1);
|
|
1991
|
+
}
|
|
1992
|
+
await createServiceModuleService(
|
|
1993
|
+
{ applicationName, serviceName, serviceDisplayName },
|
|
1994
|
+
{ log: console.log }
|
|
1995
|
+
);
|
|
1996
|
+
}
|
|
1997
|
+
|
|
1998
|
+
// src/controllers/cli/create-ui-module.cli-controller.ts
|
|
1999
|
+
async function createUiModuleCliController(args2) {
|
|
2000
|
+
if (!await isPlatformInitialized()) {
|
|
2001
|
+
console.error("Error: Cannot create a UI module \u2014 no platform initialized in this directory.");
|
|
2002
|
+
process.exit(1);
|
|
2003
|
+
}
|
|
2004
|
+
const { applicationName, applicationDisplayName } = args2;
|
|
2005
|
+
if (!applicationName || !applicationDisplayName) {
|
|
2006
|
+
console.error("Error: applicationName and applicationDisplayName are required.");
|
|
2007
|
+
process.exit(1);
|
|
2008
|
+
}
|
|
2009
|
+
if (!/^[a-z0-9-]+$/.test(applicationName)) {
|
|
2010
|
+
console.error(`Error: Application name "${applicationName}" is invalid. Use only lowercase letters, numbers, and hyphens.`);
|
|
2011
|
+
process.exit(1);
|
|
2012
|
+
}
|
|
2013
|
+
await createUiModuleService(
|
|
2014
|
+
{ applicationName, applicationDisplayName },
|
|
2015
|
+
{ log: console.log }
|
|
2016
|
+
);
|
|
2017
|
+
}
|
|
2018
|
+
|
|
1458
2019
|
// src/controllers/cli/registry.ts
|
|
1459
2020
|
var cliControllers = /* @__PURE__ */ new Map([
|
|
1460
2021
|
[CREATE_APPLICATION_COMMAND_NAME, createApplicationCliController],
|
|
1461
2022
|
[INIT_COMMAND_NAME, initCliController],
|
|
1462
2023
|
[CONFIGURE_IDP_COMMAND_NAME, configureIdpCliController],
|
|
2024
|
+
[CREATE_SERVICE_MODULE_COMMAND_NAME, createServiceModuleCliController],
|
|
2025
|
+
[CREATE_UI_MODULE_COMMAND_NAME, createUiModuleCliController],
|
|
1463
2026
|
[INSTALL_COMMAND_NAME, createLocalScriptCliController(INSTALL_COMMAND_NAME)],
|
|
1464
2027
|
[BUILD_COMMAND_NAME, createLocalScriptCliController(BUILD_COMMAND_NAME)],
|
|
1465
2028
|
[START_COMMAND_NAME, createLocalScriptCliController(START_COMMAND_NAME)],
|