feature: execute load()/unload() methods found in _pre.ts files

This commit is contained in:
Andy Burke 2025-08-11 17:12:55 -07:00
parent df8291bfc7
commit 046617bc4f
7 changed files with 116 additions and 62 deletions

View file

@ -34,8 +34,7 @@ type ROUTE_HANDLER_RECORD = {
module?: ROUTE_HANDLER;
};
const routes: ROUTE_HANDLER_RECORD[] = [];
let loading: boolean = false;
let all_routes_loaded: boolean = false;
const unloaders: (() => Promise<void> | void)[] = [];
/**
* Handles requests for which there are typescript files in the root tree.
@ -48,57 +47,6 @@ let all_routes_loaded: boolean = false;
* @returns Either a response (a handler for the request path and method was found) or undefined if unhandled.
*/
export default async function handle_typescript(request: Request): Promise<Response | undefined> {
if (!all_routes_loaded) {
if (!loading) {
loading = true;
const root_directory = path.resolve(Deno.cwd());
const imports: ROUTE_HANDLER_RECORD[] = [];
for await (
const entry of walk(root_directory, {
exts: ['.ts'],
skip: [/\.test\.ts$/]
})
) {
if (entry.isFile) {
const relative_path = entry.path.substring(root_directory.length);
const route_path = relative_path
.replace(/\.ts$/, '')
//.replace(/\[(\w+)\]/g, ':$1')
.replace(/\/index$/, '')
.replace(/___/g, ':') || // required for windows, uncivilized OS that it is
'/';
const route_pattern = new URLPattern({ pathname: route_path });
const import_path = new URL('file://' + entry.path, import.meta.url).toString();
imports.push({
route_path,
route_pattern,
import_path
});
}
}
// try to sort imports such that they're registered like:
// /permissions/test
// /api/echo/hi
// /api/echo/:input
//
// we want paths with parameters to sort later than paths without
routes.push(...imports.sort((lhs, rhs) => rhs.route_path.localeCompare(lhs.route_path)));
all_routes_loaded = true;
loading = false;
}
do {
await delay(10);
} while (!all_routes_loaded);
}
for (const route_record of routes) {
const match = route_record.route_pattern.exec(request.url.replace(/\/$/, ''));
if (match) {
@ -142,8 +90,64 @@ export default async function handle_typescript(request: Request): Promise<Respo
}
}
export function unload(): void {
loading = false;
routes.splice(0, routes.length);
all_routes_loaded = false;
export async function load(): Promise<void> {
const root_directory = path.resolve(Deno.cwd());
const imports: ROUTE_HANDLER_RECORD[] = [];
for await (
const entry of walk(root_directory, {
exts: ['.ts'],
skip: [/\.test\.ts$/]
})
) {
if (entry.isFile) {
const import_path = new URL('file://' + entry.path, import.meta.url).toString();
const filename = path.basename(entry.path);
if (filename === '_pre.ts') {
const preloader = await import(import_path);
if (typeof preloader.load === 'function') {
await preloader.load();
}
if (typeof preloader.unload === 'function') {
unloaders.push(preloader.unload);
}
continue;
}
const relative_path = entry.path.substring(root_directory.length);
const route_path = relative_path
.replace(/\.ts$/, '')
//.replace(/\[(\w+)\]/g, ':$1')
.replace(/\/index$/, '')
.replace(/___/g, ':') || // required for windows, uncivilized OS that it is
'/';
const route_pattern = new URLPattern({ pathname: route_path });
imports.push({
route_path,
route_pattern,
import_path
});
}
}
// try to sort imports such that they're registered like:
// /permissions/test
// /api/echo/hi
// /api/echo/:input
//
// we want paths with parameters to sort later than paths without
routes.push(...imports.sort((lhs, rhs) => rhs.route_path.localeCompare(lhs.route_path)));
}
export async function unload(): Promise<void> {
for (const unloader of unloaders) {
await unloader();
}
routes.splice(0, routes.length);
unloaders.splice(0, unloaders.length);
}