All files / src/functions add.fastify.routes.ts

100% Statements 43/43
100% Branches 11/11
100% Functions 11/11
100% Lines 36/36

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 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    2x 2x 2x             2x 2x 2x       2x       11x 11x   11x 11x 15x             15x 15x     11x 11x 14x 14x     11x 10x   10x 10x   10x 10x   10x   10x 2x 4x     8x         11x 10x 10x       11x 1x 1x         2x  
'use strict';
 
import * as fs from 'node:fs';
import * as path from 'node:path';
import {hrtime} from 'node:process';
import {IncomingMessage, Server, ServerResponse} from 'node:http';
 
import {FastifyInstance} from 'fastify';
 
import type {ItemStat} from '@owservable/folders';
 
import addRoute from './add.route';
import cleanRelativePath from './clean.relative.path';
import getMillisecondsFrom from './performance/get.milliseconds.from';
 
let routesRootFolder: string;
 
const addFastifyRoutes = async (
	fastify: FastifyInstance<Server<typeof IncomingMessage, typeof ServerResponse>, IncomingMessage, ServerResponse<IncomingMessage>>,
	folder: string,
	verbose: boolean = false
): Promise<void> => {
	if (!routesRootFolder) routesRootFolder = folder;
 
	const fileNames: string[] = await fs.promises.readdir(folder);
	const stats: ItemStat[] = await Promise.all(
		fileNames.map(async (name): Promise<ItemStat> => ({
			name,
			fullPath: path.join(folder, name),
			isDirectory: (await fs.promises.lstat(path.join(folder, name))).isDirectory()
		}))
	);
 
	const files: ItemStat[] = stats.filter((stat: ItemStat): boolean => !stat.isDirectory);
	const folders: ItemStat[] = stats.filter((stat: ItemStat): boolean => stat.isDirectory);
 
	// Process files in parallel batches for better performance
	const BATCH_SIZE = 10; // Process up to 10 files concurrently
	const validFiles: ItemStat[] = files.filter((file: ItemStat): boolean => {
		const ext: string = path.extname(file.name);
		return ext === '.ts' || ext === '.js';
	});
 
	const processFile = async (file: ItemStat): Promise<void> => {
		const start: number = Number(hrtime.bigint());
 
		const ext: string = path.extname(file.name);
		const relativeFilePath: string = cleanRelativePath(routesRootFolder, file.fullPath, ext as '.ts' | '.js');
 
		const routeModule: {default?: unknown} = require(file.fullPath) as {default?: unknown};
		const routes: unknown = routeModule.default || routeModule;
 
		if (verbose) console.log('[@owservable/fastify-auto-routes] -> addFastifyRoutes: loaded file', `[${getMillisecondsFrom(start).toFixed(3)}ms]${folder}/${file.name}`);
 
		if (Array.isArray(routes)) {
			for (const route of routes) {
				addRoute(fastify, route, relativeFilePath, verbose);
			}
		} else {
			addRoute(fastify, routes, relativeFilePath, verbose);
		}
	};
 
	// Process files in parallel batches
	for (let i = 0; i < validFiles.length; i += BATCH_SIZE) {
		const batch: ItemStat[] = validFiles.slice(i, i + BATCH_SIZE);
		await Promise.all(batch.map(processFile));
	}
 
	// Process subdirectories in parallel for better performance
	await Promise.all(
		folders.map(async (sub: ItemStat): Promise<void> => {
			await addFastifyRoutes(fastify, sub.fullPath, verbose);
		})
	);
};
 
export default addFastifyRoutes;