opticore-feature-component 1.0.5 → 1.0.7
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-GNR24GXE.js → core-TFP6J3AE.js} +705 -19
- package/dist/index.cjs +740 -20
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -176,7 +176,9 @@ async function choiceFeatureCleanModule() {
|
|
|
176
176
|
["opticore_principle"],
|
|
177
177
|
[
|
|
178
178
|
{ label: "OptiCoreJs CLEAN Module", value: ["opticore_clean_module"], hint: "recommended" },
|
|
179
|
-
{ label: "
|
|
179
|
+
{ label: "MVC Architecture", value: ["mvc_architecture"] },
|
|
180
|
+
{ label: "Layered Architecture", value: ["layered_architecture"] },
|
|
181
|
+
{ label: "Build your own architecture", value: ["custom_feature"] }
|
|
180
182
|
]
|
|
181
183
|
);
|
|
182
184
|
if ((0, import_prompts2.isCancel)(featureSelected)) {
|
|
@@ -1015,19 +1017,19 @@ var init_router_template = __esm({
|
|
|
1015
1017
|
const handlerName = `${capitalized}HandlerRouter`;
|
|
1016
1018
|
const controllerName = `${capitalized}Controller`;
|
|
1017
1019
|
const routesCode = (controllerMethods || []).map((method) => {
|
|
1018
|
-
const { httpMethod, path:
|
|
1020
|
+
const { httpMethod, path: path10 } = resolveRoute(method, featureName);
|
|
1019
1021
|
return `{
|
|
1020
|
-
path: \`${
|
|
1022
|
+
path: \`${path10}\`,
|
|
1021
1023
|
method: "${httpMethod}",
|
|
1022
1024
|
middlewares: [],
|
|
1023
1025
|
handler: async (ctx: ICustomContext) => await ${controllerName}.${method}(ctx.req, ctx.res)
|
|
1024
1026
|
}`;
|
|
1025
1027
|
}).join(",\n");
|
|
1026
|
-
return `import {
|
|
1028
|
+
return `import { OpticoreRoutingFactory, ICustomContext, IMultipleRouteDefinition } from "opticore-router";
|
|
1027
1029
|
import { ${controllerName} } from "../adapters/controllers/${featureName}.controller";
|
|
1028
1030
|
|
|
1029
1031
|
export const ${handlerName}: () => IMultipleRouteDefinition = () => {
|
|
1030
|
-
return
|
|
1032
|
+
return OpticoreRoutingFactory.routes(
|
|
1031
1033
|
${controllerName},
|
|
1032
1034
|
[
|
|
1033
1035
|
${routesCode.replace(/\n/g, "\n ")}
|
|
@@ -1591,19 +1593,19 @@ var init_simpleRouter_template = __esm({
|
|
|
1591
1593
|
const handlerName = `${capitalized}HandlerRouter`;
|
|
1592
1594
|
const controllerName = `${capitalized}Controller`;
|
|
1593
1595
|
const routesCode = (controllerMethods || []).map((method) => {
|
|
1594
|
-
const { httpMethod, path:
|
|
1596
|
+
const { httpMethod, path: path10 } = resolveRoute2(method, featureName);
|
|
1595
1597
|
return `{
|
|
1596
|
-
path: \`${
|
|
1598
|
+
path: \`${path10}\`,
|
|
1597
1599
|
method: "${httpMethod}",
|
|
1598
1600
|
middlewares: [],
|
|
1599
1601
|
handler: async (ctx: ICustomContext) => await ${controllerName}.${method}(ctx.req, ctx.res)
|
|
1600
1602
|
}`;
|
|
1601
1603
|
}).join(",\n");
|
|
1602
|
-
return `import {
|
|
1604
|
+
return `import { OpticoreRoutingFactory, ICustomContext, IMultipleRouteDefinition } from "opticore-router";
|
|
1603
1605
|
import { ${controllerName} } from "../controllers/${featureName}.controller";
|
|
1604
1606
|
|
|
1605
1607
|
export const ${handlerName}: () => IMultipleRouteDefinition = () => {
|
|
1606
|
-
return
|
|
1608
|
+
return OpticoreRoutingFactory.routes(
|
|
1607
1609
|
${controllerName},
|
|
1608
1610
|
[
|
|
1609
1611
|
${routesCode.replace(/\n/g, "\n ")}
|
|
@@ -1870,7 +1872,7 @@ export class ${controllerName} {}
|
|
|
1870
1872
|
*/
|
|
1871
1873
|
static async updateRegisterRouter(featureName) {
|
|
1872
1874
|
const routerName = `${this.capitalize(featureName)}Router`;
|
|
1873
|
-
const routerPath = this.structure === "simple" ? `../../features/${featureName}/routes/${featureName}.router` : this.structure === "custom" ? `../../features/${featureName}/${featureName}.router` : `../../features/${featureName}/infrastructure/routes/${featureName}.router`;
|
|
1875
|
+
const routerPath = this.structure === "simple" || this.structure === "mvc" || this.structure === "layered" ? `../../features/${featureName}/routes/${featureName}.router` : this.structure === "custom" ? `../../features/${featureName}/${featureName}.router` : `../../features/${featureName}/infrastructure/routes/${featureName}.router`;
|
|
1874
1876
|
const importStatement = `import { ${routerName} } from "${routerPath}"`;
|
|
1875
1877
|
try {
|
|
1876
1878
|
if (!import_fs2.default.existsSync(this.REGISTER_ROUTER_PATH)) {
|
|
@@ -2418,19 +2420,19 @@ export const ${moduleName.toUpperCase()}_PREFIX = "/${moduleName}";
|
|
|
2418
2420
|
const handlerName = `${cap}HandlerRouter`;
|
|
2419
2421
|
const controllerName = `${cap}Controller`;
|
|
2420
2422
|
const routesCode = (controllerMethods || []).map((method) => {
|
|
2421
|
-
const { httpMethod, path:
|
|
2423
|
+
const { httpMethod, path: path10 } = CResolveRoute(method, moduleName);
|
|
2422
2424
|
return `{
|
|
2423
|
-
path: \`${
|
|
2425
|
+
path: \`${path10}\`,
|
|
2424
2426
|
method: "${httpMethod}",
|
|
2425
2427
|
middlewares: [],
|
|
2426
2428
|
handler: async (ctx: ICustomContext) => await ${controllerName}.${method}(ctx.req, ctx.res)
|
|
2427
2429
|
}`;
|
|
2428
2430
|
}).join(",\n");
|
|
2429
|
-
return `import {
|
|
2431
|
+
return `import { OpticoreRoutingFactory, ICustomContext, IMultipleRouteDefinition } from "opticore-router";
|
|
2430
2432
|
import { ${controllerName} } from "../../app/${moduleName}.controller";
|
|
2431
2433
|
|
|
2432
2434
|
export const ${handlerName}: () => IMultipleRouteDefinition = () => {
|
|
2433
|
-
return
|
|
2435
|
+
return OpticoreRoutingFactory.routes(
|
|
2434
2436
|
${controllerName},
|
|
2435
2437
|
[
|
|
2436
2438
|
${routesCode ? routesCode.replace(/\n/g, "\n ") : ""}
|
|
@@ -2584,17 +2586,711 @@ ${import_ansi_colors9.default.bgGreen(import_ansi_colors9.default.white(`
|
|
|
2584
2586
|
}
|
|
2585
2587
|
});
|
|
2586
2588
|
|
|
2589
|
+
// src/templates/mvcModule/mvcModule.template.ts
|
|
2590
|
+
var capitalize19, generateMvcModelTemplate, generateMvcViewTemplate, generateMvcControllerTemplate, generateMethod4, generateFindAllMethod3, generateFindByIdMethod3, generateCreateMethod3, generateUpdateMethod3, generateDeleteMethod3, generateMvcRouterHandlerTemplate, generateMvcRouterTemplate, resolveRoute3;
|
|
2591
|
+
var init_mvcModule_template = __esm({
|
|
2592
|
+
"src/templates/mvcModule/mvcModule.template.ts"() {
|
|
2593
|
+
"use strict";
|
|
2594
|
+
init_cjs_shims();
|
|
2595
|
+
capitalize19 = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
|
2596
|
+
generateMvcModelTemplate = (featureName) => {
|
|
2597
|
+
const capitalized = capitalize19(featureName);
|
|
2598
|
+
const modelName = `${capitalized}Model`;
|
|
2599
|
+
return `/**
|
|
2600
|
+
* ${modelName} \u2014 Model
|
|
2601
|
+
* Owns both the data shape and the data-access logic for "${featureName}".
|
|
2602
|
+
*/
|
|
2603
|
+
export class ${modelName} {
|
|
2604
|
+
id: string;
|
|
2605
|
+
createdAt: Date;
|
|
2606
|
+
updatedAt: Date;
|
|
2607
|
+
|
|
2608
|
+
constructor(
|
|
2609
|
+
id: string,
|
|
2610
|
+
// TODO: add your model properties here
|
|
2611
|
+
createdAt?: Date,
|
|
2612
|
+
updatedAt?: Date,
|
|
2613
|
+
) {
|
|
2614
|
+
this.id = id;
|
|
2615
|
+
this.createdAt = createdAt ?? new Date();
|
|
2616
|
+
this.updatedAt = updatedAt ?? new Date();
|
|
2617
|
+
}
|
|
2618
|
+
|
|
2619
|
+
private static store: Map<string, ${modelName}> = new Map();
|
|
2620
|
+
|
|
2621
|
+
static async findAll(): Promise<${modelName}[]> {
|
|
2622
|
+
// TODO: Replace with your ORM query
|
|
2623
|
+
return Array.from(this.store.values());
|
|
2624
|
+
}
|
|
2625
|
+
|
|
2626
|
+
static async findById(id: string): Promise<${modelName} | null> {
|
|
2627
|
+
// TODO: Replace with your ORM query
|
|
2628
|
+
return this.store.get(id) ?? null;
|
|
2629
|
+
}
|
|
2630
|
+
|
|
2631
|
+
static async create(data: Record<string, unknown>): Promise<${modelName}> {
|
|
2632
|
+
const model = new ${modelName}(String(Date.now()));
|
|
2633
|
+
// TODO: Map data fields onto model
|
|
2634
|
+
this.store.set(model.id, model);
|
|
2635
|
+
return model;
|
|
2636
|
+
}
|
|
2637
|
+
|
|
2638
|
+
static async update(id: string, data: Record<string, unknown>): Promise<${modelName} | null> {
|
|
2639
|
+
const existing = this.store.get(id);
|
|
2640
|
+
if (!existing) return null;
|
|
2641
|
+
// TODO: Apply data fields onto existing model
|
|
2642
|
+
existing.updatedAt = new Date();
|
|
2643
|
+
this.store.set(id, existing);
|
|
2644
|
+
return existing;
|
|
2645
|
+
}
|
|
2646
|
+
|
|
2647
|
+
static async delete(id: string): Promise<boolean> {
|
|
2648
|
+
// TODO: Replace with your ORM delete
|
|
2649
|
+
return this.store.delete(id);
|
|
2650
|
+
}
|
|
2651
|
+
}
|
|
2652
|
+
`;
|
|
2653
|
+
};
|
|
2654
|
+
generateMvcViewTemplate = (featureName) => {
|
|
2655
|
+
const capitalized = capitalize19(featureName);
|
|
2656
|
+
const modelName = `${capitalized}Model`;
|
|
2657
|
+
const viewName = `${capitalized}View`;
|
|
2658
|
+
return `import { ${modelName} } from "../models/${featureName}.model";
|
|
2659
|
+
|
|
2660
|
+
/**
|
|
2661
|
+
* ${viewName} \u2014 View
|
|
2662
|
+
* Shapes "${featureName}" data before it is sent back as JSON.
|
|
2663
|
+
*/
|
|
2664
|
+
export class ${viewName} {
|
|
2665
|
+
static toJSON(model: ${modelName}): Record<string, unknown> {
|
|
2666
|
+
return {
|
|
2667
|
+
id: model.id,
|
|
2668
|
+
createdAt: model.createdAt,
|
|
2669
|
+
updatedAt: model.updatedAt,
|
|
2670
|
+
// TODO: expose the fields API consumers should see (and only those)
|
|
2671
|
+
};
|
|
2672
|
+
}
|
|
2673
|
+
|
|
2674
|
+
static toJSONList(models: ${modelName}[]): Record<string, unknown>[] {
|
|
2675
|
+
return models.map((model: ${modelName}): Record<string, unknown> => this.toJSON(model));
|
|
2676
|
+
}
|
|
2677
|
+
}
|
|
2678
|
+
`;
|
|
2679
|
+
};
|
|
2680
|
+
generateMvcControllerTemplate = (controllerName, featureName, methods) => {
|
|
2681
|
+
const capitalized = capitalize19(featureName);
|
|
2682
|
+
const modelName = `${capitalized}Model`;
|
|
2683
|
+
const viewName = `${capitalized}View`;
|
|
2684
|
+
const methodsCode = methods.map((method) => generateMethod4(method, capitalized, modelName, viewName)).join("\n");
|
|
2685
|
+
return `import { Request, Response } from "opticore-express";
|
|
2686
|
+
import { ResponseHandler, HttpStatusCode, IResponseHandlerSuccessData } from "opticore-http-response";
|
|
2687
|
+
import { ${modelName} } from "../models/${featureName}.model";
|
|
2688
|
+
import { ${viewName} } from "../views/${featureName}.view";
|
|
2689
|
+
|
|
2690
|
+
export class ${controllerName} {
|
|
2691
|
+
${methodsCode}
|
|
2692
|
+
private static handleError(error: unknown) {
|
|
2693
|
+
const message = error instanceof Error ? error.message : "Internal server error";
|
|
2694
|
+
return ResponseHandler.error(message, HttpStatusCode.INTERNAL_SERVER_ERROR);
|
|
2695
|
+
}
|
|
2696
|
+
}
|
|
2697
|
+
`;
|
|
2698
|
+
};
|
|
2699
|
+
generateMethod4 = (method, capitalized, modelName, viewName) => {
|
|
2700
|
+
const lower = method.toLowerCase();
|
|
2701
|
+
if (lower.includes("findall") || lower.includes("getall")) return generateFindAllMethod3(method, capitalized, modelName, viewName);
|
|
2702
|
+
if (lower.includes("findbyid") || lower.includes("getbyid") || lower.includes("getone")) return generateFindByIdMethod3(method, capitalized, modelName, viewName);
|
|
2703
|
+
if (lower.includes("create") || lower.includes("add")) return generateCreateMethod3(method, capitalized, modelName, viewName);
|
|
2704
|
+
if (lower.includes("update") || lower.includes("edit")) return generateUpdateMethod3(method, capitalized, modelName, viewName);
|
|
2705
|
+
if (lower.includes("delete") || lower.includes("remove")) return generateDeleteMethod3(method, capitalized, modelName);
|
|
2706
|
+
return `
|
|
2707
|
+
static async ${method}(req: Request, res: Response): Promise<IResponseHandlerSuccessData | ReturnType<typeof ResponseHandler.error>> {
|
|
2708
|
+
try {
|
|
2709
|
+
// TODO: Implement ${method} logic
|
|
2710
|
+
return ResponseHandler.success({}, "success", HttpStatusCode.OK);
|
|
2711
|
+
} catch (error) {
|
|
2712
|
+
return ${capitalized}Controller.handleError(error);
|
|
2713
|
+
}
|
|
2714
|
+
}
|
|
2715
|
+
`;
|
|
2716
|
+
};
|
|
2717
|
+
generateFindAllMethod3 = (method, capitalized, modelName, viewName) => `
|
|
2718
|
+
static async ${method}(req: Request, res: Response): Promise<IResponseHandlerSuccessData | ReturnType<typeof ResponseHandler.error>> {
|
|
2719
|
+
try {
|
|
2720
|
+
const models = await ${modelName}.findAll();
|
|
2721
|
+
return ResponseHandler.success(${viewName}.toJSONList(models), "success", HttpStatusCode.OK);
|
|
2722
|
+
} catch (error) {
|
|
2723
|
+
return ${capitalized}Controller.handleError(error);
|
|
2724
|
+
}
|
|
2725
|
+
}
|
|
2726
|
+
`;
|
|
2727
|
+
generateFindByIdMethod3 = (method, capitalized, modelName, viewName) => `
|
|
2728
|
+
static async ${method}(req: Request, res: Response): Promise<IResponseHandlerSuccessData | ReturnType<typeof ResponseHandler.error>> {
|
|
2729
|
+
try {
|
|
2730
|
+
const { id } = req.params;
|
|
2731
|
+
const model = await ${modelName}.findById(id);
|
|
2732
|
+
if (!model) {
|
|
2733
|
+
return ResponseHandler.error(\`Not found: \${id}\`, HttpStatusCode.NOT_FOUND);
|
|
2734
|
+
}
|
|
2735
|
+
return ResponseHandler.success(${viewName}.toJSON(model), "success", HttpStatusCode.OK);
|
|
2736
|
+
} catch (error) {
|
|
2737
|
+
return ${capitalized}Controller.handleError(error);
|
|
2738
|
+
}
|
|
2739
|
+
}
|
|
2740
|
+
`;
|
|
2741
|
+
generateCreateMethod3 = (method, capitalized, modelName, viewName) => `
|
|
2742
|
+
static async ${method}(req: Request, res: Response): Promise<IResponseHandlerSuccessData | ReturnType<typeof ResponseHandler.error>> {
|
|
2743
|
+
try {
|
|
2744
|
+
const model = await ${modelName}.create(req.body);
|
|
2745
|
+
return ResponseHandler.success(${viewName}.toJSON(model), "created", HttpStatusCode.CREATED);
|
|
2746
|
+
} catch (error) {
|
|
2747
|
+
return ${capitalized}Controller.handleError(error);
|
|
2748
|
+
}
|
|
2749
|
+
}
|
|
2750
|
+
`;
|
|
2751
|
+
generateUpdateMethod3 = (method, capitalized, modelName, viewName) => `
|
|
2752
|
+
static async ${method}(req: Request, res: Response): Promise<IResponseHandlerSuccessData | ReturnType<typeof ResponseHandler.error>> {
|
|
2753
|
+
try {
|
|
2754
|
+
const { id } = req.params;
|
|
2755
|
+
const model = await ${modelName}.update(id, req.body);
|
|
2756
|
+
if (!model) {
|
|
2757
|
+
return ResponseHandler.error(\`Not found: \${id}\`, HttpStatusCode.NOT_FOUND);
|
|
2758
|
+
}
|
|
2759
|
+
return ResponseHandler.success(${viewName}.toJSON(model), "success", HttpStatusCode.OK);
|
|
2760
|
+
} catch (error) {
|
|
2761
|
+
return ${capitalized}Controller.handleError(error);
|
|
2762
|
+
}
|
|
2763
|
+
}
|
|
2764
|
+
`;
|
|
2765
|
+
generateDeleteMethod3 = (method, capitalized, modelName) => `
|
|
2766
|
+
static async ${method}(req: Request, res: Response): Promise<IResponseHandlerSuccessData | ReturnType<typeof ResponseHandler.error>> {
|
|
2767
|
+
try {
|
|
2768
|
+
const { id } = req.params;
|
|
2769
|
+
const deleted = await ${modelName}.delete(id);
|
|
2770
|
+
if (!deleted) {
|
|
2771
|
+
return ResponseHandler.error(\`Not found: \${id}\`, HttpStatusCode.NOT_FOUND);
|
|
2772
|
+
}
|
|
2773
|
+
return ResponseHandler.success(null, "deleted", HttpStatusCode.NO_CONTENT);
|
|
2774
|
+
} catch (error) {
|
|
2775
|
+
return ${capitalized}Controller.handleError(error);
|
|
2776
|
+
}
|
|
2777
|
+
}
|
|
2778
|
+
`;
|
|
2779
|
+
generateMvcRouterHandlerTemplate = (featureName, controllerMethods) => {
|
|
2780
|
+
const capitalized = capitalize19(featureName);
|
|
2781
|
+
const handlerName = `${capitalized}HandlerRouter`;
|
|
2782
|
+
const controllerName = `${capitalized}Controller`;
|
|
2783
|
+
const routesCode = (controllerMethods || []).map((method) => {
|
|
2784
|
+
const { httpMethod, path: path10 } = resolveRoute3(method, featureName);
|
|
2785
|
+
return `{
|
|
2786
|
+
path: \`${path10}\`,
|
|
2787
|
+
method: "${httpMethod}",
|
|
2788
|
+
middlewares: [],
|
|
2789
|
+
handler: async (ctx: ICustomContext) => await ${controllerName}.${method}(ctx.req, ctx.res)
|
|
2790
|
+
}`;
|
|
2791
|
+
}).join(",\n");
|
|
2792
|
+
return `import { OpticoreRoutingFactory, ICustomContext, IMultipleRouteDefinition } from "opticore-router";
|
|
2793
|
+
import { ${controllerName} } from "../controllers/${featureName}.controller";
|
|
2794
|
+
|
|
2795
|
+
export const ${handlerName}: () => IMultipleRouteDefinition = () => {
|
|
2796
|
+
return OpticoreRoutingFactory.routes(
|
|
2797
|
+
${controllerName},
|
|
2798
|
+
[
|
|
2799
|
+
${routesCode.replace(/\n/g, "\n ")}
|
|
2800
|
+
]
|
|
2801
|
+
);
|
|
2802
|
+
};
|
|
2803
|
+
`;
|
|
2804
|
+
};
|
|
2805
|
+
generateMvcRouterTemplate = (featureName) => {
|
|
2806
|
+
const capitalized = capitalize19(featureName);
|
|
2807
|
+
const handlerName = `${capitalized}HandlerRouter`;
|
|
2808
|
+
const routerName = `${capitalized}Router`;
|
|
2809
|
+
return `import { ${handlerName} } from "./${featureName}.router.handler";
|
|
2810
|
+
import { TFeatureRoutes } from "opticore-router";
|
|
2811
|
+
|
|
2812
|
+
export const ${routerName}: TFeatureRoutes = {
|
|
2813
|
+
routes: [
|
|
2814
|
+
{
|
|
2815
|
+
path: ${handlerName}().path,
|
|
2816
|
+
handler: ${handlerName}().handler
|
|
2817
|
+
}
|
|
2818
|
+
]
|
|
2819
|
+
};
|
|
2820
|
+
`;
|
|
2821
|
+
};
|
|
2822
|
+
resolveRoute3 = (methodName, featureName) => {
|
|
2823
|
+
const lower = methodName.toLowerCase();
|
|
2824
|
+
if (lower.includes("findall") || lower.includes("getall")) return { httpMethod: "get", path: `/${featureName}` };
|
|
2825
|
+
if (lower.includes("findbyid") || lower.includes("getbyid") || lower.includes("getone")) return { httpMethod: "get", path: `/${featureName}/:id` };
|
|
2826
|
+
if (lower.includes("create") || lower.includes("add")) return { httpMethod: "post", path: `/${featureName}` };
|
|
2827
|
+
if (lower.includes("update") || lower.includes("edit")) return { httpMethod: "put", path: `/${featureName}/:id` };
|
|
2828
|
+
if (lower.includes("delete") || lower.includes("remove")) return { httpMethod: "delete", path: `/${featureName}/:id` };
|
|
2829
|
+
return { httpMethod: "get", path: `/${featureName}/${lower}` };
|
|
2830
|
+
};
|
|
2831
|
+
}
|
|
2832
|
+
});
|
|
2833
|
+
|
|
2834
|
+
// src/templates/mvcModule/mvcModuleScaffold.template.ts
|
|
2835
|
+
var import_path7, import_ansi_colors10, import_prompts6, capitalize20, mvcModuleTemplate;
|
|
2836
|
+
var init_mvcModuleScaffold_template = __esm({
|
|
2837
|
+
"src/templates/mvcModule/mvcModuleScaffold.template.ts"() {
|
|
2838
|
+
"use strict";
|
|
2839
|
+
init_cjs_shims();
|
|
2840
|
+
import_path7 = __toESM(require("path"), 1);
|
|
2841
|
+
import_ansi_colors10 = __toESM(require("ansi-colors"), 1);
|
|
2842
|
+
import_prompts6 = require("@clack/prompts");
|
|
2843
|
+
init_prompt_utils();
|
|
2844
|
+
init_fsModule_utils();
|
|
2845
|
+
init_featureComponentGenerator_utils();
|
|
2846
|
+
init_mvcModule_template();
|
|
2847
|
+
capitalize20 = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
|
2848
|
+
mvcModuleTemplate = async (featureName) => {
|
|
2849
|
+
FeatureComponentGeneratorUtils.setStructure("mvc");
|
|
2850
|
+
const basePath = import_path7.default.join("src", "features", featureName);
|
|
2851
|
+
const paths = {
|
|
2852
|
+
modelsDir: import_path7.default.join(basePath, "models"),
|
|
2853
|
+
viewsDir: import_path7.default.join(basePath, "views"),
|
|
2854
|
+
controllersDir: import_path7.default.join(basePath, "controllers"),
|
|
2855
|
+
routesDir: import_path7.default.join(basePath, "routes")
|
|
2856
|
+
};
|
|
2857
|
+
Object.values(paths).forEach((dir) => UFsModule.createDirectoryRecursively(dir));
|
|
2858
|
+
const controllerName = `${capitalize20(featureName)}Controller`;
|
|
2859
|
+
UFsModule.createFile(import_path7.default.join(paths.modelsDir, `${featureName}.model.ts`), generateMvcModelTemplate(featureName));
|
|
2860
|
+
console.log(import_ansi_colors10.default.green(`\u2705 Model created: ${import_path7.default.join(paths.modelsDir, `${featureName}.model.ts`)}`));
|
|
2861
|
+
UFsModule.createFile(import_path7.default.join(paths.viewsDir, `${featureName}.view.ts`), generateMvcViewTemplate(featureName));
|
|
2862
|
+
console.log(import_ansi_colors10.default.green(`\u2705 View created: ${import_path7.default.join(paths.viewsDir, `${featureName}.view.ts`)}`));
|
|
2863
|
+
const wantsMethods = await UPrompt.confirm("Do you want to add methods to the controller?");
|
|
2864
|
+
let methods = [];
|
|
2865
|
+
let controllerContent;
|
|
2866
|
+
if (wantsMethods && !(0, import_prompts6.isCancel)(wantsMethods)) {
|
|
2867
|
+
const methodsText = await UPrompt.text(
|
|
2868
|
+
"Enter the method names (comma separated):",
|
|
2869
|
+
"create, findAll, findById, update, delete",
|
|
2870
|
+
(v) => v ? void 0 : "You must enter at least one method."
|
|
2871
|
+
);
|
|
2872
|
+
methods = methodsText.split(",").map((m) => m.trim()).filter(Boolean);
|
|
2873
|
+
controllerContent = generateMvcControllerTemplate(controllerName, featureName, methods);
|
|
2874
|
+
} else {
|
|
2875
|
+
controllerContent = `import { Request, Response } from "opticore-express";
|
|
2876
|
+
|
|
2877
|
+
export class ${controllerName} {}
|
|
2878
|
+
`;
|
|
2879
|
+
}
|
|
2880
|
+
const controllerPath = import_path7.default.join(paths.controllersDir, `${featureName}.controller.ts`);
|
|
2881
|
+
UFsModule.createFile(controllerPath, controllerContent);
|
|
2882
|
+
console.log(import_ansi_colors10.default.green(`\u2705 Controller created: ${controllerPath}`));
|
|
2883
|
+
UFsModule.createFile(
|
|
2884
|
+
import_path7.default.join(paths.routesDir, `${featureName}.router.handler.ts`),
|
|
2885
|
+
generateMvcRouterHandlerTemplate(featureName, methods)
|
|
2886
|
+
);
|
|
2887
|
+
console.log(import_ansi_colors10.default.green(`\u2705 Router Handler created: ${import_path7.default.join(paths.routesDir, `${featureName}.router.handler.ts`)}`));
|
|
2888
|
+
UFsModule.createFile(
|
|
2889
|
+
import_path7.default.join(paths.routesDir, `${featureName}.router.ts`),
|
|
2890
|
+
generateMvcRouterTemplate(featureName)
|
|
2891
|
+
);
|
|
2892
|
+
await FeatureComponentGeneratorUtils.registerModuleRouter(featureName);
|
|
2893
|
+
console.log(import_ansi_colors10.default.green(`\u2705 Router created: ${import_path7.default.join(paths.routesDir, `${featureName}.router.ts`)}`));
|
|
2894
|
+
console.log(
|
|
2895
|
+
import_ansi_colors10.default.bgGreen(
|
|
2896
|
+
import_ansi_colors10.default.white(`
|
|
2897
|
+
\u{1F389} Feature "${featureName}" scaffolded with MVC architecture!
|
|
2898
|
+
`)
|
|
2899
|
+
)
|
|
2900
|
+
);
|
|
2901
|
+
};
|
|
2902
|
+
}
|
|
2903
|
+
});
|
|
2904
|
+
|
|
2905
|
+
// src/templates/layeredModule/layeredModule.template.ts
|
|
2906
|
+
var capitalize21, generateLayeredEntityTemplate, generateLayeredDtoTemplate, generateLayeredRepositoryTemplate, generateLayeredServiceTemplate, generateLayeredControllerTemplate, generateMethod5, generateFindAllMethod4, generateFindByIdMethod4, generateCreateMethod4, generateUpdateMethod4, generateDeleteMethod4, generateLayeredRouterHandlerTemplate, generateLayeredRouterTemplate, resolveRoute4;
|
|
2907
|
+
var init_layeredModule_template = __esm({
|
|
2908
|
+
"src/templates/layeredModule/layeredModule.template.ts"() {
|
|
2909
|
+
"use strict";
|
|
2910
|
+
init_cjs_shims();
|
|
2911
|
+
capitalize21 = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
|
2912
|
+
generateLayeredEntityTemplate = (featureName) => {
|
|
2913
|
+
const capitalized = capitalize21(featureName);
|
|
2914
|
+
const entityName = `${capitalized}Entity`;
|
|
2915
|
+
return `/**
|
|
2916
|
+
* ${entityName} \u2014 Entity
|
|
2917
|
+
* Plain data structure for the "${featureName}" domain. No data-access logic here.
|
|
2918
|
+
*/
|
|
2919
|
+
export class ${entityName} {
|
|
2920
|
+
constructor(
|
|
2921
|
+
public readonly id: string,
|
|
2922
|
+
// TODO: add your entity fields here
|
|
2923
|
+
public readonly createdAt: Date = new Date(),
|
|
2924
|
+
public readonly updatedAt: Date = new Date(),
|
|
2925
|
+
) {}
|
|
2926
|
+
}
|
|
2927
|
+
`;
|
|
2928
|
+
};
|
|
2929
|
+
generateLayeredDtoTemplate = (featureName) => {
|
|
2930
|
+
const capitalized = capitalize21(featureName);
|
|
2931
|
+
const entityName = `${capitalized}Entity`;
|
|
2932
|
+
return `import { ${entityName} } from "../entities/${featureName}.entity";
|
|
2933
|
+
|
|
2934
|
+
export interface Create${capitalized}Dto {
|
|
2935
|
+
// TODO: define the fields required to create a ${featureName}
|
|
2936
|
+
}
|
|
2937
|
+
|
|
2938
|
+
export interface Update${capitalized}Dto {
|
|
2939
|
+
// TODO: define the fields that can be updated
|
|
2940
|
+
}
|
|
2941
|
+
|
|
2942
|
+
export interface ${capitalized}ResponseDto {
|
|
2943
|
+
id: string;
|
|
2944
|
+
createdAt: Date;
|
|
2945
|
+
updatedAt: Date;
|
|
2946
|
+
// TODO: define the fields exposed to API consumers
|
|
2947
|
+
}
|
|
2948
|
+
|
|
2949
|
+
export const to${capitalized}ResponseDto = (entity: ${entityName}): ${capitalized}ResponseDto => ({
|
|
2950
|
+
id: entity.id,
|
|
2951
|
+
createdAt: entity.createdAt,
|
|
2952
|
+
updatedAt: entity.updatedAt,
|
|
2953
|
+
});
|
|
2954
|
+
`;
|
|
2955
|
+
};
|
|
2956
|
+
generateLayeredRepositoryTemplate = (featureName) => {
|
|
2957
|
+
const capitalized = capitalize21(featureName);
|
|
2958
|
+
const entityName = `${capitalized}Entity`;
|
|
2959
|
+
const repoName = `${capitalized}Repository`;
|
|
2960
|
+
return `import { ${entityName} } from "../entities/${featureName}.entity";
|
|
2961
|
+
|
|
2962
|
+
export class ${repoName} {
|
|
2963
|
+
private store: Map<string, ${entityName}> = new Map();
|
|
2964
|
+
|
|
2965
|
+
async findAll(): Promise<${entityName}[]> {
|
|
2966
|
+
// TODO: Replace with your ORM query
|
|
2967
|
+
return Array.from(this.store.values());
|
|
2968
|
+
}
|
|
2969
|
+
|
|
2970
|
+
async findById(id: string): Promise<${entityName} | null> {
|
|
2971
|
+
// TODO: Replace with your ORM query
|
|
2972
|
+
return this.store.get(id) ?? null;
|
|
2973
|
+
}
|
|
2974
|
+
|
|
2975
|
+
async create(entity: ${entityName}): Promise<${entityName}> {
|
|
2976
|
+
// TODO: Replace with your ORM save
|
|
2977
|
+
this.store.set(entity.id, entity);
|
|
2978
|
+
return entity;
|
|
2979
|
+
}
|
|
2980
|
+
|
|
2981
|
+
async update(entity: ${entityName}): Promise<${entityName} | null> {
|
|
2982
|
+
// TODO: Replace with your ORM update
|
|
2983
|
+
if (!this.store.has(entity.id)) return null;
|
|
2984
|
+
this.store.set(entity.id, entity);
|
|
2985
|
+
return entity;
|
|
2986
|
+
}
|
|
2987
|
+
|
|
2988
|
+
async delete(id: string): Promise<boolean> {
|
|
2989
|
+
// TODO: Replace with your ORM delete
|
|
2990
|
+
return this.store.delete(id);
|
|
2991
|
+
}
|
|
2992
|
+
}
|
|
2993
|
+
`;
|
|
2994
|
+
};
|
|
2995
|
+
generateLayeredServiceTemplate = (featureName) => {
|
|
2996
|
+
const capitalized = capitalize21(featureName);
|
|
2997
|
+
const entityName = `${capitalized}Entity`;
|
|
2998
|
+
const repoName = `${capitalized}Repository`;
|
|
2999
|
+
const serviceName = `${capitalized}Service`;
|
|
3000
|
+
return `import { ${repoName} } from "../repositories/${featureName}.repository";
|
|
3001
|
+
import { ${entityName} } from "../entities/${featureName}.entity";
|
|
3002
|
+
import { Create${capitalized}Dto, Update${capitalized}Dto, ${capitalized}ResponseDto, to${capitalized}ResponseDto } from "../dto/${featureName}.dto";
|
|
3003
|
+
|
|
3004
|
+
export class ${serviceName} {
|
|
3005
|
+
private readonly repository: ${repoName};
|
|
3006
|
+
|
|
3007
|
+
constructor() {
|
|
3008
|
+
this.repository = new ${repoName}();
|
|
3009
|
+
}
|
|
3010
|
+
|
|
3011
|
+
async findAll(): Promise<${capitalized}ResponseDto[]> {
|
|
3012
|
+
const entities = await this.repository.findAll();
|
|
3013
|
+
return entities.map(to${capitalized}ResponseDto);
|
|
3014
|
+
}
|
|
3015
|
+
|
|
3016
|
+
async findById(id: string): Promise<${capitalized}ResponseDto | null> {
|
|
3017
|
+
const entity = await this.repository.findById(id);
|
|
3018
|
+
return entity ? to${capitalized}ResponseDto(entity) : null;
|
|
3019
|
+
}
|
|
3020
|
+
|
|
3021
|
+
async create(data: Create${capitalized}Dto): Promise<${capitalized}ResponseDto> {
|
|
3022
|
+
const entity = new ${entityName}(String(Date.now()));
|
|
3023
|
+
// TODO: Map data fields onto entity
|
|
3024
|
+
const created = await this.repository.create(entity);
|
|
3025
|
+
return to${capitalized}ResponseDto(created);
|
|
3026
|
+
}
|
|
3027
|
+
|
|
3028
|
+
async update(id: string, data: Update${capitalized}Dto): Promise<${capitalized}ResponseDto | null> {
|
|
3029
|
+
const existing = await this.repository.findById(id);
|
|
3030
|
+
if (!existing) {
|
|
3031
|
+
return null;
|
|
3032
|
+
}
|
|
3033
|
+
// TODO: Apply data fields onto existing entity
|
|
3034
|
+
const updated = await this.repository.update(existing);
|
|
3035
|
+
return updated ? to${capitalized}ResponseDto(updated) : null;
|
|
3036
|
+
}
|
|
3037
|
+
|
|
3038
|
+
async delete(id: string): Promise<boolean> {
|
|
3039
|
+
return this.repository.delete(id);
|
|
3040
|
+
}
|
|
3041
|
+
}
|
|
3042
|
+
`;
|
|
3043
|
+
};
|
|
3044
|
+
generateLayeredControllerTemplate = (controllerName, featureName, methods) => {
|
|
3045
|
+
const capitalized = capitalize21(featureName);
|
|
3046
|
+
const serviceName = `${capitalized}Service`;
|
|
3047
|
+
const methodsCode = methods.map((method) => generateMethod5(method, capitalized, serviceName)).join("\n");
|
|
3048
|
+
return `import { Request, Response } from "opticore-express";
|
|
3049
|
+
import { ResponseHandler, HttpStatusCode, IResponseHandlerSuccessData } from "opticore-http-response";
|
|
3050
|
+
import { ${serviceName} } from "../services/${featureName}.service";
|
|
3051
|
+
|
|
3052
|
+
export class ${controllerName} {
|
|
3053
|
+
private static buildService(): ${serviceName} {
|
|
3054
|
+
return new ${serviceName}();
|
|
3055
|
+
}
|
|
3056
|
+
|
|
3057
|
+
${methodsCode}
|
|
3058
|
+
private static handleError(error: unknown) {
|
|
3059
|
+
const message = error instanceof Error ? error.message : "Internal server error";
|
|
3060
|
+
return ResponseHandler.error(message, HttpStatusCode.INTERNAL_SERVER_ERROR);
|
|
3061
|
+
}
|
|
3062
|
+
}
|
|
3063
|
+
`;
|
|
3064
|
+
};
|
|
3065
|
+
generateMethod5 = (method, capitalized, serviceName) => {
|
|
3066
|
+
const lower = method.toLowerCase();
|
|
3067
|
+
if (lower.includes("findall") || lower.includes("getall")) return generateFindAllMethod4(method, capitalized);
|
|
3068
|
+
if (lower.includes("findbyid") || lower.includes("getbyid") || lower.includes("getone")) return generateFindByIdMethod4(method, capitalized);
|
|
3069
|
+
if (lower.includes("create") || lower.includes("add")) return generateCreateMethod4(method, capitalized);
|
|
3070
|
+
if (lower.includes("update") || lower.includes("edit")) return generateUpdateMethod4(method, capitalized);
|
|
3071
|
+
if (lower.includes("delete") || lower.includes("remove")) return generateDeleteMethod4(method, capitalized);
|
|
3072
|
+
return `
|
|
3073
|
+
static async ${method}(req: Request, res: Response): Promise<IResponseHandlerSuccessData | ReturnType<typeof ResponseHandler.error>> {
|
|
3074
|
+
try {
|
|
3075
|
+
const service = ${capitalized}Controller.buildService();
|
|
3076
|
+
// TODO: Implement ${method} logic
|
|
3077
|
+
return ResponseHandler.success({}, "success", HttpStatusCode.OK);
|
|
3078
|
+
} catch (error) {
|
|
3079
|
+
return ${capitalized}Controller.handleError(error);
|
|
3080
|
+
}
|
|
3081
|
+
}
|
|
3082
|
+
`;
|
|
3083
|
+
};
|
|
3084
|
+
generateFindAllMethod4 = (method, capitalized) => `
|
|
3085
|
+
static async ${method}(req: Request, res: Response): Promise<IResponseHandlerSuccessData | ReturnType<typeof ResponseHandler.error>> {
|
|
3086
|
+
try {
|
|
3087
|
+
const service = ${capitalized}Controller.buildService();
|
|
3088
|
+
const results = await service.findAll();
|
|
3089
|
+
return ResponseHandler.success(results, "success", HttpStatusCode.OK);
|
|
3090
|
+
} catch (error) {
|
|
3091
|
+
return ${capitalized}Controller.handleError(error);
|
|
3092
|
+
}
|
|
3093
|
+
}
|
|
3094
|
+
`;
|
|
3095
|
+
generateFindByIdMethod4 = (method, capitalized) => `
|
|
3096
|
+
static async ${method}(req: Request, res: Response): Promise<IResponseHandlerSuccessData | ReturnType<typeof ResponseHandler.error>> {
|
|
3097
|
+
try {
|
|
3098
|
+
const { id } = req.params;
|
|
3099
|
+
const service = ${capitalized}Controller.buildService();
|
|
3100
|
+
const result = await service.findById(id);
|
|
3101
|
+
if (!result) {
|
|
3102
|
+
return ResponseHandler.error(\`Not found: \${id}\`, HttpStatusCode.NOT_FOUND);
|
|
3103
|
+
}
|
|
3104
|
+
return ResponseHandler.success(result, "success", HttpStatusCode.OK);
|
|
3105
|
+
} catch (error) {
|
|
3106
|
+
return ${capitalized}Controller.handleError(error);
|
|
3107
|
+
}
|
|
3108
|
+
}
|
|
3109
|
+
`;
|
|
3110
|
+
generateCreateMethod4 = (method, capitalized) => `
|
|
3111
|
+
static async ${method}(req: Request, res: Response): Promise<IResponseHandlerSuccessData | ReturnType<typeof ResponseHandler.error>> {
|
|
3112
|
+
try {
|
|
3113
|
+
const service = ${capitalized}Controller.buildService();
|
|
3114
|
+
const result = await service.create(req.body);
|
|
3115
|
+
return ResponseHandler.success(result, "created", HttpStatusCode.CREATED);
|
|
3116
|
+
} catch (error) {
|
|
3117
|
+
return ${capitalized}Controller.handleError(error);
|
|
3118
|
+
}
|
|
3119
|
+
}
|
|
3120
|
+
`;
|
|
3121
|
+
generateUpdateMethod4 = (method, capitalized) => `
|
|
3122
|
+
static async ${method}(req: Request, res: Response): Promise<IResponseHandlerSuccessData | ReturnType<typeof ResponseHandler.error>> {
|
|
3123
|
+
try {
|
|
3124
|
+
const { id } = req.params;
|
|
3125
|
+
const service = ${capitalized}Controller.buildService();
|
|
3126
|
+
const result = await service.update(id, req.body);
|
|
3127
|
+
if (!result) {
|
|
3128
|
+
return ResponseHandler.error(\`Not found: \${id}\`, HttpStatusCode.NOT_FOUND);
|
|
3129
|
+
}
|
|
3130
|
+
return ResponseHandler.success(result, "success", HttpStatusCode.OK);
|
|
3131
|
+
} catch (error) {
|
|
3132
|
+
return ${capitalized}Controller.handleError(error);
|
|
3133
|
+
}
|
|
3134
|
+
}
|
|
3135
|
+
`;
|
|
3136
|
+
generateDeleteMethod4 = (method, capitalized) => `
|
|
3137
|
+
static async ${method}(req: Request, res: Response): Promise<IResponseHandlerSuccessData | ReturnType<typeof ResponseHandler.error>> {
|
|
3138
|
+
try {
|
|
3139
|
+
const { id } = req.params;
|
|
3140
|
+
const service = ${capitalized}Controller.buildService();
|
|
3141
|
+
const deleted = await service.delete(id);
|
|
3142
|
+
if (!deleted) {
|
|
3143
|
+
return ResponseHandler.error(\`Not found: \${id}\`, HttpStatusCode.NOT_FOUND);
|
|
3144
|
+
}
|
|
3145
|
+
return ResponseHandler.success(null, "deleted", HttpStatusCode.NO_CONTENT);
|
|
3146
|
+
} catch (error) {
|
|
3147
|
+
return ${capitalized}Controller.handleError(error);
|
|
3148
|
+
}
|
|
3149
|
+
}
|
|
3150
|
+
`;
|
|
3151
|
+
generateLayeredRouterHandlerTemplate = (featureName, controllerMethods) => {
|
|
3152
|
+
const capitalized = capitalize21(featureName);
|
|
3153
|
+
const handlerName = `${capitalized}HandlerRouter`;
|
|
3154
|
+
const controllerName = `${capitalized}Controller`;
|
|
3155
|
+
const routesCode = (controllerMethods || []).map((method) => {
|
|
3156
|
+
const { httpMethod, path: path10 } = resolveRoute4(method, featureName);
|
|
3157
|
+
return `{
|
|
3158
|
+
path: \`${path10}\`,
|
|
3159
|
+
method: "${httpMethod}",
|
|
3160
|
+
middlewares: [],
|
|
3161
|
+
handler: async (ctx: ICustomContext) => await ${controllerName}.${method}(ctx.req, ctx.res)
|
|
3162
|
+
}`;
|
|
3163
|
+
}).join(",\n");
|
|
3164
|
+
return `import { OpticoreRoutingFactory, ICustomContext, IMultipleRouteDefinition } from "opticore-router";
|
|
3165
|
+
import { ${controllerName} } from "../controllers/${featureName}.controller";
|
|
3166
|
+
|
|
3167
|
+
export const ${handlerName}: () => IMultipleRouteDefinition = () => {
|
|
3168
|
+
return OpticoreRoutingFactory.routes(
|
|
3169
|
+
${controllerName},
|
|
3170
|
+
[
|
|
3171
|
+
${routesCode.replace(/\n/g, "\n ")}
|
|
3172
|
+
]
|
|
3173
|
+
);
|
|
3174
|
+
};
|
|
3175
|
+
`;
|
|
3176
|
+
};
|
|
3177
|
+
generateLayeredRouterTemplate = (featureName) => {
|
|
3178
|
+
const capitalized = capitalize21(featureName);
|
|
3179
|
+
const handlerName = `${capitalized}HandlerRouter`;
|
|
3180
|
+
const routerName = `${capitalized}Router`;
|
|
3181
|
+
return `import { ${handlerName} } from "./${featureName}.router.handler";
|
|
3182
|
+
import { TFeatureRoutes } from "opticore-router";
|
|
3183
|
+
|
|
3184
|
+
export const ${routerName}: TFeatureRoutes = {
|
|
3185
|
+
routes: [
|
|
3186
|
+
{
|
|
3187
|
+
path: ${handlerName}().path,
|
|
3188
|
+
handler: ${handlerName}().handler
|
|
3189
|
+
}
|
|
3190
|
+
]
|
|
3191
|
+
};
|
|
3192
|
+
`;
|
|
3193
|
+
};
|
|
3194
|
+
resolveRoute4 = (methodName, featureName) => {
|
|
3195
|
+
const lower = methodName.toLowerCase();
|
|
3196
|
+
if (lower.includes("findall") || lower.includes("getall")) return { httpMethod: "get", path: `/${featureName}` };
|
|
3197
|
+
if (lower.includes("findbyid") || lower.includes("getbyid") || lower.includes("getone")) return { httpMethod: "get", path: `/${featureName}/:id` };
|
|
3198
|
+
if (lower.includes("create") || lower.includes("add")) return { httpMethod: "post", path: `/${featureName}` };
|
|
3199
|
+
if (lower.includes("update") || lower.includes("edit")) return { httpMethod: "put", path: `/${featureName}/:id` };
|
|
3200
|
+
if (lower.includes("delete") || lower.includes("remove")) return { httpMethod: "delete", path: `/${featureName}/:id` };
|
|
3201
|
+
return { httpMethod: "get", path: `/${featureName}/${lower}` };
|
|
3202
|
+
};
|
|
3203
|
+
}
|
|
3204
|
+
});
|
|
3205
|
+
|
|
3206
|
+
// src/templates/layeredModule/layeredModuleScaffold.template.ts
|
|
3207
|
+
var import_path8, import_ansi_colors11, import_prompts7, capitalize22, layeredModuleTemplate;
|
|
3208
|
+
var init_layeredModuleScaffold_template = __esm({
|
|
3209
|
+
"src/templates/layeredModule/layeredModuleScaffold.template.ts"() {
|
|
3210
|
+
"use strict";
|
|
3211
|
+
init_cjs_shims();
|
|
3212
|
+
import_path8 = __toESM(require("path"), 1);
|
|
3213
|
+
import_ansi_colors11 = __toESM(require("ansi-colors"), 1);
|
|
3214
|
+
import_prompts7 = require("@clack/prompts");
|
|
3215
|
+
init_prompt_utils();
|
|
3216
|
+
init_fsModule_utils();
|
|
3217
|
+
init_featureComponentGenerator_utils();
|
|
3218
|
+
init_layeredModule_template();
|
|
3219
|
+
capitalize22 = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
|
3220
|
+
layeredModuleTemplate = async (featureName) => {
|
|
3221
|
+
FeatureComponentGeneratorUtils.setStructure("layered");
|
|
3222
|
+
const basePath = import_path8.default.join("src", "features", featureName);
|
|
3223
|
+
const paths = {
|
|
3224
|
+
entitiesDir: import_path8.default.join(basePath, "entities"),
|
|
3225
|
+
dtoDir: import_path8.default.join(basePath, "dto"),
|
|
3226
|
+
repositoriesDir: import_path8.default.join(basePath, "repositories"),
|
|
3227
|
+
servicesDir: import_path8.default.join(basePath, "services"),
|
|
3228
|
+
controllersDir: import_path8.default.join(basePath, "controllers"),
|
|
3229
|
+
routesDir: import_path8.default.join(basePath, "routes")
|
|
3230
|
+
};
|
|
3231
|
+
Object.values(paths).forEach((dir) => UFsModule.createDirectoryRecursively(dir));
|
|
3232
|
+
const controllerName = `${capitalize22(featureName)}Controller`;
|
|
3233
|
+
UFsModule.createFile(import_path8.default.join(paths.entitiesDir, `${featureName}.entity.ts`), generateLayeredEntityTemplate(featureName));
|
|
3234
|
+
console.log(import_ansi_colors11.default.green(`\u2705 Entity created: ${import_path8.default.join(paths.entitiesDir, `${featureName}.entity.ts`)}`));
|
|
3235
|
+
UFsModule.createFile(import_path8.default.join(paths.dtoDir, `${featureName}.dto.ts`), generateLayeredDtoTemplate(featureName));
|
|
3236
|
+
console.log(import_ansi_colors11.default.green(`\u2705 DTO created: ${import_path8.default.join(paths.dtoDir, `${featureName}.dto.ts`)}`));
|
|
3237
|
+
UFsModule.createFile(import_path8.default.join(paths.repositoriesDir, `${featureName}.repository.ts`), generateLayeredRepositoryTemplate(featureName));
|
|
3238
|
+
console.log(import_ansi_colors11.default.green(`\u2705 Repository created: ${import_path8.default.join(paths.repositoriesDir, `${featureName}.repository.ts`)}`));
|
|
3239
|
+
UFsModule.createFile(import_path8.default.join(paths.servicesDir, `${featureName}.service.ts`), generateLayeredServiceTemplate(featureName));
|
|
3240
|
+
console.log(import_ansi_colors11.default.green(`\u2705 Service created: ${import_path8.default.join(paths.servicesDir, `${featureName}.service.ts`)}`));
|
|
3241
|
+
const wantsMethods = await UPrompt.confirm("Do you want to add methods to the controller?");
|
|
3242
|
+
let methods = [];
|
|
3243
|
+
let controllerContent;
|
|
3244
|
+
if (wantsMethods && !(0, import_prompts7.isCancel)(wantsMethods)) {
|
|
3245
|
+
const methodsText = await UPrompt.text(
|
|
3246
|
+
"Enter the method names (comma separated):",
|
|
3247
|
+
"create, findAll, findById, update, delete",
|
|
3248
|
+
(v) => v ? void 0 : "You must enter at least one method."
|
|
3249
|
+
);
|
|
3250
|
+
methods = methodsText.split(",").map((m) => m.trim()).filter(Boolean);
|
|
3251
|
+
controllerContent = generateLayeredControllerTemplate(controllerName, featureName, methods);
|
|
3252
|
+
} else {
|
|
3253
|
+
controllerContent = `import { Request, Response } from "opticore-express";
|
|
3254
|
+
|
|
3255
|
+
export class ${controllerName} {}
|
|
3256
|
+
`;
|
|
3257
|
+
}
|
|
3258
|
+
const controllerPath = import_path8.default.join(paths.controllersDir, `${featureName}.controller.ts`);
|
|
3259
|
+
UFsModule.createFile(controllerPath, controllerContent);
|
|
3260
|
+
console.log(import_ansi_colors11.default.green(`\u2705 Controller created: ${controllerPath}`));
|
|
3261
|
+
UFsModule.createFile(
|
|
3262
|
+
import_path8.default.join(paths.routesDir, `${featureName}.router.handler.ts`),
|
|
3263
|
+
generateLayeredRouterHandlerTemplate(featureName, methods)
|
|
3264
|
+
);
|
|
3265
|
+
console.log(import_ansi_colors11.default.green(`\u2705 Router Handler created: ${import_path8.default.join(paths.routesDir, `${featureName}.router.handler.ts`)}`));
|
|
3266
|
+
UFsModule.createFile(
|
|
3267
|
+
import_path8.default.join(paths.routesDir, `${featureName}.router.ts`),
|
|
3268
|
+
generateLayeredRouterTemplate(featureName)
|
|
3269
|
+
);
|
|
3270
|
+
await FeatureComponentGeneratorUtils.registerModuleRouter(featureName);
|
|
3271
|
+
console.log(import_ansi_colors11.default.green(`\u2705 Router created: ${import_path8.default.join(paths.routesDir, `${featureName}.router.ts`)}`));
|
|
3272
|
+
console.log(
|
|
3273
|
+
import_ansi_colors11.default.bgGreen(
|
|
3274
|
+
import_ansi_colors11.default.white(`
|
|
3275
|
+
\u{1F389} Feature "${featureName}" scaffolded with Layered architecture!
|
|
3276
|
+
`)
|
|
3277
|
+
)
|
|
3278
|
+
);
|
|
3279
|
+
};
|
|
3280
|
+
}
|
|
3281
|
+
});
|
|
3282
|
+
|
|
2587
3283
|
// src/core/core.ts
|
|
2588
3284
|
var core_exports = {};
|
|
2589
|
-
var import_process2, import_node_fs2,
|
|
3285
|
+
var import_process2, import_node_fs2, import_path9, import_prompts8;
|
|
2590
3286
|
var init_core = __esm({
|
|
2591
3287
|
"src/core/core.ts"() {
|
|
2592
3288
|
"use strict";
|
|
2593
3289
|
init_cjs_shims();
|
|
2594
3290
|
import_process2 = __toESM(require("process"), 1);
|
|
2595
3291
|
import_node_fs2 = __toESM(require("fs"), 1);
|
|
2596
|
-
|
|
2597
|
-
|
|
3292
|
+
import_path9 = __toESM(require("path"), 1);
|
|
3293
|
+
import_prompts8 = require("@clack/prompts");
|
|
2598
3294
|
init_welcomeMessage_utils();
|
|
2599
3295
|
init_choiceFeatureCleanModule();
|
|
2600
3296
|
init_customFeatureInfo_utils();
|
|
@@ -2602,6 +3298,8 @@ var init_core = __esm({
|
|
|
2602
3298
|
init_base_service();
|
|
2603
3299
|
init_createController_application();
|
|
2604
3300
|
init_customModuleScaffold_template();
|
|
3301
|
+
init_mvcModuleScaffold_template();
|
|
3302
|
+
init_layeredModuleScaffold_template();
|
|
2605
3303
|
(async () => {
|
|
2606
3304
|
UWelcomeMessage();
|
|
2607
3305
|
const featureChoice = await choiceFeatureCleanModule();
|
|
@@ -2609,18 +3307,40 @@ var init_core = __esm({
|
|
|
2609
3307
|
await customModuleScaffoldTemplate();
|
|
2610
3308
|
return;
|
|
2611
3309
|
}
|
|
3310
|
+
if (featureChoice === "mvc_architecture" || featureChoice === "layered_architecture") {
|
|
3311
|
+
const featureName2 = await _featureName();
|
|
3312
|
+
const directory2 = import_path9.default.join(import_process2.default.cwd(), "src", "features");
|
|
3313
|
+
const featureDirectory2 = import_path9.default.join(directory2, featureName2.toString());
|
|
3314
|
+
if (BaseService._isSubdirectoryExists(featureName2)) {
|
|
3315
|
+
BaseService._featureFounded(featureName2);
|
|
3316
|
+
}
|
|
3317
|
+
if ((0, import_prompts8.isCancel)(featureName2)) {
|
|
3318
|
+
BaseService._cancelOperation(featureDirectory2);
|
|
3319
|
+
return;
|
|
3320
|
+
}
|
|
3321
|
+
if (!import_node_fs2.default.existsSync(directory2)) {
|
|
3322
|
+
BaseService._checkFeatureDir();
|
|
3323
|
+
return;
|
|
3324
|
+
}
|
|
3325
|
+
if (featureChoice === "mvc_architecture") {
|
|
3326
|
+
await mvcModuleTemplate(featureName2.toString());
|
|
3327
|
+
} else {
|
|
3328
|
+
await layeredModuleTemplate(featureName2.toString());
|
|
3329
|
+
}
|
|
3330
|
+
return;
|
|
3331
|
+
}
|
|
2612
3332
|
if (!featureChoice || featureChoice !== "opticore_clean_module") {
|
|
2613
3333
|
import_process2.default.exit(0);
|
|
2614
3334
|
}
|
|
2615
3335
|
UCustomFeatureInfo(featureChoice);
|
|
2616
3336
|
const featureName = await _featureName();
|
|
2617
|
-
const directory =
|
|
2618
|
-
const featureDirectory =
|
|
3337
|
+
const directory = import_path9.default.join(import_process2.default.cwd(), "src", "features");
|
|
3338
|
+
const featureDirectory = import_path9.default.join(directory, featureName.toString());
|
|
2619
3339
|
const featureCleanModule = BaseService._isSubdirectoryExists(featureName);
|
|
2620
3340
|
if (featureCleanModule) {
|
|
2621
3341
|
BaseService._featureFounded(featureName);
|
|
2622
3342
|
}
|
|
2623
|
-
if ((0,
|
|
3343
|
+
if ((0, import_prompts8.isCancel)(featureName)) {
|
|
2624
3344
|
BaseService._cancelOperation(featureDirectory);
|
|
2625
3345
|
} else {
|
|
2626
3346
|
try {
|