@mridang/nestjs-auth
Version:
A comprehensive Auth.js integration for NestJS applications with TypeScript support, framework-agnostic HTTP adapters, and role-based access control
108 lines • 3.62 kB
JavaScript
import qs from 'qs';
import { Readable } from 'node:stream';
/**
* Converts a framework-specific request (Fastify or Express) into a
* standard Web API `Request` object…
*/
export function toWebRequest(request, adapter) {
const protocol = adapter.getProtocol(request);
const host = adapter.getHost(request);
const url = `${protocol}://${host}${adapter.getUrl(request)}`;
const headers = new Headers();
const rawHeaders = adapter.getHeaders(request);
Object.entries(rawHeaders).forEach(([key, value]) => {
if (Array.isArray(value)) {
value.forEach((v) => v && headers.append(key, v));
}
else if (value) {
headers.append(key, value);
}
});
const method = adapter.getMethod(request);
const contentType = headers.get('content-type');
let body;
if (!/GET|HEAD/.test(method.toUpperCase())) {
const rawBody = adapter.getBody(request);
if (rawBody !== undefined && rawBody !== null) {
if (contentType?.includes('application/x-www-form-urlencoded')) {
body = qs.stringify(rawBody, {
arrayFormat: 'repeat'
});
}
else if (contentType?.includes('application/json')) {
body = JSON.stringify(rawBody);
}
else if (typeof rawBody === 'string') {
body = rawBody;
}
else if (Buffer.isBuffer(rawBody)) {
body = rawBody;
}
else if (typeof rawBody === 'object') {
// Fallback for object bodies without a proper content-type.
body = qs.stringify(rawBody, {
arrayFormat: 'repeat'
});
}
}
}
return new Request(url, {
method,
headers,
body
});
}
/**
* Maps a standard Web API `Response` object to a framework-specific response…
*/
export async function toHttpResponse(webResponse, res, adapter) {
// Build headers without using Headers.entries() to avoid dom.iterable dependency issues.
const groupedHeaders = {};
webResponse.headers.forEach((value, key) => {
const lowerKey = key.toLowerCase();
if (lowerKey === 'set-cookie') {
const existing = groupedHeaders[lowerKey];
if (Array.isArray(existing)) {
existing.push(value);
}
else if (existing) {
groupedHeaders[lowerKey] = [existing, value];
}
else {
groupedHeaders[lowerKey] = [value];
}
}
else {
groupedHeaders[key] = value;
}
});
Object.entries(groupedHeaders).forEach(([key, value]) => {
adapter.setHeader(res, key, value);
});
adapter.setStatus(res, webResponse.status);
const body = webResponse.body;
if (body) {
const reader = body.getReader();
const nodeStream = Readable.from((async function* () {
try {
while (true) {
const { done, value } = await reader.read();
if (done)
break;
if (value) {
yield Buffer.from(value);
}
}
}
finally {
reader.releaseLock();
}
})());
adapter.send(res, nodeStream);
}
else {
const text = await webResponse.text();
adapter.send(res, text);
}
}
//# sourceMappingURL=http-adapters.js.map