@avleon/cli 0.0.36 → 0.0.38
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 +132 -4
- package/dist/commands.js +13 -12
- package/dist/create.js +13 -11
- package/dist/service.js +73 -0
- package/package.json +1 -1
- package/readme.md +64 -2
- package/stubs/services/orm-rest-service.stub +73 -0
- package/stubs/services/rest-service.stub +15 -17
package/dist/cli.js
CHANGED
|
@@ -48,6 +48,7 @@ const controller_1 = require("./controller");
|
|
|
48
48
|
const commands_1 = require("./commands");
|
|
49
49
|
const child_process_1 = require("child_process");
|
|
50
50
|
const create_1 = require("./create");
|
|
51
|
+
const service_1 = require("./service");
|
|
51
52
|
function iqraCli() { }
|
|
52
53
|
const listedCommands = commands_1.commandList
|
|
53
54
|
.flatMap((x) => x.Command)
|
|
@@ -99,7 +100,7 @@ async function displayCommandList(info = { logo: true, all: false }) {
|
|
|
99
100
|
console.log(table.toString());
|
|
100
101
|
}
|
|
101
102
|
}
|
|
102
|
-
async function createModel(name, options = { force: false }) {
|
|
103
|
+
async function createModel(name, options = { force: false, orm: false }) {
|
|
103
104
|
if (!name) {
|
|
104
105
|
throw new Error("Model name not found . use --name or node artisan make:model ModelName");
|
|
105
106
|
}
|
|
@@ -115,7 +116,14 @@ async function createModel(name, options = { force: false }) {
|
|
|
115
116
|
console.log("Model already exists!", "Use -f or --force to overwrite.\r");
|
|
116
117
|
return;
|
|
117
118
|
}
|
|
118
|
-
const
|
|
119
|
+
const basicModel = `
|
|
120
|
+
\t
|
|
121
|
+
export class ${modelName}{
|
|
122
|
+
id:number;
|
|
123
|
+
name: string;
|
|
124
|
+
}
|
|
125
|
+
`;
|
|
126
|
+
const ormModel = `
|
|
119
127
|
import {Entity, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn } from 'typeorm';
|
|
120
128
|
\t
|
|
121
129
|
@Entity({name:'${modelName}'})
|
|
@@ -131,7 +139,7 @@ import {Entity, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn } fro
|
|
|
131
139
|
updatedAt: Date;
|
|
132
140
|
}
|
|
133
141
|
`;
|
|
134
|
-
const formatModel = await prettier.format(
|
|
142
|
+
const formatModel = await prettier.format(options.orm ? ormModel : basicModel, {
|
|
135
143
|
singleQuote: true,
|
|
136
144
|
singleAttributePerLine: true,
|
|
137
145
|
parser: "typescript",
|
|
@@ -139,6 +147,84 @@ import {Entity, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn } fro
|
|
|
139
147
|
await promises_1.default.writeFile(path_1.default.join(process.cwd(), "./src/models/" + modelName.toLowerCase() + ".ts"), formatModel);
|
|
140
148
|
console.log("Model created succssessfully!");
|
|
141
149
|
}
|
|
150
|
+
async function createMiddleware(name, options = { force: false }) {
|
|
151
|
+
if (!name) {
|
|
152
|
+
throw new Error("Model name not found . use --name or node artisan make:model ModelName");
|
|
153
|
+
}
|
|
154
|
+
const modelName = name.at(0).toUpperCase() + name.slice(1);
|
|
155
|
+
const modelExists = (0, fs_1.existsSync)(path_1.default.join(process.cwd(), `./src/middlewares/${modelName.toLowerCase()}.middleware.ts`));
|
|
156
|
+
if (modelExists && !options.force) {
|
|
157
|
+
console.log("Middleware already exists!", "Use -f or --force to overwrite.\r");
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
const modelFolderExists = (0, fs_1.existsSync)(path_1.default.join(process.cwd(), "./src/middlewares"));
|
|
161
|
+
if (!modelFolderExists) {
|
|
162
|
+
await promises_1.default.mkdir(path_1.default.join(process.cwd(), "./src/middleware"), {
|
|
163
|
+
recursive: true,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
const basicMiddleware = `
|
|
167
|
+
\t
|
|
168
|
+
import { Middleware, IMiddleware } from '@avleon/core';
|
|
169
|
+
|
|
170
|
+
@Middleware
|
|
171
|
+
export class ${modelName}Middleware implements IMiddleware{
|
|
172
|
+
|
|
173
|
+
invoke(req:IRequest){
|
|
174
|
+
// your logic goes here
|
|
175
|
+
return req;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
}
|
|
179
|
+
`;
|
|
180
|
+
const formatModel = await prettier.format(basicMiddleware, {
|
|
181
|
+
singleQuote: true,
|
|
182
|
+
singleAttributePerLine: true,
|
|
183
|
+
parser: "typescript",
|
|
184
|
+
});
|
|
185
|
+
await promises_1.default.writeFile(path_1.default.join(process.cwd(), "./src/middlewares/" + modelName.toLowerCase() + ".ts"), formatModel);
|
|
186
|
+
console.log("Middleware created succssessfully!");
|
|
187
|
+
}
|
|
188
|
+
async function createConfig(name, options = { force: false }) {
|
|
189
|
+
if (!name) {
|
|
190
|
+
throw new Error("Config name not found . use --name or node artisan make:config JwtConfig");
|
|
191
|
+
}
|
|
192
|
+
const modelName = name.at(0).toUpperCase() + name.slice(1);
|
|
193
|
+
const modelExists = (0, fs_1.existsSync)(path_1.default.join(process.cwd(), `./src/cinfigs/${modelName.toLowerCase()}.ts`));
|
|
194
|
+
if (modelExists && !options.force) {
|
|
195
|
+
console.log("Config already exists!", "Use -f or --force to overwrite.\r");
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
const modelFolderExists = (0, fs_1.existsSync)(path_1.default.join(process.cwd(), "./src/configs"));
|
|
199
|
+
if (!modelFolderExists) {
|
|
200
|
+
await promises_1.default.mkdir(path_1.default.join(process.cwd(), "./src/configs"), {
|
|
201
|
+
recursive: true,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
const basicMiddleware = `
|
|
205
|
+
\t
|
|
206
|
+
import { Config, IConfig } from '@avleon/core';
|
|
207
|
+
|
|
208
|
+
@AppConfig
|
|
209
|
+
export class ${modelName}Middleware implements IConfig<T>{
|
|
210
|
+
|
|
211
|
+
config(env: Environment){
|
|
212
|
+
// config must return config
|
|
213
|
+
return {
|
|
214
|
+
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
}
|
|
219
|
+
`;
|
|
220
|
+
const formatModel = await prettier.format(basicMiddleware, {
|
|
221
|
+
singleQuote: true,
|
|
222
|
+
singleAttributePerLine: true,
|
|
223
|
+
parser: "typescript",
|
|
224
|
+
});
|
|
225
|
+
await promises_1.default.writeFile(path_1.default.join(process.cwd(), "./src/middlewares/" + modelName.toLowerCase() + ".ts"), formatModel);
|
|
226
|
+
console.log("Middleware created succssessfully!");
|
|
227
|
+
}
|
|
142
228
|
async function run() {
|
|
143
229
|
try {
|
|
144
230
|
const args = process.argv.slice(2);
|
|
@@ -164,6 +250,9 @@ async function run() {
|
|
|
164
250
|
}
|
|
165
251
|
const flags = { minimal, force };
|
|
166
252
|
if (args[0] == "new") {
|
|
253
|
+
if (args[1] == undefined) {
|
|
254
|
+
throw new Error('Please provide a project name. Ex avleon new example_api');
|
|
255
|
+
}
|
|
167
256
|
const fname = args[1];
|
|
168
257
|
await (0, create_1.createApplication)(fname, flags);
|
|
169
258
|
}
|
|
@@ -175,7 +264,14 @@ async function run() {
|
|
|
175
264
|
console.log("Build successfully");
|
|
176
265
|
}
|
|
177
266
|
if (args[0] == "make:model") {
|
|
178
|
-
|
|
267
|
+
const orm = args.some((x) => x == "--orm");
|
|
268
|
+
await createModel(args[1], { force, orm });
|
|
269
|
+
}
|
|
270
|
+
if (args[0] == "make:config" || args[0] == "m:cfg") {
|
|
271
|
+
await createConfig(args[1], { force });
|
|
272
|
+
}
|
|
273
|
+
if (args[0] == "make:middleware" || args[0] == "m:mdlr") {
|
|
274
|
+
await createMiddleware(args[1], { force });
|
|
179
275
|
}
|
|
180
276
|
if (args[0] == "make:controller" || args[0] == "m:c") {
|
|
181
277
|
let resource = false;
|
|
@@ -214,6 +310,38 @@ async function run() {
|
|
|
214
310
|
}
|
|
215
311
|
await (0, controller_1.createController)(args[1], { force, resource, prefix, rest, model, root });
|
|
216
312
|
}
|
|
313
|
+
if (args[0] == "make:service" || args[0] == "m:s") {
|
|
314
|
+
let resource = false;
|
|
315
|
+
let rest = false;
|
|
316
|
+
let prefix = true;
|
|
317
|
+
let root = null;
|
|
318
|
+
if (args.some((x) => x == "-r" || x == "--resource" || x == '--rest')) {
|
|
319
|
+
resource = true;
|
|
320
|
+
rest = true;
|
|
321
|
+
}
|
|
322
|
+
let model = null;
|
|
323
|
+
if (args.some((x) => x == "-m" || x == "--model")) {
|
|
324
|
+
const index = args.includes("-m")
|
|
325
|
+
? args.indexOf("-m")
|
|
326
|
+
: args.indexOf("--model");
|
|
327
|
+
if (args[index + 1] == undefined) {
|
|
328
|
+
throw new Error("Model not defined");
|
|
329
|
+
}
|
|
330
|
+
const modelName = args[index + 1];
|
|
331
|
+
model = modelName;
|
|
332
|
+
}
|
|
333
|
+
if (args.some((x) => x == "-rt" || x == "--root")) {
|
|
334
|
+
const index = args.includes("-rt")
|
|
335
|
+
? args.indexOf("-rt")
|
|
336
|
+
: args.indexOf("--root");
|
|
337
|
+
if (args[index + 1] == undefined) {
|
|
338
|
+
throw new Error("Root Path not defined");
|
|
339
|
+
}
|
|
340
|
+
const rootPath = args[index + 1];
|
|
341
|
+
root = rootPath;
|
|
342
|
+
}
|
|
343
|
+
await (0, service_1.createService)(args[1], { force, resource, prefix, rest, model, root });
|
|
344
|
+
}
|
|
217
345
|
}
|
|
218
346
|
}
|
|
219
347
|
}
|
package/dist/commands.js
CHANGED
|
@@ -14,8 +14,8 @@ exports.commandList = [
|
|
|
14
14
|
},
|
|
15
15
|
{
|
|
16
16
|
Command: "make:model",
|
|
17
|
-
Alias: "m:m
|
|
18
|
-
Options: "-f --force",
|
|
17
|
+
Alias: "m:m",
|
|
18
|
+
Options: "-f --force, --orm",
|
|
19
19
|
Description: "Create a new model. Use -f or --froce to overwrite if any model exists with name",
|
|
20
20
|
},
|
|
21
21
|
{
|
|
@@ -32,7 +32,7 @@ model properties.
|
|
|
32
32
|
{
|
|
33
33
|
Command: "make:service",
|
|
34
34
|
Alias: "m:s",
|
|
35
|
-
Options: `-f, --force for force create\n -r or --resource for resource controller`,
|
|
35
|
+
Options: `-f, --force for force create\n -r or --resource for resource controller, --dtos`,
|
|
36
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
37
|
You may also pass model by -m or --model.\n
|
|
38
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
|
|
@@ -41,14 +41,15 @@ model properties.
|
|
|
41
41
|
`,
|
|
42
42
|
},
|
|
43
43
|
{
|
|
44
|
-
Command: "make:
|
|
45
|
-
Alias: "m:
|
|
46
|
-
Options:
|
|
47
|
-
Description:
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
44
|
+
Command: "make:config",
|
|
45
|
+
Alias: "m:cnf",
|
|
46
|
+
Options: "-f --force",
|
|
47
|
+
Description: "Create a new config. Use -f or --froce to overwrite if any config exists with name",
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
Command: "make:middleware",
|
|
51
|
+
Alias: "m:mlwr",
|
|
52
|
+
Options: "-f --force",
|
|
53
|
+
Description: "Create a new middleware. Use -f or --froce to overwrite if any config exists with name",
|
|
53
54
|
},
|
|
54
55
|
];
|
package/dist/create.js
CHANGED
|
@@ -74,6 +74,8 @@ async function installDependencies(pm, fname) {
|
|
|
74
74
|
child.on('exit', (code) => {
|
|
75
75
|
if (code === 0) {
|
|
76
76
|
console.log('✅ Dependencies installed successfully.');
|
|
77
|
+
console.log(`cd ${fname}`);
|
|
78
|
+
console.log(pm == 'npm' ? `npm run start:dev` : `${pm} start:dev`);
|
|
77
79
|
resolve();
|
|
78
80
|
}
|
|
79
81
|
else {
|
|
@@ -95,6 +97,9 @@ async function createApplication(fname, flags = {}) {
|
|
|
95
97
|
// await fs.ensureDir(dirs[i]);
|
|
96
98
|
// }
|
|
97
99
|
await fs_extra_1.default.ensureDir(appPaths.root + "/src");
|
|
100
|
+
await fs_extra_1.default.ensureDir(appPaths.root + "/src/controllers");
|
|
101
|
+
await fs_extra_1.default.ensureDir(appPaths.root + "/src/services");
|
|
102
|
+
await fs_extra_1.default.ensureDir(appPaths.root + "/src/models");
|
|
98
103
|
await fs_extra_1.default.ensureDir(appPaths.root + "/test");
|
|
99
104
|
await fs_extra_1.default.ensureDir(appPaths.root + "/public");
|
|
100
105
|
// copy
|
|
@@ -134,7 +139,7 @@ app.useOpenApi({
|
|
|
134
139
|
}
|
|
135
140
|
});
|
|
136
141
|
|
|
137
|
-
app.useControllers([HomeController]);
|
|
142
|
+
app.useControllers([ HomeController ]);
|
|
138
143
|
app.useStaticFiles();
|
|
139
144
|
|
|
140
145
|
export default app;
|
|
@@ -149,11 +154,11 @@ export default app;
|
|
|
149
154
|
const serveFunc = `
|
|
150
155
|
import app from "./app";
|
|
151
156
|
|
|
152
|
-
async function
|
|
157
|
+
async function start(){
|
|
153
158
|
app.run();
|
|
154
159
|
}
|
|
155
160
|
|
|
156
|
-
|
|
161
|
+
start();
|
|
157
162
|
`;
|
|
158
163
|
const formatServeFunc = await prettier.format(serveFunc, {
|
|
159
164
|
singleQuote: true,
|
|
@@ -170,10 +175,10 @@ serve();
|
|
|
170
175
|
"main": "index.js",
|
|
171
176
|
"scripts": {
|
|
172
177
|
"start:dev": "nodemon ./src/serve.ts",
|
|
173
|
-
"start:debug": "nodemon --watch src --ext ts --exec node --inspect=0.0.0.0:9229 -r ts-node/register ./src/serve.ts",
|
|
178
|
+
"start:debug": "nodemon --watch ./src --ext ts --exec node --inspect=0.0.0.0:9229 -r ts-node/register ./src/serve.ts",
|
|
174
179
|
"clean": "rimraf ./dist",
|
|
175
180
|
"build": "npm run clean & tsc --project ./tsconfig.build.json",
|
|
176
|
-
"start": "node dist/serve.js",
|
|
181
|
+
"start": "node ./dist/serve.js",
|
|
177
182
|
"test": "jest",
|
|
178
183
|
"test:watch": "jest --watch",
|
|
179
184
|
"test:cov": "jest --coverage",
|
|
@@ -183,8 +188,8 @@ serve();
|
|
|
183
188
|
"keywords": ["avleon","nodejs","typescript"],
|
|
184
189
|
"license": "ISC",
|
|
185
190
|
"dependencies": {
|
|
186
|
-
"@avleon/core": "^0.0.
|
|
187
|
-
"@avleon/cli": "^0.0.
|
|
191
|
+
"@avleon/core": "^0.0.29",
|
|
192
|
+
"@avleon/cli": "^0.0.37",
|
|
188
193
|
"class-transformer": "^0.5.1",
|
|
189
194
|
"class-validator": "^0.14.1",
|
|
190
195
|
"reflect-metadata": "^0.2.2"
|
|
@@ -249,16 +254,13 @@ serve();
|
|
|
249
254
|
await fs_extra_1.default.writeFile(win32_1.default.join(appPaths.root, ".gitignore"), `node_modules/\ndist/\n.env`);
|
|
250
255
|
// create basic service
|
|
251
256
|
// create basic controller
|
|
252
|
-
console.info("App created successfully. Run the following command to get start.");
|
|
257
|
+
// console.info("App created successfully. Run the following command to get start.");
|
|
253
258
|
// console.log(`cd ${fname} && ${pm} install`);
|
|
254
259
|
// console.log(pm == 'npm' ? `npm run start:dev` : `${pm} start:dev`);
|
|
255
260
|
try {
|
|
256
261
|
console.log(`Running ${pm} install...`);
|
|
257
262
|
await execAsync(`cd ${fname}`);
|
|
258
263
|
await installDependencies(pm, fname);
|
|
259
|
-
console.log(`cd ${fname}`);
|
|
260
|
-
console.log(pm == 'npm' ? `npm run start:dev` : `${pm} start:dev`);
|
|
261
|
-
console.log('✅ Dependencies installed successfully.');
|
|
262
264
|
}
|
|
263
265
|
catch (error) {
|
|
264
266
|
console.error('❌ Installation failed:', error);
|
package/dist/service.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
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.createService = createService;
|
|
7
|
+
const fs_1 = require("fs");
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const path_helper_1 = require("./helpers/path-helper");
|
|
10
|
+
const promises_1 = __importDefault(require("node:fs/promises"));
|
|
11
|
+
const file_helper_1 = require("./helpers/file-helper");
|
|
12
|
+
const lodash_1 = require("lodash");
|
|
13
|
+
function capitalize(str) {
|
|
14
|
+
if (!str)
|
|
15
|
+
return '';
|
|
16
|
+
return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
|
|
17
|
+
}
|
|
18
|
+
function lower(str) {
|
|
19
|
+
return str.toLowerCase();
|
|
20
|
+
}
|
|
21
|
+
const servicesStubs = {
|
|
22
|
+
basic: path_helper_1.pathHelper.stubPath('services/basic-service.stub'),
|
|
23
|
+
rest: path_helper_1.pathHelper.stubPath('services/basic-service.stub'),
|
|
24
|
+
ormRest: path_helper_1.pathHelper.stubPath('services/orm-rest-service.stub')
|
|
25
|
+
};
|
|
26
|
+
async function createService(name, options = { force: false, resource: false, prefix: true, rest: false, model: null, root: null }, p) {
|
|
27
|
+
if (!name) {
|
|
28
|
+
throw new Error("Service name not found. use --name or npx avleon make:service HomeService");
|
|
29
|
+
}
|
|
30
|
+
if ((options.rest || options.resource) && !options.model) {
|
|
31
|
+
throw new Error("Model not found. Plese ensure you pass --model or -m to create resouce service");
|
|
32
|
+
}
|
|
33
|
+
// determine stub for generate
|
|
34
|
+
let stubPath = servicesStubs.basic;
|
|
35
|
+
if (options.rest) {
|
|
36
|
+
stubPath = servicesStubs.rest;
|
|
37
|
+
if (options.model) {
|
|
38
|
+
stubPath = servicesStubs.ormRest;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const rootPath = options.root ? 'src/' + options.root + '/' : 'src/services/';
|
|
42
|
+
if (name.split("/").length > 1) {
|
|
43
|
+
if (!(0, fs_1.existsSync)(path_1.default.join(rootPath, name.split("/").splice(-1, 1).join("/")))) {
|
|
44
|
+
await promises_1.default.mkdir(path_1.default.join(rootPath, name.replace('/' + file_helper_1.fh.filenameFromPath(name), '')), { recursive: true });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const content = await promises_1.default.readFile(stubPath, 'utf8');
|
|
48
|
+
const names = (0, file_helper_1.resolveNames)(file_helper_1.fh.filenameFromPath(name), 'Service');
|
|
49
|
+
const className = names.className.replace("Service", '');
|
|
50
|
+
let replacedContent = content
|
|
51
|
+
.replaceAll('{Service}', className)
|
|
52
|
+
.replaceAll('{service}', names.varName);
|
|
53
|
+
if (options.model) {
|
|
54
|
+
replacedContent = replacedContent
|
|
55
|
+
.replaceAll('{Model}', capitalize(options.model))
|
|
56
|
+
.replaceAll('{model}', lower(options.model));
|
|
57
|
+
}
|
|
58
|
+
await promises_1.default.writeFile(path_1.default.join(rootPath, (0, file_helper_1.getFilePathWithoutName)(name) + "/" + (0, lodash_1.kebabCase)(className) + '.service.ts'), replacedContent, 'utf8');
|
|
59
|
+
console.log("Service created succssessfully!");
|
|
60
|
+
}
|
|
61
|
+
async function createRestService(name, model) {
|
|
62
|
+
let stubPath = path_helper_1.pathHelper.stubPath('services/rest-service.stub');
|
|
63
|
+
const content = await promises_1.default.readFile(stubPath, 'utf8');
|
|
64
|
+
let replacedContent = content
|
|
65
|
+
.replaceAll('{Service}', name);
|
|
66
|
+
if (model) {
|
|
67
|
+
replacedContent = replacedContent
|
|
68
|
+
.replaceAll('{Model}', capitalize(model))
|
|
69
|
+
.replaceAll('{model}', lower(model));
|
|
70
|
+
}
|
|
71
|
+
await promises_1.default.writeFile(path_1.default.join('src/services/', (0, lodash_1.kebabCase)(name) + '.service.ts'), replacedContent, 'utf8');
|
|
72
|
+
console.log("Service created succssessfully!");
|
|
73
|
+
}
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -1,4 +1,66 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
|
+
### ⚠️ WARNING: NOT FOR PRODUCTION USE
|
|
3
|
+
|
|
4
|
+
> **🚧 This project is in active development.**
|
|
5
|
+
>
|
|
6
|
+
> It is **not stable** and **not ready** for live environments.
|
|
7
|
+
> Use **only for testing, experimentation, or internal evaluation**.
|
|
8
|
+
>
|
|
9
|
+
> ####❗ Risks of using this in production:
|
|
10
|
+
>
|
|
11
|
+
> - 🔄 Breaking changes may be introduced at any time
|
|
12
|
+
> - 🧪 Features are experimental and may be unstable
|
|
13
|
+
> - 🔐 Security has not been audited
|
|
14
|
+
> - 💥 Potential for data loss or critical errors
|
|
15
|
+
>
|
|
16
|
+
> **Please do not deploy this in production environments.**
|
|
17
|
+
|
|
18
|
+
# Avleon CLI - v0.0.37
|
|
19
|
+
|
|
20
|
+
### Create Application
|
|
21
|
+
```sh
|
|
22
|
+
npx @avleon/cli new my_api
|
|
23
|
+
```
|
|
24
|
+
### Create Controller
|
|
25
|
+
```sh
|
|
26
|
+
npx avleon make:controller product
|
|
27
|
+
# or shorthand
|
|
28
|
+
npx avleon m:c product
|
|
29
|
+
# for resource controller with -r flag
|
|
30
|
+
npx avleon m:c product -m product -r
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Create Model/Entity
|
|
34
|
+
```sh
|
|
35
|
+
# basic model
|
|
36
|
+
npx avleon make:model product
|
|
37
|
+
# typeorm model
|
|
38
|
+
npx avleon m:m product --orm
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Create Service
|
|
42
|
+
```sh
|
|
43
|
+
# basic service
|
|
44
|
+
npx avleon make:service product
|
|
45
|
+
# resource service with built-in collection
|
|
46
|
+
npx avleon make:service product -m product -r
|
|
47
|
+
# resource service with typeorm collection
|
|
48
|
+
npx avleon make:service product -m product -r --orm
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Create Middleware
|
|
52
|
+
```sh
|
|
53
|
+
npx avleon make:config product
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Create Config
|
|
57
|
+
```sh
|
|
58
|
+
npx avleon make:config product
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Create authoriztion (Experimental)
|
|
62
|
+
```sh
|
|
63
|
+
npx avleon make:auth jwt
|
|
64
|
+
```
|
|
2
65
|
|
|
3
66
|
|
|
4
|
-
Coming Soon....
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { AppService, InjectRepository } from '@avleon/core';
|
|
2
|
+
import { Repository } from 'typeorm';
|
|
3
|
+
import { {Model} } from '../models/{model}.model';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@AppService
|
|
7
|
+
export class {Service}Service{
|
|
8
|
+
|
|
9
|
+
constructor(
|
|
10
|
+
@InjectRepository({Model})
|
|
11
|
+
private readonly {model}Repository:Repository<{Model}>
|
|
12
|
+
){}
|
|
13
|
+
|
|
14
|
+
async findAll(options:any={}){
|
|
15
|
+
return this.{model}Repository.find(options);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async paginate(current:number = 1, options:any={}){
|
|
19
|
+
const take = 10;
|
|
20
|
+
const skip = current > 1 ? ( current -1 ) * 10 : 0;
|
|
21
|
+
const total = await this.{model}Repository.count(options);
|
|
22
|
+
const totalPage = Math.ceil(total / take);
|
|
23
|
+
const next = current < totalPage ? current + 1 : null;
|
|
24
|
+
const prev = current > 1 ? current - 1 : null;
|
|
25
|
+
const data = await this.{model}Repository.find({
|
|
26
|
+
...options,
|
|
27
|
+
take,
|
|
28
|
+
skip
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
total,
|
|
33
|
+
totalPage,
|
|
34
|
+
current,
|
|
35
|
+
next,
|
|
36
|
+
prev,
|
|
37
|
+
data
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async findByPk(id:number){
|
|
42
|
+
return this.{model}Repository.findOne({id});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async findBy(options:any){
|
|
46
|
+
return this.{model}Repository.findBy(options);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async findOneBy(options:any){
|
|
50
|
+
return this.{model}Repository.findOneBy(options);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
async findOne(id:number){
|
|
55
|
+
return this.{model}Repository.findOne({where:{id}}) ;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async create(createBody:any){
|
|
59
|
+
const newItem = this.{model}Repository.create();
|
|
60
|
+
return await this.{model}Repository.save();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async update(id:number, updateBody:any){
|
|
64
|
+
const isUpdate = await this.{model}Repository.update({id}, updateBody);
|
|
65
|
+
return isUpdate.affected > 0;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async delete(id:number){
|
|
69
|
+
const isDeleted = await this.{model}Repository.delete({id});
|
|
70
|
+
return isDeleted.affected > 0;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { AppService,
|
|
2
|
-
import { Repository } from 'typeorm';
|
|
1
|
+
import { AppService, Collection } from '@avleon/core';
|
|
3
2
|
import { {Model} } from '../models/{model}.model';
|
|
4
3
|
|
|
5
4
|
|
|
@@ -7,22 +6,21 @@ import { {Model} } from '../models/{model}.model';
|
|
|
7
6
|
export class {Service}Service{
|
|
8
7
|
|
|
9
8
|
constructor(
|
|
10
|
-
|
|
11
|
-
private readonly {model}Repository:Repository<{Model}>
|
|
9
|
+
private readonly {model}Collection:Collection.from<{Model}>([])
|
|
12
10
|
){}
|
|
13
11
|
|
|
14
12
|
async findAll(options:any={}){
|
|
15
|
-
return this.{model}
|
|
13
|
+
return this.{model}Collection.find(options);
|
|
16
14
|
}
|
|
17
15
|
|
|
18
16
|
async paginate(current:number = 1, options:any={}){
|
|
19
17
|
const take = 10;
|
|
20
18
|
const skip = current > 1 ? ( current -1 ) * 10 : 0;
|
|
21
|
-
const total = await this.{model}
|
|
19
|
+
const total = await this.{model}Collection.count(options);
|
|
22
20
|
const totalPage = Math.ceil(total / take);
|
|
23
21
|
const next = current < totalPage ? current + 1 : null;
|
|
24
22
|
const prev = current > 1 ? current - 1 : null;
|
|
25
|
-
const data = await this.{model}
|
|
23
|
+
const data = await this.{model}Collection.find({
|
|
26
24
|
...options,
|
|
27
25
|
take,
|
|
28
26
|
skip
|
|
@@ -39,35 +37,35 @@ export class {Service}Service{
|
|
|
39
37
|
}
|
|
40
38
|
|
|
41
39
|
async findByPk(id:number){
|
|
42
|
-
return this.{model}
|
|
40
|
+
return this.{model}Collection.findOne({id});
|
|
43
41
|
}
|
|
44
42
|
|
|
45
43
|
async findBy(options:any){
|
|
46
|
-
return this.{model}
|
|
44
|
+
return this.{model}Collection.findBy(options);
|
|
47
45
|
}
|
|
48
46
|
|
|
49
47
|
async findOneBy(options:any){
|
|
50
|
-
return this.{model}
|
|
48
|
+
return this.{model}Collection.findOneBy(options);
|
|
51
49
|
}
|
|
52
50
|
|
|
53
51
|
|
|
54
52
|
async findOne(id:number){
|
|
55
|
-
return this.{model}
|
|
53
|
+
return this.{model}Collection.findOne({where:{id}}) ;
|
|
56
54
|
}
|
|
57
55
|
|
|
58
56
|
async create(createBody:any){
|
|
59
|
-
const
|
|
60
|
-
return
|
|
57
|
+
const savedItem = await this.{model}Collection.save(createBody);
|
|
58
|
+
return savedItem;
|
|
61
59
|
}
|
|
62
60
|
|
|
63
61
|
async update(id:number, updateBody:any){
|
|
64
|
-
const isUpdate = await this.{model}
|
|
65
|
-
return isUpdate
|
|
62
|
+
const isUpdate = await this.{model}Collection.update(id, updateBody);
|
|
63
|
+
return isUpdate;
|
|
66
64
|
}
|
|
67
65
|
|
|
68
66
|
async delete(id:number){
|
|
69
|
-
const isDeleted = await this.{model}
|
|
70
|
-
return isDeleted
|
|
67
|
+
const isDeleted = await this.{model}Collection.delete(id);
|
|
68
|
+
return isDeleted > 0;
|
|
71
69
|
}
|
|
72
70
|
|
|
73
71
|
}
|