Skip to content

Commit 525765e

Browse files
committed
fix express middlewares on middlewares of palmares
1 parent d35da30 commit 525765e

File tree

4 files changed

+74
-63
lines changed

4 files changed

+74
-63
lines changed

docs/examples/mainpage/src/favoritetools/express.ts

Lines changed: 19 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,44 +4,27 @@ import { path, Response, middleware } from '@palmares/server';
44
import { User } from './database';
55
import { userSchema } from './schemas';
66

7-
const companyMiddleware = middleware({
8-
request: async (request) => {
9-
return request.clone({
10-
context: {
11-
company: {
12-
id: 1
13-
}
14-
}
15-
});
16-
}
7+
// You already know how to create express middlewares, so just use it.
8+
const expressMiddleware = (req, res, next) => {
9+
req.user = 'admin';
10+
next();
11+
};
12+
13+
// You can assign the middleware as customOption
14+
// Remember, this middleware is for express
15+
const adminOnlyMiddleware = middleware({
16+
customOptions: [expressMiddleware()]
1717
});
1818

1919
export const usersRoute = path('/users')
20-
.middlewares([companyMiddleware])
20+
.middlewares([adminOnlyMiddleware])
2121
.get(async (request) => {
22-
const users = await User.default.get((qs) =>
23-
qs.where({
24-
companyId: request.context.company.id
25-
})
26-
);
27-
return Response.json({ users });
28-
})
29-
.post(async (request) => {
30-
const validationResp = await userSchema.validate((await request.json()) as any, {});
31-
if (!validationResp.isValid) {
32-
return Response.json(
33-
{
34-
success: false,
35-
errors: validationResp.errors
36-
},
37-
{ status: 400 }
38-
);
22+
// You can access the request data from Express.js from the request object
23+
const { req, res } = request.serverData();
24+
if (req.user !== 'admin') {
25+
return Response.json({ message: 'You are not admin' }, { status: 403 });
3926
}
40-
return Response.json({ success: true, data: await validationResp.save() });
41-
})
42-
.nested((path) => [
43-
path('/<id: number>').get(async (request) => {
44-
const user = await User.default.get((qs) => qs.where({ id: request.params.id }));
45-
return Response.json({ user: user[0] });
46-
})
47-
]);
27+
28+
// You can respond with the `res` object from Express.js
29+
return res.json({ message: 'You are admin' });
30+
});

packages/server/__tests__/src/core/index.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@ const __dirname = dirname(__filename);
1010

1111
const testMiddleware = middleware({
1212
options: {
13-
customOptions: [cors()]
13+
customOptions: [
14+
(req, res, next) => {
15+
req.params.test2 = 'test';
16+
next();
17+
}
18+
]
1419
}
1520
});
1621
const route = path('/test')
@@ -21,7 +26,12 @@ const route = path('/test')
2126
return Response.json({ message: 'hello' }, { status: 200 });
2227
},
2328
{
24-
customOptions: [cors()]
29+
customOptions: [
30+
(req, res, next) => {
31+
req.params.test = 'test';
32+
next();
33+
}
34+
]
2535
}
2636
);
2737

packages/server/src/app/utils.ts

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { Response } from '../response';
1919
import { HTTP_404_NOT_FOUND, HTTP_500_INTERNAL_SERVER_ERROR, isRedirect } from '../response/status';
2020
import { AsyncGeneratorFunction, GeneratorFunction } from '../response/utils';
2121
import { path } from '../router';
22+
import { mergeDeep } from '../utils/merge-deep';
2223
import { setServerAdapterInstance } from '../utils/store-server';
2324

2425
import type { ServerAdapter } from '../adapters';
@@ -377,30 +378,6 @@ function translatePathFactory(serverAdapter: ServerAdapter | ServerlessAdapter,
377378
};
378379
}
379380

380-
function mergeDeep(...objects: any[]) {
381-
const isObject = (obj: any) => obj && typeof obj === 'object';
382-
return objects.reduce(
383-
(prev, obj) => {
384-
const keys = Array.isArray(obj) ? Array.from({ length: obj.length }).map((_, index) => index) : Object.keys(obj);
385-
keys.forEach((key) => {
386-
const keyAsNumber = Number(key);
387-
const actualKeyValue = isNaN(keyAsNumber) === false ? Number(key) : key;
388-
const pVal = prev[actualKeyValue];
389-
const oVal = obj[actualKeyValue];
390-
if (Array.isArray(pVal) && Array.isArray(oVal)) {
391-
prev[actualKeyValue] = pVal.concat(...oVal);
392-
} else if (isObject(pVal) && isObject(oVal)) {
393-
prev[actualKeyValue] = mergeDeep(pVal, oVal);
394-
} else {
395-
prev[actualKeyValue] = oVal;
396-
}
397-
});
398-
return prev;
399-
},
400-
Array.isArray(objects[0]) ? [] : {}
401-
);
402-
}
403-
404381
function mergeCustomOptionsFromMiddlewaresAndHandlers(middlewares: Middleware[], options: RouterOptionsType) {
405382
const originalCustomOptions = options.customOptions;
406383
// eslint-disable-next-line ts/no-unnecessary-condition
@@ -410,6 +387,7 @@ function mergeCustomOptionsFromMiddlewaresAndHandlers(middlewares: Middleware[],
410387
if (middleware.options?.customOptions) {
411388
// eslint-disable-next-line ts/no-unnecessary-condition
412389
if (options.customOptions)
390+
// eslint-disable-next-line ts/no-unnecessary-condition
413391
options.customOptions = mergeDeep(options.customOptions, middleware.options.customOptions);
414392
else options.customOptions = middleware.options.customOptions;
415393
}
@@ -445,7 +423,6 @@ function wrapHandlerAndMiddlewares(
445423
validation?: AllServerSettingsType['servers'][string]['validation']
446424
) {
447425
if (options === undefined) options = {};
448-
console.log(options);
449426
if (server.$$type === '$PServerAdapter') mergeCustomOptionsFromMiddlewaresAndHandlers(middlewares, options);
450427
const wrappedHandler = async (serverRequestAndResponseData: any) => {
451428
const startTime = new Date().getTime();
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
export function mergeDeep<TData extends any[]>(...objects: TData): TData[number] {
2+
const isObject = (object: any) => object && typeof object === 'object' && !Array.isArray(object);
3+
4+
if (objects.length < 1) return {};
5+
if (objects.length === 1) return objects[0];
6+
7+
const firstNonNullObj = objects.find((object) => object != null);
8+
const resultIsArray = Array.isArray(firstNonNullObj);
9+
10+
const result = resultIsArray ? ([] as any) : ({} as any);
11+
12+
for (const currentObject of objects) {
13+
if (currentObject == null) continue; // Skip null/undefined objects
14+
15+
if (Array.isArray(currentObject)) {
16+
if (resultIsArray) {
17+
currentObject.forEach((item) => result.push(item));
18+
} else {
19+
currentObject.forEach((item, index) => {
20+
const existingValueAtIndex = result[index];
21+
const isDeepMergeNeeded = isObject(item) && isObject(existingValueAtIndex);
22+
23+
if (isDeepMergeNeeded) result[index] = mergeDeep(existingValueAtIndex, item);
24+
else result[index] = item;
25+
});
26+
}
27+
} else if (isObject(currentObject)) {
28+
Object.keys(currentObject).forEach((key) => {
29+
const existingValue = result[key];
30+
const newValue = currentObject[key];
31+
const areBothObjects = isObject(existingValue) && isObject(newValue);
32+
const areBothArrays = Array.isArray(existingValue) && Array.isArray(newValue);
33+
34+
if (areBothObjects || areBothArrays) result[key] = mergeDeep(existingValue, newValue);
35+
else result[key] = newValue;
36+
});
37+
}
38+
}
39+
40+
return result;
41+
}

0 commit comments

Comments
 (0)