lieko-express 1.0.0 → 1.0.2
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/lib/cors.js +0 -1
- package/lib/schema.js +4 -8
- package/lieko-express.js +82 -51
- package/package.json +1 -1
package/lib/cors.js
CHANGED
package/lib/schema.js
CHANGED
|
@@ -371,15 +371,11 @@ function validate(schema) {
|
|
|
371
371
|
try {
|
|
372
372
|
schema.validate(req.body);
|
|
373
373
|
next();
|
|
374
|
-
} catch (
|
|
375
|
-
if (
|
|
376
|
-
return res.status(400).json({
|
|
377
|
-
success: false,
|
|
378
|
-
message: 'Validation failed',
|
|
379
|
-
errors: error.errors
|
|
380
|
-
});
|
|
374
|
+
} catch (err) {
|
|
375
|
+
if (err instanceof ValidationError) {
|
|
376
|
+
return res.status(400).json({ error: { status: 400, type: "VALIDATION_ERROR", message: 'Validation failed', details: err.errors } });
|
|
381
377
|
}
|
|
382
|
-
throw
|
|
378
|
+
throw err;
|
|
383
379
|
}
|
|
384
380
|
};
|
|
385
381
|
}
|
package/lieko-express.js
CHANGED
|
@@ -781,7 +781,8 @@ ${cyan} (req, res, next) => {
|
|
|
781
781
|
return res.status(500).json({
|
|
782
782
|
error: {
|
|
783
783
|
message: "Internal Server Error",
|
|
784
|
-
|
|
784
|
+
status: 500,
|
|
785
|
+
type: "InternalServerError"
|
|
785
786
|
}
|
|
786
787
|
});
|
|
787
788
|
}
|
|
@@ -812,7 +813,7 @@ ${cyan} (req, res, next) => {
|
|
|
812
813
|
res.status(500).json({
|
|
813
814
|
error: {
|
|
814
815
|
message: "Internal Server Error",
|
|
815
|
-
|
|
816
|
+
status: 500
|
|
816
817
|
}
|
|
817
818
|
});
|
|
818
819
|
}
|
|
@@ -827,13 +828,12 @@ ${cyan} (req, res, next) => {
|
|
|
827
828
|
return res.status(500).json({
|
|
828
829
|
error: {
|
|
829
830
|
message: "Invalid error format passed to res.error()",
|
|
830
|
-
|
|
831
|
+
status: 500
|
|
831
832
|
}
|
|
832
833
|
});
|
|
833
834
|
}
|
|
834
835
|
|
|
835
836
|
const HTTP_STATUS = {
|
|
836
|
-
// 4xx – CLIENT ERRORS
|
|
837
837
|
INVALID_REQUEST: 400,
|
|
838
838
|
VALIDATION_FAILED: 400,
|
|
839
839
|
NO_TOKEN_PROVIDED: 401,
|
|
@@ -844,18 +844,21 @@ ${cyan} (req, res, next) => {
|
|
|
844
844
|
CONFLICT: 409,
|
|
845
845
|
RECORD_EXISTS: 409,
|
|
846
846
|
TOO_MANY_REQUESTS: 429,
|
|
847
|
-
|
|
848
|
-
// 5xx – SERVER ERRORS
|
|
849
847
|
SERVER_ERROR: 500,
|
|
850
848
|
SERVICE_UNAVAILABLE: 503
|
|
851
849
|
};
|
|
852
850
|
|
|
853
|
-
|
|
851
|
+
let currentStatus = res.statusCode || 200;
|
|
852
|
+
let desiredStatus = errorObj.status || HTTP_STATUS[errorObj.status];
|
|
853
|
+
|
|
854
|
+
const finalStatus = (currentStatus >= 400 && currentStatus < 600)
|
|
855
|
+
? currentStatus
|
|
856
|
+
: (desiredStatus || 500);
|
|
854
857
|
|
|
855
|
-
return res.status(
|
|
858
|
+
return res.status(finalStatus).json({
|
|
856
859
|
error: {
|
|
857
860
|
message: errorObj.message || 'An error occurred',
|
|
858
|
-
|
|
861
|
+
status: errorObj.status || finalStatus,
|
|
859
862
|
...errorObj
|
|
860
863
|
}
|
|
861
864
|
});
|
|
@@ -982,7 +985,7 @@ ${cyan} (req, res, next) => {
|
|
|
982
985
|
return res.status(413).json({
|
|
983
986
|
error: {
|
|
984
987
|
message: 'Payload Too Large',
|
|
985
|
-
|
|
988
|
+
status: 413
|
|
986
989
|
}
|
|
987
990
|
});
|
|
988
991
|
}
|
|
@@ -1032,7 +1035,7 @@ ${cyan} (req, res, next) => {
|
|
|
1032
1035
|
|
|
1033
1036
|
if (!route) {
|
|
1034
1037
|
if (this.notFoundHandler) return this.notFoundHandler(req, res);
|
|
1035
|
-
return res.status(404).
|
|
1038
|
+
return res.status(404).error('Not Found');
|
|
1036
1039
|
}
|
|
1037
1040
|
|
|
1038
1041
|
req.params = route.params;
|
|
@@ -1058,7 +1061,11 @@ ${cyan} (req, res, next) => {
|
|
|
1058
1061
|
|
|
1059
1062
|
if (res.headersSent) return;
|
|
1060
1063
|
|
|
1061
|
-
await route.handler(req, res)
|
|
1064
|
+
await route.handler(req, res, (err) => {
|
|
1065
|
+
if (err) {
|
|
1066
|
+
return this._runErrorHandlers(err, req, res);
|
|
1067
|
+
}
|
|
1068
|
+
});
|
|
1062
1069
|
|
|
1063
1070
|
} catch (error) {
|
|
1064
1071
|
if (!res.headersSent) {
|
|
@@ -1138,16 +1145,21 @@ ${cyan} (req, res, next) => {
|
|
|
1138
1145
|
.map(item => item.type);
|
|
1139
1146
|
};
|
|
1140
1147
|
|
|
1141
|
-
const
|
|
1148
|
+
const acceptedTypes = parseAccept(req.headers['accept']);
|
|
1149
|
+
|
|
1150
|
+
req.accepts = function (types) {
|
|
1151
|
+
if (arguments.length === 0) {
|
|
1152
|
+
return acceptedTypes;
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1142
1155
|
if (!Array.isArray(types)) types = [types];
|
|
1143
|
-
const accepted = parseAccept(req.headers['accept']);
|
|
1144
1156
|
|
|
1145
1157
|
for (const type of types) {
|
|
1146
1158
|
const t = type.toLowerCase();
|
|
1147
1159
|
|
|
1148
|
-
if (
|
|
1160
|
+
if (acceptedTypes.includes(t)) return type;
|
|
1149
1161
|
|
|
1150
|
-
if (
|
|
1162
|
+
if (acceptedTypes.some(a => {
|
|
1151
1163
|
if (a === '*/*') return true;
|
|
1152
1164
|
if (a.endsWith('/*')) {
|
|
1153
1165
|
const prefix = a.slice(0, -1);
|
|
@@ -1162,8 +1174,24 @@ ${cyan} (req, res, next) => {
|
|
|
1162
1174
|
return false;
|
|
1163
1175
|
};
|
|
1164
1176
|
|
|
1165
|
-
req.
|
|
1166
|
-
|
|
1177
|
+
req.responseType = function () {
|
|
1178
|
+
const accepted = this.accepts();
|
|
1179
|
+
|
|
1180
|
+
if (accepted.length > 0) {
|
|
1181
|
+
for (const type of accepted) {
|
|
1182
|
+
if (type === 'text/html') return 'html';
|
|
1183
|
+
if (type === 'application/json') return 'json';
|
|
1184
|
+
if (type === '*/*') break;
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
const ua = (this.headers['user-agent'] || '').toLowerCase();
|
|
1189
|
+
const isApi = ua.includes('curl') ||
|
|
1190
|
+
ua.includes('postman') ||
|
|
1191
|
+
this.xhr ||
|
|
1192
|
+
this.headers['content-type']?.includes('application/json');
|
|
1193
|
+
|
|
1194
|
+
return isApi ? 'json' : 'html';
|
|
1167
1195
|
};
|
|
1168
1196
|
|
|
1169
1197
|
req.acceptsLanguages = function (langs) {
|
|
@@ -1538,6 +1566,7 @@ ${cyan} (req, res, next) => {
|
|
|
1538
1566
|
status = 404;
|
|
1539
1567
|
message = 'File Not Found';
|
|
1540
1568
|
details = `The file "${filePath}" does not exist.\nFull path tried: ${file}`;
|
|
1569
|
+
console.error(details, err);
|
|
1541
1570
|
} else if (err.code === 'FORBIDDEN') {
|
|
1542
1571
|
status = 403;
|
|
1543
1572
|
message = 'Forbidden';
|
|
@@ -1576,11 +1605,9 @@ ${cyan} (req, res, next) => {
|
|
|
1576
1605
|
if (message !== undefined) payload.message = message;
|
|
1577
1606
|
return res.json(payload);
|
|
1578
1607
|
};
|
|
1579
|
-
//res.success = res.ok;
|
|
1580
1608
|
|
|
1581
1609
|
res.created = (data, message = 'Resource created successfully') => {
|
|
1582
|
-
|
|
1583
|
-
return res.status(201).json(payload);
|
|
1610
|
+
return res.status(201).json({ data, message });
|
|
1584
1611
|
};
|
|
1585
1612
|
|
|
1586
1613
|
res.noContent = () => {
|
|
@@ -1859,43 +1886,47 @@ ${cyan} (req, res, next) => {
|
|
|
1859
1886
|
}
|
|
1860
1887
|
|
|
1861
1888
|
printRoutes() {
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1889
|
+
setImmediate(() => {
|
|
1890
|
+
if (this.routes.length === 0) {
|
|
1891
|
+
console.log('\nNo routes registered.\n');
|
|
1892
|
+
return;
|
|
1893
|
+
}
|
|
1866
1894
|
|
|
1867
|
-
|
|
1895
|
+
console.log(`\nRegistered Routes: ${this.routes.length}\n`);
|
|
1868
1896
|
|
|
1869
|
-
|
|
1897
|
+
const grouped = new Map();
|
|
1870
1898
|
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1899
|
+
for (const route of this.routes) {
|
|
1900
|
+
const key = `${route.method}|${route.handler}`;
|
|
1901
|
+
if (!grouped.has(key)) {
|
|
1902
|
+
grouped.set(key, {
|
|
1903
|
+
method: route.method,
|
|
1904
|
+
paths: [],
|
|
1905
|
+
mw: route.middlewares.length
|
|
1906
|
+
});
|
|
1907
|
+
}
|
|
1908
|
+
const entry = grouped.get(key);
|
|
1909
|
+
const p = route.path || '/';
|
|
1910
|
+
if (!entry.paths.includes(p)) {
|
|
1911
|
+
entry.paths.push(p);
|
|
1912
|
+
}
|
|
1884
1913
|
}
|
|
1885
|
-
}
|
|
1886
1914
|
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1915
|
+
const sorted = Array.from(grouped.values()).sort((a, b) => {
|
|
1916
|
+
if (a.method !== b.method) return a.method.localeCompare(b.method);
|
|
1917
|
+
return a.paths[0].localeCompare(b.paths[0]);
|
|
1918
|
+
});
|
|
1891
1919
|
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1920
|
+
for (const r of sorted) {
|
|
1921
|
+
const pathStr = r.paths.length === 1
|
|
1922
|
+
? r.paths[0]
|
|
1923
|
+
: r.paths.join(', ');
|
|
1896
1924
|
|
|
1897
|
-
|
|
1898
|
-
|
|
1925
|
+
console.log(` \x1b[36m${r.method.padEnd(7)}\x1b[0m \x1b[33m${pathStr}\x1b[0m \x1b[90m(mw: ${r.mw})\x1b[0m`);
|
|
1926
|
+
}
|
|
1927
|
+
});
|
|
1928
|
+
|
|
1929
|
+
return this;
|
|
1899
1930
|
}
|
|
1900
1931
|
|
|
1901
1932
|
listen() {
|