@gieo/express 1.0.5 → 1.0.7
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/index.js +74 -135
- package/dist/test.js +95 -171
- package/package.json +4 -4
- package/src/index.ts +32 -3
- package/tsconfig.json +2 -0
- package/src/index.js +0 -89
- package/src/test.js +0 -106
package/dist/index.js
CHANGED
|
@@ -1,52 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
13
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
-
function step(op) {
|
|
16
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
-
switch (op[0]) {
|
|
21
|
-
case 0: case 1: t = op; break;
|
|
22
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
-
default:
|
|
26
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
-
if (t[2]) _.ops.pop();
|
|
31
|
-
_.trys.pop(); continue;
|
|
32
|
-
}
|
|
33
|
-
op = body.call(thisArg, _);
|
|
34
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
39
|
-
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
40
|
-
var m = o[Symbol.asyncIterator], i;
|
|
41
|
-
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);
|
|
42
|
-
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); }); }; }
|
|
43
|
-
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
44
|
-
};
|
|
45
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
3
|
+
const http_1 = require("http");
|
|
4
|
+
const url_1 = require("url");
|
|
5
|
+
class ExpressPlus {
|
|
6
|
+
constructor() {
|
|
50
7
|
this.routes = {
|
|
51
8
|
GET: [],
|
|
52
9
|
POST: [],
|
|
@@ -56,92 +13,53 @@ var ExpressPlus = /** @class */ (function () {
|
|
|
56
13
|
};
|
|
57
14
|
this.middlewares = [];
|
|
58
15
|
}
|
|
59
|
-
|
|
60
|
-
this.routes[method].push({ path
|
|
61
|
-
}
|
|
62
|
-
|
|
16
|
+
addRoute(method, path, handler) {
|
|
17
|
+
this.routes[method].push({ path, handler });
|
|
18
|
+
}
|
|
19
|
+
use(middleware) {
|
|
63
20
|
this.middlewares.push(middleware);
|
|
64
|
-
}
|
|
65
|
-
|
|
21
|
+
}
|
|
22
|
+
get(path, handler) {
|
|
66
23
|
this.addRoute("GET", path, handler);
|
|
67
|
-
}
|
|
68
|
-
|
|
24
|
+
}
|
|
25
|
+
post(path, handler) {
|
|
69
26
|
this.addRoute("POST", path, handler);
|
|
70
|
-
}
|
|
71
|
-
|
|
27
|
+
}
|
|
28
|
+
put(path, handler) {
|
|
72
29
|
this.addRoute("PUT", path, handler);
|
|
73
|
-
}
|
|
74
|
-
|
|
30
|
+
}
|
|
31
|
+
patch(path, handler) {
|
|
75
32
|
this.addRoute("PATCH", path, handler);
|
|
76
|
-
}
|
|
77
|
-
|
|
33
|
+
}
|
|
34
|
+
delete(path, handler) {
|
|
78
35
|
this.addRoute("DELETE", path, handler);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
var extendedReq = req;
|
|
88
|
-
var extendedRes = res;
|
|
36
|
+
}
|
|
37
|
+
listen(port, callback) {
|
|
38
|
+
const server = (0, http_1.createServer)((req, res) => {
|
|
39
|
+
const method = req.method;
|
|
40
|
+
const parsedUrl = (0, url_1.parse)(req.url || "", true);
|
|
41
|
+
const pathname = parsedUrl.pathname || "/";
|
|
42
|
+
const extendedReq = req;
|
|
43
|
+
const extendedRes = res;
|
|
89
44
|
extendedReq.query = parsedUrl.query;
|
|
90
|
-
extendedReq.
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
_a = false;
|
|
109
|
-
chunk = _d;
|
|
110
|
-
chunks.push(chunk);
|
|
111
|
-
_e.label = 4;
|
|
112
|
-
case 4:
|
|
113
|
-
_a = true;
|
|
114
|
-
return [3 /*break*/, 2];
|
|
115
|
-
case 5: return [3 /*break*/, 12];
|
|
116
|
-
case 6:
|
|
117
|
-
e_1_1 = _e.sent();
|
|
118
|
-
e_1 = { error: e_1_1 };
|
|
119
|
-
return [3 /*break*/, 12];
|
|
120
|
-
case 7:
|
|
121
|
-
_e.trys.push([7, , 10, 11]);
|
|
122
|
-
if (!(!_a && !_b && (_c = extendedReq_1.return))) return [3 /*break*/, 9];
|
|
123
|
-
return [4 /*yield*/, _c.call(extendedReq_1)];
|
|
124
|
-
case 8:
|
|
125
|
-
_e.sent();
|
|
126
|
-
_e.label = 9;
|
|
127
|
-
case 9: return [3 /*break*/, 11];
|
|
128
|
-
case 10:
|
|
129
|
-
if (e_1) throw e_1.error;
|
|
130
|
-
return [7 /*endfinally*/];
|
|
131
|
-
case 11: return [7 /*endfinally*/];
|
|
132
|
-
case 12:
|
|
133
|
-
raw = Buffer.concat(chunks).toString();
|
|
134
|
-
extendedReq.bodyRaw = raw;
|
|
135
|
-
try {
|
|
136
|
-
extendedReq.body = JSON.parse(raw);
|
|
137
|
-
}
|
|
138
|
-
catch (_f) {
|
|
139
|
-
extendedReq.body = {};
|
|
140
|
-
}
|
|
141
|
-
return [2 /*return*/, extendedReq.body];
|
|
142
|
-
}
|
|
143
|
-
});
|
|
144
|
-
}); };
|
|
45
|
+
extendedReq.params = {};
|
|
46
|
+
extendedReq.getBody = async () => {
|
|
47
|
+
if (extendedReq.body)
|
|
48
|
+
return extendedReq.body;
|
|
49
|
+
const chunks = [];
|
|
50
|
+
for await (const chunk of extendedReq) {
|
|
51
|
+
chunks.push(chunk);
|
|
52
|
+
}
|
|
53
|
+
const raw = Buffer.concat(chunks).toString();
|
|
54
|
+
extendedReq.bodyRaw = raw;
|
|
55
|
+
try {
|
|
56
|
+
extendedReq.body = JSON.parse(raw);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
extendedReq.body = {};
|
|
60
|
+
}
|
|
61
|
+
return extendedReq.body;
|
|
62
|
+
};
|
|
145
63
|
extendedRes.status = function (code) {
|
|
146
64
|
extendedRes.statusCode = code;
|
|
147
65
|
return extendedRes;
|
|
@@ -150,9 +68,33 @@ var ExpressPlus = /** @class */ (function () {
|
|
|
150
68
|
extendedRes.setHeader("Content-Type", "application/json");
|
|
151
69
|
extendedRes.end(JSON.stringify(data));
|
|
152
70
|
};
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
71
|
+
// 🔍 Tìm route phù hợp (hỗ trợ dynamic route)
|
|
72
|
+
const route = this.routes[method].find((r) => {
|
|
73
|
+
const routeParts = r.path.split("/").filter(Boolean);
|
|
74
|
+
const urlParts = pathname.split("/").filter(Boolean);
|
|
75
|
+
if (routeParts.length !== urlParts.length)
|
|
76
|
+
return false;
|
|
77
|
+
return routeParts.every((part, i) => {
|
|
78
|
+
return part.startsWith(":") || part === urlParts[i];
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
// 🧠 Trích xuất params nếu có
|
|
82
|
+
if (route) {
|
|
83
|
+
const routeParts = route.path.split("/").filter(Boolean);
|
|
84
|
+
const urlParts = pathname.split("/").filter(Boolean);
|
|
85
|
+
routeParts.forEach((part, i) => {
|
|
86
|
+
if (part.startsWith(":")) {
|
|
87
|
+
const key = part.slice(1);
|
|
88
|
+
extendedReq.params[key] = urlParts[i];
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
// 🧪 Logging đơn giản
|
|
93
|
+
console.log(`[${method}] ${pathname}`);
|
|
94
|
+
// 🧩 Middleware + Route handler
|
|
95
|
+
let i = 0;
|
|
96
|
+
const next = () => {
|
|
97
|
+
const middleware = this.middlewares[i++];
|
|
156
98
|
if (middleware) {
|
|
157
99
|
middleware(extendedReq, extendedRes, next);
|
|
158
100
|
}
|
|
@@ -160,15 +102,12 @@ var ExpressPlus = /** @class */ (function () {
|
|
|
160
102
|
route.handler(extendedReq, extendedRes);
|
|
161
103
|
}
|
|
162
104
|
else {
|
|
163
|
-
extendedRes.status(404).
|
|
105
|
+
extendedRes.status(404).json({ message: "Not Found" });
|
|
164
106
|
}
|
|
165
107
|
};
|
|
166
108
|
next();
|
|
167
109
|
});
|
|
168
110
|
server.listen(port, callback);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
}());
|
|
172
|
-
// ✅ Export cho cả ES Module và CommonJS
|
|
111
|
+
}
|
|
112
|
+
}
|
|
173
113
|
exports.default = ExpressPlus;
|
|
174
|
-
module.exports = ExpressPlus;
|
package/dist/test.js
CHANGED
|
@@ -1,182 +1,106 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
13
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
-
function step(op) {
|
|
16
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
-
switch (op[0]) {
|
|
21
|
-
case 0: case 1: t = op; break;
|
|
22
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
-
default:
|
|
26
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
-
if (t[2]) _.ops.pop();
|
|
31
|
-
_.trys.pop(); continue;
|
|
32
|
-
}
|
|
33
|
-
op = body.call(thisArg, _);
|
|
34
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
var __rest = (this && this.__rest) || function (s, e) {
|
|
39
|
-
var t = {};
|
|
40
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
41
|
-
t[p] = s[p];
|
|
42
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
43
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
44
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
45
|
-
t[p[i]] = s[p[i]];
|
|
46
|
-
}
|
|
47
|
-
return t;
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
48
4
|
};
|
|
49
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
app.post("/calc",
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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
|
-
success: false,
|
|
88
|
-
message: "Invalid operator",
|
|
89
|
-
})];
|
|
90
|
-
}
|
|
91
|
-
return [2 /*return*/, res.status(200).json({
|
|
92
|
-
statusCode: 200,
|
|
93
|
-
success: true,
|
|
94
|
-
result: result,
|
|
95
|
-
})];
|
|
96
|
-
}
|
|
97
|
-
catch (err) {
|
|
98
|
-
return [2 /*return*/, res.status(500).json({
|
|
99
|
-
statusCode: 500,
|
|
100
|
-
success: false,
|
|
101
|
-
message: err.message,
|
|
102
|
-
})];
|
|
103
|
-
}
|
|
104
|
-
return [2 /*return*/];
|
|
6
|
+
const index_1 = __importDefault(require("./index"));
|
|
7
|
+
const utils_1 = require("@gieo/utils");
|
|
8
|
+
const app = new index_1.default();
|
|
9
|
+
app.post("/calc", async (req, res) => {
|
|
10
|
+
const { op, ...numbers } = await req.getBody();
|
|
11
|
+
// Lấy tất cả giá trị số từ body
|
|
12
|
+
const values = Object.values(numbers)
|
|
13
|
+
.map(Number)
|
|
14
|
+
.filter((v) => !isNaN(v));
|
|
15
|
+
if (values.length < 2) {
|
|
16
|
+
return res.status(400).json({
|
|
17
|
+
statusCode: 400,
|
|
18
|
+
success: false,
|
|
19
|
+
message: "Need at least two numeric values",
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
let result;
|
|
23
|
+
try {
|
|
24
|
+
switch (op) {
|
|
25
|
+
case "sum":
|
|
26
|
+
result = (0, utils_1.sum)(...values);
|
|
27
|
+
break;
|
|
28
|
+
case "sub":
|
|
29
|
+
result = (0, utils_1.sub)(...values);
|
|
30
|
+
break;
|
|
31
|
+
case "mul":
|
|
32
|
+
result = (0, utils_1.mul)(...values);
|
|
33
|
+
break;
|
|
34
|
+
case "div":
|
|
35
|
+
result = (0, utils_1.div)(...values);
|
|
36
|
+
break;
|
|
37
|
+
default:
|
|
38
|
+
return res.status(400).json({
|
|
39
|
+
statusCode: 400,
|
|
40
|
+
success: false,
|
|
41
|
+
message: "Invalid operator",
|
|
42
|
+
});
|
|
105
43
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
return res.status(200).json({ success: true, status: 200, result: "PATCH / OK" });
|
|
120
|
-
});
|
|
121
|
-
app.delete("/", function (req, res) {
|
|
122
|
-
return res.status(200).json({ success: true, status: 200, result: "DELETE / OK" });
|
|
44
|
+
return res.status(200).json({
|
|
45
|
+
statusCode: 200,
|
|
46
|
+
success: true,
|
|
47
|
+
result,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
return res.status(500).json({
|
|
52
|
+
statusCode: 500,
|
|
53
|
+
success: false,
|
|
54
|
+
message: err.message,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
123
57
|
});
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
});
|
|
150
|
-
}); }; };
|
|
58
|
+
// Các route cơ bản
|
|
59
|
+
app.get("/", (req, res) => res.status(200).json({ success: true, status: 200, result: "GET / OK" }));
|
|
60
|
+
app.put("/", (req, res) => res.status(200).json({ success: true, status: 200, result: "PUT / OK" }));
|
|
61
|
+
app.post("/", (req, res) => res.status(200).json({ success: true, status: 200, result: "POST / OK" }));
|
|
62
|
+
app.patch("/", (req, res) => res.status(200).json({ success: true, status: 200, result: "PATCH / OK" }));
|
|
63
|
+
app.delete("/", (req, res) => res.status(200).json({ success: true, status: 200, result: "DELETE / OK" }));
|
|
64
|
+
const mathRoute = (op) => async (req, res) => {
|
|
65
|
+
const { a, b } = await req.getBody();
|
|
66
|
+
if (typeof a !== "number" || typeof b !== "number") {
|
|
67
|
+
return res.status(400).json({
|
|
68
|
+
success: false,
|
|
69
|
+
status: 400,
|
|
70
|
+
result: "Invalid input. 'a' and 'b' must be numbers.",
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
const result = op(a, b);
|
|
75
|
+
res.status(200).json({ success: true, status: 200, result });
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
res
|
|
79
|
+
.status(500)
|
|
80
|
+
.json({ success: false, status: 500, result: err.message });
|
|
81
|
+
}
|
|
82
|
+
};
|
|
151
83
|
// Math operations
|
|
152
84
|
app.post("/sum", mathRoute(utils_1.sum));
|
|
153
85
|
app.post("/sub", mathRoute(utils_1.sub));
|
|
154
86
|
app.post("/mul", mathRoute(utils_1.mul));
|
|
155
|
-
app.post("/div",
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
}
|
|
174
|
-
result = (0, utils_1.div)(a, b);
|
|
175
|
-
res.status(200).json({ success: true, status: 200, result: result });
|
|
176
|
-
return [2 /*return*/];
|
|
177
|
-
}
|
|
178
|
-
});
|
|
179
|
-
}); });
|
|
180
|
-
app.listen(3000, function () {
|
|
87
|
+
app.post("/div", async (req, res) => {
|
|
88
|
+
const { a, b } = await req.getBody();
|
|
89
|
+
if (typeof a !== "number" || typeof b !== "number") {
|
|
90
|
+
return res.status(400).json({
|
|
91
|
+
success: false,
|
|
92
|
+
status: 400,
|
|
93
|
+
result: "Invalid input. 'a' and 'b' must be numbers.",
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
if (b === 0) {
|
|
97
|
+
return res
|
|
98
|
+
.status(400)
|
|
99
|
+
.json({ success: false, status: 400, result: "Cannot divide by zero" });
|
|
100
|
+
}
|
|
101
|
+
const result = (0, utils_1.div)(a, b);
|
|
102
|
+
res.status(200).json({ success: true, status: 200, result });
|
|
103
|
+
});
|
|
104
|
+
app.listen(3000, () => {
|
|
181
105
|
console.log("✅ Server is running at http://localhost:3000");
|
|
182
106
|
});
|
package/package.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gieo/express",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"description": "",
|
|
5
|
-
"main": "./dist/
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
6
|
"keywords": [],
|
|
7
7
|
"author": "",
|
|
8
8
|
"license": "ISC",
|
|
9
9
|
"devDependencies": {
|
|
10
10
|
"@gieo/utils": "^1.0.5",
|
|
11
|
-
"@types/node": "^24.2.
|
|
11
|
+
"@types/node": "^24.2.1",
|
|
12
12
|
"jiti": "^2.5.1",
|
|
13
13
|
"typescript": "^5.9.2"
|
|
14
14
|
},
|
|
15
15
|
"scripts": {
|
|
16
|
-
"test": "
|
|
16
|
+
"test": "node dist/test.js"
|
|
17
17
|
}
|
|
18
18
|
}
|
package/src/index.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { parse } from "url";
|
|
|
4
4
|
// Mở rộng Request
|
|
5
5
|
interface ExtendedRequest extends IncomingMessage {
|
|
6
6
|
query?: Record<string, string | string[]>;
|
|
7
|
+
params?: Record<string, string>;
|
|
7
8
|
bodyRaw?: string;
|
|
8
9
|
body?: any;
|
|
9
10
|
getBody: () => Promise<any>;
|
|
@@ -78,12 +79,11 @@ class ExpressPlus {
|
|
|
78
79
|
const parsedUrl = parse(req.url || "", true);
|
|
79
80
|
const pathname = parsedUrl.pathname || "/";
|
|
80
81
|
|
|
81
|
-
const route = this.routes[method].find((r) => r.path === pathname);
|
|
82
|
-
|
|
83
82
|
const extendedReq = req as ExtendedRequest;
|
|
84
83
|
const extendedRes = res as ExtendedResponse;
|
|
85
84
|
|
|
86
85
|
extendedReq.query = parsedUrl.query;
|
|
86
|
+
extendedReq.params = {};
|
|
87
87
|
extendedReq.getBody = async () => {
|
|
88
88
|
if (extendedReq.body) return extendedReq.body;
|
|
89
89
|
|
|
@@ -114,6 +114,35 @@ class ExpressPlus {
|
|
|
114
114
|
extendedRes.end(JSON.stringify(data));
|
|
115
115
|
};
|
|
116
116
|
|
|
117
|
+
// 🔍 Tìm route phù hợp (hỗ trợ dynamic route)
|
|
118
|
+
const route = this.routes[method].find((r) => {
|
|
119
|
+
const routeParts = r.path.split("/").filter(Boolean);
|
|
120
|
+
const urlParts = pathname.split("/").filter(Boolean);
|
|
121
|
+
|
|
122
|
+
if (routeParts.length !== urlParts.length) return false;
|
|
123
|
+
|
|
124
|
+
return routeParts.every((part, i) => {
|
|
125
|
+
return part.startsWith(":") || part === urlParts[i];
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// 🧠 Trích xuất params nếu có
|
|
130
|
+
if (route) {
|
|
131
|
+
const routeParts = route.path.split("/").filter(Boolean);
|
|
132
|
+
const urlParts = pathname.split("/").filter(Boolean);
|
|
133
|
+
|
|
134
|
+
routeParts.forEach((part, i) => {
|
|
135
|
+
if (part.startsWith(":")) {
|
|
136
|
+
const key = part.slice(1);
|
|
137
|
+
extendedReq.params![key] = urlParts[i];
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// 🧪 Logging đơn giản
|
|
143
|
+
console.log(`[${method}] ${pathname}`);
|
|
144
|
+
|
|
145
|
+
// 🧩 Middleware + Route handler
|
|
117
146
|
let i = 0;
|
|
118
147
|
const next = () => {
|
|
119
148
|
const middleware = this.middlewares[i++];
|
|
@@ -122,7 +151,7 @@ class ExpressPlus {
|
|
|
122
151
|
} else if (route) {
|
|
123
152
|
route.handler(extendedReq, extendedRes);
|
|
124
153
|
} else {
|
|
125
|
-
extendedRes.status(404).
|
|
154
|
+
extendedRes.status(404).json({ message: "Not Found" });
|
|
126
155
|
}
|
|
127
156
|
};
|
|
128
157
|
|
package/tsconfig.json
CHANGED
package/src/index.js
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const http_1 = require("http");
|
|
4
|
-
const url_1 = require("url");
|
|
5
|
-
class ExpressPlus {
|
|
6
|
-
constructor() {
|
|
7
|
-
this.routes = {
|
|
8
|
-
GET: [],
|
|
9
|
-
POST: [],
|
|
10
|
-
PUT: [],
|
|
11
|
-
PATCH: [],
|
|
12
|
-
DELETE: [],
|
|
13
|
-
};
|
|
14
|
-
this.middlewares = [];
|
|
15
|
-
}
|
|
16
|
-
addRoute(method, path, handler) {
|
|
17
|
-
this.routes[method].push({ path, handler });
|
|
18
|
-
}
|
|
19
|
-
use(middleware) {
|
|
20
|
-
this.middlewares.push(middleware);
|
|
21
|
-
}
|
|
22
|
-
get(path, handler) {
|
|
23
|
-
this.addRoute("GET", path, handler);
|
|
24
|
-
}
|
|
25
|
-
post(path, handler) {
|
|
26
|
-
this.addRoute("POST", path, handler);
|
|
27
|
-
}
|
|
28
|
-
put(path, handler) {
|
|
29
|
-
this.addRoute("PUT", path, handler);
|
|
30
|
-
}
|
|
31
|
-
patch(path, handler) {
|
|
32
|
-
this.addRoute("PATCH", path, handler);
|
|
33
|
-
}
|
|
34
|
-
delete(path, handler) {
|
|
35
|
-
this.addRoute("DELETE", path, handler);
|
|
36
|
-
}
|
|
37
|
-
listen(port, callback) {
|
|
38
|
-
const server = (0, http_1.createServer)((req, res) => {
|
|
39
|
-
const method = req.method;
|
|
40
|
-
const parsedUrl = (0, url_1.parse)(req.url || "", true);
|
|
41
|
-
const pathname = parsedUrl.pathname || "/";
|
|
42
|
-
const route = this.routes[method].find((r) => r.path === pathname);
|
|
43
|
-
const extendedReq = req;
|
|
44
|
-
const extendedRes = res;
|
|
45
|
-
extendedReq.query = parsedUrl.query;
|
|
46
|
-
extendedReq.getBody = async () => {
|
|
47
|
-
if (extendedReq.body)
|
|
48
|
-
return extendedReq.body;
|
|
49
|
-
const chunks = [];
|
|
50
|
-
for await (const chunk of extendedReq) {
|
|
51
|
-
chunks.push(chunk);
|
|
52
|
-
}
|
|
53
|
-
const raw = Buffer.concat(chunks).toString();
|
|
54
|
-
extendedReq.bodyRaw = raw;
|
|
55
|
-
try {
|
|
56
|
-
extendedReq.body = JSON.parse(raw);
|
|
57
|
-
}
|
|
58
|
-
catch {
|
|
59
|
-
extendedReq.body = {};
|
|
60
|
-
}
|
|
61
|
-
return extendedReq.body;
|
|
62
|
-
};
|
|
63
|
-
extendedRes.status = function (code) {
|
|
64
|
-
extendedRes.statusCode = code;
|
|
65
|
-
return extendedRes;
|
|
66
|
-
};
|
|
67
|
-
extendedRes.json = function (data) {
|
|
68
|
-
extendedRes.setHeader("Content-Type", "application/json");
|
|
69
|
-
extendedRes.end(JSON.stringify(data));
|
|
70
|
-
};
|
|
71
|
-
let i = 0;
|
|
72
|
-
const next = () => {
|
|
73
|
-
const middleware = this.middlewares[i++];
|
|
74
|
-
if (middleware) {
|
|
75
|
-
middleware(extendedReq, extendedRes, next);
|
|
76
|
-
}
|
|
77
|
-
else if (route) {
|
|
78
|
-
route.handler(extendedReq, extendedRes);
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
extendedRes.status(404).end("Not Found");
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
next();
|
|
85
|
-
});
|
|
86
|
-
server.listen(port, callback);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
exports.default = ExpressPlus;
|
package/src/test.js
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
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
|
-
const index_1 = __importDefault(require("./index"));
|
|
7
|
-
const utils_1 = require("@gieo/utils");
|
|
8
|
-
const app = new index_1.default();
|
|
9
|
-
app.post("/calc", async (req, res) => {
|
|
10
|
-
const { op, ...numbers } = await req.getBody();
|
|
11
|
-
// Lấy tất cả giá trị số từ body
|
|
12
|
-
const values = Object.values(numbers)
|
|
13
|
-
.map(Number)
|
|
14
|
-
.filter((v) => !isNaN(v));
|
|
15
|
-
if (values.length < 2) {
|
|
16
|
-
return res.status(400).json({
|
|
17
|
-
statusCode: 400,
|
|
18
|
-
success: false,
|
|
19
|
-
message: "Need at least two numeric values",
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
let result;
|
|
23
|
-
try {
|
|
24
|
-
switch (op) {
|
|
25
|
-
case "sum":
|
|
26
|
-
result = (0, utils_1.sum)(...values);
|
|
27
|
-
break;
|
|
28
|
-
case "sub":
|
|
29
|
-
result = (0, utils_1.sub)(...values);
|
|
30
|
-
break;
|
|
31
|
-
case "mul":
|
|
32
|
-
result = (0, utils_1.mul)(...values);
|
|
33
|
-
break;
|
|
34
|
-
case "div":
|
|
35
|
-
result = (0, utils_1.div)(...values);
|
|
36
|
-
break;
|
|
37
|
-
default:
|
|
38
|
-
return res.status(400).json({
|
|
39
|
-
statusCode: 400,
|
|
40
|
-
success: false,
|
|
41
|
-
message: "Invalid operator",
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
return res.status(200).json({
|
|
45
|
-
statusCode: 200,
|
|
46
|
-
success: true,
|
|
47
|
-
result,
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
catch (err) {
|
|
51
|
-
return res.status(500).json({
|
|
52
|
-
statusCode: 500,
|
|
53
|
-
success: false,
|
|
54
|
-
message: err.message,
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
// Các route cơ bản
|
|
59
|
-
app.get("/", (req, res) => res.status(200).json({ success: true, status: 200, result: "GET / OK" }));
|
|
60
|
-
app.put("/", (req, res) => res.status(200).json({ success: true, status: 200, result: "PUT / OK" }));
|
|
61
|
-
app.post("/", (req, res) => res.status(200).json({ success: true, status: 200, result: "POST / OK" }));
|
|
62
|
-
app.patch("/", (req, res) => res.status(200).json({ success: true, status: 200, result: "PATCH / OK" }));
|
|
63
|
-
app.delete("/", (req, res) => res.status(200).json({ success: true, status: 200, result: "DELETE / OK" }));
|
|
64
|
-
const mathRoute = (op) => async (req, res) => {
|
|
65
|
-
const { a, b } = await req.getBody();
|
|
66
|
-
if (typeof a !== "number" || typeof b !== "number") {
|
|
67
|
-
return res.status(400).json({
|
|
68
|
-
success: false,
|
|
69
|
-
status: 400,
|
|
70
|
-
result: "Invalid input. 'a' and 'b' must be numbers.",
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
try {
|
|
74
|
-
const result = op(a, b);
|
|
75
|
-
res.status(200).json({ success: true, status: 200, result });
|
|
76
|
-
}
|
|
77
|
-
catch (err) {
|
|
78
|
-
res
|
|
79
|
-
.status(500)
|
|
80
|
-
.json({ success: false, status: 500, result: err.message });
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
// Math operations
|
|
84
|
-
app.post("/sum", mathRoute(utils_1.sum));
|
|
85
|
-
app.post("/sub", mathRoute(utils_1.sub));
|
|
86
|
-
app.post("/mul", mathRoute(utils_1.mul));
|
|
87
|
-
app.post("/div", async (req, res) => {
|
|
88
|
-
const { a, b } = await req.getBody();
|
|
89
|
-
if (typeof a !== "number" || typeof b !== "number") {
|
|
90
|
-
return res.status(400).json({
|
|
91
|
-
success: false,
|
|
92
|
-
status: 400,
|
|
93
|
-
result: "Invalid input. 'a' and 'b' must be numbers.",
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
if (b === 0) {
|
|
97
|
-
return res
|
|
98
|
-
.status(400)
|
|
99
|
-
.json({ success: false, status: 400, result: "Cannot divide by zero" });
|
|
100
|
-
}
|
|
101
|
-
const result = (0, utils_1.div)(a, b);
|
|
102
|
-
res.status(200).json({ success: true, status: 200, result });
|
|
103
|
-
});
|
|
104
|
-
app.listen(3000, () => {
|
|
105
|
-
console.log("✅ Server is running at http://localhost:3000");
|
|
106
|
-
});
|