@avleon/cli 0.0.46 → 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 +61 -87
- package/dist/commands.js +27 -19
- package/dist/controller.js +25 -21
- package/dist/create.js +116 -102
- package/dist/helpers/path-helper.js +19 -4
- package/dist/service.js +9 -13
- package/package.json +62 -62
- package/readme.md +116 -66
- package/stubs/app/app-controller.stub +13 -11
- package/stubs/app/app-minimal.stub +7 -17
- package/stubs/config.stub +15 -11
- package/stubs/controllers/basic-controller.stub +9 -12
- package/stubs/controllers/orm-rest-controller.stub +45 -52
- package/stubs/controllers/rest-controller.stub +29 -34
- package/stubs/models/basic-model.stub +4 -6
- package/stubs/models/entity-model.stub +18 -23
- package/stubs/serve.stub +10 -10
- package/stubs/services/basic-service.stub +8 -9
- package/stubs/services/orm-rest-service.stub +60 -73
- package/stubs/services/rest-service.stub +34 -71
- package/stubs/app/app-withdb.stub +0 -0
- package/stubs/basic-controller.stub +0 -7
- package/stubs/model.stub +0 -0
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
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
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
|
|
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("
|
|
137
|
+
throw new Error("Middleware name not found. Use npx avleon make:middleware MiddlewareName");
|
|
154
138
|
}
|
|
155
|
-
const
|
|
156
|
-
const
|
|
157
|
-
|
|
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
|
-
|
|
162
|
-
|
|
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
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
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(
|
|
187
|
-
console.log("Middleware created
|
|
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
|
|
194
|
-
const modelClassName = (0, lodash_1.capitalize)(
|
|
195
|
-
const
|
|
196
|
-
|
|
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
|
-
|
|
201
|
-
|
|
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
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
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(
|
|
228
|
-
console.log("Config created
|
|
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 == "--
|
|
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
|
-
|
|
268
|
-
(0, child_process_1.execSync)("
|
|
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
|
-
|
|
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
|
-
|
|
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: "
|
|
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 --
|
|
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:
|
|
25
|
-
Description: `Create a new controller. Use -f or --force to overwrite existing controller.
|
|
26
|
-
|
|
27
|
-
${chalk_1.default.blueBright("Note:")}
|
|
28
|
-
|
|
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:
|
|
36
|
-
Description: `Create a new
|
|
37
|
-
|
|
38
|
-
${chalk_1.default.blueBright("Note:")}
|
|
39
|
-
|
|
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 --
|
|
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 --
|
|
61
|
+
Description: "Create a new middleware extending AvleonMiddleware. Use -f or --force to overwrite an existing middleware.",
|
|
54
62
|
},
|
|
55
63
|
];
|
package/dist/controller.js
CHANGED
|
@@ -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/
|
|
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
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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(
|
|
77
|
-
console.log("Controller created
|
|
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
|
-
|
|
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
|
-
|
|
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}',
|
|
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
|
-
|
|
91
|
-
|
|
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
|
}
|