@t3ned/channel
Version:
Ergonomic, chaining-based Typescript framework for quick API development for Fastify
136 lines • 5.46 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ApplicationLoader = void 0;
const utils_1 = require("../../utils");
const errors_1 = require("../errors");
const constants_1 = require("../../constants");
const path_1 = require("path");
const promises_1 = require("fs/promises");
const Route_1 = require("./Route");
class ApplicationLoader {
/**
* @param application The application
*/
constructor(application) {
Object.defineProperty(this, "application", {
enumerable: true,
configurable: true,
writable: true,
value: application
});
}
/**
* Load all the routes
*/
async loadRoutes() {
if (!this.application.routeDirPath)
return;
for await (const path of this._recursiveReaddir(this.application.routeDirPath)) {
const mod = await Promise.resolve().then(() => __importStar(require(path))).catch(() => ({}));
const fileExtension = (0, path_1.extname)(path);
const fileName = (0, path_1.basename)(path, fileExtension);
const sliceLength = fileName.startsWith(this.application.routeFileIgnorePrefix)
? fileName.length + fileExtension.length + 1 // add one to remove trailing slash
: fileExtension.length;
const routePath = path.slice(this.application.routeDirPath.length, -sliceLength);
for (const route of Object.values(mod)) {
if (route instanceof Route_1.Route) {
this._debug(`Loading path ${route.path}`);
route.path = (0, utils_1.joinRoutePaths)(routePath, route.path);
await this.loadRoute(route);
}
}
}
}
/**
* Load a route
* @param route The routes
*/
async loadRoute(route) {
const versionedRoutes = route.toVersionedRoutes(this.application);
for (const route of versionedRoutes) {
this._debug(`Loading route ${route.path}`);
const handler = async (req, reply) => {
const validated = await (0, utils_1.validate)(req, {
params: route.paramsSchema,
query: route.querySchema,
body: route.bodySchema,
});
if (validated.success) {
const parsed = validated.data;
const result = await route.handler({ req, reply, parsed });
if (result)
return reply.status(route.httpStatus).send(result);
return result;
}
return reply
.status(constants_1.HttpStatus.BadRequest)
.send(this.application.validationErrorMapper(validated.error));
};
this.application.instance.route({
method: route.method,
url: (0, utils_1.joinRoutePaths)(this.application.routePathPrefix, route.path),
handler,
onRequest: route.onRequest,
preParsing: route.preParsing,
preValidation: route.preValidation,
preHandler: route.preHandler,
preSerialization: route.preSerialization,
onSend: route.onSend,
onResponse: route.onResponse,
onTimeout: route.onTimeout,
onError: route.onError,
});
}
}
/**
* Recursively read all the file paths in a given path
* @param path The path to read
*
* @returns Path iterator
*/
async *_recursiveReaddir(path) {
const dir = await (0, promises_1.readdir)(path, { withFileTypes: true }).catch((error) => {
throw new errors_1.ChannelError("API route directory error", { cause: error });
});
for (const file of dir) {
if (file.isDirectory())
yield* this._recursiveReaddir(`${path}/${file.name}`);
else
yield `${path}/${file.name}`;
}
}
/**
* Output a debug message
* @param message The message to log
*/
_debug(message) {
if (this.application.debug)
this.application.logger.debug(message);
}
}
exports.ApplicationLoader = ApplicationLoader;
//# sourceMappingURL=ApplicationLoader.js.map