Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(feat) Add support for generating modules #73

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,084 changes: 1,051 additions & 33 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"lint": "eslint .",
"lint:md": "remark .",
"lint:fix": "eslint --fix .",
"plop": "plop",
"start": "node dist/bin/server.js",
"serve": "cross-env NODE_ENV=development concurrently --kill-others-on-fail npm:serve:*",
"serve:assets": "cpx \"src/assets/**/*.*\" dist/assets --watch",
Expand Down Expand Up @@ -89,6 +90,7 @@
"js-yaml": "^4.1.0",
"mocha": "^9.2.0",
"nyc": "^15.1.0",
"plop": "^3.1.2",
"remark-cli": "^10.0.0",
"remark-lint": "^9.1.0",
"remark-preset-lint-recommended": "^6.1.1",
Expand Down
103 changes: 103 additions & 0 deletions plopfile.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
export default function (
/** @type {import('plop').NodePlopAPI} */
plop
) {
plop.setGenerator("basics", {
description: "this is a skeleton plopfile",
prompts: [
{
type: "input",
name: "name",
message: "Name your resource: ",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about we use module instead of resource?

},
],
actions: [
{
type: "add",
path: "src/apps/backend/modules/{{snakeCase name}}/types.ts",
templateFile: "templates/types.template.hbs",
},
{
type: "add",
path: "src/apps/backend/modules/{{snakeCase name}}/{{snakeCase name}}-service.ts",
templateFile: "templates/service.template.hbs",
},
{
type: "add",
path: "src/apps/backend/modules/{{snakeCase name}}/{{snakeCase name}}-service-manager.ts",
templateFile: "templates/service-manager.template.hbs",
},
{
type: "add",
path: "src/apps/backend/modules/{{snakeCase name}}/rest-api/{{snakeCase name}}-controller.ts",
templateFile: "templates/controller.template.hbs",
},
{
type: "add",
path: "src/apps/backend/modules/{{snakeCase name}}/rest-api/{{snakeCase name}}-rest-api-server.ts",
templateFile: "templates/rest-api-server.template.hbs",
},
{
type: "add",
path: "src/apps/backend/modules/{{snakeCase name}}/rest-api/{{snakeCase name}}-router.ts",
templateFile: "templates/router.template.hbs",
},
{
type: "add",
path: "src/apps/backend/modules/{{snakeCase name}}/internal/{{snakeCase name}}-writer.ts",
templateFile: "templates/writer.template.hbs",
},
{
type: "add",
path: "src/apps/backend/modules/{{snakeCase name}}/internal/{{snakeCase name}}-reader.ts",
templateFile: "templates/reader.template.hbs",
},
{
type: "add",
path: "src/apps/backend/modules/{{snakeCase name}}/internal/{{snakeCase name}}-utils.ts",
templateFile: "templates/utils.template.hbs",
},
{
type: "add",
path: "src/apps/backend/modules/{{snakeCase name}}/internal/store/{{snakeCase name}}-db.ts",
templateFile: "templates/db.template.hbs",
},
{
type: "add",
path: "src/apps/backend/modules/{{snakeCase name}}/internal/store/{{snakeCase name}}-repository.ts",
templateFile: "templates/repository.template.hbs",
},
],
});

plop.setHelper("titleCase", (str) => {
return str.replace(/\w\S*/g, function (txt) {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
});
});

plop.setHelper("snakeCase", (str) => {
return str
.replace(/\W+/g, " ")
.split(/ |\B(?=[A-Z])/)
.map((word) => word.toLowerCase())
.join("-");
});

plop.setHelper("titleCase", (str) => {
return str
.replace(/\W+/g, " ")
.split(/ |\B(?=[A-Z])/)
.map((txt) => txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase())
.join("");
});

plop.setHelper("camleCase", (str) => {
const string = str
.replace(/\W+/g, " ")
.split(/ |\B(?=[A-Z])/)
.map((txt) => txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase())
.join("");
return string.charAt(0).toLowerCase() + string.substr(1)
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export default class OrganizationAccountReader {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export default class OrganizationAccountUtil {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export default class OrganizationAccountWriter {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Schema, Types } from 'mongoose';

export interface OrganizationAccountDB {
_id: Types.ObjectId;
}

export const organizationAccountDbSchema: Schema = new Schema<OrganizationAccountDB>(
{
},
{
timestamps: {
createdAt: 'createdAt',
updatedAt: 'updatedAt',
},
},
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import mongoose, { CallbackError, Connection } from 'mongoose';

import ConfigService from '../../../config/config-service';

import { OrganizationAccountDB, organizationAccountDbSchema } from './organization-account-db';

export default class OrganizationAccountRepository {
public static organizationAccountDB: mongoose.Model<OrganizationAccountDB>;

static async createDBConnection(): Promise<Connection> {
return new Promise((resolve, reject) => {
const mongoURI = ConfigService.getStringValue('mongoDb.uri');
mongoose.createConnection(
mongoURI,
{},
(error: CallbackError, result: Connection): void => {
if (error) {
reject(error);
} else {
OrganizationAccountRepository.organizationAccountDB = result.model(
'OrganizationAccount',
organizationAccountDbSchema,
) as unknown as mongoose.Model<OrganizationAccountDB>;
resolve(result);
}
},
);
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Application } from 'express';

import OrganizationAccountRESTApiServer from './rest-api/organization-account-rest-api-server';

export default class OrganizationAccountServiceManager {
public static async createRestAPIServer(): Promise<Application> {
return OrganizationAccountRESTApiServer.create();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export default class OrganizationAccountService {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {
NextFunction, Request, Response,
} from 'express';

export default class OrganizationAccountController {
public static createOrganizationAccount(
_req: Request,
res: Response,
next: NextFunction,
): void {
try {
res.status(201).send({});
} catch (e) {
next(e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import bodyParser from 'body-parser';
import express, { Application } from 'express';

import ErrorHandler from '../../error/error-handler';
import OrganizationAccountRepository from '../internal/store/organization-account-repository';

import OrganizationAccountRouter from './organization-account-router';

export default class OrganizationAccountRESTApiServer {
public static async create(): Promise<Application> {
await OrganizationAccountRepository.createDBConnection();

const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

app.use('/organization account', OrganizationAccountRouter.getRoutes());

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can this be asked as a question too - like what rest base url you want for the module? If user presses Enter you can fall back to default one.

Also we are missing a hyphen


app.use(ErrorHandler.AppErrorHandler);

return Promise.resolve(app);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/* eslint-disable @typescript-eslint/no-misused-promises */
import { Router } from 'express';

import OrganizationAccountController from './organization-account-controller';

export default class OrganizationAccountRouter {
public static getRoutes(): Router {
const router = Router();

router.post('/', OrganizationAccountController.createOrganizationAccount);

return router;
}
}
3 changes: 3 additions & 0 deletions src/apps/backend/modules/organization-account/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default class OrganizationAccount {
id: string;
}
17 changes: 17 additions & 0 deletions templates/controller.template.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {
NextFunction, Request, Response,
} from 'express';

export default class {{titleCase name}}Controller {
public static create{{titleCase name}}(
_req: Request,
res: Response,
next: NextFunction,
): void {
try {
res.status(201).send({});
} catch (e) {
next(e);
}
}
}
16 changes: 16 additions & 0 deletions templates/db.template.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Schema, Types } from 'mongoose';

export interface {{titleCase name}}DB {
_id: Types.ObjectId;
}

export const {{camleCase name}}DbSchema: Schema = new Schema<{{titleCase name}}DB>(
{
},
{
timestamps: {
createdAt: 'createdAt',
updatedAt: 'updatedAt',
},
},
);
2 changes: 2 additions & 0 deletions templates/reader.template.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export default class {{titleCase name}}Reader {
}
30 changes: 30 additions & 0 deletions templates/repository.template.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import mongoose, { CallbackError, Connection } from 'mongoose';

import ConfigService from '../../../config/config-service';

import { {{titleCase name}}DB, {{camleCase name}}DbSchema } from './{{snakeCase name}}-db';

export default class {{titleCase name}}Repository {
public static {{camleCase name}}DB: mongoose.Model<{{titleCase name}}DB>;

static async createDBConnection(): Promise<Connection> {
return new Promise((resolve, reject) => {
const mongoURI = ConfigService.getStringValue('mongoDb.uri');
mongoose.createConnection(
mongoURI,
{},
(error: CallbackError, result: Connection): void => {
if (error) {
reject(error);
} else {
{{titleCase name}}Repository.{{camleCase name}}DB = result.model(
'{{titleCase name}}',
{{camleCase name}}DbSchema,
) as unknown as mongoose.Model<{{titleCase name}}DB>;
resolve(result);
}
},
);
});
}
}
23 changes: 23 additions & 0 deletions templates/rest-api-server.template.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import bodyParser from 'body-parser';
import express, { Application } from 'express';

import ErrorHandler from '../../error/error-handler';
import {{titleCase name}}Repository from '../internal/store/{{snakeCase name}}-repository';

import {{titleCase name}}Router from './{{snakeCase name}}-router';

export default class {{titleCase name}}RESTApiServer {
public static async create(): Promise<Application> {
await {{titleCase name}}Repository.createDBConnection();

const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

app.use('/{{name}}', {{titleCase name}}Router.getRoutes());

app.use(ErrorHandler.AppErrorHandler);

return Promise.resolve(app);
}
}
14 changes: 14 additions & 0 deletions templates/router.template.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/* eslint-disable @typescript-eslint/no-misused-promises */
import { Router } from 'express';

import {{titleCase name}}Controller from './{{snakeCase name}}-controller';

export default class {{titleCase name}}Router {
public static getRoutes(): Router {
const router = Router();

router.post('/', {{titleCase name}}Controller.create{{titleCase name}});

return router;
}
}
9 changes: 9 additions & 0 deletions templates/service-manager.template.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Application } from 'express';

import {{titleCase name}}RESTApiServer from './rest-api/{{snakeCase name}}-rest-api-server';

export default class {{titleCase name}}ServiceManager {
public static async createRestAPIServer(): Promise<Application> {
return {{titleCase name}}RESTApiServer.create();
}
}
2 changes: 2 additions & 0 deletions templates/service.template.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export default class {{titleCase name}}Service {
}
3 changes: 3 additions & 0 deletions templates/types.template.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default class {{titleCase name}} {
id: string;
}
2 changes: 2 additions & 0 deletions templates/utils.template.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export default class {{titleCase name}}Util {
}
2 changes: 2 additions & 0 deletions templates/writer.template.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export default class {{titleCase name}}Writer {
}