@expressots/cli 1.0.1 → 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/README.md CHANGED
@@ -8,11 +8,6 @@
8
8
 
9
9
  The Expresso TS CLI is a command-line interface tool that helps you to create `ExpressoTS` projects, develop, and maintain your applications and resources created. It assists in multiple ways, including scaffolding the project as well as the services offered by the application such as use cases, controllers, providers and more.
10
10
 
11
- ### This is an example of the CLI for the Expresso TS framework.
12
-
13
- [![asciicast](https://asciinema.org/a/7diTOTyY653mpdA0JtugjRn9a.svg)](https://asciinema.org/a/7diTOTyY653mpdA0JtugjRn9a)
14
-
15
-
16
11
  ## Installation 💻
17
12
 
18
13
  ```
@@ -21,7 +16,7 @@ npm install -g @expressots/cli
21
16
 
22
17
  ## Usage
23
18
 
24
- Learn more in the official documentation
19
+ Learn more in the [official documentation](https://expresso-ts.com/docs/category/cli)
25
20
 
26
21
  ## Stay in touch
27
22
 
@@ -0,0 +1,20 @@
1
+ export declare const enum Pattern {
2
+ LOWER_CASE = "lowercase",
3
+ KEBAB_CASE = "kebab-case",
4
+ PASCAL_CASE = "PascalCase",
5
+ CAMEL_CASE = "camelCase"
6
+ }
7
+ /**
8
+ * The configuration object for the Expresso CLI.
9
+ *
10
+ * @property {Pattern} scaffoldPattern - The pattern to use when scaffolding files.
11
+ * @property {string} sourceRoot - The root directory for the source files.
12
+ * @property {boolean} opinionated - Whether or not to use the opinionated configuration.
13
+ *
14
+ * @see [ExpressoConfig](https://expresso-ts.com/docs)
15
+ */
16
+ export interface ExpressoConfig {
17
+ scaffoldPattern: Pattern;
18
+ sourceRoot: string;
19
+ opinionated: boolean;
20
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1 @@
1
+ export * from "./config";
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./config"), exports);
package/bin/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/bin/cli.js CHANGED
@@ -6,10 +6,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  const yargs_1 = __importDefault(require("yargs"));
8
8
  const helpers_1 = require("yargs/helpers");
9
+ const generate_1 = require("./generate");
9
10
  const new_1 = require("./new");
10
11
  (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
11
12
  .example("$0 new <project-name>", "Create a new Expresso TS project")
12
13
  .command((0, new_1.createProject)())
14
+ .command((0, generate_1.generateProject)())
13
15
  .demandCommand(1, "You need at least one command before moving on")
14
16
  .epilog("For more information, visit https://expresso-ts.com")
15
17
  .help()
@@ -0,0 +1,4 @@
1
+ import { CommandModule } from "yargs";
2
+ type CommandModuleArgs = {};
3
+ declare const generateProject: () => CommandModule<CommandModuleArgs, any>;
4
+ export { generateProject };
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.generateProject = void 0;
7
+ const form_1 = require("./form");
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const generateProject = () => {
10
+ return {
11
+ command: "generate [schematic] [path..]",
12
+ describe: "Generate a schematic",
13
+ aliases: ["g"],
14
+ builder: (yargs) => {
15
+ yargs.positional("schematic", {
16
+ choices: [
17
+ "usecase",
18
+ "controller",
19
+ "dto",
20
+ "service",
21
+ "provider",
22
+ ],
23
+ describe: "The schematic to generate",
24
+ type: "string",
25
+ coerce: coerceSchematicAliases,
26
+ });
27
+ yargs.positional("path..", {
28
+ describe: "The path to generate the schematic",
29
+ type: "string",
30
+ });
31
+ return yargs;
32
+ },
33
+ handler: async ({ schematic, path }) => {
34
+ const file = await (0, form_1.createTemplate)({ schematic, path: path.join(" ") });
35
+ console.log(chalk_1.default.green(`> ${file.split(".")[0]} ${schematic} created! 🚀`));
36
+ },
37
+ };
38
+ };
39
+ exports.generateProject = generateProject;
40
+ const coerceSchematicAliases = (arg) => {
41
+ switch (arg) {
42
+ case "u":
43
+ return "usecase";
44
+ case "c":
45
+ return "controller";
46
+ case "d":
47
+ return "dto";
48
+ case "s":
49
+ return "service";
50
+ case "p":
51
+ return "provider";
52
+ default:
53
+ return arg;
54
+ }
55
+ };
@@ -0,0 +1,6 @@
1
+ type CreateTemplateProps = {
2
+ schematic: string;
3
+ path: string;
4
+ };
5
+ export declare const createTemplate: ({ schematic, path: target, }: CreateTemplateProps) => Promise<string>;
6
+ export {};
@@ -0,0 +1,206 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __asyncValues = (this && this.__asyncValues) || function (o) {
26
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
27
+ var m = o[Symbol.asyncIterator], i;
28
+ return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
29
+ function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
30
+ function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
31
+ };
32
+ var __importDefault = (this && this.__importDefault) || function (mod) {
33
+ return (mod && mod.__esModule) ? mod : { "default": mod };
34
+ };
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.createTemplate = void 0;
37
+ const nodePath = __importStar(require("path"));
38
+ const node_fs_1 = require("node:fs");
39
+ const mustache_1 = require("mustache");
40
+ const fs_1 = require("fs");
41
+ const chalk_1 = __importDefault(require("chalk"));
42
+ const boost_ts_1 = require("@expressots/boost-ts");
43
+ const compiler_1 = __importDefault(require("../utils/compiler"));
44
+ function getFileNameWithoutExtension(filePath) {
45
+ return filePath.split('.')[0];
46
+ }
47
+ const messageColors = {
48
+ usecase: (text) => chalk_1.default.cyan(text),
49
+ controller: (text) => chalk_1.default.magenta(text),
50
+ "controller-service": (text) => chalk_1.default.magenta(text),
51
+ dto: (text) => chalk_1.default.blue(text),
52
+ provider: (text) => chalk_1.default.yellow(text),
53
+ module: (text) => chalk_1.default.red(text),
54
+ };
55
+ const createTemplate = async ({ schematic, path: target, }) => {
56
+ var _a, e_1, _b, _c;
57
+ const withinSource = schematicFolder(schematic);
58
+ if (!withinSource)
59
+ return;
60
+ const { path, file, className } = await splitTarget({ target, schematic });
61
+ const { sourceRoot } = await compiler_1.default.loadConfig();
62
+ const usecaseDir = `${sourceRoot}/${withinSource}`;
63
+ (0, node_fs_1.mkdirSync)(`${usecaseDir}/${path}`, { recursive: true });
64
+ if (schematic !== "service") {
65
+ console.log(messageColors[schematic](`> [${schematic}] Creating ${file}...`));
66
+ writeTemplate({
67
+ outputPath: `${usecaseDir}/${path}${file}`,
68
+ template: {
69
+ path: `./templates/${schematic}.tpl`,
70
+ data: {
71
+ className,
72
+ route: path.replace(/\/$/, ''),
73
+ construct: (0, boost_ts_1.anyCaseToKebabCase)(className),
74
+ },
75
+ },
76
+ });
77
+ }
78
+ else {
79
+ try {
80
+ for (var _d = true, _e = __asyncValues(["controller-service", "usecase", "dto"]), _f; _f = await _e.next(), _a = _f.done, !_a;) {
81
+ _c = _f.value;
82
+ _d = false;
83
+ try {
84
+ const currentSchematic = _c;
85
+ const schematicFile = file.replace(`controller.ts`, `${currentSchematic}.ts`);
86
+ console.log(messageColors[currentSchematic](`> [${currentSchematic}] Creating ${schematicFile.replace("controller-service", "controller")}...`));
87
+ writeTemplate({
88
+ outputPath: `${usecaseDir}/${path}${schematicFile.replace("controller-service", "controller")}`,
89
+ template: {
90
+ path: `./templates/${currentSchematic}.tpl`,
91
+ data: {
92
+ className,
93
+ fileName: getFileNameWithoutExtension(file),
94
+ useCase: (0, boost_ts_1.anyCaseToCamelCase)(className),
95
+ route: path.replace(/\/$/, ''),
96
+ construct: (0, boost_ts_1.anyCaseToKebabCase)(className),
97
+ },
98
+ },
99
+ });
100
+ }
101
+ finally {
102
+ _d = true;
103
+ }
104
+ }
105
+ }
106
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
107
+ finally {
108
+ try {
109
+ if (!_d && !_a && (_b = _e.return)) await _b.call(_e);
110
+ }
111
+ finally { if (e_1) throw e_1.error; }
112
+ }
113
+ }
114
+ const moduleName = path.split("/")[0];
115
+ if (["controller", "service"].includes(schematic) && !(0, fs_1.existsSync)(`${usecaseDir}/${moduleName}/${moduleName}.module.ts`)) {
116
+ console.log(messageColors.module(`> [module] Creating ${moduleName}.module.ts...`));
117
+ writeTemplate({
118
+ outputPath: `${usecaseDir}/${moduleName}/${moduleName}.module.ts`,
119
+ template: {
120
+ path: `./templates/module.tpl`,
121
+ data: {
122
+ moduleName: moduleName[0].toUpperCase() + moduleName.slice(1),
123
+ className,
124
+ path: `${path.split("/")[1]}/${file.slice(0, file.lastIndexOf('.'))}`
125
+ },
126
+ },
127
+ });
128
+ }
129
+ return file;
130
+ };
131
+ exports.createTemplate = createTemplate;
132
+ const writeTemplate = ({ outputPath, template: { path, data }, }) => {
133
+ (0, fs_1.writeFileSync)(outputPath, (0, mustache_1.render)((0, node_fs_1.readFileSync)(nodePath.join(__dirname, path), "utf8"), data));
134
+ };
135
+ const schematicFolder = (schematic) => {
136
+ switch (schematic) {
137
+ case "usecase":
138
+ return "useCases";
139
+ case "controller":
140
+ return "useCases";
141
+ case "dto":
142
+ return "useCases";
143
+ case "service":
144
+ return "useCases";
145
+ case "provider":
146
+ return "providers";
147
+ }
148
+ return undefined;
149
+ };
150
+ const splitTarget = async ({ target, schematic, }) => {
151
+ if (schematic === "provider")
152
+ return await splitTargetProviderEdgeCase({ target, schematic });
153
+ if (schematic === "service")
154
+ schematic = "controller"; // Anything just to generate
155
+ // 1. Extract the name (first part of the target)
156
+ const [name, ...remainingPath] = target.split("/");
157
+ // 2. Check if the name is camelCase or kebab-case
158
+ const camelCaseRegex = /[A-Z]/;
159
+ const kebabCaseRegex = /[_\-\s]+/;
160
+ const isCamelCase = camelCaseRegex.test(name);
161
+ const isKebabCase = kebabCaseRegex.test(name);
162
+ if (isCamelCase || isKebabCase) {
163
+ const [wordName, ...path] = name === null || name === void 0 ? void 0 : name.split(isCamelCase ? /(?=[A-Z])/ : kebabCaseRegex).map((word) => word.toLowerCase());
164
+ return {
165
+ path: `${wordName}/${pathEdgeCase(path)}${pathEdgeCase(remainingPath)}`,
166
+ file: `${await getNameWithScaffoldPattern(name)}.${schematic}.ts`,
167
+ className: (0, boost_ts_1.anyCaseToPascalCase)(name),
168
+ };
169
+ }
170
+ // 3. Return the base case
171
+ return {
172
+ path: `${name}/${pathEdgeCase(remainingPath)}`,
173
+ file: `${await getNameWithScaffoldPattern(name)}.${schematic}.ts`,
174
+ className: (0, boost_ts_1.anyCaseToPascalCase)(name),
175
+ };
176
+ };
177
+ const splitTargetProviderEdgeCase = async ({ target, schematic, }) => {
178
+ // Check if the last path ends with a slash, if it does it's supposed to be a folder
179
+ // and the name of the file will be the same as the folder
180
+ const isFolder = target.endsWith("/");
181
+ const path = target.split("/").slice(0, -1);
182
+ const name = isFolder
183
+ ? path[path.length - 1]
184
+ : target.split("/")[target.split("/").length - 1];
185
+ return {
186
+ path: pathEdgeCase(path),
187
+ file: `${await getNameWithScaffoldPattern(name)}.${schematic}.ts`,
188
+ className: (0, boost_ts_1.anyCaseToPascalCase)(name),
189
+ };
190
+ };
191
+ const getNameWithScaffoldPattern = async (name) => {
192
+ const configObject = await compiler_1.default.loadConfig();
193
+ switch (configObject.scaffoldPattern) {
194
+ case "lowercase" /* Pattern.LOWER_CASE */:
195
+ return (0, boost_ts_1.anyCaseToLowerCase)(name);
196
+ case "kebab-case" /* Pattern.KEBAB_CASE */:
197
+ return (0, boost_ts_1.anyCaseToKebabCase)(name);
198
+ case "PascalCase" /* Pattern.PASCAL_CASE */:
199
+ return (0, boost_ts_1.anyCaseToPascalCase)(name);
200
+ case "camelCase" /* Pattern.CAMEL_CASE */:
201
+ return (0, boost_ts_1.anyCaseToCamelCase)(name);
202
+ }
203
+ };
204
+ const pathEdgeCase = (path) => {
205
+ return `${path.join("/")}${path.length > 0 ? "/" : ""}`;
206
+ };
@@ -0,0 +1 @@
1
+ export * from "./cli";
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./cli"), exports);
@@ -0,0 +1,23 @@
1
+ import { BaseController, StatusCode } from "@expressots/core";
2
+ import { controller, httpGet, response } from "inversify-express-utils";
3
+ import { {{className}}UseCase } from "./{{fileName}}.usecase";
4
+ import { I{{className}}ResponseDTO } from "./{{fileName}}.dto";
5
+
6
+ @controller("/{{{route}}}")
7
+ class {{className}}Controller extends BaseController {
8
+
9
+ constructor(private {{useCase}}UseCase: {{className}}UseCase ) {
10
+ super("{{construct}}-controller")
11
+ }
12
+
13
+ @httpGet("/")
14
+ execute(@response() res: any): I{{className}}ResponseDTO {
15
+ return this.callUseCase(
16
+ this.{{useCase}}UseCase.execute(),
17
+ res,
18
+ StatusCode.Ok,
19
+ );
20
+ }
21
+ }
22
+
23
+ export { {{className}}Controller };
@@ -0,0 +1,17 @@
1
+ import { BaseController } from "@expressots/core";
2
+ import { controller, httpGet, response } from "inversify-express-utils";
3
+
4
+ @controller("/{{{route}}}")
5
+ class {{className}}Controller extends BaseController {
6
+
7
+ constructor() {
8
+ super("{{construct}}-controller")
9
+ }
10
+
11
+ @httpGet("/")
12
+ execute(@response() res: any) {
13
+ return res.send("Hello Expresso TS");
14
+ }
15
+ }
16
+
17
+ export { {{className}}Controller };
@@ -0,0 +1,5 @@
1
+ interface I{{className}}RequestDTO { }
2
+
3
+ interface I{{className}}ResponseDTO { }
4
+
5
+ export { I{{className}}RequestDTO, I{{className}}ResponseDTO };
@@ -0,0 +1,6 @@
1
+ import { CreateModule } from "@expressots/core";
2
+ import { {{className}}Controller } from "./{{{path}}}";
3
+
4
+ const {{moduleName}}Module = CreateModule([{{className}}Controller]);
5
+
6
+ export { {{moduleName}}Module };
@@ -0,0 +1,10 @@
1
+ import { provide } from "inversify-binding-decorators";
2
+
3
+ @provide({{className}}Provider)
4
+ class {{className}}Provider {
5
+
6
+ constructor() {}
7
+
8
+ }
9
+
10
+ export { {{className}}Provider };
@@ -0,0 +1,13 @@
1
+ import { provide } from "inversify-binding-decorators";
2
+
3
+ @provide({{className}}UseCase)
4
+ class {{className}}UseCase {
5
+
6
+ constructor() {}
7
+
8
+ execute(): string {
9
+ return "your use case";
10
+ }
11
+ }
12
+
13
+ export { {{className}}UseCase };
package/bin/index.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export * from "./types";
2
+ export * from "./generate";
3
+ export * from "./utils";
4
+ export * from "./new";
package/bin/index.js ADDED
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./types"), exports);
18
+ __exportStar(require("./generate"), exports);
19
+ __exportStar(require("./utils"), exports);
20
+ __exportStar(require("./new"), exports);
@@ -0,0 +1,4 @@
1
+ import { CommandModule } from "yargs";
2
+ type CommandModuleArgs = {};
3
+ declare const createProject: () => CommandModule<CommandModuleArgs, any>;
4
+ export { createProject };
package/bin/new/cli.js ADDED
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createProject = void 0;
4
+ const form_1 = require("./form");
5
+ const createProject = () => {
6
+ return {
7
+ command: "new [project-name]",
8
+ describe: "Create a new Expresso TS project",
9
+ builder: (yargs) => {
10
+ yargs.positional("project-name", {
11
+ describe: "The name of the project",
12
+ type: "string",
13
+ });
14
+ return yargs;
15
+ },
16
+ handler: async ({ projectName }) => {
17
+ return await (0, form_1.projectForm)(projectName);
18
+ },
19
+ };
20
+ };
21
+ exports.createProject = createProject;
@@ -0,0 +1,2 @@
1
+ declare const projectForm: (projectName: string) => Promise<void>;
2
+ export { projectForm };
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.projectForm = void 0;
7
+ const inquirer_1 = __importDefault(require("inquirer"));
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const degit_1 = __importDefault(require("degit"));
10
+ const child_process_1 = require("child_process");
11
+ const cli_progress_1 = require("cli-progress");
12
+ const node_fs_1 = __importDefault(require("node:fs"));
13
+ const node_path_1 = __importDefault(require("node:path"));
14
+ async function packageManagerInstall({ packageManager, directory, progressBar, }) {
15
+ return new Promise((resolve, reject) => {
16
+ const isWindows = process.platform === "win32";
17
+ const command = isWindows
18
+ ? `${packageManager}.cmd`
19
+ : packageManager;
20
+ const installProcess = (0, child_process_1.spawn)(command, ["install"], {
21
+ cwd: directory,
22
+ });
23
+ installProcess.stdout.on("data", (data) => {
24
+ progressBar.increment(5, {
25
+ doing: `${data.toString().trim()}`,
26
+ });
27
+ });
28
+ installProcess.on("close", (code) => {
29
+ if (code === 0) {
30
+ resolve("Installation Done!");
31
+ }
32
+ else {
33
+ reject(new Error(`npm install exited with code ${code}`));
34
+ }
35
+ });
36
+ });
37
+ }
38
+ async function checkIfPackageManagerExists(packageManager) {
39
+ try {
40
+ (0, child_process_1.execSync)(`${packageManager} --version`);
41
+ return true;
42
+ }
43
+ catch (_) {
44
+ throw new Error(`Package manager ${packageManager} is not installed`);
45
+ }
46
+ }
47
+ // Change the package.json name to the user's project name
48
+ function changePackageName({ directory, name, }) {
49
+ // Get the absolute path of the input directory parameter
50
+ const absDirPath = node_path_1.default.resolve(directory);
51
+ // Load the package.json file
52
+ const packageJsonPath = node_path_1.default.join(absDirPath, "package.json");
53
+ const fileContents = node_fs_1.default.readFileSync(packageJsonPath, "utf-8");
54
+ const packageJson = JSON.parse(fileContents);
55
+ // Change the name
56
+ packageJson.name = name;
57
+ // Save the package.json file
58
+ node_fs_1.default.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
59
+ }
60
+ const projectForm = async (projectName) => {
61
+ const answer = await inquirer_1.default.prompt([
62
+ {
63
+ type: "input",
64
+ name: "name",
65
+ message: "Project name",
66
+ default: projectName,
67
+ transformer: (input) => {
68
+ return chalk_1.default.yellow(chalk_1.default.bold(input));
69
+ },
70
+ },
71
+ {
72
+ type: "list",
73
+ name: "packageManager",
74
+ message: "Package manager",
75
+ choices: ["npm", "yarn", "pnpm"],
76
+ },
77
+ {
78
+ type: "list",
79
+ name: "template",
80
+ message: "Select a template",
81
+ choices: [
82
+ "Non-Opinionated :: A simple ExpressoTS project.",
83
+ "Opinionated :: A complete ExpressoTS project with an opinionated structure and features.",
84
+ ],
85
+ },
86
+ {
87
+ type: "confirm",
88
+ name: "confirm",
89
+ message: "Do you want to create this project?",
90
+ default: true,
91
+ },
92
+ ]);
93
+ // Hashmap of templates and their directories
94
+ const templates = {
95
+ "Non-Opinionated": "non_opinionated",
96
+ Opinionated: "opinionated",
97
+ };
98
+ if (answer.confirm) {
99
+ // Check if the package manager exists
100
+ await checkIfPackageManagerExists(answer.packageManager).catch((err) => {
101
+ console.log(chalk_1.default.red(err.message));
102
+ process.exit(1);
103
+ });
104
+ const progressBar = new cli_progress_1.SingleBar({
105
+ format: "Progress |" + chalk_1.default.green("{bar}") + "| {percentage}% || {doing}",
106
+ hideCursor: true,
107
+ }, cli_progress_1.Presets.shades_classic);
108
+ progressBar.start(100, 0, {
109
+ doing: "Cloning project",
110
+ });
111
+ const [_, template] = answer.template.match(/(.*) ::/);
112
+ const emitter = (0, degit_1.default)(`expressots/expressots/templates/${templates[template]}`);
113
+ await emitter.clone(answer.name);
114
+ progressBar.update(50, {
115
+ doing: "Installing dependencies",
116
+ });
117
+ // Run the package manager install in the directory
118
+ await packageManagerInstall({
119
+ packageManager: answer.packageManager,
120
+ directory: answer.name,
121
+ progressBar,
122
+ });
123
+ progressBar.update(90);
124
+ changePackageName({
125
+ directory: answer.name,
126
+ name: answer.name,
127
+ });
128
+ progressBar.update(100);
129
+ progressBar.stop();
130
+ console.log(chalk_1.default.green("Project created successfully!"));
131
+ console.log("Run the following commands to start the project:");
132
+ console.log(chalk_1.default.bold(`cd ${answer.name}`));
133
+ console.log(chalk_1.default.bold(`${answer.packageManager} start`));
134
+ }
135
+ };
136
+ exports.projectForm = projectForm;
@@ -0,0 +1 @@
1
+ export * from "./cli";
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./cli"), exports);
package/bin/types.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./@types";
package/bin/types.js ADDED
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./@types"), exports);
@@ -0,0 +1,15 @@
1
+ import { Service } from "ts-node";
2
+ import { ExpressoConfig } from "../types";
3
+ /**
4
+ * Singleton compiler class
5
+ */
6
+ declare class Compiler {
7
+ private static instance;
8
+ private constructor();
9
+ static get Instance(): Compiler;
10
+ getService(): Promise<Service>;
11
+ private static interopRequireDefault;
12
+ private static findConfig;
13
+ static loadConfig(): Promise<ExpressoConfig>;
14
+ }
15
+ export default Compiler;
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ const node_fs_1 = require("node:fs");
30
+ const path_1 = __importDefault(require("path"));
31
+ /**
32
+ * The path to the expressots.config.ts file
33
+ */
34
+ const EXPRESSOTS_CONFIG = path_1.default.join(process.cwd(), "expressots.config.ts");
35
+ /**
36
+ * The config object
37
+ */
38
+ let globalConfigObject = null;
39
+ /**
40
+ * The ts-node register options
41
+ */
42
+ const regOpt = {
43
+ compilerOptions: {
44
+ module: "commonjs",
45
+ },
46
+ moduleTypes: {
47
+ "**": "cjs",
48
+ },
49
+ };
50
+ /**
51
+ * Singleton compiler class
52
+ */
53
+ class Compiler {
54
+ constructor() { }
55
+ static get Instance() {
56
+ if (!Compiler.instance) {
57
+ Compiler.instance = new Compiler();
58
+ }
59
+ return Compiler.instance;
60
+ }
61
+ async getService() {
62
+ const tsnode = await Promise.resolve().then(() => __importStar(require("ts-node")));
63
+ const compiler = tsnode.register(regOpt);
64
+ return compiler;
65
+ }
66
+ static interopRequireDefault(obj) {
67
+ const module = require(obj);
68
+ return module && module.__esModule ? module : { default: module };
69
+ }
70
+ static async findConfig(dir) {
71
+ const configPath = path_1.default.join(dir, "expressots.config.ts");
72
+ const exists = (0, node_fs_1.existsSync)(configPath);
73
+ if (exists)
74
+ return configPath;
75
+ const parentDir = path_1.default.join(dir, "..");
76
+ if (parentDir === dir)
77
+ throw new Error("No config file found");
78
+ return Compiler.findConfig(parentDir);
79
+ }
80
+ static async loadConfig() {
81
+ const compiler = await Compiler.Instance.getService();
82
+ compiler.enabled(true);
83
+ globalConfigObject = Compiler.interopRequireDefault(await Compiler.findConfig(process.cwd()));
84
+ compiler.enabled(false);
85
+ return globalConfigObject.default;
86
+ }
87
+ }
88
+ exports.default = Compiler;
@@ -0,0 +1 @@
1
+ export * from "./compiler";
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./compiler"), exports);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expressots/cli",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "description": "Expressots CLI - modern, fast, lightweight nodejs web framework (@cli)",
5
5
  "author": "Richard Zampieri",
6
6
  "license": "MIT",
@@ -34,20 +34,21 @@
34
34
  "start:build": "npm run build && npm run start",
35
35
  "start": "node ./bin/cli.js",
36
36
  "start:dev": "tsnd ./src/cli.ts",
37
- "build": "npm run clean && tsc -p tsconfig.json && chmod +x ./bin/cli.js",
37
+ "build": "npm run clean && tsc -p tsconfig.json && yarn cp:templates && chmod +x ./bin/cli.js",
38
+ "cp:templates": "cp -r ./src/generate/templates ./bin/generate/templates",
38
39
  "clean": "rimraf ./bin",
39
40
  "lint": "eslint .eslintrc.js --ext .ts,.tsx,.js,.jsx .",
40
41
  "release": "release-it",
41
42
  "prepare": "husky install"
42
43
  },
43
- "files": [
44
- "bin/cli.js"
45
- ],
46
44
  "dependencies": {
45
+ "@expressots/boost-ts": "^1.1.1",
47
46
  "chalk-animation": "^1",
48
47
  "cli-progress": "^3.11.2",
49
48
  "degit": "^2.8.4",
50
49
  "inquirer": "^8.0.0",
50
+ "mustache": "^4.2.0",
51
+ "ts-node": "^10.9.1",
51
52
  "yargs": "^17.6.2"
52
53
  },
53
54
  "devDependencies": {
@@ -55,6 +56,7 @@
55
56
  "@types/cli-progress": "^3.11.0",
56
57
  "@types/degit": "^2.8.3",
57
58
  "@types/inquirer": "^9.0.3",
59
+ "@types/mustache": "^4.2.2",
58
60
  "@types/node": "^18.11.19",
59
61
  "@types/yargs": "^17.0.22",
60
62
  "@typescript-eslint/eslint-plugin": "^5.53.0",