gg-express 1.0.26 → 1.0.29
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/GGApi.js +2 -2
- package/dist/GGExpress.js +11 -1
- package/dist/staticRouteInterface.d.ts +2 -1
- package/dist/test.js +26 -0
- package/package.json +2 -1
- package/readme.md +86 -68
- package/src/GGApi.ts +2 -2
- package/src/GGExpress.ts +19 -1
- package/src/staticRouteInterface.ts +1 -1
- package/src/test.ts +31 -0
package/dist/GGApi.js
CHANGED
|
@@ -70,8 +70,8 @@ function run() {
|
|
|
70
70
|
return __awaiter(this, void 0, void 0, function* () {
|
|
71
71
|
const api = new GGApi();
|
|
72
72
|
const data = yield api.post("/api/item", {
|
|
73
|
-
parameter: {
|
|
74
|
-
data: [
|
|
73
|
+
parameter: { lotNumber: 1223 },
|
|
74
|
+
data: [],
|
|
75
75
|
});
|
|
76
76
|
const data2 = yield api.get("/api/users", {});
|
|
77
77
|
data.data;
|
package/dist/GGExpress.js
CHANGED
|
@@ -14,6 +14,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
const fs_1 = __importDefault(require("fs"));
|
|
16
16
|
const path_1 = __importDefault(require("path"));
|
|
17
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
17
18
|
const myExpressRouteList = [];
|
|
18
19
|
class GGExpress {
|
|
19
20
|
constructor(app, outputPath) {
|
|
@@ -112,7 +113,16 @@ class GGExpress {
|
|
|
112
113
|
let rawString = ``;
|
|
113
114
|
if (data.length === 0)
|
|
114
115
|
return "";
|
|
115
|
-
|
|
116
|
+
const filterDuplicateUrlOut = [];
|
|
117
|
+
for (let row of data) {
|
|
118
|
+
const temp = filterDuplicateUrlOut.filter((fRow) => fRow.method === row.method && fRow.url === row.url);
|
|
119
|
+
if (temp.length <= 0)
|
|
120
|
+
filterDuplicateUrlOut.push(row);
|
|
121
|
+
else {
|
|
122
|
+
console.log(chalk_1.default.yellow(`!!! found duplicate url ${row.method} : ${row.url} -- system will keep only first one it found.`));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
rawString = filterDuplicateUrlOut
|
|
116
126
|
.map((row) => {
|
|
117
127
|
const parameterCode = genParamCodeParameter(row.requireParams);
|
|
118
128
|
const parameterDataCode = genDataParamCode(row.requireParams);
|
package/dist/test.js
CHANGED
|
@@ -34,6 +34,32 @@ function run() {
|
|
|
34
34
|
},
|
|
35
35
|
});
|
|
36
36
|
});
|
|
37
|
+
ggapp.get("/api/users", {
|
|
38
|
+
requireParams: {
|
|
39
|
+
parameter: {},
|
|
40
|
+
dataType: "singleObject",
|
|
41
|
+
structure: {},
|
|
42
|
+
},
|
|
43
|
+
responseStructure: {
|
|
44
|
+
parameter: { numberOfPeople: "number", itemName: "string" },
|
|
45
|
+
dataType: "arrayObject",
|
|
46
|
+
structure: {
|
|
47
|
+
id: "number",
|
|
48
|
+
name: "string",
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
}, (req, res, next) => {
|
|
52
|
+
const data = req.body.data.parameter;
|
|
53
|
+
return res.json({
|
|
54
|
+
message: "",
|
|
55
|
+
status: "SUCCESS",
|
|
56
|
+
data: [],
|
|
57
|
+
parameter: {
|
|
58
|
+
itemName: "",
|
|
59
|
+
numberOfPeople: 2,
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
});
|
|
37
63
|
ggapp.post("/api/item", {
|
|
38
64
|
requireParams: {
|
|
39
65
|
parameter: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gg-express",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.29",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/GGExpress.js",
|
|
6
6
|
"scripts": {
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"@types/axios": "^0.14.0",
|
|
14
14
|
"app-root-path": "^3.1.0",
|
|
15
15
|
"axios": "^1.7.7",
|
|
16
|
+
"chalk": "^4.1.2",
|
|
16
17
|
"express": "^4.21.1",
|
|
17
18
|
"fs": "^0.0.1-security",
|
|
18
19
|
"path": "^0.12.7"
|
package/readme.md
CHANGED
|
@@ -1,14 +1,30 @@
|
|
|
1
1
|
# GG-Express
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**GG-Express** is an Express.js wrapper that enforces strong type requirements for `GET`, `POST`, `PUT`, and `DELETE` methods. It ensures that `req.query` and `req.body` follow strict structure definitions and automatically generates an `apiConnector` class file for easy use in front-end development.
|
|
4
4
|
|
|
5
|
+
## Features
|
|
5
6
|
|
|
7
|
+
- Enforces required request (`req.query` and `req.body`) and response parameter types for `GET`, `POST`, `PUT`, and `DELETE` methods in Express.
|
|
8
|
+
- Automatically generates a static API URL class that strongly types parameters and auto-casts return types to match the backend's response structure.
|
|
9
|
+
- Simplifies integrating strong typing between back-end and front-end.
|
|
6
10
|
|
|
7
11
|
|
|
8
|
-
##
|
|
9
|
-
|
|
10
|
-
-
|
|
12
|
+
## Key Points
|
|
13
|
+
|
|
14
|
+
- Strict Parameter Enforcement: GG-Express ensures that only the declared parameters are accessible in your req.body or req.query.
|
|
15
|
+
|
|
16
|
+
- Type-Safe Responses: You can only return data that follows the predefined responseStructure, improving consistency between backend and frontend.
|
|
17
|
+
|
|
18
|
+
- API Connector Generation: It automatically generates an API connector class file for your front-end, making API calls more reliable and type-safe.
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
Install the package using either `npm` or `yarn`:
|
|
23
|
+
|
|
24
|
+
### Using npm:
|
|
11
25
|
|
|
26
|
+
```bash
|
|
27
|
+
npm install gg-express
|
|
12
28
|
|
|
13
29
|
## Installation
|
|
14
30
|
|
|
@@ -22,70 +38,72 @@ npm install gg-express
|
|
|
22
38
|
use case
|
|
23
39
|
```javascript
|
|
24
40
|
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
},
|
|
41
|
+
const express = require('express');
|
|
42
|
+
const GGExpress = require('gg-express'); // Import GG-Express
|
|
43
|
+
const app = express();
|
|
44
|
+
|
|
45
|
+
// Initialize GG-Express with backend and frontend file paths
|
|
46
|
+
const ggapp = new GGExpress(app, [
|
|
47
|
+
'./server/location-for-generating-file', // Path to generate backend file
|
|
48
|
+
'./myapp/location-for-generating-file', // Path to generate frontend file
|
|
49
|
+
]);
|
|
50
|
+
|
|
51
|
+
// Example of a POST request with enforced parameters
|
|
52
|
+
ggapp.post(
|
|
53
|
+
"/api/item",
|
|
54
|
+
{
|
|
55
|
+
requireParams: {
|
|
56
|
+
parameter: { lotNumber: "number" },
|
|
57
|
+
dataType: "arrayObject",
|
|
58
|
+
structure: {
|
|
59
|
+
id: "number",
|
|
60
|
+
name: "string",
|
|
61
|
+
price: "number",
|
|
47
62
|
},
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
63
|
+
},
|
|
64
|
+
responseStructure: {
|
|
65
|
+
parameter: { numberOfPeople: "number", itemName: "string" },
|
|
66
|
+
dataType: "arrayObject",
|
|
67
|
+
structure: {
|
|
68
|
+
id: "number",
|
|
69
|
+
name: "string",
|
|
55
70
|
},
|
|
56
71
|
},
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
72
|
+
},
|
|
73
|
+
(req, res, next) => {
|
|
74
|
+
// You can only access the required parameters declared above
|
|
75
|
+
const data = req.body.data;
|
|
76
|
+
|
|
77
|
+
// Expected data structure:
|
|
78
|
+
// data: {
|
|
79
|
+
// parameter: {
|
|
80
|
+
// lotNumber: number;
|
|
81
|
+
// };
|
|
82
|
+
// data: [{
|
|
83
|
+
// id: number;
|
|
84
|
+
// name: string;
|
|
85
|
+
// price: number;
|
|
86
|
+
// }];
|
|
87
|
+
// }
|
|
88
|
+
|
|
89
|
+
// Response structure also follows the predefined format
|
|
90
|
+
return res.json({
|
|
91
|
+
message: "",
|
|
92
|
+
status: "SUCCESS",
|
|
93
|
+
data: [],
|
|
94
|
+
parameter: {
|
|
95
|
+
itemName: "",
|
|
96
|
+
numberOfPeople: 2,
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
// Start the server and generate the API files
|
|
103
|
+
app.listen(3000, () => {
|
|
104
|
+
ggapp.generateAPIFiles(); // Generates the apiConnector class for front-end use
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
|
package/src/GGApi.ts
CHANGED
|
@@ -70,8 +70,8 @@ export class GGApi {
|
|
|
70
70
|
async function run() {
|
|
71
71
|
const api = new GGApi()
|
|
72
72
|
const data = await api.post("/api/item", {
|
|
73
|
-
parameter: {
|
|
74
|
-
data: [
|
|
73
|
+
parameter: { lotNumber: 1223 },
|
|
74
|
+
data: [],
|
|
75
75
|
})
|
|
76
76
|
|
|
77
77
|
const data2 = await api.get("/api/users", {})
|
package/src/GGExpress.ts
CHANGED
|
@@ -3,6 +3,8 @@ import { NextFunction, Request, Response } from "express"
|
|
|
3
3
|
import Express from "express-serve-static-core"
|
|
4
4
|
import fs from "fs"
|
|
5
5
|
import path from "path"
|
|
6
|
+
import chalk from "chalk"
|
|
7
|
+
|
|
6
8
|
// export { GGApi } from "./GGApi"
|
|
7
9
|
type Unarray<T> = T extends (infer U)[] ? U : T
|
|
8
10
|
type AsConstArray<T extends readonly any[]> = [...T]
|
|
@@ -302,7 +304,23 @@ export default class GGExpress {
|
|
|
302
304
|
const genInterfaceString = (data: typeof myExpressRouteList) => {
|
|
303
305
|
let rawString = ``
|
|
304
306
|
if (data.length === 0) return ""
|
|
305
|
-
|
|
307
|
+
|
|
308
|
+
const filterDuplicateUrlOut: typeof data = []
|
|
309
|
+
for (let row of data) {
|
|
310
|
+
const temp = filterDuplicateUrlOut.filter(
|
|
311
|
+
(fRow) => fRow.method === row.method && fRow.url === row.url
|
|
312
|
+
)
|
|
313
|
+
if (temp.length <= 0) filterDuplicateUrlOut.push(row)
|
|
314
|
+
else {
|
|
315
|
+
console.log(
|
|
316
|
+
chalk.yellow(
|
|
317
|
+
`!!! found duplicate url ${row.method} : ${row.url} -- system will keep only first one it found.`
|
|
318
|
+
)
|
|
319
|
+
)
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
rawString = filterDuplicateUrlOut
|
|
306
324
|
.map((row) => {
|
|
307
325
|
const parameterCode = genParamCodeParameter(row.requireParams)
|
|
308
326
|
const parameterDataCode = genDataParamCode(row.requireParams)
|
|
@@ -7,7 +7,7 @@ export interface staticRouteInterface {
|
|
|
7
7
|
parameter : { numberOfPeople : number, itemName : string}, data : { id : number, name : string } []}
|
|
8
8
|
} },
|
|
9
9
|
post : { "/api/item" : {
|
|
10
|
-
requireParams : { parameter:{
|
|
10
|
+
requireParams : { parameter:{ lotNumber : number} , data:{ id : number, name : string, price : number}[]},
|
|
11
11
|
responseStructure : {
|
|
12
12
|
status : "SUCCESS" | "ERROR",
|
|
13
13
|
message : string,
|
package/src/test.ts
CHANGED
|
@@ -3,6 +3,37 @@ import express, { Express } from "express"
|
|
|
3
3
|
function run() {
|
|
4
4
|
const app = express()
|
|
5
5
|
const ggapp = new GGExpress(app, ["./"])
|
|
6
|
+
ggapp.get(
|
|
7
|
+
"/api/users",
|
|
8
|
+
{
|
|
9
|
+
requireParams: {
|
|
10
|
+
parameter: {},
|
|
11
|
+
dataType: "singleObject",
|
|
12
|
+
structure: {},
|
|
13
|
+
},
|
|
14
|
+
responseStructure: {
|
|
15
|
+
parameter: { numberOfPeople: "number", itemName: "string" },
|
|
16
|
+
dataType: "arrayObject",
|
|
17
|
+
structure: {
|
|
18
|
+
id: "number",
|
|
19
|
+
name: "string",
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
(req, res, next) => {
|
|
24
|
+
const data = req.body.data.parameter
|
|
25
|
+
return res.json({
|
|
26
|
+
message: "",
|
|
27
|
+
status: "SUCCESS",
|
|
28
|
+
data: [],
|
|
29
|
+
parameter: {
|
|
30
|
+
itemName: "",
|
|
31
|
+
numberOfPeople: 2,
|
|
32
|
+
},
|
|
33
|
+
})
|
|
34
|
+
}
|
|
35
|
+
)
|
|
36
|
+
|
|
6
37
|
ggapp.get(
|
|
7
38
|
"/api/users",
|
|
8
39
|
{
|