@avleon/cli 0.0.45 → 0.0.47

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/cli.js CHANGED
@@ -42,6 +42,7 @@ exports.run = run;
42
42
  const cli_table3_1 = __importDefault(require("cli-table3"));
43
43
  const path_1 = __importDefault(require("path"));
44
44
  const promises_1 = __importDefault(require("fs/promises"));
45
+ const fs_extra_1 = __importDefault(require("fs-extra"));
45
46
  const fs_1 = require("fs");
46
47
  const prettier = __importStar(require("prettier"));
47
48
  const controller_1 = require("./controller");
@@ -49,6 +50,7 @@ const commands_1 = require("./commands");
49
50
  const child_process_1 = require("child_process");
50
51
  const create_1 = require("./create");
51
52
  const service_1 = require("./service");
53
+ const path_helper_1 = require("./helpers/path-helper");
52
54
  const lodash_1 = require("lodash");
53
55
  function iqraCli() { }
54
56
  const listedCommands = commands_1.commandList
@@ -117,115 +119,88 @@ async function createModel(name, options = { force: false, orm: false }) {
117
119
  console.log("Model already exists!", "Use -f or --force to overwrite.\r");
118
120
  return;
119
121
  }
120
- const basicModel = `
121
- \t
122
- export class ${modelName}{
123
- id:number;
124
- name: string;
125
- }
126
- `;
127
- const ormModel = `
128
- import {Entity, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn } from 'typeorm';
129
- \t
130
- @Entity({name:'${modelName}'})
131
- export class ${modelName}{
132
-
133
- @PrimaryGeneratedColumn()
134
- id:number;
135
-
136
- @CreateDateColumn()
137
- createdAt: Date;
138
-
139
- @UpdateDateColumn()
140
- updatedAt: Date;
141
- }
142
- `;
143
- const formatModel = await prettier.format(options.orm ? ormModel : basicModel, {
122
+ const stubPath = path_helper_1.pathHelper.stubPath(options.orm ? "models/entity-model.stub" : "models/basic-model.stub");
123
+ const stub = await promises_1.default.readFile(stubPath, "utf8");
124
+ const model = stub
125
+ .replaceAll("{Model}", modelName)
126
+ .replaceAll("{model}", modelName.toLowerCase());
127
+ const formatModel = await prettier.format(model, {
144
128
  singleQuote: true,
145
129
  singleAttributePerLine: true,
146
130
  parser: "typescript",
147
131
  });
148
132
  await promises_1.default.writeFile(path_1.default.join(process.cwd(), "./src/models/" + modelName.toLowerCase() + ".ts"), formatModel);
149
- console.log("Model created succssessfully!");
133
+ console.log("Model created successfully!");
150
134
  }
151
135
  async function createMiddleware(name, options = { force: false }) {
152
136
  if (!name) {
153
- throw new Error("Model name not found . use --name or node artisan make:model ModelName");
137
+ throw new Error("Middleware name not found. Use npx avleon make:middleware MiddlewareName");
154
138
  }
155
- const modelName = name.at(0).toUpperCase() + name.slice(1);
156
- const modelExists = (0, fs_1.existsSync)(path_1.default.join(process.cwd(), `./src/middlewares/${modelName.toLowerCase()}.middleware.ts`));
157
- if (modelExists && !options.force) {
139
+ const baseName = name.replace(/middleware$/i, "");
140
+ const className = baseName.at(0).toUpperCase() + baseName.slice(1) + "Middleware";
141
+ const fileName = `${baseName.toLowerCase()}.middleware.ts`;
142
+ const middlewareDir = path_1.default.join(process.cwd(), "./src/middlewares");
143
+ const filePath = path_1.default.join(middlewareDir, fileName);
144
+ if ((0, fs_1.existsSync)(filePath) && !options.force) {
158
145
  console.log("Middleware already exists!", "Use -f or --force to overwrite.\r");
159
146
  return;
160
147
  }
161
- const modelFolderExists = (0, fs_1.existsSync)(path_1.default.join(process.cwd(), "./src/middlewares"));
162
- if (!modelFolderExists) {
163
- await promises_1.default.mkdir(path_1.default.join(process.cwd(), "./src/middleware"), {
164
- recursive: true,
165
- });
148
+ if (!(0, fs_1.existsSync)(middlewareDir)) {
149
+ await promises_1.default.mkdir(middlewareDir, { recursive: true });
166
150
  }
167
- const basicMiddleware = `
168
- \t
169
- import { Middleware, IMiddleware } from '@avleon/core';
170
-
171
- @Middleware
172
- export class ${modelName}Middleware implements IMiddleware{
173
-
174
- invoke(req:IRequest){
175
- // your logic goes here
176
- return req;
177
- }
178
-
179
- }
151
+ const basicMiddleware = `
152
+ import { AppMiddleware, AvleonMiddleware, IRequest, IResponse } from '@avleon/core';
153
+
154
+ @AppMiddleware
155
+ export class ${className} extends AvleonMiddleware {
156
+ async invoke(req: IRequest, res?: IResponse) {
157
+ // your logic goes here
158
+ return req;
159
+ }
160
+ }
180
161
  `;
181
162
  const formatModel = await prettier.format(basicMiddleware, {
182
163
  singleQuote: true,
183
164
  singleAttributePerLine: true,
184
165
  parser: "typescript",
185
166
  });
186
- await promises_1.default.writeFile(path_1.default.join(process.cwd(), "./src/middlewares/" + modelName.toLowerCase() + ".ts"), formatModel);
187
- console.log("Middleware created succssessfully!");
167
+ await promises_1.default.writeFile(filePath, formatModel);
168
+ console.log("Middleware created successfully!");
188
169
  }
189
170
  async function createConfig(name, options = { force: false }) {
190
171
  if (!name) {
191
172
  throw new Error("Config name not found . use --name or node artisan make:config JwtConfig");
192
173
  }
193
- const modelName = name.at(0).toUpperCase() + name.slice(1);
194
- const modelClassName = (0, lodash_1.capitalize)(modelName).endsWith('Config') ? (0, lodash_1.capitalize)(modelName) : (0, lodash_1.capitalize)(modelName) + "Config";
195
- const modelExists = (0, fs_1.existsSync)(path_1.default.join(process.cwd(), `./src/config/${modelName.toLowerCase()}.ts`));
196
- if (modelExists && !options.force) {
174
+ const baseName = name.replace(/config$/i, "");
175
+ const modelClassName = (0, lodash_1.capitalize)(baseName) + "Config";
176
+ const fileName = `${baseName.toLowerCase()}.config.ts`;
177
+ const configDir = path_1.default.join(process.cwd(), "./src/config");
178
+ const filePath = path_1.default.join(configDir, fileName);
179
+ if ((0, fs_1.existsSync)(filePath) && !options.force) {
197
180
  console.log("Config already exists!", "Use -f or --force to overwrite.\r");
198
181
  return;
199
182
  }
200
- const modelFolderExists = (0, fs_1.existsSync)(path_1.default.join(process.cwd(), "./src/config"));
201
- if (!modelFolderExists) {
202
- await promises_1.default.mkdir(path_1.default.join(process.cwd(), "./src/config"), {
203
- recursive: true,
204
- });
183
+ if (!(0, fs_1.existsSync)(configDir)) {
184
+ await promises_1.default.mkdir(configDir, { recursive: true });
205
185
  }
206
- const basicMiddleware = `
207
- \t
208
- import { AppConfig, IConfig } from '@avleon/core';
209
-
210
- @AppConfig
211
- export class ${modelClassName} implements IConfig<T>{
212
-
213
- config(env: Environment){
214
- // config must return config
215
- return {
216
-
217
- };
218
- }
219
-
220
- }
186
+ const basicMiddleware = `
187
+ import { AppConfig, AvleonConfig, Environment } from '@avleon/core';
188
+
189
+ @AppConfig
190
+ export class ${modelClassName} extends AvleonConfig {
191
+ config(env: Environment) {
192
+ // config must return the configuration object
193
+ return {};
194
+ }
195
+ }
221
196
  `;
222
197
  const formatModel = await prettier.format(basicMiddleware, {
223
198
  singleQuote: true,
224
199
  singleAttributePerLine: true,
225
200
  parser: "typescript",
226
201
  });
227
- await promises_1.default.writeFile(path_1.default.join(process.cwd(), "./src/config/" + modelName.toLowerCase() + ".ts"), formatModel);
228
- console.log("Config created succssessfully!");
202
+ await promises_1.default.writeFile(filePath, formatModel);
203
+ console.log("Config created successfully!");
229
204
  }
230
205
  async function run() {
231
206
  try {
@@ -251,7 +226,7 @@ async function run() {
251
226
  if (args.some((x) => x == "-f" || x == "--force")) {
252
227
  force = true;
253
228
  }
254
- if (args.some((x) => x == "--mimimal")) {
229
+ if (args.some((x) => x == "--minimal" || x == "-m")) {
255
230
  minimal = true;
256
231
  }
257
232
  const flags = { minimal, force };
@@ -264,19 +239,18 @@ async function run() {
264
239
  }
265
240
  if (args[0] == "build") {
266
241
  process.env.NODE_ENV = "production";
267
- //const appPath =
268
- (0, child_process_1.execSync)("rm -r ./dist");
269
- (0, child_process_1.execSync)("npx tsc --project tsconfig.build.json");
242
+ await fs_extra_1.default.remove(path_1.default.join(process.cwd(), "dist"));
243
+ (0, child_process_1.execSync)("npx tsc --project tsconfig.build.json", { stdio: "inherit" });
270
244
  console.log("Build successfully");
271
245
  }
272
- if (args[0] == "make:model") {
246
+ if (args[0] == "make:model" || args[0] == "m:m") {
273
247
  const orm = args.some((x) => x == "--orm");
274
248
  await createModel(args[1], { force, orm });
275
249
  }
276
- if (args[0] == "make:config" || args[0] == "m:cfg") {
250
+ if (args[0] == "make:config" || args[0] == "m:cnf" || args[0] == "m:cfg") {
277
251
  await createConfig(args[1], { force });
278
252
  }
279
- if (args[0] == "make:middleware" || args[0] == "m:mdlr") {
253
+ if (args[0] == "make:middleware" || args[0] == "m:mlwr" || args[0] == "m:mdlr") {
280
254
  await createMiddleware(args[1], { force });
281
255
  }
282
256
  if (args[0] == "make:controller" || args[0] == "m:c") {
@@ -284,10 +258,8 @@ async function run() {
284
258
  let rest = false;
285
259
  let prefix = true;
286
260
  let root = null;
287
- if (args.some((x) => x == "-r" || x == "--resource")) {
261
+ if (args.some((x) => x == "-r" || x == "--resource" || x == "--rest")) {
288
262
  resource = true;
289
- }
290
- if (args.some((x) => x == "-r" || x == "--rest")) {
291
263
  rest = true;
292
264
  }
293
265
  if (args.some((x) => x == "--base-path")) {
@@ -314,7 +286,8 @@ async function run() {
314
286
  const rootPath = args[index + 1];
315
287
  root = rootPath;
316
288
  }
317
- await (0, controller_1.createController)(args[1], { force, resource, prefix, rest, model, root });
289
+ const orm = args.some((x) => x == "--orm");
290
+ await (0, controller_1.createController)(args[1], { force, resource, prefix, rest, model, root, orm });
318
291
  }
319
292
  if (args[0] == "make:service" || args[0] == "m:s") {
320
293
  let resource = false;
@@ -346,7 +319,8 @@ async function run() {
346
319
  const rootPath = args[index + 1];
347
320
  root = rootPath;
348
321
  }
349
- await (0, service_1.createService)(args[1], { force, resource, prefix, rest, model, root });
322
+ const orm = args.some((x) => x == "--orm");
323
+ await (0, service_1.createService)(args[1], { force, resource, prefix, rest, model, root, orm });
350
324
  }
351
325
  }
352
326
  }
package/dist/commands.js CHANGED
@@ -9,47 +9,55 @@ exports.commandList = [
9
9
  {
10
10
  Command: "new",
11
11
  Alias: "",
12
- Options: "--minimal -m, -d --database",
13
- Description: "Create a new application"
12
+ Options: "-m --minimal",
13
+ Description: "Create a new application",
14
+ },
15
+ {
16
+ Command: "serve",
17
+ Alias: "",
18
+ Options: "",
19
+ Description: "Start the development server. Compiles src/ on change and restarts the app.",
20
+ },
21
+ {
22
+ Command: "build",
23
+ Alias: "",
24
+ Options: "",
25
+ Description: "Compile the application using tsconfig.build.json",
14
26
  },
15
27
  {
16
28
  Command: "make:model",
17
29
  Alias: "m:m",
18
30
  Options: "-f --force, --orm",
19
- Description: "Create a new model. Use -f or --froce to overwrite if any model exists with name",
31
+ Description: "Create a new model. Use -f or --force to overwrite an existing model. Pass --orm to generate a TypeORM entity.",
20
32
  },
21
33
  {
22
34
  Command: "make:controller",
23
35
  Alias: "m:c",
24
- Options: `-f, --force for force create\n -r or --resource for resource controller`,
25
- Description: `Create a new controller. Use -f or --force to overwrite existing controller. If you want to create a resource controller pass options -r or --resource.
26
- You may also pass model by -m or --model.\n
27
- ${chalk_1.default.blueBright("Note:")} when using a resource contorller iqra will automaticall check for dtos related to model name. If -m is user then
28
- it will check for dtos like UserCreateDto and UserUpdateDto. If dtos not found it will create automatically using
29
- model properties.
30
- `,
36
+ Options: "-f --force, -r --resource, -m --model, -rt --root, --orm, --base-path",
37
+ Description: `Create a new controller. Use -f or --force to overwrite an existing controller.
38
+ Pass -r or --resource for a full REST skeleton, and -m or --model to bind it to a model.\n
39
+ ${chalk_1.default.blueBright("Note:")} with -m, the matching service is generated in src/services and the
40
+ controller delegates to it. Add --orm to back that service with a TypeORM repository.`,
31
41
  },
32
42
  {
33
43
  Command: "make:service",
34
44
  Alias: "m:s",
35
- Options: `-f, --force for force create\n -r or --resource for resource controller, --dtos`,
36
- Description: `Create a new controller. Use -f or --force to overwrite existing controller. If you want to create a resource controller pass options -r or --resource.
37
- You may also pass model by -m or --model.\n
38
- ${chalk_1.default.blueBright("Note:")} when using a resource contorller iqra will automaticall check for dtos related to model name. If -m is user then
39
- it will check for dtos like UserCreateDto and UserUpdateDto. If dtos not found it will create automatically using
40
- model properties.
41
- `,
45
+ Options: "-f --force, -r --resource, -m --model, -rt --root, --orm",
46
+ Description: `Create a new service. Use -f or --force to overwrite an existing service.
47
+ Pass -r or --resource together with -m or --model for a REST service.\n
48
+ ${chalk_1.default.blueBright("Note:")} a resource service uses an in-memory Collection by default.
49
+ Add --orm to generate one backed by a TypeORM repository instead.`,
42
50
  },
43
51
  {
44
52
  Command: "make:config",
45
53
  Alias: "m:cnf",
46
54
  Options: "-f --force",
47
- Description: "Create a new config. Use -f or --froce to overwrite if any config exists with name",
55
+ Description: "Create a new config class registered with @AppConfig. Use -f or --force to overwrite an existing config.",
48
56
  },
49
57
  {
50
58
  Command: "make:middleware",
51
59
  Alias: "m:mlwr",
52
60
  Options: "-f --force",
53
- Description: "Create a new middleware. Use -f or --froce to overwrite if any config exists with name",
61
+ Description: "Create a new middleware extending AvleonMiddleware. Use -f or --force to overwrite an existing middleware.",
54
62
  },
55
63
  ];
@@ -32,35 +32,33 @@ function exportNamesAndPath(input) {
32
32
  }
33
33
  const controllersStubs = {
34
34
  basic: path_helper_1.pathHelper.stubPath('controllers/basic-controller.stub'),
35
- rest: path_helper_1.pathHelper.stubPath('controllers/basic-controller.stub'),
35
+ rest: path_helper_1.pathHelper.stubPath('controllers/rest-controller.stub'),
36
36
  ormRest: path_helper_1.pathHelper.stubPath('controllers/orm-rest-controller.stub')
37
37
  };
38
- async function createController(name, options = { force: false, resource: false, prefix: true, rest: false, model: null, root: null }, p) {
38
+ async function createController(name, options = { force: false, resource: false, prefix: true, rest: false, model: null, root: null, orm: false }, p) {
39
39
  if (!name) {
40
40
  throw new Error("Controller name not found. use --name or npx avleon make:controller HomeController");
41
41
  }
42
42
  // determine stub for generate
43
+ // A model means the controller can delegate to a generated service; without
44
+ // one there is nothing to call, so emit the unimplemented REST skeleton.
43
45
  let stubPath = controllersStubs.basic;
44
- if (options.rest) {
45
- stubPath = controllersStubs.rest;
46
- if (options.model) {
47
- stubPath = controllersStubs.ormRest;
48
- }
46
+ if (options.rest || options.resource) {
47
+ stubPath = options.model ? controllersStubs.ormRest : controllersStubs.rest;
49
48
  }
50
49
  // determine root path for create controller file
51
50
  const rootPath = options.root ? 'src/' + options.root + '/' : 'src/controllers/';
52
- // ensure file create directory exits
53
- if (name.split("/").length > 1) {
54
- if (!(0, fs_1.existsSync)(path_1.default.join(rootPath, name.split("/").splice(-1, 1).join("/")))) {
55
- await promises_1.default.mkdir(path_1.default.join(rootPath, name.replace('/' + file_helper_1.fh.filenameFromPath(name), '')), { recursive: true });
56
- }
51
+ // ensure the output directory exists
52
+ const outDir = path_1.default.join(rootPath, (0, file_helper_1.getFilePathWithoutName)(name));
53
+ if (!(0, fs_1.existsSync)(outDir)) {
54
+ await promises_1.default.mkdir(outDir, { recursive: true });
57
55
  }
58
56
  // read stub content from stub file
59
57
  const content = await promises_1.default.readFile(stubPath, 'utf8');
60
58
  const names = (0, file_helper_1.resolveNames)(file_helper_1.fh.filenameFromPath(name), 'Controller');
61
59
  const className = names.className.replace("Controller", '');
62
60
  if (options.model) {
63
- await createRestService(className, options.model);
61
+ await createRestService(className, options.model, options.orm);
64
62
  }
65
63
  let replacedContent = content
66
64
  .replaceAll('{Controller}', className)
@@ -73,20 +71,26 @@ async function createController(name, options = { force: false, resource: false,
73
71
  if (!options.prefix) {
74
72
  replacedContent = replacedContent.replace(/@ApiController\s*\(([^)]*)\)/g, '@ApiController');
75
73
  }
76
- await promises_1.default.writeFile(path_1.default.join(rootPath, (0, file_helper_1.getFilePathWithoutName)(name) + "/" + (0, lodash_1.kebabCase)(className) + '.controller.ts'), replacedContent, 'utf8');
77
- console.log("Controller created succssessfully!");
74
+ await promises_1.default.writeFile(path_1.default.join(outDir, (0, lodash_1.kebabCase)(className) + '.controller.ts'), replacedContent, 'utf8');
75
+ console.log("Controller created successfully!");
78
76
  }
79
- async function createRestService(name, model) {
80
- let stubPath = path_helper_1.pathHelper.stubPath('services/rest-service.stub');
77
+ async function createRestService(name, model, orm = false) {
78
+ const stubPath = path_helper_1.pathHelper.stubPath(orm ? 'services/orm-rest-service.stub' : 'services/rest-service.stub');
81
79
  const content = await promises_1.default.readFile(stubPath, 'utf8');
82
- const names = (0, file_helper_1.resolveNames)(file_helper_1.fh.filenameFromPath(name), 'Controller');
80
+ // The generated controller imports `{Model}Service` from
81
+ // `../services/{model}.service`, so the file must be named after the model.
82
+ const serviceName = model ? capitalize(model) : name;
83
83
  let replacedContent = content
84
- .replaceAll('{Service}', name);
84
+ .replaceAll('{Service}', serviceName);
85
85
  if (model) {
86
86
  replacedContent = replacedContent
87
87
  .replaceAll('{Model}', capitalize(model))
88
88
  .replaceAll('{model}', lower(model));
89
89
  }
90
- await promises_1.default.writeFile(path_1.default.join('src/services/', (0, lodash_1.kebabCase)(name) + '.service.ts'), replacedContent, 'utf8');
91
- console.log("Service created succssessfully!");
90
+ const serviceDir = path_1.default.join('src', 'services');
91
+ if (!(0, fs_1.existsSync)(serviceDir)) {
92
+ await promises_1.default.mkdir(serviceDir, { recursive: true });
93
+ }
94
+ await promises_1.default.writeFile(path_1.default.join(serviceDir, lower(serviceName) + '.service.ts'), replacedContent, 'utf8');
95
+ console.log("Service created successfully!");
92
96
  }