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,72 @@
|
|
|
1
|
+
import { getMiddlewarePathsForPathname } from "./middlewareTable.js";
|
|
2
|
+
import { loadMiddlewareFromFile } from "./middlewareLoader.js";
|
|
3
|
+
const middlewareCache = new Map();
|
|
4
|
+
function middlewareCacheKey(appDir, pathname, method) {
|
|
5
|
+
return `${appDir}\0${pathname}\0${method}`;
|
|
6
|
+
}
|
|
7
|
+
function isPromise(v) {
|
|
8
|
+
return typeof v?.then === "function";
|
|
9
|
+
}
|
|
10
|
+
export function createMiddlewareResolver(appDir) {
|
|
11
|
+
return {
|
|
12
|
+
resolveForPathname(pathname, method) {
|
|
13
|
+
const key = middlewareCacheKey(appDir, pathname, method);
|
|
14
|
+
const cached = middlewareCache.get(key);
|
|
15
|
+
if (cached !== undefined && !isPromise(cached))
|
|
16
|
+
return cached;
|
|
17
|
+
let promise;
|
|
18
|
+
if (cached !== undefined && isPromise(cached)) {
|
|
19
|
+
promise = cached;
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
promise = (async () => {
|
|
23
|
+
const paths = getMiddlewarePathsForPathname(pathname, appDir);
|
|
24
|
+
const all = [];
|
|
25
|
+
for (const filePath of paths) {
|
|
26
|
+
const fns = await loadMiddlewareFromFile(filePath, method);
|
|
27
|
+
all.push(...fns);
|
|
28
|
+
}
|
|
29
|
+
return all;
|
|
30
|
+
})();
|
|
31
|
+
middlewareCache.set(key, promise);
|
|
32
|
+
}
|
|
33
|
+
return promise.then((arr) => {
|
|
34
|
+
middlewareCache.set(key, arr);
|
|
35
|
+
return arr;
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
const resolverCache = new Map();
|
|
41
|
+
export function clearMiddlewareResolverCache(appDir) {
|
|
42
|
+
if (appDir !== undefined) {
|
|
43
|
+
resolverCache.delete(appDir);
|
|
44
|
+
const prefix = appDir + "\0";
|
|
45
|
+
for (const key of middlewareCache.keys()) {
|
|
46
|
+
if (key.startsWith(prefix))
|
|
47
|
+
middlewareCache.delete(key);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
resolverCache.clear();
|
|
52
|
+
middlewareCache.clear();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
export function getOrCreateMiddlewareResolver(appDir) {
|
|
56
|
+
let r = resolverCache.get(appDir);
|
|
57
|
+
if (!r) {
|
|
58
|
+
r = createMiddlewareResolver(appDir);
|
|
59
|
+
resolverCache.set(appDir, r);
|
|
60
|
+
}
|
|
61
|
+
return r;
|
|
62
|
+
}
|
|
63
|
+
/** Pathname + method pairs to preload (e.g. from route table). */
|
|
64
|
+
export async function preloadMiddleware(appDir, pathnameMethodPairs) {
|
|
65
|
+
const resolver = getOrCreateMiddlewareResolver(appDir);
|
|
66
|
+
const promises = pathnameMethodPairs.map(({ pathname, method }) => {
|
|
67
|
+
const result = resolver.resolveForPathname(pathname, method);
|
|
68
|
+
return Array.isArray(result) ? Promise.resolve(result) : result;
|
|
69
|
+
});
|
|
70
|
+
await Promise.all(promises);
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=middlewareResolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middlewareResolver.js","sourceRoot":"","sources":["../../../src/middleware/middlewareResolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { LegonodeContext } from "../core/context.js";
|
|
2
|
+
export type Next = (err?: unknown) => Promise<void>;
|
|
3
|
+
export type Middleware = (ctx: LegonodeContext, next: Next) => Promise<void> | void;
|
|
4
|
+
/** Thrown when middleware calls next(err); request handler catches and passes to errorHandler */
|
|
5
|
+
export declare class NextError extends Error {
|
|
6
|
+
readonly error: unknown;
|
|
7
|
+
constructor(error: unknown);
|
|
8
|
+
}
|
|
9
|
+
export declare function runMiddlewareStack(ctx: LegonodeContext, middleware: Middleware[], handler: () => Promise<void>): Promise<void>;
|
|
10
|
+
//# sourceMappingURL=middlewareRunner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middlewareRunner.d.ts","sourceRoot":"","sources":["../../../src/middleware/middlewareRunner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1D,MAAM,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AACpD,MAAM,MAAM,UAAU,GAAG,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAEpF,iGAAiG;AACjG,qBAAa,SAAU,SAAQ,KAAK;aACN,KAAK,EAAE,OAAO;gBAAd,KAAK,EAAE,OAAO;CAI3C;AAED,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,eAAe,EAAE,UAAU,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,iBAepH"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** Thrown when middleware calls next(err); request handler catches and passes to errorHandler */
|
|
2
|
+
export class NextError extends Error {
|
|
3
|
+
error;
|
|
4
|
+
constructor(error) {
|
|
5
|
+
super("next(err) called");
|
|
6
|
+
this.error = error;
|
|
7
|
+
this.name = "NextError";
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export async function runMiddlewareStack(ctx, middleware, handler) {
|
|
11
|
+
let idx = -1;
|
|
12
|
+
async function dispatch(i) {
|
|
13
|
+
if (i <= idx)
|
|
14
|
+
throw new Error("next() called multiple times");
|
|
15
|
+
idx = i;
|
|
16
|
+
const fn = middleware[i];
|
|
17
|
+
if (!fn)
|
|
18
|
+
return handler();
|
|
19
|
+
await fn(ctx, (err) => {
|
|
20
|
+
if (err !== undefined && err !== null)
|
|
21
|
+
throw new NextError(err);
|
|
22
|
+
return dispatch(i + 1);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
await dispatch(0);
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=middlewareRunner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middlewareRunner.js","sourceRoot":"","sources":["../../../src/middleware/middlewareRunner.ts"],"names":[],"mappings":"AAKA,iGAAiG;AACjG,MAAM,OAAO,SAAU,SAAQ,KAAK;IACN;IAA5B,YAA4B,KAAc;QACxC,KAAK,CAAC,kBAAkB,CAAC,CAAC;QADA,UAAK,GAAL,KAAK,CAAS;QAExC,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;IAC1B,CAAC;CACF;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,GAAoB,EAAE,UAAwB,EAAE,OAA4B;IACnH,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC;IAEb,KAAK,UAAU,QAAQ,CAAC,CAAS;QAC/B,IAAI,CAAC,IAAI,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAC9D,GAAG,GAAG,CAAC,CAAC;QACR,MAAM,EAAE,GAA2B,UAAU,CAAC,CAAC,CAAC,CAAC;QACjD,IAAI,CAAC,EAAE;YAAE,OAAO,OAAO,EAAE,CAAC;QAC1B,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAa,EAAE,EAAE;YAC9B,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,IAAI;gBAAE,MAAM,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC;YAChE,OAAO,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,QAAQ,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ScannedMiddleware } from "../loader/fileScanner.js";
|
|
2
|
+
export declare function getMiddlewareTable(appDir: string): ScannedMiddleware[];
|
|
3
|
+
/** Ordered list of middleware file paths for this pathname (ancestor first). Uses exact pathPrefix so group middleware (e.g. api/(user)) only runs for routes inside that group. */
|
|
4
|
+
export declare function getMiddlewarePathsForPathname(pathname: string, appDir: string): string[];
|
|
5
|
+
export declare function clearMiddlewareTableCache(appDir?: string): void;
|
|
6
|
+
//# sourceMappingURL=middlewareTable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middlewareTable.d.ts","sourceRoot":"","sources":["../../../src/middleware/middlewareTable.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAKlE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAOtE;AAgBD,oLAAoL;AACpL,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAUxF;AAED,wBAAgB,yBAAyB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAG/D"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { scanMiddlewareFiles } from "../loader/fileScanner.js";
|
|
2
|
+
const cache = new Map();
|
|
3
|
+
export function getMiddlewareTable(appDir) {
|
|
4
|
+
let table = cache.get(appDir);
|
|
5
|
+
if (!table) {
|
|
6
|
+
table = scanMiddlewareFiles(appDir);
|
|
7
|
+
cache.set(appDir, table);
|
|
8
|
+
}
|
|
9
|
+
return table;
|
|
10
|
+
}
|
|
11
|
+
/** Pathname e.g. /api/hello -> path prefixes ["", "api", "api/hello"] */
|
|
12
|
+
function pathnameToPrefixes(pathname) {
|
|
13
|
+
const normalized = pathname.startsWith("/") ? pathname.slice(1) : pathname;
|
|
14
|
+
if (!normalized)
|
|
15
|
+
return [""];
|
|
16
|
+
const segments = normalized.split("/").filter(Boolean);
|
|
17
|
+
const prefixes = [""];
|
|
18
|
+
let acc = "";
|
|
19
|
+
for (const s of segments) {
|
|
20
|
+
acc = acc ? `${acc}/${s}` : s;
|
|
21
|
+
prefixes.push(acc);
|
|
22
|
+
}
|
|
23
|
+
return prefixes;
|
|
24
|
+
}
|
|
25
|
+
/** Ordered list of middleware file paths for this pathname (ancestor first). Uses exact pathPrefix so group middleware (e.g. api/(user)) only runs for routes inside that group. */
|
|
26
|
+
export function getMiddlewarePathsForPathname(pathname, appDir) {
|
|
27
|
+
const table = getMiddlewareTable(appDir);
|
|
28
|
+
const prefixes = pathnameToPrefixes(pathname);
|
|
29
|
+
const paths = [];
|
|
30
|
+
for (const p of prefixes) {
|
|
31
|
+
for (const m of table) {
|
|
32
|
+
if (m.pathPrefix === p)
|
|
33
|
+
paths.push(m.filePath);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return paths;
|
|
37
|
+
}
|
|
38
|
+
export function clearMiddlewareTableCache(appDir) {
|
|
39
|
+
if (appDir)
|
|
40
|
+
cache.delete(appDir);
|
|
41
|
+
else
|
|
42
|
+
cache.clear();
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=middlewareTable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middlewareTable.js","sourceRoot":"","sources":["../../../src/middleware/middlewareTable.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,MAAM,KAAK,GAAG,IAAI,GAAG,EAA+B,CAAC;AAErD,MAAM,UAAU,kBAAkB,CAAC,MAAc;IAC/C,IAAI,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,KAAK,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;QACpC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC3B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,yEAAyE;AACzE,SAAS,kBAAkB,CAAC,QAAgB;IAC1C,MAAM,UAAU,GAAG,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC3E,IAAI,CAAC,UAAU;QAAE,OAAO,CAAC,EAAE,CAAC,CAAC;IAC7B,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACvD,MAAM,QAAQ,GAAa,CAAC,EAAE,CAAC,CAAC;IAChC,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9B,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,oLAAoL;AACpL,MAAM,UAAU,6BAA6B,CAAC,QAAgB,EAAE,MAAc;IAC5E,MAAM,KAAK,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,IAAI,CAAC,CAAC,UAAU,KAAK,CAAC;gBAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,MAAe;IACvD,IAAI,MAAM;QAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;;QAC5B,KAAK,CAAC,KAAK,EAAE,CAAC;AACrB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { LegonodeContext } from "../core/context.js";
|
|
2
|
+
import type { Middleware } from "../middleware/middlewareRunner.js";
|
|
3
|
+
export type PipelineHandler = (ctx: LegonodeContext) => unknown | Promise<unknown>;
|
|
4
|
+
/**
|
|
5
|
+
* Compose middleware + handler into a single pipeline function (no loop at request time).
|
|
6
|
+
* Builds a chain: mw1(ctx, () => mw2(ctx, () => ... () => handler(ctx))).
|
|
7
|
+
* Returns sync when handler (and chain) returns sync to avoid extra microtasks.
|
|
8
|
+
*/
|
|
9
|
+
export declare function compose(middleware: Middleware[], handler: PipelineHandler): (ctx: LegonodeContext) => unknown | Promise<unknown>;
|
|
10
|
+
//# sourceMappingURL=compose.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../../../src/pipeline/compose.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAC;AAEpE,MAAM,MAAM,eAAe,GAAG,CAAC,GAAG,EAAE,eAAe,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAOnF;;;;GAIG;AACH,wBAAgB,OAAO,CACrB,UAAU,EAAE,UAAU,EAAE,EACxB,OAAO,EAAE,eAAe,GACvB,CAAC,GAAG,EAAE,eAAe,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CA0BtD"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/** True if value is thenable (has .then). */
|
|
2
|
+
function isThenable(v) {
|
|
3
|
+
return v != null && typeof v.then === "function";
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Compose middleware + handler into a single pipeline function (no loop at request time).
|
|
7
|
+
* Builds a chain: mw1(ctx, () => mw2(ctx, () => ... () => handler(ctx))).
|
|
8
|
+
* Returns sync when handler (and chain) returns sync to avoid extra microtasks.
|
|
9
|
+
*/
|
|
10
|
+
export function compose(middleware, handler) {
|
|
11
|
+
if (middleware.length === 0) {
|
|
12
|
+
return (ctx) => handler(ctx);
|
|
13
|
+
}
|
|
14
|
+
let fn = (ctx) => handler(ctx);
|
|
15
|
+
for (let i = middleware.length - 1; i >= 0; i--) {
|
|
16
|
+
const mw = middleware[i];
|
|
17
|
+
const next = fn;
|
|
18
|
+
fn = (ctx) => new Promise((resolve, reject) => {
|
|
19
|
+
const nextCb = (err) => {
|
|
20
|
+
if (err !== undefined && err !== null)
|
|
21
|
+
return Promise.reject(err);
|
|
22
|
+
const ret = next(ctx);
|
|
23
|
+
if (isThenable(ret))
|
|
24
|
+
return ret.then(resolve, reject);
|
|
25
|
+
resolve(ret);
|
|
26
|
+
return Promise.resolve();
|
|
27
|
+
};
|
|
28
|
+
const ret = mw(ctx, nextCb);
|
|
29
|
+
if (isThenable(ret))
|
|
30
|
+
ret.then(() => { }, reject);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
return fn;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=compose.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose.js","sourceRoot":"","sources":["../../../src/pipeline/compose.ts"],"names":[],"mappings":"AAKA,6CAA6C;AAC7C,SAAS,UAAU,CAAC,CAAU;IAC5B,OAAO,CAAC,IAAI,IAAI,IAAI,OAAQ,CAAsB,CAAC,IAAI,KAAK,UAAU,CAAC;AACzE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,OAAO,CACrB,UAAwB,EACxB,OAAwB;IAExB,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,GAAoB,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAChD,CAAC;IAED,IAAI,EAAE,GAAyD,CAAC,GAAoB,EAAE,EAAE,CACtF,OAAO,CAAC,GAAG,CAAC,CAAC;IAEf,KAAK,IAAI,CAAC,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAChD,MAAM,EAAE,GAAG,UAAU,CAAC,CAAC,CAAE,CAAC;QAC1B,MAAM,IAAI,GAAG,EAAE,CAAC;QAChB,EAAE,GAAG,CAAC,GAAoB,EAAE,EAAE,CAC5B,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC9B,MAAM,MAAM,GAAG,CAAC,GAAa,EAAiB,EAAE;gBAC9C,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,IAAI;oBAAE,OAAO,OAAO,CAAC,MAAM,CAAC,GAAG,CAAkB,CAAC;gBACnF,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;gBACtB,IAAI,UAAU,CAAC,GAAG,CAAC;oBAAE,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAkB,CAAC;gBACvE,OAAO,CAAC,GAAG,CAAC,CAAC;gBACb,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;YAC3B,CAAC,CAAC;YACF,MAAM,GAAG,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YAC5B,IAAI,UAAU,CAAC,GAAG,CAAC;gBAAG,GAAwB,CAAC,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,EAAE,MAAM,CAAC,CAAC;QACxE,CAAC,CAAC,CAAC;IACP,CAAC;IAED,OAAO,EAAE,CAAC;AACZ,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { LegonodeContext } from "../core/context.js";
|
|
2
|
+
import type { LoadedRoute } from "../router/routeLoader.js";
|
|
3
|
+
import type { Middleware } from "../middleware/middlewareRunner.js";
|
|
4
|
+
export type PipelineEntry = {
|
|
5
|
+
pathname: string;
|
|
6
|
+
method: string;
|
|
7
|
+
route: LoadedRoute;
|
|
8
|
+
middleware: Middleware[];
|
|
9
|
+
};
|
|
10
|
+
/** Returns a compiled pipeline (validation? + middleware + handler). Never throws; rejects on error. */
|
|
11
|
+
export declare function getOrCreatePipeline(appDir: string, pathname: string, method: string, route: LoadedRoute, middleware: Middleware[]): (ctx: LegonodeContext) => unknown | Promise<unknown>;
|
|
12
|
+
/** Preload pipelines for the given entries (call after preloadRoutes + preloadMiddleware). */
|
|
13
|
+
export declare function preloadPipelines(appDir: string, entries: PipelineEntry[]): void;
|
|
14
|
+
export declare function clearPipelineForRoute(appDir: string, pathname: string, method: string): void;
|
|
15
|
+
export declare function clearPipelineCache(appDir: string): void;
|
|
16
|
+
//# sourceMappingURL=pipelineCache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipelineCache.d.ts","sourceRoot":"","sources":["../../../src/pipeline/pipelineCache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAC;AAWpE,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,WAAW,CAAC;IACnB,UAAU,EAAE,UAAU,EAAE,CAAC;CAC1B,CAAC;AAqBF,wGAAwG;AACxG,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,WAAW,EAClB,UAAU,EAAE,UAAU,EAAE,GACvB,CAAC,GAAG,EAAE,eAAe,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAmBtD;AAED,8FAA8F;AAC9F,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,GAAG,IAAI,CAI/E;AAID,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAM5F;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAKvD"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { mergeRouteSchema } from "../validation/routeSchema.js";
|
|
2
|
+
import { validateRoute, ValidationError } from "../validation/routeSchema.js";
|
|
3
|
+
import { compose } from "./compose.js";
|
|
4
|
+
const pipelineCache = new Map();
|
|
5
|
+
function pipelineCacheKey(appDir, pathname, method) {
|
|
6
|
+
return `${appDir}\0${pathname}\0${method}`;
|
|
7
|
+
}
|
|
8
|
+
/** Validation as middleware: throws ValidationError on failure, else assigns and calls next(). */
|
|
9
|
+
function createValidationMiddleware(mergedSchema, method) {
|
|
10
|
+
return (ctx, next) => {
|
|
11
|
+
const v = validateRoute(mergedSchema, method, {
|
|
12
|
+
body: ctx.body,
|
|
13
|
+
params: ctx.params,
|
|
14
|
+
query: ctx.query
|
|
15
|
+
});
|
|
16
|
+
if (!v.ok)
|
|
17
|
+
throw new ValidationError(v.status, v.json);
|
|
18
|
+
if ("body" in v && v.body !== undefined)
|
|
19
|
+
ctx.body = v.body;
|
|
20
|
+
if ("params" in v && v.params !== undefined)
|
|
21
|
+
ctx.params = v.params;
|
|
22
|
+
if ("query" in v && v.query !== undefined)
|
|
23
|
+
ctx.query = v.query;
|
|
24
|
+
return next();
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/** Returns a compiled pipeline (validation? + middleware + handler). Never throws; rejects on error. */
|
|
28
|
+
export function getOrCreatePipeline(appDir, pathname, method, route, middleware) {
|
|
29
|
+
const key = pipelineCacheKey(appDir, pathname, method);
|
|
30
|
+
let fn = pipelineCache.get(key);
|
|
31
|
+
if (fn)
|
|
32
|
+
return fn;
|
|
33
|
+
const mergedSchema = mergeRouteSchema(route.schema, route.methodSchema);
|
|
34
|
+
const hasValidation = !!(mergedSchema.body ?? mergedSchema.params ?? mergedSchema.query);
|
|
35
|
+
const mwList = hasValidation
|
|
36
|
+
? [createValidationMiddleware(mergedSchema, method), ...middleware]
|
|
37
|
+
: middleware.length > 0 ? middleware : [];
|
|
38
|
+
const composed = compose(mwList, (ctx) => route.handler(ctx));
|
|
39
|
+
fn = (ctx) => {
|
|
40
|
+
try {
|
|
41
|
+
return composed(ctx);
|
|
42
|
+
}
|
|
43
|
+
catch (e) {
|
|
44
|
+
return Promise.reject(e);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
pipelineCache.set(key, fn);
|
|
48
|
+
return fn;
|
|
49
|
+
}
|
|
50
|
+
/** Preload pipelines for the given entries (call after preloadRoutes + preloadMiddleware). */
|
|
51
|
+
export function preloadPipelines(appDir, entries) {
|
|
52
|
+
for (const { pathname, method, route, middleware } of entries) {
|
|
53
|
+
getOrCreatePipeline(appDir, pathname, method, route, middleware);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const ALL_HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
|
|
57
|
+
export function clearPipelineForRoute(appDir, pathname, method) {
|
|
58
|
+
if (method === "") {
|
|
59
|
+
for (const m of ALL_HTTP_METHODS)
|
|
60
|
+
pipelineCache.delete(pipelineCacheKey(appDir, pathname, m));
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
pipelineCache.delete(pipelineCacheKey(appDir, pathname, method));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
export function clearPipelineCache(appDir) {
|
|
67
|
+
const prefix = appDir + "\0";
|
|
68
|
+
for (const key of pipelineCache.keys()) {
|
|
69
|
+
if (key.startsWith(prefix))
|
|
70
|
+
pipelineCache.delete(key);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=pipelineCache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipelineCache.js","sourceRoot":"","sources":["../../../src/pipeline/pipelineCache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { LegonodeContext } from "../core/context.js";
|
|
2
|
+
export type LegonodeCommandName = "dev" | "build" | "start";
|
|
3
|
+
export type LegonodeCommandHookContext = {
|
|
4
|
+
command: LegonodeCommandName;
|
|
5
|
+
cwd: string;
|
|
6
|
+
appDir?: string;
|
|
7
|
+
host?: string;
|
|
8
|
+
port?: number;
|
|
9
|
+
buildPath?: string;
|
|
10
|
+
reason?: string;
|
|
11
|
+
filename?: string;
|
|
12
|
+
changedPath?: string;
|
|
13
|
+
fileExists?: boolean;
|
|
14
|
+
fileType?: "route" | "middleware" | "cron" | "event" | "other";
|
|
15
|
+
name?: string;
|
|
16
|
+
source?: "manual" | "scheduler";
|
|
17
|
+
payload?: unknown;
|
|
18
|
+
error?: unknown;
|
|
19
|
+
};
|
|
20
|
+
export type LegonodePlugin = {
|
|
21
|
+
name: string;
|
|
22
|
+
onRequest?: (ctx: LegonodeContext) => void | Promise<void>;
|
|
23
|
+
onRouteMatch?: (ctx: LegonodeContext) => void | Promise<void>;
|
|
24
|
+
onMiddlewareResolved?: (ctx: LegonodeContext, info: {
|
|
25
|
+
pathname: string;
|
|
26
|
+
method: string;
|
|
27
|
+
count: number;
|
|
28
|
+
}) => void | Promise<void>;
|
|
29
|
+
onEventEmit?: (ctx: LegonodeContext, info: {
|
|
30
|
+
name: string;
|
|
31
|
+
payload?: unknown;
|
|
32
|
+
}) => void | Promise<void>;
|
|
33
|
+
onCronRun?: (ctx: LegonodeContext | undefined, info: {
|
|
34
|
+
name: string;
|
|
35
|
+
payload?: unknown;
|
|
36
|
+
source: "manual" | "scheduler";
|
|
37
|
+
}) => void | Promise<void>;
|
|
38
|
+
onCronError?: (ctx: LegonodeContext | undefined, info: {
|
|
39
|
+
name: string;
|
|
40
|
+
payload?: unknown;
|
|
41
|
+
source: "manual" | "scheduler";
|
|
42
|
+
error: unknown;
|
|
43
|
+
}) => void | Promise<void>;
|
|
44
|
+
beforeHandler?: (ctx: LegonodeContext) => void | Promise<void>;
|
|
45
|
+
afterHandler?: (ctx: LegonodeContext, result: unknown) => void | Promise<void>;
|
|
46
|
+
/** Runs before any response is sent (headers can still be set). */
|
|
47
|
+
beforeResponse?: (ctx: LegonodeContext) => void | Promise<void>;
|
|
48
|
+
/** Runs after the response has been sent (in finally block). */
|
|
49
|
+
afterResponse?: (ctx: LegonodeContext) => void | Promise<void>;
|
|
50
|
+
onError?: (ctx: LegonodeContext, error: unknown) => void | Promise<void>;
|
|
51
|
+
onDevStart?: (ctx: LegonodeCommandHookContext) => void | Promise<void>;
|
|
52
|
+
onDevFileChange?: (ctx: LegonodeCommandHookContext) => void | Promise<void>;
|
|
53
|
+
onDevRestart?: (ctx: LegonodeCommandHookContext) => void | Promise<void>;
|
|
54
|
+
onDevStop?: (ctx: LegonodeCommandHookContext) => void | Promise<void>;
|
|
55
|
+
onBuildStart?: (ctx: LegonodeCommandHookContext) => void | Promise<void>;
|
|
56
|
+
onBuildComplete?: (ctx: LegonodeCommandHookContext) => void | Promise<void>;
|
|
57
|
+
onBuildError?: (ctx: LegonodeCommandHookContext) => void | Promise<void>;
|
|
58
|
+
onStartStart?: (ctx: LegonodeCommandHookContext) => void | Promise<void>;
|
|
59
|
+
onStartListening?: (ctx: LegonodeCommandHookContext) => void | Promise<void>;
|
|
60
|
+
onStartStop?: (ctx: LegonodeCommandHookContext) => void | Promise<void>;
|
|
61
|
+
onStartError?: (ctx: LegonodeCommandHookContext) => void | Promise<void>;
|
|
62
|
+
};
|
|
63
|
+
//# sourceMappingURL=pluginAPI.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pluginAPI.d.ts","sourceRoot":"","sources":["../../../src/plugin/pluginAPI.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pluginAPI.js","sourceRoot":"","sources":["../../../src/plugin/pluginAPI.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { LegonodePlugin } from "./pluginAPI.js";
|
|
2
|
+
export declare function createPluginManager(plugins?: LegonodePlugin[]): {
|
|
3
|
+
plugins: LegonodePlugin[];
|
|
4
|
+
runHook(hook: keyof LegonodePlugin, ...args: unknown[]): Promise<void>;
|
|
5
|
+
};
|
|
6
|
+
//# sourceMappingURL=pluginManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pluginManager.d.ts","sourceRoot":"","sources":["../../../src/plugin/pluginManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAIrD,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,cAAc,EAAO;;kBAI1C,MAAM,cAAc,WAAW,OAAO,EAAE;EAQ/D"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export function createPluginManager(plugins = []) {
|
|
2
|
+
const hasPlugins = plugins.length > 0;
|
|
3
|
+
return {
|
|
4
|
+
plugins,
|
|
5
|
+
async runHook(hook, ...args) {
|
|
6
|
+
if (!hasPlugins)
|
|
7
|
+
return;
|
|
8
|
+
for (const plugin of plugins) {
|
|
9
|
+
const fn = plugin[hook];
|
|
10
|
+
if (typeof fn === "function")
|
|
11
|
+
await fn(...args);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=pluginManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pluginManager.js","sourceRoot":"","sources":["../../../src/plugin/pluginManager.ts"],"names":[],"mappings":"AAIA,MAAM,UAAU,mBAAmB,CAAC,UAA4B,EAAE;IAChE,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IACtC,OAAO;QACL,OAAO;QACP,KAAK,CAAC,OAAO,CAAC,IAA0B,EAAE,GAAG,IAAe;YAC1D,IAAI,CAAC,UAAU;gBAAE,OAAO;YACxB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;gBAC7B,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAe,CAAC;gBACtC,IAAI,OAAO,EAAE,KAAK,UAAU;oBAAE,MAAM,EAAE,CAAC,GAAI,IAAkB,CAAC,CAAC;YACjE,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ScannedRoute } from "../loader/fileScanner.js";
|
|
2
|
+
export type MatchResult = {
|
|
3
|
+
routeId: string;
|
|
4
|
+
/** Method -> file path. "" = route.ts (all methods). GET, POST, etc. = get.ts, post.ts. */
|
|
5
|
+
fileByMethod: Record<string, string>;
|
|
6
|
+
/** Catch-all [[...x]] params are string[], others are string. */
|
|
7
|
+
params: Record<string, string | string[]>;
|
|
8
|
+
};
|
|
9
|
+
export declare function matchRoute(method: string, pathname: string, routes: ScannedRoute[]): MatchResult | null;
|
|
10
|
+
//# sourceMappingURL=matcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matcher.d.ts","sourceRoot":"","sources":["../../../src/router/matcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,2FAA2F;IAC3F,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,iEAAiE;IACjE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;CAC3C,CAAC;AAEF,wBAAgB,UAAU,CACxB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,YAAY,EAAE,GACrB,WAAW,GAAG,IAAI,CA+EpB"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export function matchRoute(method, pathname, routes) {
|
|
2
|
+
const urlSegments = pathname.replace(/^\/+/, "").split("/").filter(Boolean);
|
|
3
|
+
for (const route of routes) {
|
|
4
|
+
const patternSegments = route.pathname.replace(/^\/+/, "").split("/").filter(Boolean);
|
|
5
|
+
const params = {};
|
|
6
|
+
let i = 0;
|
|
7
|
+
let j = 0;
|
|
8
|
+
let match = true;
|
|
9
|
+
while (i < patternSegments.length && j < urlSegments.length) {
|
|
10
|
+
const rawSeg = patternSegments[i];
|
|
11
|
+
if (rawSeg === undefined) {
|
|
12
|
+
match = false;
|
|
13
|
+
break;
|
|
14
|
+
}
|
|
15
|
+
const seg = rawSeg;
|
|
16
|
+
// Route groups: (main) – ignore in URL structure
|
|
17
|
+
if (seg.startsWith("(") && seg.endsWith(")")) {
|
|
18
|
+
i += 1;
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
const urlSeg = urlSegments[j] ?? "";
|
|
22
|
+
// Optional catch-all: [[...all]]
|
|
23
|
+
const catchAllMatch = seg.match(/^\[\[\.\.\.(.+)\]\]$/);
|
|
24
|
+
if (catchAllMatch) {
|
|
25
|
+
const name = catchAllMatch[1];
|
|
26
|
+
params[name] = decodeURIComponent(urlSegments.slice(j).join("/"));
|
|
27
|
+
// catch-all must be the last pattern segment
|
|
28
|
+
i = patternSegments.length;
|
|
29
|
+
j = urlSegments.length;
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
// Dynamic segment: [id]
|
|
33
|
+
const dynMatch = seg.match(/^\[(.+)\]$/);
|
|
34
|
+
if (dynMatch) {
|
|
35
|
+
const name = dynMatch[1];
|
|
36
|
+
params[name] = decodeURIComponent(urlSeg);
|
|
37
|
+
i += 1;
|
|
38
|
+
j += 1;
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
// Static segment
|
|
42
|
+
if (seg !== urlSeg) {
|
|
43
|
+
match = false;
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
i += 1;
|
|
47
|
+
j += 1;
|
|
48
|
+
}
|
|
49
|
+
// Skip remaining route groups at the end
|
|
50
|
+
while (i < patternSegments.length) {
|
|
51
|
+
const seg = patternSegments[i];
|
|
52
|
+
if (!seg || !(seg.startsWith("(") && seg.endsWith(")")))
|
|
53
|
+
break;
|
|
54
|
+
i += 1;
|
|
55
|
+
}
|
|
56
|
+
const hasExtraUrlSegments = j < urlSegments.length;
|
|
57
|
+
const hasUnmatchedPatternSegments = i < patternSegments.length;
|
|
58
|
+
if (!match || hasExtraUrlSegments || hasUnmatchedPatternSegments)
|
|
59
|
+
continue;
|
|
60
|
+
const fileByMethod = route.method ? { [route.method]: route.filePath } : { "": route.filePath };
|
|
61
|
+
return {
|
|
62
|
+
routeId: route.pathname,
|
|
63
|
+
fileByMethod,
|
|
64
|
+
params
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=matcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matcher.js","sourceRoot":"","sources":["../../../src/router/matcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ScannedRoute } from "../loader/fileScanner.js";
|
|
2
|
+
import type { MatchResult } from "./matcher.js";
|
|
3
|
+
/** Match result when using per-method tree (no fileByMethod lookup). Catch-all params are string[]. */
|
|
4
|
+
export type MatchResultPerMethod = {
|
|
5
|
+
routeId: string;
|
|
6
|
+
filePath: string;
|
|
7
|
+
params: Record<string, string | string[]>;
|
|
8
|
+
};
|
|
9
|
+
export type RadixTree = {
|
|
10
|
+
match(pathname: string): MatchResult | null;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Build a radix tree from scanned routes. Groups by pathname and merges method-specific files (get.ts, post.ts) with route.ts.
|
|
14
|
+
*/
|
|
15
|
+
export declare function buildRadixTree(routes: ScannedRoute[]): RadixTree;
|
|
16
|
+
export type RadixTreePerMethod = {
|
|
17
|
+
match(pathname: string): MatchResultPerMethod | null;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Build a radix tree for a single HTTP method (find-my-way style).
|
|
21
|
+
* Lookup is O(path depth) with no method map; returns filePath directly.
|
|
22
|
+
*/
|
|
23
|
+
export declare function buildRadixTreeForMethod(routes: ScannedRoute[], method: string): RadixTreePerMethod;
|
|
24
|
+
//# sourceMappingURL=radixTree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"radixTree.d.ts","sourceRoot":"","sources":["../../../src/router/radixTree.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,uGAAuG;AACvG,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;CAC3C,CAAC;AAqEF,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAAC;CAC7C,CAAC;AAEF;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,SAAS,CAkEhE;AAgDD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,oBAAoB,GAAG,IAAI,CAAC;CACtD,CAAC;AAEF;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,YAAY,EAAE,EACtB,MAAM,EAAE,MAAM,GACb,kBAAkB,CA+DpB"}
|