legonode 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +107 -0
- package/dist/cli/cli.d.ts +3 -0
- package/dist/cli/cli.d.ts.map +1 -0
- package/dist/cli/cli.js +44 -0
- package/dist/cli/cli.js.map +1 -0
- package/dist/cli/commands/build.d.ts +8 -0
- package/dist/cli/commands/build.d.ts.map +1 -0
- package/dist/cli/commands/build.js +101 -0
- package/dist/cli/commands/build.js.map +1 -0
- package/dist/cli/commands/dev.d.ts +13 -0
- package/dist/cli/commands/dev.d.ts.map +1 -0
- package/dist/cli/commands/dev.js +285 -0
- package/dist/cli/commands/dev.js.map +1 -0
- package/dist/cli/commands/start.d.ts +10 -0
- package/dist/cli/commands/start.d.ts.map +1 -0
- package/dist/cli/commands/start.js +108 -0
- package/dist/cli/commands/start.js.map +1 -0
- package/dist/cli/pluginHooks.d.ts +5 -0
- package/dist/cli/pluginHooks.d.ts.map +1 -0
- package/dist/cli/pluginHooks.js +11 -0
- package/dist/cli/pluginHooks.js.map +1 -0
- package/dist/src/body/parseBody.d.ts +11 -0
- package/dist/src/body/parseBody.d.ts.map +1 -0
- package/dist/src/body/parseBody.js +113 -0
- package/dist/src/body/parseBody.js.map +1 -0
- package/dist/src/config/loadConfig.d.ts +71 -0
- package/dist/src/config/loadConfig.d.ts.map +1 -0
- package/dist/src/config/loadConfig.js +69 -0
- package/dist/src/config/loadConfig.js.map +1 -0
- package/dist/src/core/context.d.ts +139 -0
- package/dist/src/core/context.d.ts.map +1 -0
- package/dist/src/core/context.js +293 -0
- package/dist/src/core/context.js.map +1 -0
- package/dist/src/core/lifecycle.d.ts +3 -0
- package/dist/src/core/lifecycle.d.ts.map +1 -0
- package/dist/src/core/lifecycle.js +14 -0
- package/dist/src/core/lifecycle.js.map +1 -0
- package/dist/src/core/runtime.d.ts +28 -0
- package/dist/src/core/runtime.d.ts.map +1 -0
- package/dist/src/core/runtime.js +104 -0
- package/dist/src/core/runtime.js.map +1 -0
- package/dist/src/cors/cors.d.ts +5 -0
- package/dist/src/cors/cors.d.ts.map +1 -0
- package/dist/src/cors/cors.js +75 -0
- package/dist/src/cors/cors.js.map +1 -0
- package/dist/src/events/eventBus.d.ts +19 -0
- package/dist/src/events/eventBus.d.ts.map +1 -0
- package/dist/src/events/eventBus.js +29 -0
- package/dist/src/events/eventBus.js.map +1 -0
- package/dist/src/events/eventExecutor.d.ts +5 -0
- package/dist/src/events/eventExecutor.d.ts.map +1 -0
- package/dist/src/events/eventExecutor.js +84 -0
- package/dist/src/events/eventExecutor.js.map +1 -0
- package/dist/src/index.d.ts +23 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +13 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/json/fastStringify.d.ts +7 -0
- package/dist/src/json/fastStringify.d.ts.map +1 -0
- package/dist/src/json/fastStringify.js +73 -0
- package/dist/src/json/fastStringify.js.map +1 -0
- package/dist/src/loader/fileScanner.d.ts +18 -0
- package/dist/src/loader/fileScanner.d.ts.map +1 -0
- package/dist/src/loader/fileScanner.js +133 -0
- package/dist/src/loader/fileScanner.js.map +1 -0
- package/dist/src/loader/moduleCache.d.ts +3 -0
- package/dist/src/loader/moduleCache.d.ts.map +1 -0
- package/dist/src/loader/moduleCache.js +19 -0
- package/dist/src/loader/moduleCache.js.map +1 -0
- package/dist/src/loader/moduleLoader.d.ts +2 -0
- package/dist/src/loader/moduleLoader.d.ts.map +1 -0
- package/dist/src/loader/moduleLoader.js +4 -0
- package/dist/src/loader/moduleLoader.js.map +1 -0
- package/dist/src/logger/requestLogger.d.ts +20 -0
- package/dist/src/logger/requestLogger.d.ts.map +1 -0
- package/dist/src/logger/requestLogger.js +63 -0
- package/dist/src/logger/requestLogger.js.map +1 -0
- package/dist/src/middleware/middlewareLoader.d.ts +3 -0
- package/dist/src/middleware/middlewareLoader.d.ts.map +1 -0
- package/dist/src/middleware/middlewareLoader.js +28 -0
- package/dist/src/middleware/middlewareLoader.js.map +1 -0
- package/dist/src/middleware/middlewareResolver.d.ts +13 -0
- package/dist/src/middleware/middlewareResolver.d.ts.map +1 -0
- package/dist/src/middleware/middlewareResolver.js +72 -0
- package/dist/src/middleware/middlewareResolver.js.map +1 -0
- package/dist/src/middleware/middlewareRunner.d.ts +10 -0
- package/dist/src/middleware/middlewareRunner.d.ts.map +1 -0
- package/dist/src/middleware/middlewareRunner.js +27 -0
- package/dist/src/middleware/middlewareRunner.js.map +1 -0
- package/dist/src/middleware/middlewareTable.d.ts +6 -0
- package/dist/src/middleware/middlewareTable.d.ts.map +1 -0
- package/dist/src/middleware/middlewareTable.js +44 -0
- package/dist/src/middleware/middlewareTable.js.map +1 -0
- package/dist/src/pipeline/compose.d.ts +10 -0
- package/dist/src/pipeline/compose.d.ts.map +1 -0
- package/dist/src/pipeline/compose.js +35 -0
- package/dist/src/pipeline/compose.js.map +1 -0
- package/dist/src/pipeline/pipelineCache.d.ts +16 -0
- package/dist/src/pipeline/pipelineCache.d.ts.map +1 -0
- package/dist/src/pipeline/pipelineCache.js +73 -0
- package/dist/src/pipeline/pipelineCache.js.map +1 -0
- package/dist/src/plugin/pluginAPI.d.ts +63 -0
- package/dist/src/plugin/pluginAPI.d.ts.map +1 -0
- package/dist/src/plugin/pluginAPI.js +2 -0
- package/dist/src/plugin/pluginAPI.js.map +1 -0
- package/dist/src/plugin/pluginManager.d.ts +6 -0
- package/dist/src/plugin/pluginManager.d.ts.map +1 -0
- package/dist/src/plugin/pluginManager.js +16 -0
- package/dist/src/plugin/pluginManager.js.map +1 -0
- package/dist/src/router/matcher.d.ts +10 -0
- package/dist/src/router/matcher.d.ts.map +1 -0
- package/dist/src/router/matcher.js +69 -0
- package/dist/src/router/matcher.js.map +1 -0
- package/dist/src/router/radixTree.d.ts +24 -0
- package/dist/src/router/radixTree.d.ts.map +1 -0
- package/dist/src/router/radixTree.js +208 -0
- package/dist/src/router/radixTree.js.map +1 -0
- package/dist/src/router/routeLoader.d.ts +22 -0
- package/dist/src/router/routeLoader.d.ts.map +1 -0
- package/dist/src/router/routeLoader.js +94 -0
- package/dist/src/router/routeLoader.js.map +1 -0
- package/dist/src/router/routeTable.d.ts +25 -0
- package/dist/src/router/routeTable.d.ts.map +1 -0
- package/dist/src/router/routeTable.js +133 -0
- package/dist/src/router/routeTable.js.map +1 -0
- package/dist/src/router/router.d.ts +18 -0
- package/dist/src/router/router.d.ts.map +1 -0
- package/dist/src/router/router.js +158 -0
- package/dist/src/router/router.js.map +1 -0
- package/dist/src/schedules/parseSchedule.d.ts +15 -0
- package/dist/src/schedules/parseSchedule.d.ts.map +1 -0
- package/dist/src/schedules/parseSchedule.js +111 -0
- package/dist/src/schedules/parseSchedule.js.map +1 -0
- package/dist/src/schedules/runScheduler.d.ts +14 -0
- package/dist/src/schedules/runScheduler.d.ts.map +1 -0
- package/dist/src/schedules/runScheduler.js +58 -0
- package/dist/src/schedules/runScheduler.js.map +1 -0
- package/dist/src/schedules/scheduleLoader.d.ts +14 -0
- package/dist/src/schedules/scheduleLoader.d.ts.map +1 -0
- package/dist/src/schedules/scheduleLoader.js +122 -0
- package/dist/src/schedules/scheduleLoader.js.map +1 -0
- package/dist/src/schedules/types.d.ts +37 -0
- package/dist/src/schedules/types.d.ts.map +1 -0
- package/dist/src/schedules/types.js +2 -0
- package/dist/src/schedules/types.js.map +1 -0
- package/dist/src/server/errorHandler.d.ts +4 -0
- package/dist/src/server/errorHandler.d.ts.map +1 -0
- package/dist/src/server/errorHandler.js +10 -0
- package/dist/src/server/errorHandler.js.map +1 -0
- package/dist/src/server/requestHandler.d.ts +35 -0
- package/dist/src/server/requestHandler.d.ts.map +1 -0
- package/dist/src/server/requestHandler.js +439 -0
- package/dist/src/server/requestHandler.js.map +1 -0
- package/dist/src/server/server.d.ts +20 -0
- package/dist/src/server/server.d.ts.map +1 -0
- package/dist/src/server/server.js +74 -0
- package/dist/src/server/server.js.map +1 -0
- package/dist/src/tasks/scheduler.d.ts +10 -0
- package/dist/src/tasks/scheduler.d.ts.map +1 -0
- package/dist/src/tasks/scheduler.js +10 -0
- package/dist/src/tasks/scheduler.js.map +1 -0
- package/dist/src/tasks/taskRunner.d.ts +3 -0
- package/dist/src/tasks/taskRunner.d.ts.map +1 -0
- package/dist/src/tasks/taskRunner.js +4 -0
- package/dist/src/tasks/taskRunner.js.map +1 -0
- package/dist/src/trace/traceEngine.d.ts +45 -0
- package/dist/src/trace/traceEngine.d.ts.map +1 -0
- package/dist/src/trace/traceEngine.js +63 -0
- package/dist/src/trace/traceEngine.js.map +1 -0
- package/dist/src/trace/traceStore.d.ts +10 -0
- package/dist/src/trace/traceStore.d.ts.map +1 -0
- package/dist/src/trace/traceStore.js +10 -0
- package/dist/src/trace/traceStore.js.map +1 -0
- package/dist/src/utils/logger.d.ts +6 -0
- package/dist/src/utils/logger.d.ts.map +1 -0
- package/dist/src/utils/logger.js +21 -0
- package/dist/src/utils/logger.js.map +1 -0
- package/dist/src/utils/path.d.ts +2 -0
- package/dist/src/utils/path.d.ts.map +1 -0
- package/dist/src/utils/path.js +4 -0
- package/dist/src/utils/path.js.map +1 -0
- package/dist/src/validation/routeSchema.d.ts +77 -0
- package/dist/src/validation/routeSchema.d.ts.map +1 -0
- package/dist/src/validation/routeSchema.js +134 -0
- package/dist/src/validation/routeSchema.js.map +1 -0
- package/dist/src/validation/validateApp.d.ts +20 -0
- package/dist/src/validation/validateApp.d.ts.map +1 -0
- package/dist/src/validation/validateApp.js +23 -0
- package/dist/src/validation/validateApp.js.map +1 -0
- package/dist/src/validation/validateBody.d.ts +7 -0
- package/dist/src/validation/validateBody.d.ts.map +1 -0
- package/dist/src/validation/validateBody.js +8 -0
- package/dist/src/validation/validateBody.js.map +1 -0
- package/package.json +31 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { readdirSync } from "node:fs";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
import { pathToFileURL } from "node:url";
|
|
4
|
+
import { invalidateModuleCache } from "../loader/moduleCache.js";
|
|
5
|
+
import { createEventBus } from "./eventBus.js";
|
|
6
|
+
const eventBusCache = new Map();
|
|
7
|
+
export async function getOrCreateEventBus(appDir) {
|
|
8
|
+
const key = resolve(appDir);
|
|
9
|
+
let bus = eventBusCache.get(key);
|
|
10
|
+
if (bus)
|
|
11
|
+
return bus;
|
|
12
|
+
bus = createEventBus();
|
|
13
|
+
await registerEventHandlersFromApp(bus, appDir);
|
|
14
|
+
eventBusCache.set(key, bus);
|
|
15
|
+
return bus;
|
|
16
|
+
}
|
|
17
|
+
export function clearEventBusCache(appDir) {
|
|
18
|
+
if (appDir)
|
|
19
|
+
eventBusCache.delete(resolve(appDir));
|
|
20
|
+
else
|
|
21
|
+
eventBusCache.clear();
|
|
22
|
+
}
|
|
23
|
+
const EVENT_EXTENSIONS = [".event.ts", ".event.js", ".event.mts", ".event.mjs"];
|
|
24
|
+
const EVENTS_DIR = "events";
|
|
25
|
+
/** Convert filename (e.g. userCreated) to event name (e.g. user.created) */
|
|
26
|
+
function eventNameFromFile(baseName) {
|
|
27
|
+
if (!baseName.length)
|
|
28
|
+
return "";
|
|
29
|
+
const parts = [];
|
|
30
|
+
let current = baseName[0].toLowerCase();
|
|
31
|
+
for (let i = 1; i < baseName.length; i++) {
|
|
32
|
+
const c = baseName[i];
|
|
33
|
+
if (c >= "A" && c <= "Z") {
|
|
34
|
+
parts.push(current);
|
|
35
|
+
current = c.toLowerCase();
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
current += c;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
parts.push(current);
|
|
42
|
+
return parts.join(".");
|
|
43
|
+
}
|
|
44
|
+
export async function registerEventHandlersFromApp(bus, appDir) {
|
|
45
|
+
const eventsDir = resolve(appDir, EVENTS_DIR);
|
|
46
|
+
let entries;
|
|
47
|
+
try {
|
|
48
|
+
entries = readdirSync(eventsDir, { withFileTypes: true }).map((e) => ({
|
|
49
|
+
name: e.name,
|
|
50
|
+
isFile: e.isFile()
|
|
51
|
+
}));
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
for (const entry of entries) {
|
|
57
|
+
if (!entry.isFile)
|
|
58
|
+
continue;
|
|
59
|
+
const ext = EVENT_EXTENSIONS.find((e) => entry.name.endsWith(e));
|
|
60
|
+
if (!ext)
|
|
61
|
+
continue;
|
|
62
|
+
const baseName = entry.name.slice(0, -ext.length);
|
|
63
|
+
const eventName = eventNameFromFile(baseName);
|
|
64
|
+
if (!eventName)
|
|
65
|
+
continue;
|
|
66
|
+
const filePath = join(eventsDir, entry.name);
|
|
67
|
+
try {
|
|
68
|
+
const bust = process.env.LEGONODE_EVENT_RELOAD_TOKEN;
|
|
69
|
+
if (bust)
|
|
70
|
+
invalidateModuleCache(filePath);
|
|
71
|
+
const url = pathToFileURL(filePath).href;
|
|
72
|
+
const importUrl = bust ? `${url}?t=${bust}` : url;
|
|
73
|
+
const mod = await import(importUrl);
|
|
74
|
+
const handler = mod.default;
|
|
75
|
+
if (typeof handler !== "function")
|
|
76
|
+
continue;
|
|
77
|
+
bus.on(eventName, handler);
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// skip invalid or failing modules
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=eventExecutor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eventExecutor.js","sourceRoot":"","sources":["../../../src/events/eventExecutor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export type { LegonodeContext, LegonodeResponse, ResStatusChain, ResStatusChainTyped, LegonodeResponseTyped, ResponseBodyByStatus, ContextWithResponses, Response, Context, TraceRef } from "./core/context.js";
|
|
2
|
+
export type { Next, Middleware } from "./middleware/middlewareRunner.js";
|
|
3
|
+
export { NextError } from "./middleware/middlewareRunner.js";
|
|
4
|
+
export type { CorsConfig, ErrorHandler, LegonodeConfig } from "./config/loadConfig.js";
|
|
5
|
+
export type { LegonodePlugin } from "./plugin/pluginAPI.js";
|
|
6
|
+
export { createContext } from "./core/context.js";
|
|
7
|
+
export { handleNodeRequest, warmRuntime } from "./server/requestHandler.js";
|
|
8
|
+
export { createNodeServer } from "./server/server.js";
|
|
9
|
+
export { validateBody } from "./validation/validateBody.js";
|
|
10
|
+
export type { RouteSchema, SimpleType, SimpleSchemaShape, SchemaPart, ResponseSchemaMap, ResponseValidationResult, InferResponseBodies } from "./validation/routeSchema.js";
|
|
11
|
+
export { z, mergeRouteSchema, validateRoute, validateResponseBody, ValidationError } from "./validation/routeSchema.js";
|
|
12
|
+
export { getCorsHeaders } from "./cors/cors.js";
|
|
13
|
+
export { getOrCreateEventBus, clearEventBusCache, registerEventHandlersFromApp } from "./events/eventExecutor.js";
|
|
14
|
+
export type { EventContext, EventHandler, EventEmitterFn } from "./events/eventBus.js";
|
|
15
|
+
export type { LegonodeLogger } from "./logger/requestLogger.js";
|
|
16
|
+
export { getBaseLogger, setBaseLogger, createRequestLogger, createPrettyLogger, getNoopLogger } from "./logger/requestLogger.js";
|
|
17
|
+
export type { TraceData, TraceStartData, TracerFn, TraceStartFn, TraceSpan } from "./trace/traceEngine.js";
|
|
18
|
+
export { createTraceSpan } from "./trace/traceEngine.js";
|
|
19
|
+
export type { ScheduleDef, Schedule, TaskContext, TaskRunFn, LoadedTask } from "./schedules/types.js";
|
|
20
|
+
export type { ScheduleRunnerFn } from "./schedules/scheduleLoader.js";
|
|
21
|
+
export { loadSchedulesFromApp, scanScheduleFiles, loadScheduleModule, createScheduleRunner, getOrCreateScheduleRunner, clearScheduleRunnerCache } from "./schedules/scheduleLoader.js";
|
|
22
|
+
export { runScheduler } from "./schedules/runScheduler.js";
|
|
23
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,mBAAmB,EACnB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,QAAQ,EACR,OAAO,EACP,QAAQ,EACT,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAC7D,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACvF,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC5E,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,iBAAiB,EAAE,UAAU,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAC5K,OAAO,EAAE,CAAC,EAAE,gBAAgB,EAAE,aAAa,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AACxH,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,4BAA4B,EAC7B,MAAM,2BAA2B,CAAC;AACnC,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACvF,YAAY,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AACjI,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAC3G,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACtG,YAAY,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,yBAAyB,EACzB,wBAAwB,EACzB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { NextError } from "./middleware/middlewareRunner.js";
|
|
2
|
+
export { createContext } from "./core/context.js";
|
|
3
|
+
export { handleNodeRequest, warmRuntime } from "./server/requestHandler.js";
|
|
4
|
+
export { createNodeServer } from "./server/server.js";
|
|
5
|
+
export { validateBody } from "./validation/validateBody.js";
|
|
6
|
+
export { z, mergeRouteSchema, validateRoute, validateResponseBody, ValidationError } from "./validation/routeSchema.js";
|
|
7
|
+
export { getCorsHeaders } from "./cors/cors.js";
|
|
8
|
+
export { getOrCreateEventBus, clearEventBusCache, registerEventHandlersFromApp } from "./events/eventExecutor.js";
|
|
9
|
+
export { getBaseLogger, setBaseLogger, createRequestLogger, createPrettyLogger, getNoopLogger } from "./logger/requestLogger.js";
|
|
10
|
+
export { createTraceSpan } from "./trace/traceEngine.js";
|
|
11
|
+
export { loadSchedulesFromApp, scanScheduleFiles, loadScheduleModule, createScheduleRunner, getOrCreateScheduleRunner, clearScheduleRunnerCache } from "./schedules/scheduleLoader.js";
|
|
12
|
+
export { runScheduler } from "./schedules/runScheduler.js";
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAG7D,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC5E,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAE5D,OAAO,EAAE,CAAC,EAAE,gBAAgB,EAAE,aAAa,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AACxH,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,4BAA4B,EAC7B,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAEjI,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,yBAAyB,EACzB,wBAAwB,EACzB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ResponseSchemaMap } from "../validation/routeSchema.js";
|
|
2
|
+
/**
|
|
3
|
+
* Returns a fast serializer for the given status when the response schema is a SimpleSchemaShape.
|
|
4
|
+
* Returns null when no schema or Zod schema (fall back to JSON.stringify).
|
|
5
|
+
*/
|
|
6
|
+
export declare function getStringifier(responseSchema: ResponseSchemaMap | undefined, status: number): ((data: unknown) => string) | null;
|
|
7
|
+
//# sourceMappingURL=fastStringify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fastStringify.d.ts","sourceRoot":"","sources":["../../../src/json/fastStringify.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AA0EtE;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,cAAc,EAAE,iBAAiB,GAAG,SAAS,EAC7C,MAAM,EAAE,MAAM,GACb,CAAC,CAAC,IAAI,EAAE,OAAO,KAAK,MAAM,CAAC,GAAG,IAAI,CAKpC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import fastJsonStringify from "fast-json-stringify";
|
|
2
|
+
function isZodType(v) {
|
|
3
|
+
return (v != null &&
|
|
4
|
+
typeof v === "object" &&
|
|
5
|
+
"safeParse" in v &&
|
|
6
|
+
typeof v.safeParse === "function");
|
|
7
|
+
}
|
|
8
|
+
function isSimpleSchemaShape(part) {
|
|
9
|
+
return typeof part === "object" && part !== null && !isZodType(part);
|
|
10
|
+
}
|
|
11
|
+
function simpleTypeToJsonSchema(value) {
|
|
12
|
+
const optional = value.endsWith("?");
|
|
13
|
+
const type = (optional ? value.slice(0, -1) : value);
|
|
14
|
+
const schema = type === "object" || type === "array" ? { type: type } : { type };
|
|
15
|
+
return { schema, optional };
|
|
16
|
+
}
|
|
17
|
+
function simpleShapeToJsonSchema(shape) {
|
|
18
|
+
const properties = {};
|
|
19
|
+
const required = [];
|
|
20
|
+
for (const [key, value] of Object.entries(shape)) {
|
|
21
|
+
if (typeof value === "string") {
|
|
22
|
+
const { schema, optional } = simpleTypeToJsonSchema(value);
|
|
23
|
+
properties[key] = schema;
|
|
24
|
+
if (!optional)
|
|
25
|
+
required.push(key);
|
|
26
|
+
}
|
|
27
|
+
else if (typeof value === "object" && value !== null && !isZodType(value)) {
|
|
28
|
+
properties[key] = simpleShapeToJsonSchema(value);
|
|
29
|
+
required.push(key);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const out = {
|
|
33
|
+
type: "object",
|
|
34
|
+
additionalProperties: false
|
|
35
|
+
};
|
|
36
|
+
if (Object.keys(properties).length > 0)
|
|
37
|
+
out.properties = properties;
|
|
38
|
+
if (required.length > 0)
|
|
39
|
+
out.required = required;
|
|
40
|
+
return out;
|
|
41
|
+
}
|
|
42
|
+
const serializerCache = new Map();
|
|
43
|
+
function cacheKey(schema) {
|
|
44
|
+
return JSON.stringify(schema);
|
|
45
|
+
}
|
|
46
|
+
function getCachedSerializer(jsonSchema) {
|
|
47
|
+
const key = cacheKey(jsonSchema);
|
|
48
|
+
let fn = serializerCache.get(key);
|
|
49
|
+
if (!fn) {
|
|
50
|
+
try {
|
|
51
|
+
const stringify = fastJsonStringify(jsonSchema);
|
|
52
|
+
fn = (data) => stringify(data);
|
|
53
|
+
serializerCache.set(key, fn);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
fn = (data) => JSON.stringify(data);
|
|
57
|
+
serializerCache.set(key, fn);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return fn;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Returns a fast serializer for the given status when the response schema is a SimpleSchemaShape.
|
|
64
|
+
* Returns null when no schema or Zod schema (fall back to JSON.stringify).
|
|
65
|
+
*/
|
|
66
|
+
export function getStringifier(responseSchema, status) {
|
|
67
|
+
const part = responseSchema?.[status];
|
|
68
|
+
if (part == null || !isSimpleSchemaShape(part))
|
|
69
|
+
return null;
|
|
70
|
+
const jsonSchema = simpleShapeToJsonSchema(part);
|
|
71
|
+
return getCachedSerializer(jsonSchema);
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=fastStringify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fastStringify.js","sourceRoot":"","sources":["../../../src/json/fastStringify.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type ScannedRoute = {
|
|
2
|
+
pathname: string;
|
|
3
|
+
filePath: string;
|
|
4
|
+
/** Set for method-specific files (get.ts, get.route.ts, post.ts, etc.). Empty for route.ts (handles all methods). */
|
|
5
|
+
method?: string;
|
|
6
|
+
};
|
|
7
|
+
export type ScannedMiddleware = {
|
|
8
|
+
pathPrefix: string;
|
|
9
|
+
filePath: string;
|
|
10
|
+
};
|
|
11
|
+
export declare function scanAppFiles(appDir: string): ScannedRoute[];
|
|
12
|
+
/**
|
|
13
|
+
* Scan only the given directory for route files (no nested subdirs).
|
|
14
|
+
* pathname is computed relative to appDir so it matches the route path.
|
|
15
|
+
*/
|
|
16
|
+
export declare function scanRouteFilesInDir(appDir: string, dir: string): ScannedRoute[];
|
|
17
|
+
export declare function scanMiddlewareFiles(appDir: string): ScannedMiddleware[];
|
|
18
|
+
//# sourceMappingURL=fileScanner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fileScanner.d.ts","sourceRoot":"","sources":["../../../src/loader/fileScanner.ts"],"names":[],"mappings":"AAkBA,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,qHAAqH;IACrH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAUF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,EAAE,CAsC3D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,YAAY,EAAE,CA+B/E;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAkCvE"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { readdirSync } from "node:fs";
|
|
2
|
+
import { join, relative, resolve } from "node:path";
|
|
3
|
+
const ROUTE_FILES = ["route.ts", "route.js", "route.mts", "route.mjs"];
|
|
4
|
+
const METHOD_FILE_NAMES = ["get", "post", "put", "patch", "delete", "head", "options"];
|
|
5
|
+
const METHOD_EXTENSIONS = [".ts", ".js", ".mts", ".mjs"];
|
|
6
|
+
const METHOD_FILES = new Set();
|
|
7
|
+
const METHOD_ROUTE_FILES = new Set(); // get.route.ts, post.route.js, etc.
|
|
8
|
+
for (const name of METHOD_FILE_NAMES) {
|
|
9
|
+
for (const ext of METHOD_EXTENSIONS) {
|
|
10
|
+
METHOD_FILES.add(name + ext);
|
|
11
|
+
METHOD_ROUTE_FILES.add(name + ".route" + ext);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
const MIDDLEWARE_FILES = ["middleware.ts", "middleware.js", "middleware.mts", "middleware.mjs"];
|
|
15
|
+
function methodFromFilename(name) {
|
|
16
|
+
for (const m of METHOD_FILE_NAMES) {
|
|
17
|
+
if (METHOD_FILES.has(name) && name.startsWith(m))
|
|
18
|
+
return m.toUpperCase();
|
|
19
|
+
if (METHOD_ROUTE_FILES.has(name) && name.startsWith(m + ".route"))
|
|
20
|
+
return m.toUpperCase();
|
|
21
|
+
}
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
export function scanAppFiles(appDir) {
|
|
25
|
+
const base = resolve(appDir);
|
|
26
|
+
const routes = [];
|
|
27
|
+
function walk(dir, segments) {
|
|
28
|
+
let entries;
|
|
29
|
+
try {
|
|
30
|
+
entries = readdirSync(dir, { withFileTypes: true }).map((e) => ({
|
|
31
|
+
name: e.name,
|
|
32
|
+
isFile: e.isFile()
|
|
33
|
+
}));
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
for (const entry of entries) {
|
|
39
|
+
const fullPath = join(dir, entry.name);
|
|
40
|
+
const seg = [...segments, entry.name];
|
|
41
|
+
if (entry.isFile) {
|
|
42
|
+
if (ROUTE_FILES.includes(entry.name)) {
|
|
43
|
+
const pathname = "/" + segments.join("/");
|
|
44
|
+
const formattedPathname = pathname.replace(/\/\([^/]+\)/g, "");
|
|
45
|
+
routes.push({ pathname: formattedPathname, filePath: fullPath });
|
|
46
|
+
}
|
|
47
|
+
else if (METHOD_FILES.has(entry.name) || METHOD_ROUTE_FILES.has(entry.name)) {
|
|
48
|
+
const pathname = "/" + segments.join("/");
|
|
49
|
+
const formattedPathname = pathname.replace(/\/\([^/]+\)/g, "");
|
|
50
|
+
const method = methodFromFilename(entry.name);
|
|
51
|
+
if (method)
|
|
52
|
+
routes.push({ pathname: formattedPathname, filePath: fullPath, method });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
walk(fullPath, seg);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
walk(base, []);
|
|
61
|
+
return routes;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Scan only the given directory for route files (no nested subdirs).
|
|
65
|
+
* pathname is computed relative to appDir so it matches the route path.
|
|
66
|
+
*/
|
|
67
|
+
export function scanRouteFilesInDir(appDir, dir) {
|
|
68
|
+
const base = resolve(appDir);
|
|
69
|
+
const targetDir = resolve(dir);
|
|
70
|
+
const routes = [];
|
|
71
|
+
const pathPrefix = "/" + relative(base, targetDir).replace(/\\/g, "/").replace(/^\.\/?/, "").replace(/\/$/, "") || "";
|
|
72
|
+
let entries;
|
|
73
|
+
try {
|
|
74
|
+
entries = readdirSync(targetDir, { withFileTypes: true }).map((e) => ({
|
|
75
|
+
name: e.name,
|
|
76
|
+
isFile: e.isFile()
|
|
77
|
+
}));
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return routes;
|
|
81
|
+
}
|
|
82
|
+
for (const entry of entries) {
|
|
83
|
+
if (!entry.isFile)
|
|
84
|
+
continue;
|
|
85
|
+
const fullPath = join(targetDir, entry.name);
|
|
86
|
+
if (ROUTE_FILES.includes(entry.name)) {
|
|
87
|
+
const pathname = pathPrefix || "/";
|
|
88
|
+
routes.push({ pathname, filePath: fullPath });
|
|
89
|
+
}
|
|
90
|
+
else if (METHOD_FILES.has(entry.name) || METHOD_ROUTE_FILES.has(entry.name)) {
|
|
91
|
+
const method = methodFromFilename(entry.name);
|
|
92
|
+
if (method) {
|
|
93
|
+
const pathname = pathPrefix || "/";
|
|
94
|
+
routes.push({ pathname, filePath: fullPath, method });
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return routes;
|
|
99
|
+
}
|
|
100
|
+
export function scanMiddlewareFiles(appDir) {
|
|
101
|
+
// Middleware is colocated under the router tree only.
|
|
102
|
+
// This keeps scanning consistent with route file discovery (`{appDir}/router/**`).
|
|
103
|
+
const base = resolve(appDir, "router");
|
|
104
|
+
const list = [];
|
|
105
|
+
function walk(dir, segments) {
|
|
106
|
+
let entries;
|
|
107
|
+
try {
|
|
108
|
+
entries = readdirSync(dir, { withFileTypes: true }).map((e) => ({
|
|
109
|
+
name: e.name,
|
|
110
|
+
isFile: e.isFile()
|
|
111
|
+
}));
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
for (const entry of entries) {
|
|
117
|
+
const fullPath = join(dir, entry.name);
|
|
118
|
+
const seg = [...segments, entry.name];
|
|
119
|
+
if (entry.isFile) {
|
|
120
|
+
if (MIDDLEWARE_FILES.includes(entry.name)) {
|
|
121
|
+
const pathPrefix = segments.join("/");
|
|
122
|
+
list.push({ pathPrefix, filePath: fullPath });
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
walk(fullPath, seg);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
walk(base, []);
|
|
131
|
+
return list;
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=fileScanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fileScanner.js","sourceRoot":"","sources":["../../../src/loader/fileScanner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"moduleCache.d.ts","sourceRoot":"","sources":["../../../src/loader/moduleCache.ts"],"names":[],"mappings":"AAMA,qGAAqG;AACrG,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAS5D"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { pathToFileURL } from "node:url";
|
|
4
|
+
const _require = createRequire(import.meta.url);
|
|
5
|
+
/** Invalidate Node/Bun module cache for a file so the next import() loads fresh (dev hot reload). */
|
|
6
|
+
export function invalidateModuleCache(filePath) {
|
|
7
|
+
if (!_require.cache)
|
|
8
|
+
return;
|
|
9
|
+
const url = pathToFileURL(filePath).href;
|
|
10
|
+
const resolved = resolve(filePath);
|
|
11
|
+
const keys = new Set([url, resolved]);
|
|
12
|
+
for (const key of Object.keys(_require.cache)) {
|
|
13
|
+
if (key === resolved || key.endsWith(filePath) || key.endsWith(resolved))
|
|
14
|
+
keys.add(key);
|
|
15
|
+
}
|
|
16
|
+
for (const k of keys)
|
|
17
|
+
delete _require.cache[k];
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=moduleCache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"moduleCache.js","sourceRoot":"","sources":["../../../src/loader/moduleCache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEhD,qGAAqG;AACrG,MAAM,UAAU,qBAAqB,CAAC,QAAgB;IACpD,IAAI,CAAC,QAAQ,CAAC,KAAK;QAAE,OAAO;IAC5B,MAAM,GAAG,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC;IACzC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAS,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC9C,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9C,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC1F,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,IAAI;QAAE,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACjD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"moduleLoader.d.ts","sourceRoot":"","sources":["../../../src/loader/moduleLoader.ts"],"names":[],"mappings":"AAAA,wBAAsB,YAAY,CAAC,CAAC,GAAG,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAE7E"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"moduleLoader.js","sourceRoot":"","sources":["../../../src/loader/moduleLoader.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,KAAK,UAAU,YAAY,CAAc,SAAiB;IAC/D,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;AACnD,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type Logger } from "pino";
|
|
2
|
+
/** Request-scoped logger with traceId in bindings. Use ctx.logger in handlers; tracing is automatic. */
|
|
3
|
+
export type LegonodeLogger = Logger;
|
|
4
|
+
export type RequestLogLevel = "trace" | "debug" | "info" | "warn" | "error" | "fatal";
|
|
5
|
+
export type RequestLogEntry = {
|
|
6
|
+
level: RequestLogLevel;
|
|
7
|
+
args: unknown[];
|
|
8
|
+
timestamp: string;
|
|
9
|
+
};
|
|
10
|
+
/** Base logger used to create request-scoped children. Override via setBaseLogger. */
|
|
11
|
+
export declare function getBaseLogger(): Logger;
|
|
12
|
+
/** Create a pino logger with pino-pretty for human-readable dev output (e.g. when dev.logPretty is true). */
|
|
13
|
+
export declare function createPrettyLogger(): Logger;
|
|
14
|
+
/** Set a custom base logger (e.g. from legonode.config). Request loggers will be children of this. */
|
|
15
|
+
export declare function setBaseLogger(logger: Logger): void;
|
|
16
|
+
/** Create a request-scoped logger with traceId so all logs correlate with the same request/trace. */
|
|
17
|
+
export declare function createRequestLogger(traceId: string, base?: Logger, sink?: RequestLogEntry[]): LegonodeLogger;
|
|
18
|
+
/** No-op logger for context placeholder before runtime assigns request logger. */
|
|
19
|
+
export declare function getNoopLogger(): LegonodeLogger;
|
|
20
|
+
//# sourceMappingURL=requestLogger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requestLogger.d.ts","sourceRoot":"","sources":["../../../src/logger/requestLogger.ts"],"names":[],"mappings":"AAAA,OAAa,EAAE,KAAK,MAAM,EAAE,MAAM,MAAM,CAAC;AAGzC,wGAAwG;AACxG,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC;AACpC,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AACtF,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,eAAe,CAAC;IACvB,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAMF,sFAAsF;AACtF,wBAAgB,aAAa,IAAI,MAAM,CAOtC;AAED,6GAA6G;AAC7G,wBAAgB,kBAAkB,IAAI,MAAM,CAS3C;AAED,sGAAsG;AACtG,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAElD;AAED,qGAAqG;AACrG,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,eAAe,EAAE,GAAG,cAAc,CAK5G;AAED,kFAAkF;AAClF,wBAAgB,aAAa,IAAI,cAAc,CAE9C"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import pino, {} from "pino";
|
|
2
|
+
import pinoPretty from "pino-pretty";
|
|
3
|
+
const LOG_LEVEL_METHODS = new Set(["trace", "debug", "info", "warn", "error", "fatal"]);
|
|
4
|
+
let defaultLogger = null;
|
|
5
|
+
/** Base logger used to create request-scoped children. Override via setBaseLogger. */
|
|
6
|
+
export function getBaseLogger() {
|
|
7
|
+
if (!defaultLogger) {
|
|
8
|
+
defaultLogger = pino({
|
|
9
|
+
level: process.env.LOG_LEVEL ?? "info"
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
return defaultLogger;
|
|
13
|
+
}
|
|
14
|
+
/** Create a pino logger with pino-pretty for human-readable dev output (e.g. when dev.logPretty is true). */
|
|
15
|
+
export function createPrettyLogger() {
|
|
16
|
+
const stream = pinoPretty({
|
|
17
|
+
colorize: true,
|
|
18
|
+
translateTime: "SYS:HH:MM:ss"
|
|
19
|
+
});
|
|
20
|
+
return pino({ level: process.env.LOG_LEVEL ?? "info" }, stream);
|
|
21
|
+
}
|
|
22
|
+
/** Set a custom base logger (e.g. from legonode.config). Request loggers will be children of this. */
|
|
23
|
+
export function setBaseLogger(logger) {
|
|
24
|
+
defaultLogger = logger;
|
|
25
|
+
}
|
|
26
|
+
/** Create a request-scoped logger with traceId so all logs correlate with the same request/trace. */
|
|
27
|
+
export function createRequestLogger(traceId, base, sink) {
|
|
28
|
+
const baseLogger = base ?? getBaseLogger();
|
|
29
|
+
const requestLogger = baseLogger.child(traceId ? { traceId } : {});
|
|
30
|
+
if (!sink)
|
|
31
|
+
return requestLogger;
|
|
32
|
+
return wrapLoggerWithSink(requestLogger, sink);
|
|
33
|
+
}
|
|
34
|
+
/** No-op logger for context placeholder before runtime assigns request logger. */
|
|
35
|
+
export function getNoopLogger() {
|
|
36
|
+
return pino({ level: "silent" });
|
|
37
|
+
}
|
|
38
|
+
function wrapLoggerWithSink(logger, sink) {
|
|
39
|
+
return new Proxy(logger, {
|
|
40
|
+
get(target, prop, receiver) {
|
|
41
|
+
const raw = Reflect.get(target, prop, receiver);
|
|
42
|
+
if (typeof prop === "string" && LOG_LEVEL_METHODS.has(prop) && typeof raw === "function") {
|
|
43
|
+
const level = prop;
|
|
44
|
+
return (...args) => {
|
|
45
|
+
sink.push({
|
|
46
|
+
level,
|
|
47
|
+
args,
|
|
48
|
+
timestamp: new Date().toISOString()
|
|
49
|
+
});
|
|
50
|
+
return raw.apply(target, args);
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
if (prop === "child" && typeof raw === "function") {
|
|
54
|
+
return (...args) => {
|
|
55
|
+
const child = raw.apply(target, args);
|
|
56
|
+
return wrapLoggerWithSink(child, sink);
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
return raw;
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=requestLogger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requestLogger.js","sourceRoot":"","sources":["../../../src/logger/requestLogger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middlewareLoader.d.ts","sourceRoot":"","sources":["../../../src/middleware/middlewareLoader.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AASxD,wBAAsB,sBAAsB,CAC1C,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,UAAU,EAAE,CAAC,CAgBvB"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { pathToFileURL } from "node:url";
|
|
2
|
+
import { invalidateModuleCache } from "../loader/moduleCache.js";
|
|
3
|
+
const METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
|
|
4
|
+
function toMiddlewareArray(raw) {
|
|
5
|
+
if (!Array.isArray(raw))
|
|
6
|
+
return [];
|
|
7
|
+
return raw.filter((fn) => typeof fn === "function");
|
|
8
|
+
}
|
|
9
|
+
export async function loadMiddlewareFromFile(filePath, method) {
|
|
10
|
+
try {
|
|
11
|
+
const bust = process.env.LEGONODE_MIDDLEWARE_RELOAD_TOKEN;
|
|
12
|
+
if (bust)
|
|
13
|
+
invalidateModuleCache(filePath);
|
|
14
|
+
const url = pathToFileURL(filePath).href;
|
|
15
|
+
const importUrl = bust ? `${url}?t=${bust}` : url;
|
|
16
|
+
const mod = await import(importUrl);
|
|
17
|
+
const all = toMiddlewareArray(mod.default);
|
|
18
|
+
const methodKey = `${method}_middleware`;
|
|
19
|
+
if (METHODS.includes(method) && mod[methodKey] != null) {
|
|
20
|
+
all.push(...toMiddlewareArray(mod[methodKey]));
|
|
21
|
+
}
|
|
22
|
+
return all;
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=middlewareLoader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middlewareLoader.js","sourceRoot":"","sources":["../../../src/middleware/middlewareLoader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAGjE,MAAM,OAAO,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;AAE7E,SAAS,iBAAiB,CAAC,GAAY;IACrC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IACnC,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,EAAW,EAAoB,EAAE,CAAC,OAAO,EAAE,KAAK,UAAU,CAAC,CAAC;AACjF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,QAAgB,EAChB,MAAc;IAEd,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC;QAC1D,IAAI,IAAI;YAAE,qBAAqB,CAAC,QAAQ,CAAC,CAAC;QAC1C,MAAM,GAAG,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC;QACzC,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;QAClD,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;QACpC,MAAM,GAAG,GAAG,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC3C,MAAM,SAAS,GAAG,GAAG,MAAM,aAAa,CAAC;QACzC,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI,EAAE,CAAC;YACvD,GAAG,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QACjD,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Middleware } from "./middlewareRunner.js";
|
|
2
|
+
export type MiddlewareResolver = {
|
|
3
|
+
resolveForPathname: (pathname: string, method: string) => Middleware[] | Promise<Middleware[]>;
|
|
4
|
+
};
|
|
5
|
+
export declare function createMiddlewareResolver(appDir: string): MiddlewareResolver;
|
|
6
|
+
export declare function clearMiddlewareResolverCache(appDir?: string): void;
|
|
7
|
+
export declare function getOrCreateMiddlewareResolver(appDir: string): MiddlewareResolver;
|
|
8
|
+
/** Pathname + method pairs to preload (e.g. from route table). */
|
|
9
|
+
export declare function preloadMiddleware(appDir: string, pathnameMethodPairs: Array<{
|
|
10
|
+
pathname: string;
|
|
11
|
+
method: string;
|
|
12
|
+
}>): Promise<void>;
|
|
13
|
+
//# sourceMappingURL=middlewareResolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middlewareResolver.d.ts","sourceRoot":"","sources":["../../../src/middleware/middlewareResolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAgBxD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,kBAAkB,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,UAAU,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;CAChG,CAAC;AAEF,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,kBAAkB,CA0B3E;AAID,wBAAgB,4BAA4B,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAWlE;AAED,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,MAAM,GAAG,kBAAkB,CAOhF;AAED,kEAAkE;AAClE,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,mBAAmB,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,GAC/D,OAAO,CAAC,IAAI,CAAC,CAOf"}
|