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,108 @@
|
|
|
1
|
+
import { resolve, relative, join } from "node:path";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { setupServer } from "../../src/server/server.js";
|
|
4
|
+
import { loadConfig, getBuildPath, getAppDir } from "../../src/config/loadConfig.js";
|
|
5
|
+
import { loadSchedulesFromApp } from "../../src/schedules/scheduleLoader.js";
|
|
6
|
+
import { runScheduler } from "../../src/schedules/runScheduler.js";
|
|
7
|
+
import { validateApp } from "../../src/validation/validateApp.js";
|
|
8
|
+
import { runPluginHook } from "../pluginHooks.js";
|
|
9
|
+
import { appLogger } from "../../src/utils/logger.js";
|
|
10
|
+
export const startCommand = {
|
|
11
|
+
name: "legonode start",
|
|
12
|
+
run: async (opts = {}) => {
|
|
13
|
+
const host = opts.host ?? "127.0.0.1";
|
|
14
|
+
const cwd = process.cwd();
|
|
15
|
+
const config = await loadConfig(cwd);
|
|
16
|
+
const plugins = config.plugins;
|
|
17
|
+
const buildPath = opts.buildPath ? resolve(cwd, opts.buildPath) : getBuildPath(config, cwd);
|
|
18
|
+
// Built app lives at buildPath/app (same structure as source appDir)
|
|
19
|
+
const currentAppDir = getAppDir(config, cwd);
|
|
20
|
+
const appDirRelative = relative(cwd, currentAppDir || "");
|
|
21
|
+
const appDir = join(buildPath, appDirRelative);
|
|
22
|
+
if (!existsSync(appDir)) {
|
|
23
|
+
appLogger.error(`Built app dir not found: ${appDir}. Run "legonode build" first, or check --build-path.`);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
const port = opts.port ? Number(opts.port) : (config.port ?? 3000);
|
|
27
|
+
if (!Number.isFinite(port) || port <= 0) {
|
|
28
|
+
throw new Error(`Invalid --port: ${opts.port ?? config.port ?? ""}`);
|
|
29
|
+
}
|
|
30
|
+
await runPluginHook(plugins, "onStartStart", {
|
|
31
|
+
command: "start",
|
|
32
|
+
cwd,
|
|
33
|
+
appDir,
|
|
34
|
+
host,
|
|
35
|
+
port,
|
|
36
|
+
buildPath,
|
|
37
|
+
});
|
|
38
|
+
const isValid = await validateApp(appDir);
|
|
39
|
+
if (!isValid) {
|
|
40
|
+
appLogger.error("Failed to validate the app");
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
const app = setupServer(config, cwd, appDir, port, host);
|
|
44
|
+
if (app) {
|
|
45
|
+
await app.listen();
|
|
46
|
+
await runPluginHook(plugins, "onStartListening", {
|
|
47
|
+
command: "start",
|
|
48
|
+
cwd,
|
|
49
|
+
appDir,
|
|
50
|
+
host,
|
|
51
|
+
port,
|
|
52
|
+
buildPath,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
await runPluginHook(plugins, "onStartError", {
|
|
57
|
+
command: "start",
|
|
58
|
+
cwd,
|
|
59
|
+
appDir,
|
|
60
|
+
host,
|
|
61
|
+
port,
|
|
62
|
+
buildPath,
|
|
63
|
+
error: new Error("Failed to start the server"),
|
|
64
|
+
});
|
|
65
|
+
appLogger.error("Failed to start the server");
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
const tasks = await loadSchedulesFromApp(appDir);
|
|
69
|
+
let stopScheduler = null;
|
|
70
|
+
if (tasks.length > 0) {
|
|
71
|
+
stopScheduler = runScheduler(tasks, {
|
|
72
|
+
onRun: async (name, taskCtx) => {
|
|
73
|
+
await runPluginHook(plugins, "onCronRun", undefined, {
|
|
74
|
+
name,
|
|
75
|
+
payload: taskCtx.payload,
|
|
76
|
+
source: "scheduler",
|
|
77
|
+
});
|
|
78
|
+
},
|
|
79
|
+
onError: (name, err) => {
|
|
80
|
+
void runPluginHook(plugins, "onCronError", undefined, {
|
|
81
|
+
name,
|
|
82
|
+
payload: undefined,
|
|
83
|
+
source: "scheduler",
|
|
84
|
+
error: err,
|
|
85
|
+
});
|
|
86
|
+
appLogger.error(`[legonode task ${name}]`, err);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
const onSignal = () => {
|
|
91
|
+
void runPluginHook(plugins, "onStartStop", {
|
|
92
|
+
command: "start",
|
|
93
|
+
cwd,
|
|
94
|
+
appDir,
|
|
95
|
+
host,
|
|
96
|
+
port,
|
|
97
|
+
buildPath,
|
|
98
|
+
reason: "signal",
|
|
99
|
+
});
|
|
100
|
+
stopScheduler?.();
|
|
101
|
+
void app?.close().catch(() => { });
|
|
102
|
+
process.exit(0);
|
|
103
|
+
};
|
|
104
|
+
process.on("SIGINT", onSignal);
|
|
105
|
+
process.on("SIGTERM", onSignal);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
//# sourceMappingURL=start.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../../cli/commands/start.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { LegonodePlugin } from "../src/plugin/pluginAPI.js";
|
|
2
|
+
type HookName = keyof LegonodePlugin;
|
|
3
|
+
export declare function runPluginHook(plugins: LegonodePlugin[] | undefined, hook: HookName, ...args: unknown[]): Promise<void>;
|
|
4
|
+
export {};
|
|
5
|
+
//# sourceMappingURL=pluginHooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pluginHooks.d.ts","sourceRoot":"","sources":["../../cli/pluginHooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAEjE,KAAK,QAAQ,GAAG,MAAM,cAAc,CAAC;AAIrC,wBAAsB,aAAa,CACjC,OAAO,EAAE,cAAc,EAAE,GAAG,SAAS,EACrC,IAAI,EAAE,QAAQ,EACd,GAAG,IAAI,EAAE,OAAO,EAAE,GACjB,OAAO,CAAC,IAAI,CAAC,CAQf"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export async function runPluginHook(plugins, hook, ...args) {
|
|
2
|
+
if (!plugins || plugins.length === 0)
|
|
3
|
+
return;
|
|
4
|
+
for (const plugin of plugins) {
|
|
5
|
+
const fn = plugin[hook];
|
|
6
|
+
if (typeof fn === "function") {
|
|
7
|
+
await fn(...args);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=pluginHooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pluginHooks.js","sourceRoot":"","sources":["../../cli/pluginHooks.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,OAAqC,EACrC,IAAc,EACd,GAAG,IAAe;IAElB,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAC7C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAe,CAAC;QACtC,IAAI,OAAO,EAAE,KAAK,UAAU,EAAE,CAAC;YAC7B,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;QACpB,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { IncomingMessage } from "node:http";
|
|
2
|
+
export type ParseBodyResult = {
|
|
3
|
+
ok: true;
|
|
4
|
+
body: unknown;
|
|
5
|
+
} | {
|
|
6
|
+
ok: false;
|
|
7
|
+
status: number;
|
|
8
|
+
body: unknown;
|
|
9
|
+
};
|
|
10
|
+
export declare function parseBody(req: IncomingMessage, maxBodySize?: number): Promise<ParseBodyResult>;
|
|
11
|
+
//# sourceMappingURL=parseBody.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseBody.d.ts","sourceRoot":"","sources":["../../../src/body/parseBody.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAIjD,MAAM,MAAM,eAAe,GACvB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAC3B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AA8EjD,wBAAsB,SAAS,CAC7B,GAAG,EAAE,eAAe,EACpB,WAAW,GAAE,MAA8B,GAC1C,OAAO,CAAC,eAAe,CAAC,CAsC1B"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
const DEFAULT_MAX_BODY_SIZE = 1_000_000; // 1MB
|
|
2
|
+
const PAYLOAD_TOO_LARGE = new Error("Payload too large");
|
|
3
|
+
function readStream(req, maxSize) {
|
|
4
|
+
return new Promise((resolve, reject) => {
|
|
5
|
+
const contentLength = req.headers["content-length"];
|
|
6
|
+
const length = contentLength ? parseInt(contentLength, 10) : null;
|
|
7
|
+
if (length !== null && (isNaN(length) || length < 0 || length > maxSize)) {
|
|
8
|
+
reject(PAYLOAD_TOO_LARGE);
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
if (length === 0) {
|
|
12
|
+
resolve(Buffer.allocUnsafe(0));
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
if (length !== null && length <= maxSize) {
|
|
16
|
+
const buf = Buffer.allocUnsafe(length);
|
|
17
|
+
let offset = 0;
|
|
18
|
+
req.on("data", (chunk) => {
|
|
19
|
+
const toCopy = Math.min(chunk.length, length - offset);
|
|
20
|
+
chunk.copy(buf, offset, 0, toCopy);
|
|
21
|
+
offset += toCopy;
|
|
22
|
+
if (offset > maxSize) {
|
|
23
|
+
req.destroy();
|
|
24
|
+
reject(PAYLOAD_TOO_LARGE);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
req.on("end", () => resolve(buf.subarray(0, offset)));
|
|
28
|
+
req.on("error", reject);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const chunks = [];
|
|
32
|
+
let total = 0;
|
|
33
|
+
req.on("data", (chunk) => {
|
|
34
|
+
total += chunk.length;
|
|
35
|
+
if (total > maxSize) {
|
|
36
|
+
req.destroy();
|
|
37
|
+
reject(PAYLOAD_TOO_LARGE);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
chunks.push(chunk);
|
|
41
|
+
});
|
|
42
|
+
req.on("end", () => resolve(Buffer.concat(chunks)));
|
|
43
|
+
req.on("error", reject);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
function parseJson(buf) {
|
|
47
|
+
if (buf.length === 0)
|
|
48
|
+
return null;
|
|
49
|
+
const raw = buf.toString("utf-8");
|
|
50
|
+
return JSON.parse(raw);
|
|
51
|
+
}
|
|
52
|
+
function parseUrlEncoded(buf) {
|
|
53
|
+
if (buf.length === 0)
|
|
54
|
+
return {};
|
|
55
|
+
const raw = buf.toString("utf-8");
|
|
56
|
+
const out = {};
|
|
57
|
+
for (const pair of raw.split("&")) {
|
|
58
|
+
const eq = pair.indexOf("=");
|
|
59
|
+
if (eq === -1) {
|
|
60
|
+
out[decodeURIComponent(pair.replace(/\+/g, " "))] = "";
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
const key = decodeURIComponent(pair.slice(0, eq).replace(/\+/g, " "));
|
|
64
|
+
const value = decodeURIComponent(pair.slice(eq + 1).replace(/\+/g, " "));
|
|
65
|
+
out[key] = value;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
70
|
+
function getContentType(req) {
|
|
71
|
+
const raw = req.headers["content-type"];
|
|
72
|
+
if (!raw || typeof raw !== "string")
|
|
73
|
+
return null;
|
|
74
|
+
const part = raw.split(";")[0];
|
|
75
|
+
return part ? part.trim().toLowerCase() : null;
|
|
76
|
+
}
|
|
77
|
+
export async function parseBody(req, maxBodySize = DEFAULT_MAX_BODY_SIZE) {
|
|
78
|
+
const method = (req.method ?? "GET").toUpperCase();
|
|
79
|
+
if (method === "GET" || method === "HEAD") {
|
|
80
|
+
return { ok: true, body: null };
|
|
81
|
+
}
|
|
82
|
+
const contentLength = req.headers["content-length"];
|
|
83
|
+
if (contentLength === "0" || contentLength === undefined) {
|
|
84
|
+
return { ok: true, body: null };
|
|
85
|
+
}
|
|
86
|
+
let buffer;
|
|
87
|
+
try {
|
|
88
|
+
buffer = await readStream(req, maxBodySize);
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
const message = err === PAYLOAD_TOO_LARGE ? "Payload too large" : "Bad request";
|
|
92
|
+
return { ok: false, status: 413, body: { error: message } };
|
|
93
|
+
}
|
|
94
|
+
const contentType = getContentType(req);
|
|
95
|
+
if (!contentType || buffer.length === 0) {
|
|
96
|
+
return { ok: true, body: null };
|
|
97
|
+
}
|
|
98
|
+
if (contentType === "application/json") {
|
|
99
|
+
try {
|
|
100
|
+
const body = parseJson(buffer);
|
|
101
|
+
return { ok: true, body };
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return { ok: false, status: 400, body: { error: "Invalid JSON" } };
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (contentType === "application/x-www-form-urlencoded") {
|
|
108
|
+
const body = parseUrlEncoded(buffer);
|
|
109
|
+
return { ok: true, body };
|
|
110
|
+
}
|
|
111
|
+
return { ok: true, body: buffer };
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=parseBody.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseBody.js","sourceRoot":"","sources":["../../../src/body/parseBody.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { LegonodeContext } from "../core/context.js";
|
|
2
|
+
import type { LegonodePlugin } from "../plugin/pluginAPI.js";
|
|
3
|
+
import type { ResponseSchemaMap } from "../validation/routeSchema.js";
|
|
4
|
+
import type { LegonodeLogger } from "../logger/requestLogger.js";
|
|
5
|
+
import type { TracerFn, TraceStartFn } from "../trace/traceEngine.js";
|
|
6
|
+
export type CorsConfig = {
|
|
7
|
+
origin?: string | string[] | boolean;
|
|
8
|
+
methods?: string[];
|
|
9
|
+
allowedHeaders?: string[];
|
|
10
|
+
credentials?: boolean;
|
|
11
|
+
};
|
|
12
|
+
export type ErrorHandlerResult = {
|
|
13
|
+
status?: number;
|
|
14
|
+
headers?: Record<string, string>;
|
|
15
|
+
json?: unknown;
|
|
16
|
+
} | {
|
|
17
|
+
status?: number;
|
|
18
|
+
headers?: Record<string, string>;
|
|
19
|
+
body?: string | Uint8Array;
|
|
20
|
+
};
|
|
21
|
+
export type ErrorHandler = (ctx: LegonodeContext, err: unknown) => void | ErrorHandlerResult | Promise<void | ErrorHandlerResult>;
|
|
22
|
+
export type LegonodeConfig = {
|
|
23
|
+
appDir?: string;
|
|
24
|
+
buildPath?: string;
|
|
25
|
+
/** Port for dev/start (CLI --port overrides). */
|
|
26
|
+
port?: number;
|
|
27
|
+
/** Dev-only options. */
|
|
28
|
+
dev?: {
|
|
29
|
+
/** Set false to disable cron jobs in development (default: true). */
|
|
30
|
+
cron?: boolean;
|
|
31
|
+
/** Set true to use pino-pretty for human-readable logs in development. */
|
|
32
|
+
logPretty?: boolean;
|
|
33
|
+
};
|
|
34
|
+
maxBodySize?: number;
|
|
35
|
+
errorHandler?: ErrorHandler;
|
|
36
|
+
cors?: CorsConfig;
|
|
37
|
+
plugins?: LegonodePlugin[];
|
|
38
|
+
/** Default response body schemas per status code. Enforced before send; invalid response becomes 500. */
|
|
39
|
+
responses?: ResponseSchemaMap;
|
|
40
|
+
/** Base logger for request loggers (ctx.logger). If not set, a default pino logger is used. */
|
|
41
|
+
logger?: LegonodeLogger;
|
|
42
|
+
/** Set false to disable request lifecycle logging (request started / request completed) and tracer/traceStart callbacks (default: true). */
|
|
43
|
+
tracing?: boolean;
|
|
44
|
+
/** Called when a request span ends with trace data (method, pathname, duration, status, responseSize, etc.). */
|
|
45
|
+
tracer?: TracerFn;
|
|
46
|
+
/** Called when a request span starts. Default logs "request started" via logger. */
|
|
47
|
+
traceStart?: TraceStartFn;
|
|
48
|
+
};
|
|
49
|
+
export declare function loadConfig(cwd: string): Promise<LegonodeConfig>;
|
|
50
|
+
export declare function getAppDir(config: LegonodeConfig, cwd: string): string | undefined;
|
|
51
|
+
export declare function getBuildPath(config: LegonodeConfig, cwd: string): string;
|
|
52
|
+
export type RequestHandlerOptionsFromConfig = {
|
|
53
|
+
appDir: string;
|
|
54
|
+
maxBodySize?: number;
|
|
55
|
+
errorHandler?: ErrorHandler;
|
|
56
|
+
cors?: CorsConfig;
|
|
57
|
+
plugins?: LegonodePlugin[];
|
|
58
|
+
responses?: ResponseSchemaMap;
|
|
59
|
+
logger?: LegonodeLogger;
|
|
60
|
+
dev?: {
|
|
61
|
+
cron?: boolean;
|
|
62
|
+
logPretty?: boolean;
|
|
63
|
+
};
|
|
64
|
+
tracing?: boolean;
|
|
65
|
+
tracer?: TracerFn;
|
|
66
|
+
traceStart?: TraceStartFn;
|
|
67
|
+
};
|
|
68
|
+
export declare function getRequestHandlerOptionsFromConfig(config: LegonodeConfig, cwd: string, overrides?: {
|
|
69
|
+
appDir?: string;
|
|
70
|
+
}): RequestHandlerOptionsFromConfig;
|
|
71
|
+
//# sourceMappingURL=loadConfig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loadConfig.d.ts","sourceRoot":"","sources":["../../../src/config/loadConfig.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
import { pathToFileURL } from "node:url";
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { appLogger } from "../utils/logger.js";
|
|
5
|
+
export async function loadConfig(cwd) {
|
|
6
|
+
const candidates = ["legonode.config.ts", "legonode.config.js", "legonode.config.mjs"];
|
|
7
|
+
for (const name of candidates) {
|
|
8
|
+
const configPath = resolve(cwd, name);
|
|
9
|
+
try {
|
|
10
|
+
const url = pathToFileURL(configPath).href;
|
|
11
|
+
const mod = await import(url);
|
|
12
|
+
const config = mod.default ?? mod;
|
|
13
|
+
return typeof config === "object" && config !== null ? config : {};
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return {};
|
|
20
|
+
}
|
|
21
|
+
export function getAppDir(config, cwd) {
|
|
22
|
+
// Default app directory layout:
|
|
23
|
+
// - routes live under `${appDir}/router/**`
|
|
24
|
+
// - other runtime features (events/schedules/middleware/etc.) use `${appDir}`
|
|
25
|
+
try {
|
|
26
|
+
const appDir = config.appDir ?? "./src";
|
|
27
|
+
const routerDir = resolve(appDir);
|
|
28
|
+
if (existsSync(routerDir)) {
|
|
29
|
+
return routerDir;
|
|
30
|
+
}
|
|
31
|
+
throw new Error();
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
appLogger.error("App directory not found: ", config.appDir);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
// const raw = config.appDir ?? "./src";
|
|
38
|
+
// return raw.startsWith("/") ? raw : resolve(cwd, raw);
|
|
39
|
+
}
|
|
40
|
+
export function getBuildPath(config, cwd) {
|
|
41
|
+
const raw = config.buildPath ?? "./dist";
|
|
42
|
+
return raw.startsWith("/") ? raw : resolve(cwd, raw);
|
|
43
|
+
}
|
|
44
|
+
export function getRequestHandlerOptionsFromConfig(config, cwd, overrides) {
|
|
45
|
+
const appDir = overrides?.appDir ?? getAppDir(config, cwd);
|
|
46
|
+
const out = { appDir: appDir || "" };
|
|
47
|
+
if (config.maxBodySize !== undefined)
|
|
48
|
+
out.maxBodySize = config.maxBodySize;
|
|
49
|
+
if (config.errorHandler !== undefined)
|
|
50
|
+
out.errorHandler = config.errorHandler;
|
|
51
|
+
if (config.cors !== undefined)
|
|
52
|
+
out.cors = config.cors;
|
|
53
|
+
if (config.plugins !== undefined)
|
|
54
|
+
out.plugins = config.plugins;
|
|
55
|
+
if (config.responses !== undefined)
|
|
56
|
+
out.responses = config.responses;
|
|
57
|
+
if (config.logger !== undefined)
|
|
58
|
+
out.logger = config.logger;
|
|
59
|
+
if (config.dev !== undefined)
|
|
60
|
+
out.dev = config.dev;
|
|
61
|
+
if (config.tracing !== undefined)
|
|
62
|
+
out.tracing = config.tracing;
|
|
63
|
+
if (config.tracer !== undefined)
|
|
64
|
+
out.tracer = config.tracer;
|
|
65
|
+
if (config.traceStart !== undefined)
|
|
66
|
+
out.traceStart = config.traceStart;
|
|
67
|
+
return out;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=loadConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loadConfig.js","sourceRoot":"","sources":["../../../src/config/loadConfig.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
2
|
+
import type { Readable } from "node:stream";
|
|
3
|
+
import type { TraceSpan } from "../trace/traceEngine.js";
|
|
4
|
+
import type { RequestLogEntry, LegonodeLogger } from "../logger/requestLogger.js";
|
|
5
|
+
/** Exposed on ctx.trace so the user can get the request trace id (e.g. for logging). */
|
|
6
|
+
export type TraceRef = {
|
|
7
|
+
readonly traceId: string;
|
|
8
|
+
};
|
|
9
|
+
import type { EventEmitterFn } from "../events/eventBus.js";
|
|
10
|
+
import type { ScheduleRunnerFn } from "../schedules/scheduleLoader.js";
|
|
11
|
+
import type { ResponseSchemaMap } from "../validation/routeSchema.js";
|
|
12
|
+
export type Response = {
|
|
13
|
+
status?: number;
|
|
14
|
+
headers?: Record<string, string>;
|
|
15
|
+
body?: string | Uint8Array;
|
|
16
|
+
} | {
|
|
17
|
+
status?: number;
|
|
18
|
+
headers?: Record<string, string>;
|
|
19
|
+
json: unknown;
|
|
20
|
+
};
|
|
21
|
+
/** Chainable return type for ctx.res.status(code).json() / .send() / .text() / .html() */
|
|
22
|
+
export type ResStatusChain = {
|
|
23
|
+
json: (data: unknown) => void | Promise<void>;
|
|
24
|
+
send: (body: string | Buffer | Uint8Array) => void | Promise<void>;
|
|
25
|
+
text: (body: string) => void | Promise<void>;
|
|
26
|
+
html: (body: string) => void | Promise<void>;
|
|
27
|
+
};
|
|
28
|
+
/** Fluent response API on ctx.res */
|
|
29
|
+
export type LegonodeResponse = {
|
|
30
|
+
/** Raw Node HTTP response */
|
|
31
|
+
raw: ServerResponse;
|
|
32
|
+
/** Set status code; returns chainable .json() / .send() / .text() */
|
|
33
|
+
status: (code: number) => ResStatusChain;
|
|
34
|
+
/** Current status code (e.g. set by status()); used when handler returns data without calling res.json() */
|
|
35
|
+
readonly statusCode: number;
|
|
36
|
+
/** Headers to send (merged when response is sent) */
|
|
37
|
+
headers: Record<string, string | number>;
|
|
38
|
+
/** Set a single header */
|
|
39
|
+
setHeader: (name: string, value: string | number) => void;
|
|
40
|
+
/** Send raw body (HTML, buffer). Default content-type not set; use setHeader for HTML */
|
|
41
|
+
send: (body: string | Buffer | Uint8Array) => void | Promise<void>;
|
|
42
|
+
/** Send HTML (content-type text/html) */
|
|
43
|
+
html: (body: string) => void | Promise<void>;
|
|
44
|
+
/** Send JSON (content-type application/json) */
|
|
45
|
+
json: (data: unknown) => void | Promise<void>;
|
|
46
|
+
/** Send plain text (content-type text/plain) */
|
|
47
|
+
text: (body: string) => void | Promise<void>;
|
|
48
|
+
/** Redirect to url (default 302). Use status as second arg for 301 etc. */
|
|
49
|
+
redirect: (url: string, status?: number) => void | Promise<void>;
|
|
50
|
+
/** Pipe a readable stream as the response body */
|
|
51
|
+
stream: (readable: Readable) => void | Promise<void>;
|
|
52
|
+
/** True if response was already sent (e.g. via res.json()) */
|
|
53
|
+
readonly sent: boolean;
|
|
54
|
+
/** @internal Reuse for another request when using context pool. */
|
|
55
|
+
reinit?: (nodeRes: ServerResponse, defaultStatusRef: DefaultStatusRef, responseSizeRef?: {
|
|
56
|
+
current: number;
|
|
57
|
+
}) => void;
|
|
58
|
+
};
|
|
59
|
+
export type LegonodeContext = {
|
|
60
|
+
req: IncomingMessage;
|
|
61
|
+
res: LegonodeResponse;
|
|
62
|
+
/** Path params; catch-all [[...x]] params are string[], others are string. */
|
|
63
|
+
params: Record<string, string | string[]>;
|
|
64
|
+
/** Query params (parsed from URL or replaced by validated Record after validation). */
|
|
65
|
+
query: Record<string, string>;
|
|
66
|
+
body: unknown;
|
|
67
|
+
state: Record<string, unknown>;
|
|
68
|
+
emit: EventEmitterFn;
|
|
69
|
+
/** Trigger a cron by name (e.g. "interval.example"). Same run() as in app/cron/*.cron.ts. */
|
|
70
|
+
schedule: ScheduleRunnerFn;
|
|
71
|
+
/** Request-scoped logger with traceId in bindings. Use for application logs; tracing is automatic. */
|
|
72
|
+
logger: LegonodeLogger;
|
|
73
|
+
/** Request-scoped captured logger output for plugin/readback use. */
|
|
74
|
+
log: {
|
|
75
|
+
state: RequestLogEntry[];
|
|
76
|
+
};
|
|
77
|
+
/** Request trace id (one per request). Use ctx.trace.traceId for correlation. */
|
|
78
|
+
trace: TraceRef;
|
|
79
|
+
/** @internal Used by framework for span start/annotate/end; do not use. */
|
|
80
|
+
__traceSpan?: TraceSpan;
|
|
81
|
+
/** @internal Set by framework so res.json() can validate against response schema for current status. */
|
|
82
|
+
__responseSchemaRef?: ResponseSchemaRef;
|
|
83
|
+
/** @internal Set by framework from merged response schema (route + config) so res uses that default when status() not called. */
|
|
84
|
+
__defaultStatusRef?: DefaultStatusRef;
|
|
85
|
+
/** @internal Set by framework when response is sent; used for trace responseSize. */
|
|
86
|
+
__responseSizeRef?: {
|
|
87
|
+
current: number;
|
|
88
|
+
};
|
|
89
|
+
/** @internal Backing for query getter; reset on release for context pool. */
|
|
90
|
+
__queryCache?: Record<string, string> | undefined;
|
|
91
|
+
/** @internal Ref for beforeSend to resolve ctx when res sends. */
|
|
92
|
+
__ctxRef?: {
|
|
93
|
+
current: LegonodeContext | null;
|
|
94
|
+
};
|
|
95
|
+
};
|
|
96
|
+
/** Map status codes to response body types for typed res.status(code).json(data). */
|
|
97
|
+
export type ResponseBodyByStatus = Record<number, unknown>;
|
|
98
|
+
/** Chain with json(data) typed by status code. */
|
|
99
|
+
export type ResStatusChainTyped<T> = {
|
|
100
|
+
json: (data: T) => void;
|
|
101
|
+
send: (body: string | Buffer | Uint8Array) => void;
|
|
102
|
+
text: (body: string) => void;
|
|
103
|
+
html: (body: string) => void;
|
|
104
|
+
};
|
|
105
|
+
/** Response API: status(code) accepts any number; .json(data) typed for codes in T when possible. */
|
|
106
|
+
export type LegonodeResponseTyped<T extends ResponseBodyByStatus> = Omit<LegonodeResponse, "status" | "json"> & {
|
|
107
|
+
/** Accepts any status code; .json() payload is typed when code is in your response schema. */
|
|
108
|
+
status: (code: number) => ResStatusChainTyped<unknown>;
|
|
109
|
+
json: (data: unknown) => void;
|
|
110
|
+
};
|
|
111
|
+
/** Context with res.json() typed by status from response schema. */
|
|
112
|
+
export type ContextWithResponses<T extends ResponseBodyByStatus> = Omit<LegonodeContext, "res"> & {
|
|
113
|
+
res: LegonodeResponseTyped<T>;
|
|
114
|
+
};
|
|
115
|
+
/**
|
|
116
|
+
* Context type. Use without a generic for untyped res, or with a response body type map to enforce schema typing.
|
|
117
|
+
* @example
|
|
118
|
+
* export default async function GET(ctx: Context) { ... }
|
|
119
|
+
* // Or with response schema typing:
|
|
120
|
+
* type Res = InferResponseBodies<typeof RESPONSE_SCHEMA>;
|
|
121
|
+
* export default async function GET(ctx: Context<Res>) { ctx.res.status(200).json([...]); }
|
|
122
|
+
*/
|
|
123
|
+
export type Context<T extends ResponseBodyByStatus = never> = [T] extends [never] ? Omit<LegonodeContext, "__traceSpan" | "__responseSchemaRef" | "__defaultStatusRef" | "__responseSizeRef"> : Omit<ContextWithResponses<T>, "__traceSpan" | "__responseSchemaRef" | "__defaultStatusRef" | "__responseSizeRef">;
|
|
124
|
+
export type ResponseSchemaRef = {
|
|
125
|
+
current?: ResponseSchemaMap;
|
|
126
|
+
};
|
|
127
|
+
export type DefaultStatusRef = {
|
|
128
|
+
current: number;
|
|
129
|
+
};
|
|
130
|
+
/** Pick default status when handler does not call res.status(): prefer 200, then 201, then 204; else 200. */
|
|
131
|
+
export declare function getDefaultStatusFromSchema(schema: ResponseSchemaMap | undefined): number;
|
|
132
|
+
export type BeforeSendFn = (ctx: LegonodeContext) => void | Promise<void>;
|
|
133
|
+
/** Get context from pool or create new. Use releaseContext(ctx) in finally when done. When usePool is false, always alloc (faster hot path for hello-world). */
|
|
134
|
+
export declare function getContext(req: IncomingMessage, res: ServerResponse, usePool?: boolean, beforeSend?: BeforeSendFn): LegonodeContext;
|
|
135
|
+
/** Return context to pool. Call in request handler finally. Keeps ctx.res for reuse via reinit. */
|
|
136
|
+
export declare function releaseContext(ctx: LegonodeContext): void;
|
|
137
|
+
/** Get a request context (from pool when possible). Same as getContext; exported for backwards compatibility. */
|
|
138
|
+
export declare const createContext: typeof getContext;
|
|
139
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/core/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAElF,wFAAwF;AACxF,MAAM,MAAM,QAAQ,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAEtE,MAAM,MAAM,QAAQ,GAChB;IACE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;CAC5B,GACD;IACE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,IAAI,EAAE,OAAO,CAAC;CACf,CAAC;AAEN,0FAA0F;AAC1F,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9C,CAAC;AAEF,qCAAqC;AACrC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,6BAA6B;IAC7B,GAAG,EAAE,cAAc,CAAC;IACpB,qEAAqE;IACrE,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,cAAc,CAAC;IACzC,4GAA4G;IAC5G,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,qDAAqD;IACrD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;IACzC,0BAA0B;IAC1B,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,KAAK,IAAI,CAAC;IAC1D,yFAAyF;IACzF,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,yCAAyC;IACzC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,gDAAgD;IAChD,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,gDAAgD;IAChD,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,2EAA2E;IAC3E,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,kDAAkD;IAClD,MAAM,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,8DAA8D;IAC9D,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,mEAAmE;IACnE,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,eAAe,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CACvH,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,GAAG,EAAE,eAAe,CAAC;IACrB,GAAG,EAAE,gBAAgB,CAAC;IACtB,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC1C,uFAAuF;IACvF,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,IAAI,EAAE,cAAc,CAAC;IACrB,6FAA6F;IAC7F,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,sGAAsG;IACtG,MAAM,EAAE,cAAc,CAAC;IACvB,qEAAqE;IACrE,GAAG,EAAE;QAAE,KAAK,EAAE,eAAe,EAAE,CAAA;KAAE,CAAC;IAClC,iFAAiF;IACjF,KAAK,EAAE,QAAQ,CAAC;IAChB,2EAA2E;IAC3E,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,wGAAwG;IACxG,mBAAmB,CAAC,EAAE,iBAAiB,CAAC;IACxC,iIAAiI;IACjI,kBAAkB,CAAC,EAAE,gBAAgB,CAAC;IACtC,qFAAqF;IACrF,iBAAiB,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IACxC,6EAA6E;IAC7E,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;IAClD,kEAAkE;IAClE,QAAQ,CAAC,EAAE;QAAE,OAAO,EAAE,eAAe,GAAG,IAAI,CAAA;KAAE,CAAC;CAChD,CAAC;AAEF,qFAAqF;AACrF,MAAM,MAAM,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE3D,kDAAkD;AAClD,MAAM,MAAM,mBAAmB,CAAC,CAAC,IAAI;IACnC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;IACxB,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,KAAK,IAAI,CAAC;IACnD,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9B,CAAC;AAEF,qGAAqG;AACrG,MAAM,MAAM,qBAAqB,CAAC,CAAC,SAAS,oBAAoB,IAAI,IAAI,CACtE,gBAAgB,EAChB,QAAQ,GAAG,MAAM,CAClB,GAAG;IACF,8FAA8F;IAC9F,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACvD,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CAC/B,CAAC;AAEF,oEAAoE;AACpE,MAAM,MAAM,oBAAoB,CAAC,CAAC,SAAS,oBAAoB,IAAI,IAAI,CAAC,eAAe,EAAE,KAAK,CAAC,GAAG;IAChG,GAAG,EAAE,qBAAqB,CAAC,CAAC,CAAC,CAAC;CAC/B,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,MAAM,OAAO,CAAC,CAAC,SAAS,oBAAoB,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GAC7E,IAAI,CACF,eAAe,EACf,aAAa,GAAG,qBAAqB,GAAG,oBAAoB,GAAG,mBAAmB,CACnF,GACD,IAAI,CACF,oBAAoB,CAAC,CAAC,CAAC,EACvB,aAAa,GAAG,qBAAqB,GAAG,oBAAoB,GAAG,mBAAmB,CACnF,CAAC;AAEN,MAAM,MAAM,iBAAiB,GAAG;IAAE,OAAO,CAAC,EAAE,iBAAiB,CAAA;CAAE,CAAC;AAEhE,MAAM,MAAM,gBAAgB,GAAG;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnD,6GAA6G;AAC7G,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,iBAAiB,GAAG,SAAS,GAAG,MAAM,CAUxF;AAYD,MAAM,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AA+Q1E,gKAAgK;AAChK,wBAAgB,UAAU,CACxB,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,OAAO,UAAQ,EACf,UAAU,CAAC,EAAE,YAAY,GACxB,eAAe,CAKjB;AAED,mGAAmG;AACnG,wBAAgB,cAAc,CAAC,GAAG,EAAE,eAAe,GAAG,IAAI,CAQzD;AAED,iHAAiH;AACjH,eAAO,MAAM,aAAa,mBAAa,CAAC"}
|