opticore-feature-component 1.0.7 → 1.1.0
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/{core-TFP6J3AE.js → chunk-X2ZHQ6T5.js} +421 -430
- package/dist/cli.cjs +3062 -0
- package/dist/cli.d.cts +13 -0
- package/dist/cli.d.ts +13 -0
- package/dist/cli.js +28 -0
- package/dist/index.cjs +1452 -1788
- package/dist/index.js +4 -1
- package/package.json +13 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import process3 from "process";
|
|
3
3
|
import fs5 from "fs";
|
|
4
4
|
import path9 from "path";
|
|
5
|
-
import { isCancel as
|
|
5
|
+
import { isCancel as isCancel9 } from "@clack/prompts";
|
|
6
6
|
|
|
7
7
|
// src/utils/welcomeMessage.utils.ts
|
|
8
8
|
import cfonts from "cfonts";
|
|
@@ -33,10 +33,10 @@ function UWelcomeMessage() {
|
|
|
33
33
|
|
|
34
34
|
// src/utils/choiceFeatureCleanModule.ts
|
|
35
35
|
import colors2 from "ansi-colors";
|
|
36
|
-
import { isCancel } from "@clack/prompts";
|
|
36
|
+
import { isCancel as isCancel2 } from "@clack/prompts";
|
|
37
37
|
|
|
38
38
|
// src/utils/prompt.utils.ts
|
|
39
|
-
import { confirm, select, text } from "@clack/prompts";
|
|
39
|
+
import { confirm, isCancel, select, text } from "@clack/prompts";
|
|
40
40
|
import colors from "ansi-colors";
|
|
41
41
|
|
|
42
42
|
// src/utils/fsModule.utils.ts
|
|
@@ -110,11 +110,14 @@ var UPrompt = class {
|
|
|
110
110
|
process.exit(0);
|
|
111
111
|
}
|
|
112
112
|
static async select(message, defaultValue, options) {
|
|
113
|
-
|
|
113
|
+
const optSelected = await select({
|
|
114
114
|
message,
|
|
115
115
|
initialValue: defaultValue,
|
|
116
116
|
options
|
|
117
117
|
});
|
|
118
|
+
if (isCancel(optSelected)) {
|
|
119
|
+
return optSelected;
|
|
120
|
+
}
|
|
118
121
|
return optSelected[0];
|
|
119
122
|
}
|
|
120
123
|
};
|
|
@@ -131,7 +134,7 @@ async function choiceFeatureCleanModule() {
|
|
|
131
134
|
{ label: "Build your own architecture", value: ["custom_feature"] }
|
|
132
135
|
]
|
|
133
136
|
);
|
|
134
|
-
if (
|
|
137
|
+
if (isCancel2(featureSelected)) {
|
|
135
138
|
console.log(`${colors2.bgRed(`${colors2.white("Operation cancelled.")}`)}`);
|
|
136
139
|
process.exit(0);
|
|
137
140
|
} else {
|
|
@@ -155,7 +158,7 @@ You have chosen : ${choice === "opticore_clean_module" ? colors3.cyan("OptiCoreJ
|
|
|
155
158
|
const diagram = [
|
|
156
159
|
` ` + I(`INFRASTRUCTURE`),
|
|
157
160
|
` ` + I(`controllers \xB7 repositories \xB7 routes`),
|
|
158
|
-
`
|
|
161
|
+
` ` + I(`presenters \xB7 routes`),
|
|
159
162
|
``,
|
|
160
163
|
` ` + A(`APPLICATION`),
|
|
161
164
|
` ` + A(`ports \xB7 interfaces \xB7 dtos \xB7 use-cases`),
|
|
@@ -179,7 +182,7 @@ var _featureName = async () => {
|
|
|
179
182
|
"Enter feature's name :",
|
|
180
183
|
"login",
|
|
181
184
|
(value) => {
|
|
182
|
-
let pattern = new RegExp("^[a-z][A-Za-
|
|
185
|
+
let pattern = new RegExp("^[a-z][A-Za-z_-]+$");
|
|
183
186
|
if (!value) {
|
|
184
187
|
return "Please enter a feature's name.";
|
|
185
188
|
}
|
|
@@ -267,7 +270,7 @@ async function _controllerType(messageText, defaultValue, options) {
|
|
|
267
270
|
}
|
|
268
271
|
|
|
269
272
|
// src/core/components/application/createController.application.ts
|
|
270
|
-
import { isCancel as
|
|
273
|
+
import { isCancel as isCancel5 } from "@clack/prompts";
|
|
271
274
|
|
|
272
275
|
// src/core/domains/constants/cleanType.constant.ts
|
|
273
276
|
var CCleanType = {
|
|
@@ -284,6 +287,7 @@ import colors6 from "ansi-colors";
|
|
|
284
287
|
import path2 from "path";
|
|
285
288
|
import colors5 from "ansi-colors";
|
|
286
289
|
import fs3 from "fs";
|
|
290
|
+
import { isCancel as isCancel3 } from "@clack/prompts";
|
|
287
291
|
import { LoggerCore as LoggerCore2 } from "opticore-logger";
|
|
288
292
|
|
|
289
293
|
// src/templates/cleanComponents/controller.template.ts
|
|
@@ -1387,11 +1391,21 @@ var capitalize15 = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
|
|
1387
1391
|
// src/templates/simpleComponent/simpleRouter.template.ts
|
|
1388
1392
|
var resolveRoute2 = (methodName, featureName) => {
|
|
1389
1393
|
const lower = methodName.toLowerCase();
|
|
1390
|
-
if (lower.includes("findall") || lower.includes("getall"))
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
if (lower.includes("
|
|
1394
|
-
|
|
1394
|
+
if (lower.includes("findall") || lower.includes("getall")) {
|
|
1395
|
+
return { httpMethod: "get", path: `/${featureName}` };
|
|
1396
|
+
}
|
|
1397
|
+
if (lower.includes("findbyid") || lower.includes("getbyid") || lower.includes("getone")) {
|
|
1398
|
+
return { httpMethod: "get", path: `/${featureName}/:id` };
|
|
1399
|
+
}
|
|
1400
|
+
if (lower.includes("create") || lower.includes("add")) {
|
|
1401
|
+
return { httpMethod: "post", path: `/${featureName}` };
|
|
1402
|
+
}
|
|
1403
|
+
if (lower.includes("update") || lower.includes("edit")) {
|
|
1404
|
+
return { httpMethod: "put", path: `/${featureName}/:id` };
|
|
1405
|
+
}
|
|
1406
|
+
if (lower.includes("delete") || lower.includes("remove")) {
|
|
1407
|
+
return { httpMethod: "delete", path: `/${featureName}/:id` };
|
|
1408
|
+
}
|
|
1395
1409
|
return { httpMethod: "get", path: `/${featureName}/${lower}` };
|
|
1396
1410
|
};
|
|
1397
1411
|
var generateSimpleRouterHandlerTemplate = (featureName, controllerMethods) => {
|
|
@@ -1462,7 +1476,7 @@ var FeatureComponentGeneratorUtils = class {
|
|
|
1462
1476
|
const entityName = `${this.capitalize(featureName)}Entity`;
|
|
1463
1477
|
const filePath = path2.join(entityDir, `${featureName}.entity.ts`);
|
|
1464
1478
|
UFsModule.createFile(filePath, generateEntityTemplate(entityName, featureName));
|
|
1465
|
-
console.log(colors5.green(`\
|
|
1479
|
+
console.log(colors5.green(`\u2714 Entity created: ${filePath}`));
|
|
1466
1480
|
}
|
|
1467
1481
|
/**
|
|
1468
1482
|
* Creates the domain event file.
|
|
@@ -1470,7 +1484,7 @@ var FeatureComponentGeneratorUtils = class {
|
|
|
1470
1484
|
static async createEvent(featureName, eventDir) {
|
|
1471
1485
|
const filePath = path2.join(eventDir, `${featureName}.event.ts`);
|
|
1472
1486
|
UFsModule.createFile(filePath, generateEventTemplate(featureName));
|
|
1473
|
-
console.log(colors5.green(`\
|
|
1487
|
+
console.log(colors5.green(`\u2714 Event created: ${filePath}`));
|
|
1474
1488
|
}
|
|
1475
1489
|
/**
|
|
1476
1490
|
* Creates the domain exception file.
|
|
@@ -1478,7 +1492,7 @@ var FeatureComponentGeneratorUtils = class {
|
|
|
1478
1492
|
static async createException(featureName, exceptionDir) {
|
|
1479
1493
|
const filePath = path2.join(exceptionDir, `${featureName}.exception.ts`);
|
|
1480
1494
|
UFsModule.createFile(filePath, generateExceptionTemplate(featureName));
|
|
1481
|
-
console.log(colors5.green(`\
|
|
1495
|
+
console.log(colors5.green(`\u2714 Exception created: ${filePath}`));
|
|
1482
1496
|
}
|
|
1483
1497
|
/**
|
|
1484
1498
|
* Creates the repository port interface.
|
|
@@ -1487,7 +1501,7 @@ var FeatureComponentGeneratorUtils = class {
|
|
|
1487
1501
|
const interfaceName = `I${this.capitalize(featureName)}Repository`;
|
|
1488
1502
|
const filePath = path2.join(interfaceDir, `${featureName}.repository.interface.ts`);
|
|
1489
1503
|
UFsModule.createFile(filePath, generateRepositoryInterfaceTemplate(interfaceName, featureName));
|
|
1490
|
-
console.log(colors5.green(`\
|
|
1504
|
+
console.log(colors5.green(`\u2714 Repository interface created: ${filePath}`));
|
|
1491
1505
|
}
|
|
1492
1506
|
/**
|
|
1493
1507
|
* Creates the presenter port interface.
|
|
@@ -1495,7 +1509,7 @@ var FeatureComponentGeneratorUtils = class {
|
|
|
1495
1509
|
static async createPresenterInterface(featureName, presenterInterfaceDir) {
|
|
1496
1510
|
const filePath = path2.join(presenterInterfaceDir, `${featureName}.presenter.interface.ts`);
|
|
1497
1511
|
UFsModule.createFile(filePath, generatePresenterInterfaceTemplate(featureName));
|
|
1498
|
-
console.log(colors5.green(`\
|
|
1512
|
+
console.log(colors5.green(`\u2714 Presenter interface created: ${filePath}`));
|
|
1499
1513
|
}
|
|
1500
1514
|
/**
|
|
1501
1515
|
* Creates the application service port interface.
|
|
@@ -1503,7 +1517,7 @@ var FeatureComponentGeneratorUtils = class {
|
|
|
1503
1517
|
static async createService(featureName, serviceDir) {
|
|
1504
1518
|
const filePath = path2.join(serviceDir, `${featureName}.service.ts`);
|
|
1505
1519
|
UFsModule.createFile(filePath, generateServiceTemplate(featureName));
|
|
1506
|
-
console.log(colors5.green(`\
|
|
1520
|
+
console.log(colors5.green(`\u2714 Service interface created: ${filePath}`));
|
|
1507
1521
|
}
|
|
1508
1522
|
/**
|
|
1509
1523
|
* Creates the DTO file (input + output shapes + mapper).
|
|
@@ -1511,7 +1525,7 @@ var FeatureComponentGeneratorUtils = class {
|
|
|
1511
1525
|
static async createDto(featureName, dtoDir) {
|
|
1512
1526
|
const filePath = path2.join(dtoDir, `${featureName}.dto.ts`);
|
|
1513
1527
|
UFsModule.createFile(filePath, generateDtoTemplate(featureName));
|
|
1514
|
-
console.log(colors5.green(`\
|
|
1528
|
+
console.log(colors5.green(`\u2714 DTO created: ${filePath}`));
|
|
1515
1529
|
}
|
|
1516
1530
|
/**
|
|
1517
1531
|
* Creates the use case file.
|
|
@@ -1520,7 +1534,7 @@ var FeatureComponentGeneratorUtils = class {
|
|
|
1520
1534
|
const useCaseName = `${this.capitalize(featureName)}UseCase`;
|
|
1521
1535
|
const filePath = path2.join(useCaseDir, `${featureName}.usecase.ts`);
|
|
1522
1536
|
UFsModule.createFile(filePath, generateUseCaseTemplate(useCaseName, featureName));
|
|
1523
|
-
console.log(colors5.green(`\
|
|
1537
|
+
console.log(colors5.green(`\u2714 UseCase created: ${filePath}`));
|
|
1524
1538
|
}
|
|
1525
1539
|
/**
|
|
1526
1540
|
* Creates the concrete repository implementation.
|
|
@@ -1529,7 +1543,7 @@ var FeatureComponentGeneratorUtils = class {
|
|
|
1529
1543
|
const interfaceImportPath = `../../../application/ports/repositories/${featureName}.repository.interface`;
|
|
1530
1544
|
const filePath = path2.join(repositoryImplDir, `${featureName}.repository.ts`);
|
|
1531
1545
|
UFsModule.createFile(filePath, generateRepositoryImplTemplate(featureName, interfaceImportPath));
|
|
1532
|
-
console.log(colors5.green(`\
|
|
1546
|
+
console.log(colors5.green(`\u2714 Repository implementation created: ${filePath}`));
|
|
1533
1547
|
}
|
|
1534
1548
|
/**
|
|
1535
1549
|
* Creates the concrete presenter implementation.
|
|
@@ -1537,7 +1551,7 @@ var FeatureComponentGeneratorUtils = class {
|
|
|
1537
1551
|
static async createPresenterImpl(featureName, presenterImplDir) {
|
|
1538
1552
|
const filePath = path2.join(presenterImplDir, `${featureName}.presenter.ts`);
|
|
1539
1553
|
UFsModule.createFile(filePath, generatePresenterImplTemplate(featureName));
|
|
1540
|
-
console.log(colors5.green(`\
|
|
1554
|
+
console.log(colors5.green(`\u2714 Presenter implementation created: ${filePath}`));
|
|
1541
1555
|
}
|
|
1542
1556
|
/**
|
|
1543
1557
|
* Creates the HTTP controller.
|
|
@@ -1551,13 +1565,15 @@ var FeatureComponentGeneratorUtils = class {
|
|
|
1551
1565
|
const wantsMethods = await UPrompt.confirm("Do you want to add methods to the controller?");
|
|
1552
1566
|
let methods = [];
|
|
1553
1567
|
let content;
|
|
1554
|
-
if (wantsMethods) {
|
|
1568
|
+
if (wantsMethods && !isCancel3(wantsMethods)) {
|
|
1555
1569
|
const methodsText = await UPrompt.text(
|
|
1556
1570
|
"Enter the method names (comma separated):",
|
|
1557
1571
|
"create, findAll, findById, update, delete",
|
|
1558
1572
|
(v) => v ? void 0 : "You must enter at least one method."
|
|
1559
1573
|
);
|
|
1560
|
-
|
|
1574
|
+
if (!isCancel3(methodsText)) {
|
|
1575
|
+
methods = methodsText.split(",").map((m) => m.trim()).filter(Boolean);
|
|
1576
|
+
}
|
|
1561
1577
|
content = generateControllerTemplate(controllerName, featureName, methods);
|
|
1562
1578
|
} else {
|
|
1563
1579
|
content = `import { Request, Response } from "express";
|
|
@@ -1566,7 +1582,7 @@ export class ${controllerName} {}
|
|
|
1566
1582
|
`;
|
|
1567
1583
|
}
|
|
1568
1584
|
UFsModule.createFile(filePath, content);
|
|
1569
|
-
console.log(colors5.green(`\
|
|
1585
|
+
console.log(colors5.green(`\u2714 Controller created: ${filePath}`));
|
|
1570
1586
|
return { controllerName, methods };
|
|
1571
1587
|
}
|
|
1572
1588
|
/**
|
|
@@ -1575,7 +1591,7 @@ export class ${controllerName} {}
|
|
|
1575
1591
|
static async createModel(featureName, modelDir) {
|
|
1576
1592
|
const filePath = path2.join(modelDir, `${featureName}.model.ts`);
|
|
1577
1593
|
UFsModule.createFile(filePath, generateModelTemplate(featureName));
|
|
1578
|
-
console.log(colors5.green(`\
|
|
1594
|
+
console.log(colors5.green(`\u2714 Model created: ${filePath}`));
|
|
1579
1595
|
}
|
|
1580
1596
|
/**
|
|
1581
1597
|
* Creates the simple repository (no interface, uses the model directly).
|
|
@@ -1583,7 +1599,7 @@ export class ${controllerName} {}
|
|
|
1583
1599
|
static async createSimpleRepository(featureName, repositoryDir) {
|
|
1584
1600
|
const filePath = path2.join(repositoryDir, `${featureName}.repository.ts`);
|
|
1585
1601
|
UFsModule.createFile(filePath, generateSimpleRepositoryTemplate(featureName));
|
|
1586
|
-
console.log(colors5.green(`\
|
|
1602
|
+
console.log(colors5.green(`\u2714 Repository created: ${filePath}`));
|
|
1587
1603
|
}
|
|
1588
1604
|
/**
|
|
1589
1605
|
* Creates the simple concrete service (no interface, wires the repository).
|
|
@@ -1591,7 +1607,7 @@ export class ${controllerName} {}
|
|
|
1591
1607
|
static async createSimpleService(featureName, serviceDir) {
|
|
1592
1608
|
const filePath = path2.join(serviceDir, `${featureName}.service.ts`);
|
|
1593
1609
|
UFsModule.createFile(filePath, generateSimpleServiceTemplate(featureName));
|
|
1594
|
-
console.log(colors5.green(`\
|
|
1610
|
+
console.log(colors5.green(`\u2714 Service created: ${filePath}`));
|
|
1595
1611
|
}
|
|
1596
1612
|
/**
|
|
1597
1613
|
* Creates the simple controller (delegates to service, no use-case/presenter).
|
|
@@ -1602,13 +1618,15 @@ export class ${controllerName} {}
|
|
|
1602
1618
|
const wantsMethods = await UPrompt.confirm("Do you want to add methods to the controller?");
|
|
1603
1619
|
let methods = [];
|
|
1604
1620
|
let content;
|
|
1605
|
-
if (wantsMethods) {
|
|
1621
|
+
if (wantsMethods && !isCancel3(wantsMethods)) {
|
|
1606
1622
|
const methodsText = await UPrompt.text(
|
|
1607
1623
|
"Enter the method names (comma separated):",
|
|
1608
1624
|
"create, findAll, findById, update, delete",
|
|
1609
1625
|
(v) => v ? void 0 : "You must enter at least one method."
|
|
1610
1626
|
);
|
|
1611
|
-
|
|
1627
|
+
if (!isCancel3(methodsText)) {
|
|
1628
|
+
methods = methodsText.split(",").map((m) => m.trim()).filter(Boolean);
|
|
1629
|
+
}
|
|
1612
1630
|
content = generateSimpleControllerTemplate(controllerName, featureName, methods);
|
|
1613
1631
|
} else {
|
|
1614
1632
|
content = `import { Request, Response } from "express";
|
|
@@ -1617,7 +1635,7 @@ export class ${controllerName} {}
|
|
|
1617
1635
|
`;
|
|
1618
1636
|
}
|
|
1619
1637
|
UFsModule.createFile(filePath, content);
|
|
1620
|
-
console.log(colors5.green(`\
|
|
1638
|
+
console.log(colors5.green(`\u2714 Controller created: ${filePath}`));
|
|
1621
1639
|
return { controllerName, methods };
|
|
1622
1640
|
}
|
|
1623
1641
|
/**
|
|
@@ -1628,7 +1646,7 @@ export class ${controllerName} {}
|
|
|
1628
1646
|
const filePath = path2.join(routerHandlerDir, `${featureName}.router.handler.ts`);
|
|
1629
1647
|
const content = this.structure === "simple" ? generateSimpleRouterHandlerTemplate(featureName, controllerMethods) : generateRouterHandlerTemplate(featureName, controllerMethods);
|
|
1630
1648
|
UFsModule.createFile(filePath, content);
|
|
1631
|
-
console.log(colors5.green(`\
|
|
1649
|
+
console.log(colors5.green(`\u2714 Router Handler created: ${filePath}`));
|
|
1632
1650
|
}
|
|
1633
1651
|
/**
|
|
1634
1652
|
* Creates the feature router and registers it in register.router.ts.
|
|
@@ -1639,7 +1657,7 @@ export class ${controllerName} {}
|
|
|
1639
1657
|
const content = this.structure === "simple" ? generateSimpleRouterTemplate(featureName) : generateRouterTemplate(featureName);
|
|
1640
1658
|
UFsModule.createFile(filePath, content);
|
|
1641
1659
|
await this.updateRegisterRouter(featureName);
|
|
1642
|
-
console.log(colors5.green(`\
|
|
1660
|
+
console.log(colors5.green(`\u2714 Router created: ${filePath}`));
|
|
1643
1661
|
}
|
|
1644
1662
|
static capitalize(str) {
|
|
1645
1663
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
@@ -1654,13 +1672,13 @@ export class ${controllerName} {}
|
|
|
1654
1672
|
try {
|
|
1655
1673
|
if (!fs3.existsSync(this.REGISTER_ROUTER_PATH)) {
|
|
1656
1674
|
console.log(
|
|
1657
|
-
colors5.yellow(`\u26A0
|
|
1675
|
+
colors5.yellow(`\u26A0 register.router.ts not found at ${this.REGISTER_ROUTER_PATH}, skipping auto-registration.`)
|
|
1658
1676
|
);
|
|
1659
1677
|
return;
|
|
1660
1678
|
}
|
|
1661
1679
|
let content = fs3.readFileSync(this.REGISTER_ROUTER_PATH, "utf-8");
|
|
1662
1680
|
if (content.includes(`import { ${routerName} } from`)) {
|
|
1663
|
-
console.log(colors5.cyan(`\u2139
|
|
1681
|
+
console.log(colors5.cyan(`\u2139 ${routerName} is already registered.`));
|
|
1664
1682
|
return;
|
|
1665
1683
|
}
|
|
1666
1684
|
const lines = content.split("\n");
|
|
@@ -1678,12 +1696,12 @@ export class ${controllerName} {}
|
|
|
1678
1696
|
const ARRAY_CLOSE = "]);";
|
|
1679
1697
|
const startIdx = content.indexOf(ARRAY_OPEN);
|
|
1680
1698
|
if (startIdx === -1) {
|
|
1681
|
-
console.log(colors5.yellow(`\u26A0
|
|
1699
|
+
console.log(colors5.yellow(`\u26A0 Could not find 'registered([' in register.router.ts.`));
|
|
1682
1700
|
return;
|
|
1683
1701
|
}
|
|
1684
1702
|
const endIdx = content.indexOf(ARRAY_CLOSE, startIdx + ARRAY_OPEN.length);
|
|
1685
1703
|
if (endIdx === -1) {
|
|
1686
|
-
console.log(colors5.yellow(`\u26A0
|
|
1704
|
+
console.log(colors5.yellow(`\u26A0 Could not find matching ']);' in register.router.ts.`));
|
|
1687
1705
|
return;
|
|
1688
1706
|
}
|
|
1689
1707
|
const arrayContent = content.substring(startIdx + ARRAY_OPEN.length, endIdx);
|
|
@@ -1696,9 +1714,9 @@ export class ${controllerName} {}
|
|
|
1696
1714
|
${indentedRoutes}
|
|
1697
1715
|
` + content.substring(endIdx);
|
|
1698
1716
|
fs3.writeFileSync(this.REGISTER_ROUTER_PATH, newContent, "utf-8");
|
|
1699
|
-
console.log(colors5.green(`\
|
|
1717
|
+
console.log(colors5.green(`\u2714 register.router.ts updated with ${routerName}.`));
|
|
1700
1718
|
} catch (error) {
|
|
1701
|
-
console.error(colors5.red(`\
|
|
1719
|
+
console.error(colors5.red(`\u2718 Failed to update register.router.ts: ${error.message}`));
|
|
1702
1720
|
}
|
|
1703
1721
|
}
|
|
1704
1722
|
};
|
|
@@ -1802,14 +1820,14 @@ var fullCleanComponentTemplate = async (featureName) => {
|
|
|
1802
1820
|
// src/templates/cleanComponentByStep/cleanComponentByStep.template.ts
|
|
1803
1821
|
import path5 from "path";
|
|
1804
1822
|
import colors8 from "ansi-colors";
|
|
1805
|
-
import { isCancel as
|
|
1823
|
+
import { isCancel as isCancel4 } from "@clack/prompts";
|
|
1806
1824
|
var cleanComponentByStepTemplate = async (featureName) => {
|
|
1807
1825
|
const base = path5.join("src", "features", featureName);
|
|
1808
1826
|
let created = 0;
|
|
1809
1827
|
let controller = { controllerName: "", methods: [] };
|
|
1810
1828
|
const ask = async (label) => {
|
|
1811
1829
|
const answer = await UPrompt.confirm(label, false);
|
|
1812
|
-
if (
|
|
1830
|
+
if (isCancel4(answer)) {
|
|
1813
1831
|
UFsModule.removeDir(base, true, true);
|
|
1814
1832
|
process.exit(0);
|
|
1815
1833
|
}
|
|
@@ -1818,7 +1836,7 @@ var cleanComponentByStepTemplate = async (featureName) => {
|
|
|
1818
1836
|
const track = () => {
|
|
1819
1837
|
created++;
|
|
1820
1838
|
};
|
|
1821
|
-
console.log(colors8.bold(colors8.cyan("\n
|
|
1839
|
+
console.log(colors8.bold(colors8.cyan("\n Domain ")));
|
|
1822
1840
|
const mkDir = (dir) => {
|
|
1823
1841
|
UFsModule.createDirectoryRecursively(dir);
|
|
1824
1842
|
return dir;
|
|
@@ -1835,7 +1853,7 @@ var cleanComponentByStepTemplate = async (featureName) => {
|
|
|
1835
1853
|
await FeatureComponentGeneratorUtils.createException(featureName, mkDir(path5.join(base, "domain", "exceptions")));
|
|
1836
1854
|
track();
|
|
1837
1855
|
}
|
|
1838
|
-
console.log(colors8.bold(colors8.cyan("\n
|
|
1856
|
+
console.log(colors8.bold(colors8.cyan("\n Application ")));
|
|
1839
1857
|
if (await ask(`Repo Interface - ${featureName}.repository.interface.ts`)) {
|
|
1840
1858
|
await FeatureComponentGeneratorUtils.createRepositoryInterface(featureName, mkDir(path5.join(base, "application", "ports", "repositories")));
|
|
1841
1859
|
track();
|
|
@@ -1856,7 +1874,7 @@ var cleanComponentByStepTemplate = async (featureName) => {
|
|
|
1856
1874
|
await FeatureComponentGeneratorUtils.createUseCase(featureName, mkDir(path5.join(base, "application", "use-cases")));
|
|
1857
1875
|
track();
|
|
1858
1876
|
}
|
|
1859
|
-
console.log(colors8.bold(colors8.cyan("\n
|
|
1877
|
+
console.log(colors8.bold(colors8.cyan("\n Infrastructure ")));
|
|
1860
1878
|
if (await ask(`Repo Impl - ${featureName}.repository.ts`)) {
|
|
1861
1879
|
await FeatureComponentGeneratorUtils.createRepositoryImpl(featureName, mkDir(path5.join(base, "infrastructure", "adapters", "repositories")));
|
|
1862
1880
|
track();
|
|
@@ -1879,7 +1897,7 @@ var cleanComponentByStepTemplate = async (featureName) => {
|
|
|
1879
1897
|
}
|
|
1880
1898
|
if (created === 0) {
|
|
1881
1899
|
console.log(colors8.yellow(`
|
|
1882
|
-
\u26A0
|
|
1900
|
+
\u26A0 No files were created for feature "${featureName}".`));
|
|
1883
1901
|
} else {
|
|
1884
1902
|
console.log(
|
|
1885
1903
|
colors8.bgGreen(colors8.white(`
|
|
@@ -1900,7 +1918,7 @@ var createComponentApplication = async (featureDirectory, featureName) => {
|
|
|
1900
1918
|
{ label: "Full CLEAN Architecture component", value: [CCleanType.full_clean_component] }
|
|
1901
1919
|
]
|
|
1902
1920
|
);
|
|
1903
|
-
if (
|
|
1921
|
+
if (isCancel5(askComponentType) === true || askComponentType === void 0) {
|
|
1904
1922
|
BaseService._cancelOperation(featureDirectory);
|
|
1905
1923
|
} else {
|
|
1906
1924
|
switch (askComponentType) {
|
|
@@ -1917,11 +1935,11 @@ var createComponentApplication = async (featureDirectory, featureName) => {
|
|
|
1917
1935
|
}
|
|
1918
1936
|
};
|
|
1919
1937
|
|
|
1920
|
-
// src/templates/customModule/
|
|
1938
|
+
// src/templates/customModule/buildYourOwnArchitectureScaffold.template.ts
|
|
1921
1939
|
import path6 from "path";
|
|
1922
1940
|
import fs4 from "fs";
|
|
1923
1941
|
import colors9 from "ansi-colors";
|
|
1924
|
-
import { isCancel as
|
|
1942
|
+
import { isCancel as isCancel6 } from "@clack/prompts";
|
|
1925
1943
|
|
|
1926
1944
|
// src/core/domains/constants/resolveRoute.constant.ts
|
|
1927
1945
|
var CResolveRoute = (methodName, moduleName) => {
|
|
@@ -1934,373 +1952,318 @@ var CResolveRoute = (methodName, moduleName) => {
|
|
|
1934
1952
|
return { httpMethod: "get", path: `/${moduleName}/${lower}` };
|
|
1935
1953
|
};
|
|
1936
1954
|
|
|
1937
|
-
// src/templates/customModule/
|
|
1938
|
-
var capitalize17 = (
|
|
1939
|
-
var
|
|
1940
|
-
const
|
|
1941
|
-
const
|
|
1942
|
-
const body = methods.length === 0 ? ` // TODO: add your handler methods here` : methods.map((m) => generateMethod3(m, cap, serviceName)).join("\n");
|
|
1943
|
-
const serviceImport = methods.length === 0 ? `` : `import { ${serviceName} } from "./${moduleName}.service";
|
|
1944
|
-
`;
|
|
1945
|
-
return `import { Request, Response } from "opticore-express";
|
|
1946
|
-
import { ResponseHandler, HttpStatusCode, IResponseHandlerSuccessData } from "opticore-http-response";
|
|
1947
|
-
${serviceImport}
|
|
1948
|
-
export class ${controllerName} {${methods.length > 0 ? `
|
|
1949
|
-
private static buildService(): ${serviceName} {
|
|
1950
|
-
return new ${serviceName}();
|
|
1951
|
-
}
|
|
1952
|
-
` : ""}
|
|
1953
|
-
${body}
|
|
1954
|
-
private static handleError(error: unknown) {
|
|
1955
|
-
const message = error instanceof Error ? error.message : "Internal server error";
|
|
1956
|
-
return ResponseHandler.error(message, HttpStatusCode.INTERNAL_SERVER_ERROR);
|
|
1957
|
-
}
|
|
1958
|
-
}`.trimEnd();
|
|
1959
|
-
};
|
|
1960
|
-
var generateMethod3 = (method, cap, serviceName) => {
|
|
1961
|
-
const lower = method.toLowerCase();
|
|
1962
|
-
if (lower.includes("findall") || lower.includes("getall")) return methodFindAll(method, cap);
|
|
1963
|
-
if (lower.includes("findbyid") || lower.includes("getbyid") || lower.includes("getone")) return methodFindById(method, cap);
|
|
1964
|
-
if (lower.includes("create") || lower.includes("add")) return methodCreate(method, cap);
|
|
1965
|
-
if (lower.includes("update") || lower.includes("edit")) return methodUpdate(method, cap);
|
|
1966
|
-
if (lower.includes("delete") || lower.includes("remove")) return methodDelete(method, cap);
|
|
1967
|
-
return `
|
|
1955
|
+
// src/templates/customModule/buildYourOwnArchitecture.template.ts
|
|
1956
|
+
var capitalize17 = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
|
1957
|
+
var generateBuildYourOwnControllerTemplate = (fileName, methods) => {
|
|
1958
|
+
const controllerName = `${capitalize17(fileName)}Controller`;
|
|
1959
|
+
const body = methods.length === 0 ? ` // TODO: add your handler methods here` : methods.map((method) => `
|
|
1968
1960
|
static async ${method}(req: Request, res: Response): Promise<IResponseHandlerSuccessData | ReturnType<typeof ResponseHandler.error>> {
|
|
1969
1961
|
try {
|
|
1970
|
-
const service = ${cap}Controller.buildService();
|
|
1971
1962
|
// TODO: implement ${method}
|
|
1972
1963
|
return ResponseHandler.success({}, "success", HttpStatusCode.OK);
|
|
1973
1964
|
} catch (error) {
|
|
1974
|
-
|
|
1965
|
+
const message = error instanceof Error ? error.message : "Internal server error";
|
|
1966
|
+
return ResponseHandler.error(message, HttpStatusCode.INTERNAL_SERVER_ERROR);
|
|
1975
1967
|
}
|
|
1976
|
-
}
|
|
1977
|
-
};
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
}
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
}
|
|
2009
|
-
}`;
|
|
2010
|
-
var methodUpdate = (m, cap) => `
|
|
2011
|
-
static async ${m}(req: Request, res: Response): Promise<IResponseHandlerSuccessData | ReturnType<typeof ResponseHandler.error>> {
|
|
2012
|
-
try {
|
|
2013
|
-
const { id } = req.params;
|
|
2014
|
-
const service = ${cap}Controller.buildService();
|
|
2015
|
-
const result = await service.update(id, req.body);
|
|
2016
|
-
if (!result) return ResponseHandler.error(\`Not found: \${id}\`, HttpStatusCode.NOT_FOUND);
|
|
2017
|
-
return ResponseHandler.success(result, "success", HttpStatusCode.OK);
|
|
2018
|
-
} catch (error) {
|
|
2019
|
-
return ${cap}Controller.handleError(error);
|
|
2020
|
-
}
|
|
2021
|
-
}`;
|
|
2022
|
-
var methodDelete = (m, cap) => `
|
|
2023
|
-
static async ${m}(req: Request, res: Response): Promise<IResponseHandlerSuccessData | ReturnType<typeof ResponseHandler.error>> {
|
|
2024
|
-
try {
|
|
2025
|
-
const { id } = req.params;
|
|
2026
|
-
const service = ${cap}Controller.buildService();
|
|
2027
|
-
const deleted = await service.delete(id);
|
|
2028
|
-
if (!deleted) return ResponseHandler.error(\`Not found: \${id}\`, HttpStatusCode.NOT_FOUND);
|
|
2029
|
-
return ResponseHandler.success(null, "deleted", HttpStatusCode.NO_CONTENT);
|
|
2030
|
-
} catch (error) {
|
|
2031
|
-
return ${cap}Controller.handleError(error);
|
|
2032
|
-
}
|
|
2033
|
-
}`;
|
|
2034
|
-
var generateCustomServiceTemplate = (moduleName) => {
|
|
2035
|
-
const cap = capitalize17(moduleName);
|
|
2036
|
-
return `export class ${cap}Service {
|
|
2037
|
-
async findAll(): Promise<unknown[]> {
|
|
2038
|
-
// TODO: implement
|
|
2039
|
-
return [];
|
|
2040
|
-
}
|
|
2041
|
-
async findById(id: string): Promise<unknown | null> {
|
|
2042
|
-
// TODO: implement
|
|
2043
|
-
return null;
|
|
2044
|
-
}
|
|
2045
|
-
async create(data: Record<string, unknown>): Promise<unknown> {
|
|
2046
|
-
// TODO: implement
|
|
2047
|
-
return data;
|
|
2048
|
-
}
|
|
2049
|
-
async update(id: string, data: Record<string, unknown>): Promise<unknown | null> {
|
|
2050
|
-
// TODO: implement
|
|
2051
|
-
return null;
|
|
2052
|
-
}
|
|
2053
|
-
async delete(id: string): Promise<boolean> {
|
|
2054
|
-
// TODO: implement
|
|
2055
|
-
return false;
|
|
2056
|
-
}
|
|
2057
|
-
}`.trimEnd();
|
|
1968
|
+
}`).join("\n");
|
|
1969
|
+
return `import { Request, Response } from "opticore-express";
|
|
1970
|
+
import { ResponseHandler, HttpStatusCode, IResponseHandlerSuccessData } from "opticore-http-response";
|
|
1971
|
+
|
|
1972
|
+
export class ${controllerName} {
|
|
1973
|
+
${body}
|
|
1974
|
+
}`.trimEnd() + "\n";
|
|
1975
|
+
};
|
|
1976
|
+
var generateBuildYourOwnServiceClassTemplate = (fileName, methods) => {
|
|
1977
|
+
const serviceName = `${capitalize17(fileName)}Service`;
|
|
1978
|
+
const body = methods.length === 0 ? ` // TODO: add your service methods here` : methods.map((method) => `
|
|
1979
|
+
async ${method}(): Promise<unknown> {
|
|
1980
|
+
// TODO: implement ${method}
|
|
1981
|
+
throw new Error("Not implemented");
|
|
1982
|
+
}`).join("\n");
|
|
1983
|
+
return `export class ${serviceName} {
|
|
1984
|
+
${body}
|
|
1985
|
+
}`.trimEnd() + "\n";
|
|
1986
|
+
};
|
|
1987
|
+
var generateBuildYourOwnServiceFunctionTemplate = (fileName) => {
|
|
1988
|
+
const functionName = `${fileName}Service`;
|
|
1989
|
+
return `export async function ${functionName}(): Promise<unknown> {
|
|
1990
|
+
// TODO: implement ${functionName}
|
|
1991
|
+
throw new Error("Not implemented");
|
|
1992
|
+
}`.trimEnd() + "\n";
|
|
1993
|
+
};
|
|
1994
|
+
var generateBuildYourOwnDtoTemplate = (fileName, fields) => {
|
|
1995
|
+
const dtoName = `${capitalize17(fileName)}Dto`;
|
|
1996
|
+
const body = fields.length === 0 ? ` // TODO: define the fields of this DTO` : fields.map((field) => ` ${field.name}: ${field.type};`).join("\n");
|
|
1997
|
+
return `export interface ${dtoName} {
|
|
1998
|
+
${body}
|
|
1999
|
+
}`.trimEnd() + "\n";
|
|
2058
2000
|
};
|
|
2059
|
-
var
|
|
2060
|
-
const
|
|
2061
|
-
const
|
|
2062
|
-
|
|
2063
|
-
if (isAuthRelated) {
|
|
2064
|
-
return `export class ${cap}Repository {
|
|
2065
|
-
// TODO: inject your data source (ORM, DB client, etc.)
|
|
2066
|
-
|
|
2067
|
-
async findByEmail(email: string): Promise<User | null> {
|
|
2068
|
-
throw new Error("Not implemented");
|
|
2069
|
-
}
|
|
2070
|
-
|
|
2071
|
-
async findByUsernameOrEmail(identity: string): Promise<User | null> {
|
|
2072
|
-
throw new Error("Not implemented");
|
|
2073
|
-
}
|
|
2074
|
-
|
|
2075
|
-
async updateLastLogin(userId: string, date: Date): Promise<void> {
|
|
2076
|
-
throw new Error("Not implemented");
|
|
2077
|
-
}
|
|
2078
|
-
|
|
2079
|
-
async incrementLoginAttempts(userId: string): Promise<number> {
|
|
2080
|
-
throw new Error("Not implemented");
|
|
2081
|
-
}
|
|
2082
|
-
|
|
2083
|
-
async resetLoginAttempts(userId: string): Promise<void> {
|
|
2084
|
-
throw new Error("Not implemented");
|
|
2085
|
-
}
|
|
2086
|
-
|
|
2087
|
-
async saveToken(userId: string, token: string): Promise<void> {
|
|
2088
|
-
throw new Error("Not implemented");
|
|
2089
|
-
}
|
|
2090
|
-
}`.trimEnd();
|
|
2091
|
-
}
|
|
2092
|
-
return `export class ${cap}Repository {
|
|
2093
|
-
// TODO: inject your data source (ORM, DB client, etc.)
|
|
2094
|
-
async findAll(): Promise<unknown[]> { throw new Error("Not implemented"); }
|
|
2095
|
-
async findById(id: string): Promise<unknown | null> { throw new Error("Not implemented"); }
|
|
2096
|
-
async create(data: Record<string, unknown>): Promise<unknown> { throw new Error("Not implemented"); }
|
|
2097
|
-
async update(id: string, data: Record<string, unknown>): Promise<unknown | null> { throw new Error("Not implemented"); }
|
|
2098
|
-
async delete(id: string): Promise<boolean> { throw new Error("Not implemented"); }
|
|
2099
|
-
}`.trimEnd();
|
|
2100
|
-
};
|
|
2101
|
-
var generateCustomModelTemplate = (moduleName) => {
|
|
2102
|
-
const cap = capitalize17(moduleName);
|
|
2103
|
-
return `export class ${cap}Model {
|
|
2001
|
+
var generateBuildYourOwnEntityTemplate = (fileName, properties) => {
|
|
2002
|
+
const entityName = `${capitalize17(fileName)}Entity`;
|
|
2003
|
+
const ctorParams = properties.length === 0 ? ` // TODO: define the properties of this entity` : properties.map((prop) => ` public readonly ${prop.name}: ${prop.type},`).join("\n");
|
|
2004
|
+
return `export class ${entityName} {
|
|
2104
2005
|
constructor(
|
|
2105
|
-
|
|
2106
|
-
// TODO: add your fields here
|
|
2006
|
+
${ctorParams}
|
|
2107
2007
|
) {}
|
|
2108
|
-
}`.trimEnd();
|
|
2109
|
-
};
|
|
2110
|
-
var generateCustomTypesTemplate = (moduleName) => `// ${moduleName} types
|
|
2111
|
-
export type ${capitalize17(moduleName)}Id = string;
|
|
2112
|
-
// TODO: add your domain types here`.trimEnd();
|
|
2113
|
-
var generateCustomMiddlewareTemplate = (moduleName) => {
|
|
2114
|
-
const cap = capitalize17(moduleName);
|
|
2115
|
-
return `import { Request, Response, NextFunction } from "opticore-express";
|
|
2116
|
-
|
|
2117
|
-
export function ${moduleName}Middleware(req: Request, res: Response, next: NextFunction): void {
|
|
2118
|
-
// TODO: implement ${cap} middleware logic
|
|
2119
|
-
next();
|
|
2120
|
-
}`.trimEnd();
|
|
2121
|
-
};
|
|
2122
|
-
var generateCustomUtilsTemplate = (moduleName) => `// ${moduleName} utilities
|
|
2123
|
-
// TODO: add helper functions here`.trimEnd();
|
|
2124
|
-
var generateCustomErrorsTemplate = (moduleName) => {
|
|
2125
|
-
const cap = capitalize17(moduleName);
|
|
2126
|
-
return `export class ${cap}NotFoundError extends Error {
|
|
2127
|
-
constructor(id: string) {
|
|
2128
|
-
super(\`${cap} not found: \${id}\`);
|
|
2129
|
-
this.name = "${cap}NotFoundError";
|
|
2130
|
-
}
|
|
2131
|
-
}
|
|
2132
|
-
export class ${cap}ValidationError extends Error {
|
|
2133
|
-
constructor(message: string) {
|
|
2134
|
-
super(message);
|
|
2135
|
-
this.name = "${cap}ValidationError";
|
|
2136
|
-
}
|
|
2137
|
-
}`.trimEnd();
|
|
2008
|
+
}`.trimEnd() + "\n";
|
|
2138
2009
|
};
|
|
2139
|
-
var
|
|
2140
|
-
|
|
2141
|
-
// TODO:
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2010
|
+
var generateBuildYourOwnRepositoryTemplate = (fileName, methods) => {
|
|
2011
|
+
const repositoryName = `${capitalize17(fileName)}Repository`;
|
|
2012
|
+
const body = methods.length === 0 ? ` // TODO: define the actions this repository can perform` : methods.map((method) => ` async ${method}(): Promise<unknown> { throw new Error("Not implemented"); }`).join("\n");
|
|
2013
|
+
return `export class ${repositoryName} {
|
|
2014
|
+
// TODO: inject your data source (ORM, DB client, etc.)
|
|
2015
|
+
${body}
|
|
2016
|
+
}`.trimEnd() + "\n";
|
|
2017
|
+
};
|
|
2018
|
+
var generateBuildYourOwnRouteTemplate = (fileName, actions) => {
|
|
2019
|
+
const capitalized = capitalize17(fileName);
|
|
2020
|
+
const handlerName = `${capitalized}HandlerRouter`;
|
|
2021
|
+
const controllerName = `${capitalized}Controller`;
|
|
2022
|
+
const routes = actions.map((action) => {
|
|
2023
|
+
const { httpMethod, path: path10 } = CResolveRoute(action, fileName);
|
|
2024
|
+
return { httpMethod, path: path10, action };
|
|
2025
|
+
});
|
|
2026
|
+
const body = routes.length === 0 ? ` // TODO: define the routes for this module` : routes.map((route) => `{
|
|
2027
|
+
path: "${route.path}",
|
|
2028
|
+
method: "${route.httpMethod}",
|
|
2151
2029
|
middlewares: [],
|
|
2152
|
-
handler: async (ctx: ICustomContext) => await ${controllerName}.${
|
|
2153
|
-
}
|
|
2154
|
-
}).join(",\n");
|
|
2030
|
+
handler: async (ctx: ICustomContext) => await ${controllerName}.${route.action}(ctx.req, ctx.res)
|
|
2031
|
+
}`).join(",\n").replace(/\n/g, "\n ");
|
|
2155
2032
|
return `import { OpticoreRoutingFactory, ICustomContext, IMultipleRouteDefinition } from "opticore-router";
|
|
2156
|
-
import
|
|
2033
|
+
// TODO: adjust this import if "${controllerName}" lives in a different folder
|
|
2034
|
+
import { ${controllerName} } from "./${fileName}.controller";
|
|
2157
2035
|
|
|
2158
2036
|
export const ${handlerName}: () => IMultipleRouteDefinition = () => {
|
|
2159
2037
|
return OpticoreRoutingFactory.routes(
|
|
2160
2038
|
${controllerName},
|
|
2161
2039
|
[
|
|
2162
|
-
${
|
|
2040
|
+
${body}
|
|
2163
2041
|
]
|
|
2164
2042
|
);
|
|
2165
|
-
};`.trimEnd();
|
|
2166
|
-
};
|
|
2167
|
-
var generateCustomRouterTemplate = (moduleName) => {
|
|
2168
|
-
const cap = capitalize17(moduleName);
|
|
2169
|
-
const handlerName = `${cap}HandlerRouter`;
|
|
2170
|
-
const routerName = `${cap}Router`;
|
|
2171
|
-
return `import { ${handlerName} } from "./core/handler/${moduleName}.router.handler";
|
|
2172
|
-
import { TFeatureRoutes } from "opticore-router";
|
|
2173
|
-
|
|
2174
|
-
export const ${routerName}: TFeatureRoutes = {
|
|
2175
|
-
routes: [
|
|
2176
|
-
{
|
|
2177
|
-
path: ${handlerName}().path,
|
|
2178
|
-
handler: ${handlerName}().handler
|
|
2179
|
-
}
|
|
2180
|
-
]
|
|
2181
|
-
};`.trimEnd();
|
|
2043
|
+
};`.trimEnd() + "\n";
|
|
2182
2044
|
};
|
|
2183
2045
|
|
|
2184
|
-
// src/templates/customModule/
|
|
2046
|
+
// src/templates/customModule/buildYourOwnArchitectureScaffold.template.ts
|
|
2185
2047
|
var ok = (msg) => {
|
|
2186
|
-
console.log(colors9.green(`\
|
|
2048
|
+
console.log(colors9.green(`\u2714 ${msg}`));
|
|
2187
2049
|
};
|
|
2188
|
-
var
|
|
2189
|
-
console.log(colors9.
|
|
2050
|
+
var info = (msg) => {
|
|
2051
|
+
console.log(colors9.cyan(`\u2139 ${msg}`));
|
|
2190
2052
|
};
|
|
2191
|
-
var
|
|
2192
|
-
async
|
|
2193
|
-
const
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
);
|
|
2204
|
-
if (isCancel4(raw)) return [];
|
|
2205
|
-
return raw.split(",").map((m) => m.trim()).filter(Boolean);
|
|
2206
|
-
}
|
|
2207
|
-
var customModuleScaffoldTemplate = async () => {
|
|
2208
|
-
const rawName = await _featureName();
|
|
2209
|
-
if (isCancel4(rawName)) {
|
|
2210
|
-
console.log(colors9.bgRed(colors9.white("Operation cancelled.")));
|
|
2211
|
-
process.exit(0);
|
|
2053
|
+
var NAME_PATTERN = /^[a-zA-Z][a-zA-Z0-9_-]*$/;
|
|
2054
|
+
var askName = async (message, placeholder) => {
|
|
2055
|
+
const raw = await UPrompt.text(message, placeholder, (value) => {
|
|
2056
|
+
if (!value) {
|
|
2057
|
+
return "Please enter a name.";
|
|
2058
|
+
}
|
|
2059
|
+
if (!NAME_PATTERN.test(value)) {
|
|
2060
|
+
return "Use letters, numbers, - or _, starting with a letter.";
|
|
2061
|
+
}
|
|
2062
|
+
});
|
|
2063
|
+
if (isCancel6(raw)) {
|
|
2064
|
+
return void 0;
|
|
2212
2065
|
}
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2066
|
+
return raw;
|
|
2067
|
+
};
|
|
2068
|
+
var askCommaSeparatedList = async (message, placeholder) => {
|
|
2069
|
+
const raw = await UPrompt.text(message, placeholder, () => void 0);
|
|
2070
|
+
if (isCancel6(raw) || !raw) return [];
|
|
2071
|
+
return raw.split(",").map((v) => v.trim()).filter(Boolean);
|
|
2072
|
+
};
|
|
2073
|
+
var parseFieldDefinitions = (raw) => raw.map((entry) => {
|
|
2074
|
+
const [name, type] = entry.split(":").map((v) => v.trim());
|
|
2075
|
+
return { name: name || entry, type: type || "string" };
|
|
2076
|
+
});
|
|
2077
|
+
var renderTree = (node, prefix = "") => {
|
|
2078
|
+
const lines = [];
|
|
2079
|
+
const children = node.children ?? [];
|
|
2080
|
+
children.forEach((child, index) => {
|
|
2081
|
+
const isLast = index === children.length - 1;
|
|
2082
|
+
const branch = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
2083
|
+
lines.push(`${prefix}${branch}${child.name}${child.type === "dir" ? "/" : ""}`);
|
|
2084
|
+
if (child.type === "dir") {
|
|
2085
|
+
const nextPrefix = prefix + (isLast ? " " : "\u2502 ");
|
|
2086
|
+
lines.push(...renderTree(child, nextPrefix));
|
|
2087
|
+
}
|
|
2088
|
+
});
|
|
2089
|
+
return lines;
|
|
2090
|
+
};
|
|
2091
|
+
var printTree = (root) => {
|
|
2092
|
+
console.log(colors9.yellow(`${root.name}/`));
|
|
2093
|
+
renderTree(root).forEach((line) => console.log(colors9.yellow(line)));
|
|
2094
|
+
};
|
|
2095
|
+
async function handleFileCreation(dirPath) {
|
|
2096
|
+
const fileType = await UPrompt.select(
|
|
2097
|
+
"What type of file do you want to create?",
|
|
2098
|
+
["controller"],
|
|
2099
|
+
[
|
|
2100
|
+
{ label: "Controller", value: ["controller"] },
|
|
2101
|
+
{ label: "Service", value: ["service"] },
|
|
2102
|
+
{ label: "DTO", value: ["dto"] },
|
|
2103
|
+
{ label: "Entity", value: ["entity"] },
|
|
2104
|
+
{ label: "Repository", value: ["repository"] },
|
|
2105
|
+
{ label: "Route", value: ["route"] }
|
|
2106
|
+
]
|
|
2107
|
+
);
|
|
2108
|
+
if (isCancel6(fileType)) return void 0;
|
|
2109
|
+
const baseName = await askName(`Enter the name of this ${fileType} (without extension):`, "user");
|
|
2110
|
+
if (!baseName) return void 0;
|
|
2111
|
+
let fileName;
|
|
2112
|
+
let content;
|
|
2113
|
+
switch (fileType) {
|
|
2114
|
+
case "controller": {
|
|
2115
|
+
const wantsMethods = await UPrompt.confirm("Do you want to create methods for this controller?");
|
|
2116
|
+
let methods = [];
|
|
2117
|
+
if (wantsMethods === true) {
|
|
2118
|
+
methods = await askCommaSeparatedList(
|
|
2119
|
+
"Enter the method names (comma separated):",
|
|
2120
|
+
"create, findAll, findById, update, delete"
|
|
2121
|
+
);
|
|
2122
|
+
}
|
|
2123
|
+
fileName = `${baseName}.controller.ts`;
|
|
2124
|
+
content = generateBuildYourOwnControllerTemplate(baseName, methods);
|
|
2125
|
+
break;
|
|
2126
|
+
}
|
|
2127
|
+
case "service": {
|
|
2128
|
+
const kind = await UPrompt.select(
|
|
2129
|
+
"Do you want a class with methods, or a service that is just a function?",
|
|
2130
|
+
["class"],
|
|
2131
|
+
[
|
|
2132
|
+
{ label: "Class with methods", value: ["class"] },
|
|
2133
|
+
{ label: "Single function", value: ["function"] }
|
|
2134
|
+
]
|
|
2135
|
+
);
|
|
2136
|
+
if (isCancel6(kind)) return void 0;
|
|
2137
|
+
fileName = `${baseName}.service.ts`;
|
|
2138
|
+
if (kind === "class") {
|
|
2139
|
+
const methods = await askCommaSeparatedList(
|
|
2140
|
+
"Enter the method names (comma separated):",
|
|
2141
|
+
"findAll, findById, create, update, delete"
|
|
2142
|
+
);
|
|
2143
|
+
content = generateBuildYourOwnServiceClassTemplate(baseName, methods);
|
|
2144
|
+
} else {
|
|
2145
|
+
content = generateBuildYourOwnServiceFunctionTemplate(baseName);
|
|
2146
|
+
}
|
|
2147
|
+
break;
|
|
2148
|
+
}
|
|
2149
|
+
case "dto": {
|
|
2150
|
+
const raw = await askCommaSeparatedList(
|
|
2151
|
+
"Enter the DTO fields as name:type pairs, comma separated:",
|
|
2152
|
+
"name:string, email:string"
|
|
2153
|
+
);
|
|
2154
|
+
fileName = `${baseName}.dto.ts`;
|
|
2155
|
+
content = generateBuildYourOwnDtoTemplate(baseName, parseFieldDefinitions(raw));
|
|
2156
|
+
break;
|
|
2157
|
+
}
|
|
2158
|
+
case "entity": {
|
|
2159
|
+
const raw = await askCommaSeparatedList(
|
|
2160
|
+
"Enter the entity properties as name:type pairs, comma separated:",
|
|
2161
|
+
"id:string, name:string, createdAt:Date"
|
|
2162
|
+
);
|
|
2163
|
+
fileName = `${baseName}.entity.ts`;
|
|
2164
|
+
content = generateBuildYourOwnEntityTemplate(baseName, parseFieldDefinitions(raw));
|
|
2165
|
+
break;
|
|
2166
|
+
}
|
|
2167
|
+
case "repository": {
|
|
2168
|
+
const methods = await askCommaSeparatedList(
|
|
2169
|
+
"Enter the actions this repository should perform (comma separated):",
|
|
2170
|
+
"findAll, findById, save, update, delete"
|
|
2171
|
+
);
|
|
2172
|
+
fileName = `${baseName}.repository.ts`;
|
|
2173
|
+
content = generateBuildYourOwnRepositoryTemplate(baseName, methods);
|
|
2174
|
+
break;
|
|
2175
|
+
}
|
|
2176
|
+
case "route": {
|
|
2177
|
+
const actions = await askCommaSeparatedList(
|
|
2178
|
+
"Enter the actions to expose as routes (comma separated):",
|
|
2179
|
+
"findAll, findById, create, update, delete"
|
|
2180
|
+
);
|
|
2181
|
+
fileName = `${baseName}.route.ts`;
|
|
2182
|
+
content = generateBuildYourOwnRouteTemplate(baseName, actions);
|
|
2183
|
+
break;
|
|
2184
|
+
}
|
|
2218
2185
|
}
|
|
2219
|
-
const
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
path6.join(appDir, `${moduleName}.controller.ts`),
|
|
2235
|
-
generateCustomControllerTemplate(`${capitalize18(moduleName)}Controller`, moduleName, controllerMethods)
|
|
2186
|
+
const filePath = path6.join(dirPath, fileName);
|
|
2187
|
+
UFsModule.createFile(filePath, content);
|
|
2188
|
+
ok(fileName);
|
|
2189
|
+
return { name: fileName, type: "file" };
|
|
2190
|
+
}
|
|
2191
|
+
async function handleDirectory(dirPath, node) {
|
|
2192
|
+
let keepGoing = true;
|
|
2193
|
+
while (keepGoing) {
|
|
2194
|
+
const choice = await UPrompt.select(
|
|
2195
|
+
`Inside "${node.name}", do you want to create a file or a folder?`,
|
|
2196
|
+
["file"],
|
|
2197
|
+
[
|
|
2198
|
+
{ label: "File", value: ["file"] },
|
|
2199
|
+
{ label: "Folder", value: ["folder"] }
|
|
2200
|
+
]
|
|
2236
2201
|
);
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2202
|
+
if (isCancel6(choice)) return;
|
|
2203
|
+
if (choice === "folder") {
|
|
2204
|
+
const folderName = await askName("Enter the folder name:", "core");
|
|
2205
|
+
if (!folderName) return;
|
|
2206
|
+
const subDir = path6.join(dirPath, folderName);
|
|
2207
|
+
UFsModule.createDirectoryRecursively(subDir);
|
|
2208
|
+
const subNode = { name: folderName, type: "dir", children: [] };
|
|
2209
|
+
node.children.push(subNode);
|
|
2210
|
+
ok(`${folderName}/`);
|
|
2211
|
+
await handleDirectory(subDir, subNode);
|
|
2212
|
+
} else {
|
|
2213
|
+
const fileNode = await handleFileCreation(dirPath);
|
|
2214
|
+
if (fileNode) {
|
|
2215
|
+
node.children.push(fileNode);
|
|
2216
|
+
}
|
|
2217
|
+
}
|
|
2218
|
+
info(`Current structure of "${node.name}":`);
|
|
2219
|
+
printTree(node);
|
|
2220
|
+
const wantsContinue = await UPrompt.confirm(`Continue creating files/folders inside "${node.name}"?`);
|
|
2221
|
+
if (isCancel6(wantsContinue) || wantsContinue !== true) {
|
|
2222
|
+
keepGoing = false;
|
|
2223
|
+
}
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
2226
|
+
var buildYourOwnArchitectureScaffoldTemplate = async () => {
|
|
2227
|
+
const featuresDir = path6.join(process.cwd(), "src", "features");
|
|
2228
|
+
const forest = [];
|
|
2229
|
+
let creatingNewRoot = true;
|
|
2230
|
+
while (creatingNewRoot) {
|
|
2231
|
+
const rootName = await askName("Enter the name of the root folder for your architecture:", "myArchitecture");
|
|
2232
|
+
if (!rootName) {
|
|
2233
|
+
console.log(colors9.bgRed(colors9.white("Operation cancelled.")));
|
|
2234
|
+
process.exit(0);
|
|
2235
|
+
}
|
|
2236
|
+
const rootDir = path6.join(featuresDir, rootName);
|
|
2237
|
+
if (fs4.existsSync(rootDir)) {
|
|
2238
|
+
info(`Folder "${rootName}" already exists, new files/folders will be added inside it.`);
|
|
2239
|
+
}
|
|
2240
|
+
UFsModule.createDirectoryRecursively(rootDir);
|
|
2241
|
+
const rootNode = { name: rootName, type: "dir", children: [] };
|
|
2242
|
+
forest.push(rootNode);
|
|
2243
|
+
await handleDirectory(rootDir, rootNode);
|
|
2244
|
+
const wantsNewRoot = await UPrompt.confirm(
|
|
2245
|
+
"Do you want to create a new folder at the root of your architecture?",
|
|
2246
|
+
false
|
|
2261
2247
|
);
|
|
2262
|
-
|
|
2248
|
+
if (isCancel6(wantsNewRoot) || wantsNewRoot !== true) {
|
|
2249
|
+
console.log(colors9.cyan("En disant non, ce sera la fin de la cr\xE9ation de votre propre architecture."));
|
|
2250
|
+
creatingNewRoot = false;
|
|
2251
|
+
}
|
|
2263
2252
|
}
|
|
2264
|
-
UFsModule.createFile(
|
|
2265
|
-
path6.join(coreHandlerDir, `${moduleName}.router.handler.ts`),
|
|
2266
|
-
generateCustomRouterHandlerTemplate(moduleName, controllerMethods)
|
|
2267
|
-
);
|
|
2268
|
-
ok(`core/handler/${moduleName}.router.handler.ts`);
|
|
2269
|
-
UFsModule.createFile(path6.join(sharedUtilsDir, `${moduleName}.utils.ts`), generateCustomUtilsTemplate(moduleName));
|
|
2270
|
-
UFsModule.createFile(path6.join(sharedErrorsDir, `${moduleName}.errors.ts`), generateCustomErrorsTemplate(moduleName));
|
|
2271
|
-
UFsModule.createFile(path6.join(sharedConstantsDir, `${moduleName}.constants.ts`), generateCustomConstantsTemplate(moduleName));
|
|
2272
|
-
ok(`shared/utils/${moduleName}.utils.ts`);
|
|
2273
|
-
ok(`shared/errors/${moduleName}.errors.ts`);
|
|
2274
|
-
ok(`shared/constants/${moduleName}.constants.ts`);
|
|
2275
|
-
UFsModule.createFile(path6.join(moduleDir, `${moduleName}.router.ts`), generateCustomRouterTemplate(moduleName));
|
|
2276
|
-
ok(`${moduleName}.router.ts`);
|
|
2277
|
-
FeatureComponentGeneratorUtils.setStructure("custom");
|
|
2278
|
-
await FeatureComponentGeneratorUtils.registerModuleRouter(moduleName);
|
|
2279
|
-
tip(`src/features/${moduleName}/`);
|
|
2280
|
-
tip(`\u251C\u2500\u2500 app/`);
|
|
2281
|
-
tip(`\u251C\u2500\u2500 core/`);
|
|
2282
|
-
tip(`\u2502 \u251C\u2500\u2500 middlewares/`);
|
|
2283
|
-
tip(`\u2502 \u2514\u2500\u2500 handler/`);
|
|
2284
|
-
tip(`\u251C\u2500\u2500 shared/`);
|
|
2285
|
-
tip(`\u2502 \u251C\u2500\u2500 utils/`);
|
|
2286
|
-
tip(`\u2502 \u251C\u2500\u2500 errors/`);
|
|
2287
|
-
tip(`\u2502 \u2514\u2500\u2500 constants/`);
|
|
2288
|
-
tip(`\u2514\u2500\u2500 ${moduleName}.router.ts`);
|
|
2289
2253
|
console.log(`
|
|
2290
|
-
${colors9.bgGreen(colors9.white(`
|
|
2291
|
-
|
|
2292
|
-
`))}`);
|
|
2254
|
+
${colors9.bgGreen(colors9.white("\n\u{1F389} Your custom architecture has been created!\n"))}`);
|
|
2255
|
+
forest.forEach((root) => printTree(root));
|
|
2293
2256
|
};
|
|
2294
2257
|
|
|
2295
2258
|
// src/templates/mvcModule/mvcModuleScaffold.template.ts
|
|
2296
2259
|
import path7 from "path";
|
|
2297
2260
|
import colors10 from "ansi-colors";
|
|
2298
|
-
import { isCancel as
|
|
2261
|
+
import { isCancel as isCancel7 } from "@clack/prompts";
|
|
2299
2262
|
|
|
2300
2263
|
// src/templates/mvcModule/mvcModule.template.ts
|
|
2301
|
-
var
|
|
2264
|
+
var capitalize18 = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
|
2302
2265
|
var generateMvcModelTemplate = (featureName) => {
|
|
2303
|
-
const capitalized =
|
|
2266
|
+
const capitalized = capitalize18(featureName);
|
|
2304
2267
|
const modelName = `${capitalized}Model`;
|
|
2305
2268
|
return `/**
|
|
2306
2269
|
* ${modelName} \u2014 Model
|
|
@@ -2358,7 +2321,7 @@ export class ${modelName} {
|
|
|
2358
2321
|
`;
|
|
2359
2322
|
};
|
|
2360
2323
|
var generateMvcViewTemplate = (featureName) => {
|
|
2361
|
-
const capitalized =
|
|
2324
|
+
const capitalized = capitalize18(featureName);
|
|
2362
2325
|
const modelName = `${capitalized}Model`;
|
|
2363
2326
|
const viewName = `${capitalized}View`;
|
|
2364
2327
|
return `import { ${modelName} } from "../models/${featureName}.model";
|
|
@@ -2384,10 +2347,10 @@ export class ${viewName} {
|
|
|
2384
2347
|
`;
|
|
2385
2348
|
};
|
|
2386
2349
|
var generateMvcControllerTemplate = (controllerName, featureName, methods) => {
|
|
2387
|
-
const capitalized =
|
|
2350
|
+
const capitalized = capitalize18(featureName);
|
|
2388
2351
|
const modelName = `${capitalized}Model`;
|
|
2389
2352
|
const viewName = `${capitalized}View`;
|
|
2390
|
-
const methodsCode = methods.map((method) =>
|
|
2353
|
+
const methodsCode = methods.map((method) => generateMethod3(method, capitalized, modelName, viewName)).join("\n");
|
|
2391
2354
|
return `import { Request, Response } from "opticore-express";
|
|
2392
2355
|
import { ResponseHandler, HttpStatusCode, IResponseHandlerSuccessData } from "opticore-http-response";
|
|
2393
2356
|
import { ${modelName} } from "../models/${featureName}.model";
|
|
@@ -2402,13 +2365,23 @@ ${methodsCode}
|
|
|
2402
2365
|
}
|
|
2403
2366
|
`;
|
|
2404
2367
|
};
|
|
2405
|
-
var
|
|
2368
|
+
var generateMethod3 = (method, capitalized, modelName, viewName) => {
|
|
2406
2369
|
const lower = method.toLowerCase();
|
|
2407
|
-
if (lower.includes("findall") || lower.includes("getall"))
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
if (lower.includes("
|
|
2411
|
-
|
|
2370
|
+
if (lower.includes("findall") || lower.includes("getall")) {
|
|
2371
|
+
return generateFindAllMethod3(method, capitalized, modelName, viewName);
|
|
2372
|
+
}
|
|
2373
|
+
if (lower.includes("findbyid") || lower.includes("getbyid") || lower.includes("getone")) {
|
|
2374
|
+
return generateFindByIdMethod3(method, capitalized, modelName, viewName);
|
|
2375
|
+
}
|
|
2376
|
+
if (lower.includes("create") || lower.includes("add")) {
|
|
2377
|
+
return generateCreateMethod3(method, capitalized, modelName, viewName);
|
|
2378
|
+
}
|
|
2379
|
+
if (lower.includes("update") || lower.includes("edit")) {
|
|
2380
|
+
return generateUpdateMethod3(method, capitalized, modelName, viewName);
|
|
2381
|
+
}
|
|
2382
|
+
if (lower.includes("delete") || lower.includes("remove")) {
|
|
2383
|
+
return generateDeleteMethod3(method, capitalized, modelName);
|
|
2384
|
+
}
|
|
2412
2385
|
return `
|
|
2413
2386
|
static async ${method}(req: Request, res: Response): Promise<IResponseHandlerSuccessData | ReturnType<typeof ResponseHandler.error>> {
|
|
2414
2387
|
try {
|
|
@@ -2483,7 +2456,7 @@ var generateDeleteMethod3 = (method, capitalized, modelName) => `
|
|
|
2483
2456
|
}
|
|
2484
2457
|
`;
|
|
2485
2458
|
var generateMvcRouterHandlerTemplate = (featureName, controllerMethods) => {
|
|
2486
|
-
const capitalized =
|
|
2459
|
+
const capitalized = capitalize18(featureName);
|
|
2487
2460
|
const handlerName = `${capitalized}HandlerRouter`;
|
|
2488
2461
|
const controllerName = `${capitalized}Controller`;
|
|
2489
2462
|
const routesCode = (controllerMethods || []).map((method) => {
|
|
@@ -2509,7 +2482,7 @@ export const ${handlerName}: () => IMultipleRouteDefinition = () => {
|
|
|
2509
2482
|
`;
|
|
2510
2483
|
};
|
|
2511
2484
|
var generateMvcRouterTemplate = (featureName) => {
|
|
2512
|
-
const capitalized =
|
|
2485
|
+
const capitalized = capitalize18(featureName);
|
|
2513
2486
|
const handlerName = `${capitalized}HandlerRouter`;
|
|
2514
2487
|
const routerName = `${capitalized}Router`;
|
|
2515
2488
|
return `import { ${handlerName} } from "./${featureName}.router.handler";
|
|
@@ -2527,16 +2500,26 @@ export const ${routerName}: TFeatureRoutes = {
|
|
|
2527
2500
|
};
|
|
2528
2501
|
var resolveRoute3 = (methodName, featureName) => {
|
|
2529
2502
|
const lower = methodName.toLowerCase();
|
|
2530
|
-
if (lower.includes("findall") || lower.includes("getall"))
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
if (lower.includes("
|
|
2534
|
-
|
|
2503
|
+
if (lower.includes("findall") || lower.includes("getall")) {
|
|
2504
|
+
return { httpMethod: "get", path: `/${featureName}` };
|
|
2505
|
+
}
|
|
2506
|
+
if (lower.includes("findbyid") || lower.includes("getbyid") || lower.includes("getone")) {
|
|
2507
|
+
return { httpMethod: "get", path: `/${featureName}/:id` };
|
|
2508
|
+
}
|
|
2509
|
+
if (lower.includes("create") || lower.includes("add")) {
|
|
2510
|
+
return { httpMethod: "post", path: `/${featureName}` };
|
|
2511
|
+
}
|
|
2512
|
+
if (lower.includes("update") || lower.includes("edit")) {
|
|
2513
|
+
return { httpMethod: "put", path: `/${featureName}/:id` };
|
|
2514
|
+
}
|
|
2515
|
+
if (lower.includes("delete") || lower.includes("remove")) {
|
|
2516
|
+
return { httpMethod: "delete", path: `/${featureName}/:id` };
|
|
2517
|
+
}
|
|
2535
2518
|
return { httpMethod: "get", path: `/${featureName}/${lower}` };
|
|
2536
2519
|
};
|
|
2537
2520
|
|
|
2538
2521
|
// src/templates/mvcModule/mvcModuleScaffold.template.ts
|
|
2539
|
-
var
|
|
2522
|
+
var capitalize19 = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
|
2540
2523
|
var mvcModuleTemplate = async (featureName) => {
|
|
2541
2524
|
FeatureComponentGeneratorUtils.setStructure("mvc");
|
|
2542
2525
|
const basePath = path7.join("src", "features", featureName);
|
|
@@ -2547,21 +2530,23 @@ var mvcModuleTemplate = async (featureName) => {
|
|
|
2547
2530
|
routesDir: path7.join(basePath, "routes")
|
|
2548
2531
|
};
|
|
2549
2532
|
Object.values(paths).forEach((dir) => UFsModule.createDirectoryRecursively(dir));
|
|
2550
|
-
const controllerName = `${
|
|
2533
|
+
const controllerName = `${capitalize19(featureName)}Controller`;
|
|
2551
2534
|
UFsModule.createFile(path7.join(paths.modelsDir, `${featureName}.model.ts`), generateMvcModelTemplate(featureName));
|
|
2552
|
-
console.log(colors10.green(`\
|
|
2535
|
+
console.log(colors10.green(`\u2714 Model created: ${path7.join(paths.modelsDir, `${featureName}.model.ts`)}`));
|
|
2553
2536
|
UFsModule.createFile(path7.join(paths.viewsDir, `${featureName}.view.ts`), generateMvcViewTemplate(featureName));
|
|
2554
|
-
console.log(colors10.green(`\
|
|
2537
|
+
console.log(colors10.green(`\u2714 View created: ${path7.join(paths.viewsDir, `${featureName}.view.ts`)}`));
|
|
2555
2538
|
const wantsMethods = await UPrompt.confirm("Do you want to add methods to the controller?");
|
|
2556
2539
|
let methods = [];
|
|
2557
2540
|
let controllerContent;
|
|
2558
|
-
if (wantsMethods && !
|
|
2541
|
+
if (wantsMethods && !isCancel7(wantsMethods)) {
|
|
2559
2542
|
const methodsText = await UPrompt.text(
|
|
2560
2543
|
"Enter the method names (comma separated):",
|
|
2561
2544
|
"create, findAll, findById, update, delete",
|
|
2562
2545
|
(v) => v ? void 0 : "You must enter at least one method."
|
|
2563
2546
|
);
|
|
2564
|
-
|
|
2547
|
+
if (!isCancel7(methodsText)) {
|
|
2548
|
+
methods = methodsText.split(",").map((m) => m.trim()).filter(Boolean);
|
|
2549
|
+
}
|
|
2565
2550
|
controllerContent = generateMvcControllerTemplate(controllerName, featureName, methods);
|
|
2566
2551
|
} else {
|
|
2567
2552
|
controllerContent = `import { Request, Response } from "opticore-express";
|
|
@@ -2571,18 +2556,18 @@ export class ${controllerName} {}
|
|
|
2571
2556
|
}
|
|
2572
2557
|
const controllerPath = path7.join(paths.controllersDir, `${featureName}.controller.ts`);
|
|
2573
2558
|
UFsModule.createFile(controllerPath, controllerContent);
|
|
2574
|
-
console.log(colors10.green(`\
|
|
2559
|
+
console.log(colors10.green(`\u2714 Controller created: ${controllerPath}`));
|
|
2575
2560
|
UFsModule.createFile(
|
|
2576
2561
|
path7.join(paths.routesDir, `${featureName}.router.handler.ts`),
|
|
2577
2562
|
generateMvcRouterHandlerTemplate(featureName, methods)
|
|
2578
2563
|
);
|
|
2579
|
-
console.log(colors10.green(`\
|
|
2564
|
+
console.log(colors10.green(`\u2714 Router Handler created: ${path7.join(paths.routesDir, `${featureName}.router.handler.ts`)}`));
|
|
2580
2565
|
UFsModule.createFile(
|
|
2581
2566
|
path7.join(paths.routesDir, `${featureName}.router.ts`),
|
|
2582
2567
|
generateMvcRouterTemplate(featureName)
|
|
2583
2568
|
);
|
|
2584
2569
|
await FeatureComponentGeneratorUtils.registerModuleRouter(featureName);
|
|
2585
|
-
console.log(colors10.green(`\
|
|
2570
|
+
console.log(colors10.green(`\u2714 Router created: ${path7.join(paths.routesDir, `${featureName}.router.ts`)}`));
|
|
2586
2571
|
console.log(
|
|
2587
2572
|
colors10.bgGreen(
|
|
2588
2573
|
colors10.white(`
|
|
@@ -2595,12 +2580,12 @@ export class ${controllerName} {}
|
|
|
2595
2580
|
// src/templates/layeredModule/layeredModuleScaffold.template.ts
|
|
2596
2581
|
import path8 from "path";
|
|
2597
2582
|
import colors11 from "ansi-colors";
|
|
2598
|
-
import { isCancel as
|
|
2583
|
+
import { isCancel as isCancel8 } from "@clack/prompts";
|
|
2599
2584
|
|
|
2600
2585
|
// src/templates/layeredModule/layeredModule.template.ts
|
|
2601
|
-
var
|
|
2586
|
+
var capitalize20 = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
|
2602
2587
|
var generateLayeredEntityTemplate = (featureName) => {
|
|
2603
|
-
const capitalized =
|
|
2588
|
+
const capitalized = capitalize20(featureName);
|
|
2604
2589
|
const entityName = `${capitalized}Entity`;
|
|
2605
2590
|
return `/**
|
|
2606
2591
|
* ${entityName} \u2014 Entity
|
|
@@ -2617,7 +2602,7 @@ export class ${entityName} {
|
|
|
2617
2602
|
`;
|
|
2618
2603
|
};
|
|
2619
2604
|
var generateLayeredDtoTemplate = (featureName) => {
|
|
2620
|
-
const capitalized =
|
|
2605
|
+
const capitalized = capitalize20(featureName);
|
|
2621
2606
|
const entityName = `${capitalized}Entity`;
|
|
2622
2607
|
return `import { ${entityName} } from "../entities/${featureName}.entity";
|
|
2623
2608
|
|
|
@@ -2644,7 +2629,7 @@ export const to${capitalized}ResponseDto = (entity: ${entityName}): ${capitalize
|
|
|
2644
2629
|
`;
|
|
2645
2630
|
};
|
|
2646
2631
|
var generateLayeredRepositoryTemplate = (featureName) => {
|
|
2647
|
-
const capitalized =
|
|
2632
|
+
const capitalized = capitalize20(featureName);
|
|
2648
2633
|
const entityName = `${capitalized}Entity`;
|
|
2649
2634
|
const repoName = `${capitalized}Repository`;
|
|
2650
2635
|
return `import { ${entityName} } from "../entities/${featureName}.entity";
|
|
@@ -2683,7 +2668,7 @@ export class ${repoName} {
|
|
|
2683
2668
|
`;
|
|
2684
2669
|
};
|
|
2685
2670
|
var generateLayeredServiceTemplate = (featureName) => {
|
|
2686
|
-
const capitalized =
|
|
2671
|
+
const capitalized = capitalize20(featureName);
|
|
2687
2672
|
const entityName = `${capitalized}Entity`;
|
|
2688
2673
|
const repoName = `${capitalized}Repository`;
|
|
2689
2674
|
const serviceName = `${capitalized}Service`;
|
|
@@ -2732,9 +2717,9 @@ export class ${serviceName} {
|
|
|
2732
2717
|
`;
|
|
2733
2718
|
};
|
|
2734
2719
|
var generateLayeredControllerTemplate = (controllerName, featureName, methods) => {
|
|
2735
|
-
const capitalized =
|
|
2720
|
+
const capitalized = capitalize20(featureName);
|
|
2736
2721
|
const serviceName = `${capitalized}Service`;
|
|
2737
|
-
const methodsCode = methods.map((method) =>
|
|
2722
|
+
const methodsCode = methods.map((method) => generateMethod4(method, capitalized, serviceName)).join("\n");
|
|
2738
2723
|
return `import { Request, Response } from "opticore-express";
|
|
2739
2724
|
import { ResponseHandler, HttpStatusCode, IResponseHandlerSuccessData } from "opticore-http-response";
|
|
2740
2725
|
import { ${serviceName} } from "../services/${featureName}.service";
|
|
@@ -2752,7 +2737,7 @@ ${methodsCode}
|
|
|
2752
2737
|
}
|
|
2753
2738
|
`;
|
|
2754
2739
|
};
|
|
2755
|
-
var
|
|
2740
|
+
var generateMethod4 = (method, capitalized, serviceName) => {
|
|
2756
2741
|
const lower = method.toLowerCase();
|
|
2757
2742
|
if (lower.includes("findall") || lower.includes("getall")) return generateFindAllMethod4(method, capitalized);
|
|
2758
2743
|
if (lower.includes("findbyid") || lower.includes("getbyid") || lower.includes("getone")) return generateFindByIdMethod4(method, capitalized);
|
|
@@ -2839,7 +2824,7 @@ var generateDeleteMethod4 = (method, capitalized) => `
|
|
|
2839
2824
|
}
|
|
2840
2825
|
`;
|
|
2841
2826
|
var generateLayeredRouterHandlerTemplate = (featureName, controllerMethods) => {
|
|
2842
|
-
const capitalized =
|
|
2827
|
+
const capitalized = capitalize20(featureName);
|
|
2843
2828
|
const handlerName = `${capitalized}HandlerRouter`;
|
|
2844
2829
|
const controllerName = `${capitalized}Controller`;
|
|
2845
2830
|
const routesCode = (controllerMethods || []).map((method) => {
|
|
@@ -2865,7 +2850,7 @@ export const ${handlerName}: () => IMultipleRouteDefinition = () => {
|
|
|
2865
2850
|
`;
|
|
2866
2851
|
};
|
|
2867
2852
|
var generateLayeredRouterTemplate = (featureName) => {
|
|
2868
|
-
const capitalized =
|
|
2853
|
+
const capitalized = capitalize20(featureName);
|
|
2869
2854
|
const handlerName = `${capitalized}HandlerRouter`;
|
|
2870
2855
|
const routerName = `${capitalized}Router`;
|
|
2871
2856
|
return `import { ${handlerName} } from "./${featureName}.router.handler";
|
|
@@ -2892,7 +2877,7 @@ var resolveRoute4 = (methodName, featureName) => {
|
|
|
2892
2877
|
};
|
|
2893
2878
|
|
|
2894
2879
|
// src/templates/layeredModule/layeredModuleScaffold.template.ts
|
|
2895
|
-
var
|
|
2880
|
+
var capitalize21 = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
|
2896
2881
|
var layeredModuleTemplate = async (featureName) => {
|
|
2897
2882
|
FeatureComponentGeneratorUtils.setStructure("layered");
|
|
2898
2883
|
const basePath = path8.join("src", "features", featureName);
|
|
@@ -2905,25 +2890,27 @@ var layeredModuleTemplate = async (featureName) => {
|
|
|
2905
2890
|
routesDir: path8.join(basePath, "routes")
|
|
2906
2891
|
};
|
|
2907
2892
|
Object.values(paths).forEach((dir) => UFsModule.createDirectoryRecursively(dir));
|
|
2908
|
-
const controllerName = `${
|
|
2893
|
+
const controllerName = `${capitalize21(featureName)}Controller`;
|
|
2909
2894
|
UFsModule.createFile(path8.join(paths.entitiesDir, `${featureName}.entity.ts`), generateLayeredEntityTemplate(featureName));
|
|
2910
|
-
console.log(colors11.green(`\
|
|
2895
|
+
console.log(colors11.green(`\u2714 Entity created: ${path8.join(paths.entitiesDir, `${featureName}.entity.ts`)}`));
|
|
2911
2896
|
UFsModule.createFile(path8.join(paths.dtoDir, `${featureName}.dto.ts`), generateLayeredDtoTemplate(featureName));
|
|
2912
|
-
console.log(colors11.green(`\
|
|
2897
|
+
console.log(colors11.green(`\u2714 DTO created: ${path8.join(paths.dtoDir, `${featureName}.dto.ts`)}`));
|
|
2913
2898
|
UFsModule.createFile(path8.join(paths.repositoriesDir, `${featureName}.repository.ts`), generateLayeredRepositoryTemplate(featureName));
|
|
2914
|
-
console.log(colors11.green(`\
|
|
2899
|
+
console.log(colors11.green(`\u2714 Repository created: ${path8.join(paths.repositoriesDir, `${featureName}.repository.ts`)}`));
|
|
2915
2900
|
UFsModule.createFile(path8.join(paths.servicesDir, `${featureName}.service.ts`), generateLayeredServiceTemplate(featureName));
|
|
2916
|
-
console.log(colors11.green(`\
|
|
2901
|
+
console.log(colors11.green(`\u2714 Service created: ${path8.join(paths.servicesDir, `${featureName}.service.ts`)}`));
|
|
2917
2902
|
const wantsMethods = await UPrompt.confirm("Do you want to add methods to the controller?");
|
|
2918
2903
|
let methods = [];
|
|
2919
2904
|
let controllerContent;
|
|
2920
|
-
if (wantsMethods && !
|
|
2905
|
+
if (wantsMethods && !isCancel8(wantsMethods)) {
|
|
2921
2906
|
const methodsText = await UPrompt.text(
|
|
2922
2907
|
"Enter the method names (comma separated):",
|
|
2923
2908
|
"create, findAll, findById, update, delete",
|
|
2924
2909
|
(v) => v ? void 0 : "You must enter at least one method."
|
|
2925
2910
|
);
|
|
2926
|
-
|
|
2911
|
+
if (!isCancel8(methodsText)) {
|
|
2912
|
+
methods = methodsText.split(",").map((m) => m.trim()).filter(Boolean);
|
|
2913
|
+
}
|
|
2927
2914
|
controllerContent = generateLayeredControllerTemplate(controllerName, featureName, methods);
|
|
2928
2915
|
} else {
|
|
2929
2916
|
controllerContent = `import { Request, Response } from "opticore-express";
|
|
@@ -2933,18 +2920,18 @@ export class ${controllerName} {}
|
|
|
2933
2920
|
}
|
|
2934
2921
|
const controllerPath = path8.join(paths.controllersDir, `${featureName}.controller.ts`);
|
|
2935
2922
|
UFsModule.createFile(controllerPath, controllerContent);
|
|
2936
|
-
console.log(colors11.green(`\
|
|
2923
|
+
console.log(colors11.green(`\u2714 Controller created: ${controllerPath}`));
|
|
2937
2924
|
UFsModule.createFile(
|
|
2938
2925
|
path8.join(paths.routesDir, `${featureName}.router.handler.ts`),
|
|
2939
2926
|
generateLayeredRouterHandlerTemplate(featureName, methods)
|
|
2940
2927
|
);
|
|
2941
|
-
console.log(colors11.green(`\
|
|
2928
|
+
console.log(colors11.green(`\u2714 Router Handler created: ${path8.join(paths.routesDir, `${featureName}.router.handler.ts`)}`));
|
|
2942
2929
|
UFsModule.createFile(
|
|
2943
2930
|
path8.join(paths.routesDir, `${featureName}.router.ts`),
|
|
2944
2931
|
generateLayeredRouterTemplate(featureName)
|
|
2945
2932
|
);
|
|
2946
2933
|
await FeatureComponentGeneratorUtils.registerModuleRouter(featureName);
|
|
2947
|
-
console.log(colors11.green(`\
|
|
2934
|
+
console.log(colors11.green(`\u2714 Router created: ${path8.join(paths.routesDir, `${featureName}.router.ts`)}`));
|
|
2948
2935
|
console.log(
|
|
2949
2936
|
colors11.bgGreen(
|
|
2950
2937
|
colors11.white(`
|
|
@@ -2955,11 +2942,11 @@ export class ${controllerName} {}
|
|
|
2955
2942
|
};
|
|
2956
2943
|
|
|
2957
2944
|
// src/core/core.ts
|
|
2958
|
-
|
|
2945
|
+
async function runFeatureCommand() {
|
|
2959
2946
|
UWelcomeMessage();
|
|
2960
2947
|
const featureChoice = await choiceFeatureCleanModule();
|
|
2961
2948
|
if (featureChoice === "custom_feature") {
|
|
2962
|
-
await
|
|
2949
|
+
await buildYourOwnArchitectureScaffoldTemplate();
|
|
2963
2950
|
return;
|
|
2964
2951
|
}
|
|
2965
2952
|
if (featureChoice === "mvc_architecture" || featureChoice === "layered_architecture") {
|
|
@@ -2969,7 +2956,7 @@ export class ${controllerName} {}
|
|
|
2969
2956
|
if (BaseService._isSubdirectoryExists(featureName2)) {
|
|
2970
2957
|
BaseService._featureFounded(featureName2);
|
|
2971
2958
|
}
|
|
2972
|
-
if (
|
|
2959
|
+
if (isCancel9(featureName2)) {
|
|
2973
2960
|
BaseService._cancelOperation(featureDirectory2);
|
|
2974
2961
|
return;
|
|
2975
2962
|
}
|
|
@@ -2995,7 +2982,7 @@ export class ${controllerName} {}
|
|
|
2995
2982
|
if (featureCleanModule) {
|
|
2996
2983
|
BaseService._featureFounded(featureName);
|
|
2997
2984
|
}
|
|
2998
|
-
if (
|
|
2985
|
+
if (isCancel9(featureName)) {
|
|
2999
2986
|
BaseService._cancelOperation(featureDirectory);
|
|
3000
2987
|
} else {
|
|
3001
2988
|
try {
|
|
@@ -3009,4 +2996,8 @@ export class ${controllerName} {}
|
|
|
3009
2996
|
process3.exit();
|
|
3010
2997
|
}
|
|
3011
2998
|
}
|
|
3012
|
-
}
|
|
2999
|
+
}
|
|
3000
|
+
|
|
3001
|
+
export {
|
|
3002
|
+
runFeatureCommand
|
|
3003
|
+
};
|