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.
Files changed (194) hide show
  1. package/README.md +107 -0
  2. package/dist/cli/cli.d.ts +3 -0
  3. package/dist/cli/cli.d.ts.map +1 -0
  4. package/dist/cli/cli.js +44 -0
  5. package/dist/cli/cli.js.map +1 -0
  6. package/dist/cli/commands/build.d.ts +8 -0
  7. package/dist/cli/commands/build.d.ts.map +1 -0
  8. package/dist/cli/commands/build.js +101 -0
  9. package/dist/cli/commands/build.js.map +1 -0
  10. package/dist/cli/commands/dev.d.ts +13 -0
  11. package/dist/cli/commands/dev.d.ts.map +1 -0
  12. package/dist/cli/commands/dev.js +285 -0
  13. package/dist/cli/commands/dev.js.map +1 -0
  14. package/dist/cli/commands/start.d.ts +10 -0
  15. package/dist/cli/commands/start.d.ts.map +1 -0
  16. package/dist/cli/commands/start.js +108 -0
  17. package/dist/cli/commands/start.js.map +1 -0
  18. package/dist/cli/pluginHooks.d.ts +5 -0
  19. package/dist/cli/pluginHooks.d.ts.map +1 -0
  20. package/dist/cli/pluginHooks.js +11 -0
  21. package/dist/cli/pluginHooks.js.map +1 -0
  22. package/dist/src/body/parseBody.d.ts +11 -0
  23. package/dist/src/body/parseBody.d.ts.map +1 -0
  24. package/dist/src/body/parseBody.js +113 -0
  25. package/dist/src/body/parseBody.js.map +1 -0
  26. package/dist/src/config/loadConfig.d.ts +71 -0
  27. package/dist/src/config/loadConfig.d.ts.map +1 -0
  28. package/dist/src/config/loadConfig.js +69 -0
  29. package/dist/src/config/loadConfig.js.map +1 -0
  30. package/dist/src/core/context.d.ts +139 -0
  31. package/dist/src/core/context.d.ts.map +1 -0
  32. package/dist/src/core/context.js +293 -0
  33. package/dist/src/core/context.js.map +1 -0
  34. package/dist/src/core/lifecycle.d.ts +3 -0
  35. package/dist/src/core/lifecycle.d.ts.map +1 -0
  36. package/dist/src/core/lifecycle.js +14 -0
  37. package/dist/src/core/lifecycle.js.map +1 -0
  38. package/dist/src/core/runtime.d.ts +28 -0
  39. package/dist/src/core/runtime.d.ts.map +1 -0
  40. package/dist/src/core/runtime.js +104 -0
  41. package/dist/src/core/runtime.js.map +1 -0
  42. package/dist/src/cors/cors.d.ts +5 -0
  43. package/dist/src/cors/cors.d.ts.map +1 -0
  44. package/dist/src/cors/cors.js +75 -0
  45. package/dist/src/cors/cors.js.map +1 -0
  46. package/dist/src/events/eventBus.d.ts +19 -0
  47. package/dist/src/events/eventBus.d.ts.map +1 -0
  48. package/dist/src/events/eventBus.js +29 -0
  49. package/dist/src/events/eventBus.js.map +1 -0
  50. package/dist/src/events/eventExecutor.d.ts +5 -0
  51. package/dist/src/events/eventExecutor.d.ts.map +1 -0
  52. package/dist/src/events/eventExecutor.js +84 -0
  53. package/dist/src/events/eventExecutor.js.map +1 -0
  54. package/dist/src/index.d.ts +23 -0
  55. package/dist/src/index.d.ts.map +1 -0
  56. package/dist/src/index.js +13 -0
  57. package/dist/src/index.js.map +1 -0
  58. package/dist/src/json/fastStringify.d.ts +7 -0
  59. package/dist/src/json/fastStringify.d.ts.map +1 -0
  60. package/dist/src/json/fastStringify.js +73 -0
  61. package/dist/src/json/fastStringify.js.map +1 -0
  62. package/dist/src/loader/fileScanner.d.ts +18 -0
  63. package/dist/src/loader/fileScanner.d.ts.map +1 -0
  64. package/dist/src/loader/fileScanner.js +133 -0
  65. package/dist/src/loader/fileScanner.js.map +1 -0
  66. package/dist/src/loader/moduleCache.d.ts +3 -0
  67. package/dist/src/loader/moduleCache.d.ts.map +1 -0
  68. package/dist/src/loader/moduleCache.js +19 -0
  69. package/dist/src/loader/moduleCache.js.map +1 -0
  70. package/dist/src/loader/moduleLoader.d.ts +2 -0
  71. package/dist/src/loader/moduleLoader.d.ts.map +1 -0
  72. package/dist/src/loader/moduleLoader.js +4 -0
  73. package/dist/src/loader/moduleLoader.js.map +1 -0
  74. package/dist/src/logger/requestLogger.d.ts +20 -0
  75. package/dist/src/logger/requestLogger.d.ts.map +1 -0
  76. package/dist/src/logger/requestLogger.js +63 -0
  77. package/dist/src/logger/requestLogger.js.map +1 -0
  78. package/dist/src/middleware/middlewareLoader.d.ts +3 -0
  79. package/dist/src/middleware/middlewareLoader.d.ts.map +1 -0
  80. package/dist/src/middleware/middlewareLoader.js +28 -0
  81. package/dist/src/middleware/middlewareLoader.js.map +1 -0
  82. package/dist/src/middleware/middlewareResolver.d.ts +13 -0
  83. package/dist/src/middleware/middlewareResolver.d.ts.map +1 -0
  84. package/dist/src/middleware/middlewareResolver.js +72 -0
  85. package/dist/src/middleware/middlewareResolver.js.map +1 -0
  86. package/dist/src/middleware/middlewareRunner.d.ts +10 -0
  87. package/dist/src/middleware/middlewareRunner.d.ts.map +1 -0
  88. package/dist/src/middleware/middlewareRunner.js +27 -0
  89. package/dist/src/middleware/middlewareRunner.js.map +1 -0
  90. package/dist/src/middleware/middlewareTable.d.ts +6 -0
  91. package/dist/src/middleware/middlewareTable.d.ts.map +1 -0
  92. package/dist/src/middleware/middlewareTable.js +44 -0
  93. package/dist/src/middleware/middlewareTable.js.map +1 -0
  94. package/dist/src/pipeline/compose.d.ts +10 -0
  95. package/dist/src/pipeline/compose.d.ts.map +1 -0
  96. package/dist/src/pipeline/compose.js +35 -0
  97. package/dist/src/pipeline/compose.js.map +1 -0
  98. package/dist/src/pipeline/pipelineCache.d.ts +16 -0
  99. package/dist/src/pipeline/pipelineCache.d.ts.map +1 -0
  100. package/dist/src/pipeline/pipelineCache.js +73 -0
  101. package/dist/src/pipeline/pipelineCache.js.map +1 -0
  102. package/dist/src/plugin/pluginAPI.d.ts +63 -0
  103. package/dist/src/plugin/pluginAPI.d.ts.map +1 -0
  104. package/dist/src/plugin/pluginAPI.js +2 -0
  105. package/dist/src/plugin/pluginAPI.js.map +1 -0
  106. package/dist/src/plugin/pluginManager.d.ts +6 -0
  107. package/dist/src/plugin/pluginManager.d.ts.map +1 -0
  108. package/dist/src/plugin/pluginManager.js +16 -0
  109. package/dist/src/plugin/pluginManager.js.map +1 -0
  110. package/dist/src/router/matcher.d.ts +10 -0
  111. package/dist/src/router/matcher.d.ts.map +1 -0
  112. package/dist/src/router/matcher.js +69 -0
  113. package/dist/src/router/matcher.js.map +1 -0
  114. package/dist/src/router/radixTree.d.ts +24 -0
  115. package/dist/src/router/radixTree.d.ts.map +1 -0
  116. package/dist/src/router/radixTree.js +208 -0
  117. package/dist/src/router/radixTree.js.map +1 -0
  118. package/dist/src/router/routeLoader.d.ts +22 -0
  119. package/dist/src/router/routeLoader.d.ts.map +1 -0
  120. package/dist/src/router/routeLoader.js +94 -0
  121. package/dist/src/router/routeLoader.js.map +1 -0
  122. package/dist/src/router/routeTable.d.ts +25 -0
  123. package/dist/src/router/routeTable.d.ts.map +1 -0
  124. package/dist/src/router/routeTable.js +133 -0
  125. package/dist/src/router/routeTable.js.map +1 -0
  126. package/dist/src/router/router.d.ts +18 -0
  127. package/dist/src/router/router.d.ts.map +1 -0
  128. package/dist/src/router/router.js +158 -0
  129. package/dist/src/router/router.js.map +1 -0
  130. package/dist/src/schedules/parseSchedule.d.ts +15 -0
  131. package/dist/src/schedules/parseSchedule.d.ts.map +1 -0
  132. package/dist/src/schedules/parseSchedule.js +111 -0
  133. package/dist/src/schedules/parseSchedule.js.map +1 -0
  134. package/dist/src/schedules/runScheduler.d.ts +14 -0
  135. package/dist/src/schedules/runScheduler.d.ts.map +1 -0
  136. package/dist/src/schedules/runScheduler.js +58 -0
  137. package/dist/src/schedules/runScheduler.js.map +1 -0
  138. package/dist/src/schedules/scheduleLoader.d.ts +14 -0
  139. package/dist/src/schedules/scheduleLoader.d.ts.map +1 -0
  140. package/dist/src/schedules/scheduleLoader.js +122 -0
  141. package/dist/src/schedules/scheduleLoader.js.map +1 -0
  142. package/dist/src/schedules/types.d.ts +37 -0
  143. package/dist/src/schedules/types.d.ts.map +1 -0
  144. package/dist/src/schedules/types.js +2 -0
  145. package/dist/src/schedules/types.js.map +1 -0
  146. package/dist/src/server/errorHandler.d.ts +4 -0
  147. package/dist/src/server/errorHandler.d.ts.map +1 -0
  148. package/dist/src/server/errorHandler.js +10 -0
  149. package/dist/src/server/errorHandler.js.map +1 -0
  150. package/dist/src/server/requestHandler.d.ts +35 -0
  151. package/dist/src/server/requestHandler.d.ts.map +1 -0
  152. package/dist/src/server/requestHandler.js +439 -0
  153. package/dist/src/server/requestHandler.js.map +1 -0
  154. package/dist/src/server/server.d.ts +20 -0
  155. package/dist/src/server/server.d.ts.map +1 -0
  156. package/dist/src/server/server.js +74 -0
  157. package/dist/src/server/server.js.map +1 -0
  158. package/dist/src/tasks/scheduler.d.ts +10 -0
  159. package/dist/src/tasks/scheduler.d.ts.map +1 -0
  160. package/dist/src/tasks/scheduler.js +10 -0
  161. package/dist/src/tasks/scheduler.js.map +1 -0
  162. package/dist/src/tasks/taskRunner.d.ts +3 -0
  163. package/dist/src/tasks/taskRunner.d.ts.map +1 -0
  164. package/dist/src/tasks/taskRunner.js +4 -0
  165. package/dist/src/tasks/taskRunner.js.map +1 -0
  166. package/dist/src/trace/traceEngine.d.ts +45 -0
  167. package/dist/src/trace/traceEngine.d.ts.map +1 -0
  168. package/dist/src/trace/traceEngine.js +63 -0
  169. package/dist/src/trace/traceEngine.js.map +1 -0
  170. package/dist/src/trace/traceStore.d.ts +10 -0
  171. package/dist/src/trace/traceStore.d.ts.map +1 -0
  172. package/dist/src/trace/traceStore.js +10 -0
  173. package/dist/src/trace/traceStore.js.map +1 -0
  174. package/dist/src/utils/logger.d.ts +6 -0
  175. package/dist/src/utils/logger.d.ts.map +1 -0
  176. package/dist/src/utils/logger.js +21 -0
  177. package/dist/src/utils/logger.js.map +1 -0
  178. package/dist/src/utils/path.d.ts +2 -0
  179. package/dist/src/utils/path.d.ts.map +1 -0
  180. package/dist/src/utils/path.js +4 -0
  181. package/dist/src/utils/path.js.map +1 -0
  182. package/dist/src/validation/routeSchema.d.ts +77 -0
  183. package/dist/src/validation/routeSchema.d.ts.map +1 -0
  184. package/dist/src/validation/routeSchema.js +134 -0
  185. package/dist/src/validation/routeSchema.js.map +1 -0
  186. package/dist/src/validation/validateApp.d.ts +20 -0
  187. package/dist/src/validation/validateApp.d.ts.map +1 -0
  188. package/dist/src/validation/validateApp.js +23 -0
  189. package/dist/src/validation/validateApp.js.map +1 -0
  190. package/dist/src/validation/validateBody.d.ts +7 -0
  191. package/dist/src/validation/validateBody.d.ts.map +1 -0
  192. package/dist/src/validation/validateBody.js +8 -0
  193. package/dist/src/validation/validateBody.js.map +1 -0
  194. package/package.json +31 -0
@@ -0,0 +1,158 @@
1
+ import { dirname, relative, resolve } from "node:path";
2
+ import { getRadixTreeForMethod, getRouteTable, addRouteFileToTable } from "./routeTable.js";
3
+ import { loadRoute } from "./routeLoader.js";
4
+ const routeCache = new Map();
5
+ /** Cached resolved route for static routes (no params). */
6
+ const staticResolvedCache = new Map();
7
+ function routeCacheKey(appDir, filePath, method) {
8
+ return `${appDir}\0${filePath}\0${method}`;
9
+ }
10
+ function isPromise(v) {
11
+ return typeof v?.then === "function";
12
+ }
13
+ function getMiddlewarePathFromFile(appDir, filePath) {
14
+ const routerBase = resolve(appDir, "router");
15
+ const routeDir = dirname(resolve(filePath));
16
+ const rel = relative(routerBase, routeDir).replace(/\\/g, "/");
17
+ if (!rel || rel === ".")
18
+ return "/";
19
+ return "/" + rel;
20
+ }
21
+ /**
22
+ * Resolve route using per-method radix tree (find-my-way style): one tree per HTTP method,
23
+ * direct filePath from match, no method map lookup.
24
+ */
25
+ export function resolveRoute(method, pathname, appDir) {
26
+ const tree = getRadixTreeForMethod(appDir, method);
27
+ const match = tree.match(pathname);
28
+ if (!match)
29
+ return null;
30
+ const key = routeCacheKey(appDir, match.filePath, method);
31
+ const middlewarePath = getMiddlewarePathFromFile(appDir, match.filePath);
32
+ const cached = routeCache.get(key);
33
+ if (cached !== undefined && !isPromise(cached)) {
34
+ if (!cached)
35
+ return null;
36
+ const paramCount = Object.keys(match.params).length;
37
+ if (paramCount === 0) {
38
+ let resolved = staticResolvedCache.get(key);
39
+ if (!resolved) {
40
+ resolved = {
41
+ route: cached,
42
+ params: Object.create(null),
43
+ middlewarePath
44
+ };
45
+ staticResolvedCache.set(key, resolved);
46
+ }
47
+ return resolved;
48
+ }
49
+ return { route: cached, params: match.params, middlewarePath };
50
+ }
51
+ let loadPromise;
52
+ if (cached !== undefined && isPromise(cached)) {
53
+ loadPromise = cached;
54
+ }
55
+ else {
56
+ loadPromise = loadRoute(match.filePath, method, match.routeId);
57
+ routeCache.set(key, loadPromise);
58
+ }
59
+ return loadPromise.then((loaded) => {
60
+ routeCache.set(key, loaded);
61
+ if (!loaded)
62
+ return null;
63
+ return { route: loaded, params: match.params, middlewarePath };
64
+ });
65
+ }
66
+ /** Preload all routes and warm per-method radix trees so resolveRoute is sync. */
67
+ export async function preloadRoutes(appDir) {
68
+ const table = getRouteTable(appDir);
69
+ const byPath = new Map();
70
+ const methodsToWarm = new Set();
71
+ for (const r of table) {
72
+ let fileByMethod = byPath.get(r.pathname);
73
+ if (!fileByMethod) {
74
+ fileByMethod = {};
75
+ byPath.set(r.pathname, fileByMethod);
76
+ }
77
+ const m = r.method ?? "";
78
+ fileByMethod[m] = r.filePath;
79
+ if (m)
80
+ methodsToWarm.add(m);
81
+ else {
82
+ methodsToWarm.add("");
83
+ methodsToWarm.add("GET");
84
+ methodsToWarm.add("POST");
85
+ methodsToWarm.add("PUT");
86
+ methodsToWarm.add("PATCH");
87
+ methodsToWarm.add("DELETE");
88
+ methodsToWarm.add("HEAD");
89
+ methodsToWarm.add("OPTIONS");
90
+ }
91
+ }
92
+ const promises = [];
93
+ for (const [pathname, fileByMethod] of byPath) {
94
+ for (const [method, filePath] of Object.entries(fileByMethod)) {
95
+ // route.ts (method "") exports GET, POST, etc. per method — only cache under "" so we load with the real HTTP method on first request
96
+ const keys = method === "" ? [""] : [method];
97
+ const key = routeCacheKey(appDir, filePath, keys[0]);
98
+ if (routeCache.has(key))
99
+ continue;
100
+ const p = loadRoute(filePath, method, pathname);
101
+ for (const m of keys)
102
+ routeCache.set(routeCacheKey(appDir, filePath, m), p);
103
+ promises.push(p.then((loaded) => {
104
+ for (const m of keys)
105
+ routeCache.set(routeCacheKey(appDir, filePath, m), loaded);
106
+ }));
107
+ }
108
+ }
109
+ await Promise.all(promises);
110
+ for (const method of methodsToWarm) {
111
+ getRadixTreeForMethod(appDir, method);
112
+ }
113
+ }
114
+ const ALL_METHODS = ["", "GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
115
+ /** Reload handler cache for the given route file (dev hot reload). */
116
+ export async function reloadRoute(appDir, filePath) {
117
+ const table = getRouteTable(appDir);
118
+ const resolvedTarget = resolve(filePath);
119
+ const entries = table.filter((r) => resolve(r.filePath) === resolvedTarget);
120
+ if (entries.length === 0) {
121
+ // New route file not yet in the route table: add it and rebuild caches lazily.
122
+ addRouteFileToTable(appDir, filePath);
123
+ return;
124
+ }
125
+ const filePathForKey = entries[0].filePath;
126
+ const methodsToClear = new Set();
127
+ for (const r of entries) {
128
+ const m = r.method ?? "";
129
+ if (m)
130
+ methodsToClear.add(m);
131
+ else
132
+ ALL_METHODS.forEach((x) => methodsToClear.add(x));
133
+ }
134
+ for (const m of methodsToClear) {
135
+ const key = routeCacheKey(appDir, filePathForKey, m);
136
+ routeCache.delete(key);
137
+ staticResolvedCache.delete(key);
138
+ }
139
+ const promises = [];
140
+ const seen = new Set();
141
+ for (const r of entries) {
142
+ const method = r.method ?? "";
143
+ const keys = method === "" ? [""] : [method];
144
+ const cacheKey = routeCacheKey(appDir, filePathForKey, keys[0]);
145
+ if (seen.has(cacheKey))
146
+ continue;
147
+ seen.add(cacheKey);
148
+ const p = loadRoute(r.filePath, method, r.pathname);
149
+ for (const m of keys)
150
+ routeCache.set(routeCacheKey(appDir, filePathForKey, m), p);
151
+ promises.push(p.then((loaded) => {
152
+ for (const m of keys)
153
+ routeCache.set(routeCacheKey(appDir, filePathForKey, m), loaded);
154
+ }));
155
+ }
156
+ await Promise.all(promises);
157
+ }
158
+ //# sourceMappingURL=router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../../../src/router/router.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { ScheduleDef } from "./types.js";
2
+ /**
3
+ * Returns interval in ms for setInterval, or null if this is an "at" schedule (day/week/month).
4
+ */
5
+ export declare function getIntervalMs(def: ScheduleDef): number | null;
6
+ /**
7
+ * Returns true if this schedule runs at a specific time (day at, week day at, month date at).
8
+ */
9
+ export declare function isAtSchedule(def: ScheduleDef): boolean;
10
+ /**
11
+ * Get ms until the next run for "at" schedules (day at HH:MM, week day at HH:MM, month date at HH:MM).
12
+ * Never returns 0 so we avoid setTimeout(..., 0) and immediate re-runs.
13
+ */
14
+ export declare function getNextRunMs(def: ScheduleDef): number;
15
+ //# sourceMappingURL=parseSchedule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseSchedule.d.ts","sourceRoot":"","sources":["../../../src/schedules/parseSchedule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AA0C9C;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI,CAM7D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAKtD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,CAkCrD"}
@@ -0,0 +1,111 @@
1
+ const DAY_MS = 24 * 60 * 60 * 1000;
2
+ const HOUR_MS = 60 * 60 * 1000;
3
+ const MINUTE_MS = 60 * 1000;
4
+ const WEEKDAYS = {
5
+ sunday: 0,
6
+ monday: 1,
7
+ tuesday: 2,
8
+ wednesday: 3,
9
+ thursday: 4,
10
+ friday: 5,
11
+ saturday: 6
12
+ };
13
+ function parseTime(at) {
14
+ const match = /^(\d{1,2}):(\d{2})$/.exec(at.trim());
15
+ if (!match)
16
+ return { hours: 0, minutes: 0 };
17
+ return {
18
+ hours: Math.min(23, Math.max(0, parseInt(match[1], 10))),
19
+ minutes: Math.min(59, Math.max(0, parseInt(match[2], 10)))
20
+ };
21
+ }
22
+ /** Parse interval string like "5m", "10s", "1h" to ms. */
23
+ function parseIntervalEvery(every) {
24
+ const s = every.trim().toLowerCase();
25
+ const match = /^(\d+)\s*(s|sec|m|min|h|hr|d|day)s?$/.exec(s);
26
+ if (match) {
27
+ const n = parseInt(match[1], 10);
28
+ const unit = match[2];
29
+ if (unit === "s" || unit === "sec")
30
+ return n * 1000;
31
+ if (unit === "m" || unit === "min")
32
+ return n * MINUTE_MS;
33
+ if (unit === "h" || unit === "hr")
34
+ return n * HOUR_MS;
35
+ if (unit === "d" || unit === "day")
36
+ return n * DAY_MS;
37
+ }
38
+ if (s === "minute" || s === "1m")
39
+ return MINUTE_MS;
40
+ if (s === "hour" || s === "1h")
41
+ return HOUR_MS;
42
+ return null;
43
+ }
44
+ /**
45
+ * Returns interval in ms for setInterval, or null if this is an "at" schedule (day/week/month).
46
+ */
47
+ export function getIntervalMs(def) {
48
+ if (def.every === "minute")
49
+ return MINUTE_MS;
50
+ if (def.every === "hour")
51
+ return HOUR_MS;
52
+ const interval = parseIntervalEvery(def.every);
53
+ if (interval !== null)
54
+ return interval;
55
+ return null;
56
+ }
57
+ /**
58
+ * Returns true if this schedule runs at a specific time (day at, week day at, month date at).
59
+ */
60
+ export function isAtSchedule(def) {
61
+ if (def.every === "day" && "at" in def)
62
+ return true;
63
+ if (def.every === "week")
64
+ return true;
65
+ if (def.every === "month")
66
+ return true;
67
+ return false;
68
+ }
69
+ /**
70
+ * Get ms until the next run for "at" schedules (day at HH:MM, week day at HH:MM, month date at HH:MM).
71
+ * Never returns 0 so we avoid setTimeout(..., 0) and immediate re-runs.
72
+ */
73
+ export function getNextRunMs(def) {
74
+ const now = new Date();
75
+ const at = "at" in def && typeof def.at === "string" ? def.at : "00:00";
76
+ const { hours, minutes } = parseTime(at);
77
+ let ms;
78
+ if (def.every === "day") {
79
+ let next = new Date(now);
80
+ next.setHours(hours, minutes, 0, 0);
81
+ if (next.getTime() <= now.getTime())
82
+ next = new Date(next.getTime() + DAY_MS);
83
+ ms = next.getTime() - now.getTime();
84
+ }
85
+ else if (def.every === "week") {
86
+ const dayName = def.day ?? "monday";
87
+ const targetDay = WEEKDAYS[dayName.toLowerCase()] ?? 1;
88
+ let next = new Date(now);
89
+ next.setHours(hours, minutes, 0, 0);
90
+ let diff = targetDay - next.getDay();
91
+ if (diff < 0)
92
+ diff += 7;
93
+ else if (diff === 0 && next.getTime() <= now.getTime())
94
+ diff = 7;
95
+ next = new Date(next.getTime() + diff * DAY_MS);
96
+ ms = next.getTime() - now.getTime();
97
+ }
98
+ else if (def.every === "month") {
99
+ const date = def.date ?? 1;
100
+ let next = new Date(now.getFullYear(), now.getMonth(), date, hours, minutes, 0, 0);
101
+ if (next.getTime() <= now.getTime()) {
102
+ next = new Date(now.getFullYear(), now.getMonth() + 1, date, hours, minutes, 0, 0);
103
+ }
104
+ ms = next.getTime() - now.getTime();
105
+ }
106
+ else {
107
+ ms = DAY_MS;
108
+ }
109
+ return Math.max(1, ms);
110
+ }
111
+ //# sourceMappingURL=parseSchedule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseSchedule.js","sourceRoot":"","sources":["../../../src/schedules/parseSchedule.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AACnC,MAAM,OAAO,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAC/B,MAAM,SAAS,GAAG,EAAE,GAAG,IAAI,CAAC;AAE5B,MAAM,QAAQ,GAA2B;IACvC,MAAM,EAAE,CAAC;IACT,MAAM,EAAE,CAAC;IACT,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,CAAC;IACZ,QAAQ,EAAE,CAAC;IACX,MAAM,EAAE,CAAC;IACT,QAAQ,EAAE,CAAC;CACZ,CAAC;AAEF,SAAS,SAAS,CAAC,EAAU;IAC3B,MAAM,KAAK,GAAG,qBAAqB,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;IACpD,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;IAC5C,OAAO;QACL,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QACzD,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC,CAAC,CAAC;KAC5D,CAAC;AACJ,CAAC;AAED,0DAA0D;AAC1D,SAAS,kBAAkB,CAAC,KAAa;IACvC,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACrC,MAAM,KAAK,GAAG,sCAAsC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC7D,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC,CAAC;QAClC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,KAAK;YAAE,OAAO,CAAC,GAAG,IAAI,CAAC;QACpD,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,KAAK;YAAE,OAAO,CAAC,GAAG,SAAS,CAAC;QACzD,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO,CAAC,GAAG,OAAO,CAAC;QACtD,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,KAAK;YAAE,OAAO,CAAC,GAAG,MAAM,CAAC;IACxD,CAAC;IACD,IAAI,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IACnD,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,OAAO,CAAC;IAC/C,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,GAAgB;IAC5C,IAAI,GAAG,CAAC,KAAK,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAC7C,IAAI,GAAG,CAAC,KAAK,KAAK,MAAM;QAAE,OAAO,OAAO,CAAC;IACzC,MAAM,QAAQ,GAAG,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC/C,IAAI,QAAQ,KAAK,IAAI;QAAE,OAAO,QAAQ,CAAC;IACvC,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,GAAgB;IAC3C,IAAI,GAAG,CAAC,KAAK,KAAK,KAAK,IAAI,IAAI,IAAI,GAAG;QAAE,OAAO,IAAI,CAAC;IACpD,IAAI,GAAG,CAAC,KAAK,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IACtC,IAAI,GAAG,CAAC,KAAK,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC;IACvC,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,GAAgB;IAC3C,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,MAAM,EAAE,GAAG,IAAI,IAAI,GAAG,IAAI,OAAQ,GAAW,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAE,GAAW,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;IAC1F,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC;IAEzC,IAAI,EAAU,CAAC;IAEf,IAAI,GAAG,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;QACxB,IAAI,IAAI,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;QACzB,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACpC,IAAI,IAAI,CAAC,OAAO,EAAE,IAAI,GAAG,CAAC,OAAO,EAAE;YAAE,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,CAAC;QAC9E,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC;IACtC,CAAC;SAAM,IAAI,GAAG,CAAC,KAAK,KAAK,MAAM,EAAE,CAAC;QAChC,MAAM,OAAO,GAAI,GAAW,CAAC,GAAG,IAAI,QAAQ,CAAC;QAC7C,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,CAAC;QACvD,IAAI,IAAI,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;QACzB,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACpC,IAAI,IAAI,GAAG,SAAS,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QACrC,IAAI,IAAI,GAAG,CAAC;YAAE,IAAI,IAAI,CAAC,CAAC;aACnB,IAAI,IAAI,KAAK,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,IAAI,GAAG,CAAC,OAAO,EAAE;YAAE,IAAI,GAAG,CAAC,CAAC;QACjE,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,GAAG,MAAM,CAAC,CAAC;QAChD,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC;IACtC,CAAC;SAAM,IAAI,GAAG,CAAC,KAAK,KAAK,OAAO,EAAE,CAAC;QACjC,MAAM,IAAI,GAAI,GAAW,CAAC,IAAI,IAAI,CAAC,CAAC;QACpC,IAAI,IAAI,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,GAAG,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACnF,IAAI,IAAI,CAAC,OAAO,EAAE,IAAI,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC;YACpC,IAAI,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACrF,CAAC;QACD,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC;IACtC,CAAC;SAAM,CAAC;QACN,EAAE,GAAG,MAAM,CAAC;IACd,CAAC;IAED,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AACzB,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { LoadedTask, TaskContext } from "./types.js";
2
+ export type RunSchedulerOptions = {
3
+ ctx?: TaskContext;
4
+ onRun?: (taskName: string, ctx: TaskContext) => void | Promise<void>;
5
+ onComplete?: (taskName: string, ctx: TaskContext) => void | Promise<void>;
6
+ onError?: (taskName: string, err: unknown) => void;
7
+ };
8
+ /**
9
+ * Start the scheduler for the given tasks. Uses setInterval for interval-based schedules
10
+ * and setTimeout for "at" schedules (day/week/month), then reschedules.
11
+ * Does not return; call from a long-running process.
12
+ */
13
+ export declare function runScheduler(tasks: LoadedTask[], options?: RunSchedulerOptions): () => void;
14
+ //# sourceMappingURL=runScheduler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runScheduler.d.ts","sourceRoot":"","sources":["../../../src/schedules/runScheduler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG1D,MAAM,MAAM,mBAAmB,GAAG;IAChC,GAAG,CAAC,EAAE,WAAW,CAAC;IAClB,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrE,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1E,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;CACpD,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,OAAO,GAAE,mBAAwB,GAAG,MAAM,IAAI,CAiD/F"}
@@ -0,0 +1,58 @@
1
+ import { getIntervalMs, isAtSchedule, getNextRunMs } from "./parseSchedule.js";
2
+ /**
3
+ * Start the scheduler for the given tasks. Uses setInterval for interval-based schedules
4
+ * and setTimeout for "at" schedules (day/week/month), then reschedules.
5
+ * Does not return; call from a long-running process.
6
+ */
7
+ export function runScheduler(tasks, options = {}) {
8
+ const ctx = options.ctx ?? {};
9
+ const onRun = options.onRun ?? null;
10
+ const onComplete = options.onComplete ?? null;
11
+ const onError = options.onError ?? ((name, err) => console.error(`[legonode task ${name}]`, err));
12
+ const timeouts = [];
13
+ const intervals = [];
14
+ function runTask(task) {
15
+ void (async () => {
16
+ try {
17
+ if (onRun)
18
+ await onRun(task.name, ctx);
19
+ await task.run(ctx);
20
+ if (onComplete)
21
+ await onComplete(task.name, ctx);
22
+ }
23
+ catch (err) {
24
+ onError(task.name, err);
25
+ }
26
+ })();
27
+ }
28
+ function scheduleAt(task, def) {
29
+ // Use at least 1s delay so we don't reschedule in the same second and risk multiple runs (e.g. hot reload).
30
+ const ms = Math.max(1000, getNextRunMs(def));
31
+ const t = setTimeout(() => {
32
+ runTask(task);
33
+ scheduleAt(task, def);
34
+ }, ms);
35
+ timeouts.push(t);
36
+ }
37
+ for (const task of tasks) {
38
+ for (const def of task.schedule) {
39
+ const intervalMs = getIntervalMs(def);
40
+ if (intervalMs !== null) {
41
+ // First run after intervalMs, then every intervalMs (no run at startup)
42
+ const t = setInterval(() => runTask(task), intervalMs);
43
+ intervals.push(t);
44
+ continue;
45
+ }
46
+ if (isAtSchedule(def)) {
47
+ scheduleAt(task, def);
48
+ }
49
+ }
50
+ }
51
+ return function stop() {
52
+ for (const t of timeouts)
53
+ clearTimeout(t);
54
+ for (const t of intervals)
55
+ clearInterval(t);
56
+ };
57
+ }
58
+ //# sourceMappingURL=runScheduler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runScheduler.js","sourceRoot":"","sources":["../../../src/schedules/runScheduler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAS/E;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,KAAmB,EAAE,UAA+B,EAAE;IACjF,MAAM,GAAG,GAAgB,OAAO,CAAC,GAAG,IAAI,EAAE,CAAC;IAC3C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC;IACpC,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,IAAI,CAAC;IAC9C,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,kBAAkB,IAAI,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;IAClG,MAAM,QAAQ,GAAoC,EAAE,CAAC;IACrD,MAAM,SAAS,GAAqC,EAAE,CAAC;IAEvD,SAAS,OAAO,CAAC,IAAgB;QAC/B,KAAK,CAAC,KAAK,IAAI,EAAE;YACf,IAAI,CAAC;gBACH,IAAI,KAAK;oBAAE,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;gBACvC,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBACpB,IAAI,UAAU;oBAAE,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YACnD,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;IACP,CAAC;IAED,SAAS,UAAU,CAAC,IAAgB,EAAE,GAAqC;QACzE,4GAA4G;QAC5G,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;QAC7C,MAAM,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE;YACxB,OAAO,CAAC,IAAI,CAAC,CAAC;YACd,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACxB,CAAC,EAAE,EAAE,CAAC,CAAC;QACP,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACnB,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAChC,MAAM,UAAU,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;YACtC,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;gBACxB,wEAAwE;gBACxE,MAAM,CAAC,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC,CAAC;gBACvD,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAClB,SAAS;YACX,CAAC;YACD,IAAI,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;gBACtB,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,SAAS,IAAI;QAClB,KAAK,MAAM,CAAC,IAAI,QAAQ;YAAE,YAAY,CAAC,CAAC,CAAC,CAAC;QAC1C,KAAK,MAAM,CAAC,IAAI,SAAS;YAAE,aAAa,CAAC,CAAC,CAAC,CAAC;IAC9C,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { LoadedTask } from "./types.js";
2
+ export type ScheduleRunnerFn = (name: string, payload?: unknown) => void | Promise<void>;
3
+ /** Build a runner that invokes a schedule's run by name (e.g. "interval.example"). */
4
+ export declare function createScheduleRunner(tasks: LoadedTask[]): ScheduleRunnerFn;
5
+ export declare function getOrCreateScheduleRunner(appDir: string): Promise<ScheduleRunnerFn>;
6
+ export declare function clearScheduleRunnerCache(appDir?: string): void;
7
+ export type ScannedSchedule = {
8
+ name: string;
9
+ filePath: string;
10
+ };
11
+ export declare function scanScheduleFiles(appDir: string): ScannedSchedule[];
12
+ export declare function loadScheduleModule(filePath: string, cacheBust?: string): Promise<LoadedTask | null>;
13
+ export declare function loadSchedulesFromApp(appDir: string, cacheBust?: string): Promise<LoadedTask[]>;
14
+ //# sourceMappingURL=scheduleLoader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduleLoader.d.ts","sourceRoot":"","sources":["../../../src/schedules/scheduleLoader.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAyB,UAAU,EAA0B,MAAM,YAAY,CAAC;AAuB5F,MAAM,MAAM,gBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAIzF,sFAAsF;AACtF,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,gBAAgB,CAc1E;AAED,wBAAsB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CASzF;AAED,wBAAgB,wBAAwB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAG9D;AAOD,MAAM,MAAM,eAAe,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,eAAe,EAAE,CAoBnE;AAED,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAmB5B;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,UAAU,EAAE,CAAC,CAQvB"}
@@ -0,0 +1,122 @@
1
+ import { readdirSync } from "node:fs";
2
+ import { join, resolve, basename } from "node:path";
3
+ import { pathToFileURL } from "node:url";
4
+ import { invalidateModuleCache } from "../loader/moduleCache.js";
5
+ const CRON_EXTENSIONS = [".cron.ts", ".cron.js", ".cron.mts", ".cron.mjs"];
6
+ const CRON_DIR = "cron";
7
+ /** Convert task name (e.g. intervalExample) to schedule name (e.g. interval.example). */
8
+ function toScheduleName(name) {
9
+ if (!name.length)
10
+ return "";
11
+ const parts = [];
12
+ let current = name[0].toLowerCase();
13
+ for (let i = 1; i < name.length; i++) {
14
+ const c = name[i];
15
+ if (c >= "A" && c <= "Z") {
16
+ parts.push(current);
17
+ current = c.toLowerCase();
18
+ }
19
+ else {
20
+ current += c;
21
+ }
22
+ }
23
+ parts.push(current);
24
+ return parts.join(".");
25
+ }
26
+ const scheduleRunnerCache = new Map();
27
+ /** Build a runner that invokes a schedule's run by name (e.g. "interval.example"). */
28
+ export function createScheduleRunner(tasks) {
29
+ const byName = new Map();
30
+ for (const task of tasks) {
31
+ byName.set(toScheduleName(task.name), task);
32
+ }
33
+ return (name, payload) => {
34
+ const task = byName.get(name);
35
+ if (!task) {
36
+ console.warn(`[legonode] schedule not found: "${name}"`);
37
+ return;
38
+ }
39
+ const ctx = { payload };
40
+ return Promise.resolve(task.run(ctx));
41
+ };
42
+ }
43
+ export async function getOrCreateScheduleRunner(appDir) {
44
+ const key = resolve(appDir);
45
+ let runner = scheduleRunnerCache.get(key);
46
+ if (runner)
47
+ return runner;
48
+ const cacheBust = typeof process !== "undefined" ? process.env.LEGONODE_CRON_RELOAD_TOKEN : undefined;
49
+ const tasks = await loadSchedulesFromApp(appDir, cacheBust);
50
+ runner = createScheduleRunner(tasks);
51
+ scheduleRunnerCache.set(key, runner);
52
+ return runner;
53
+ }
54
+ export function clearScheduleRunnerCache(appDir) {
55
+ if (appDir)
56
+ scheduleRunnerCache.delete(resolve(appDir));
57
+ else
58
+ scheduleRunnerCache.clear();
59
+ }
60
+ function normalizeSchedule(schedule) {
61
+ if (Array.isArray(schedule))
62
+ return schedule;
63
+ return [schedule];
64
+ }
65
+ export function scanScheduleFiles(appDir) {
66
+ const base = resolve(appDir, CRON_DIR);
67
+ const list = [];
68
+ let entries;
69
+ try {
70
+ entries = readdirSync(base, { withFileTypes: true }).map((e) => ({
71
+ name: e.name,
72
+ isFile: e.isFile()
73
+ }));
74
+ }
75
+ catch {
76
+ return list;
77
+ }
78
+ for (const entry of entries) {
79
+ if (!entry.isFile)
80
+ continue;
81
+ const ext = CRON_EXTENSIONS.find((e) => entry.name.endsWith(e));
82
+ if (!ext)
83
+ continue;
84
+ const name = entry.name.slice(0, -ext.length);
85
+ list.push({ name, filePath: join(base, entry.name) });
86
+ }
87
+ return list;
88
+ }
89
+ export async function loadScheduleModule(filePath, cacheBust) {
90
+ try {
91
+ if (cacheBust)
92
+ invalidateModuleCache(filePath);
93
+ const url = pathToFileURL(filePath).href;
94
+ const importUrl = cacheBust ? `${url}?t=${cacheBust}` : url;
95
+ const mod = await import(importUrl);
96
+ const schedule = mod.schedule;
97
+ const run = mod.run;
98
+ if (schedule == null || typeof run !== "function")
99
+ return null;
100
+ const scheduleList = normalizeSchedule(schedule);
101
+ const name = (mod.name ?? basename(filePath).replace(/\.cron\.(ts|js|mts|mjs)$/i, "")) || "task";
102
+ return {
103
+ name,
104
+ schedule: scheduleList,
105
+ run: run
106
+ };
107
+ }
108
+ catch {
109
+ return null;
110
+ }
111
+ }
112
+ export async function loadSchedulesFromApp(appDir, cacheBust) {
113
+ const scanned = scanScheduleFiles(appDir);
114
+ const tasks = [];
115
+ for (const { filePath } of scanned) {
116
+ const task = await loadScheduleModule(filePath, cacheBust);
117
+ if (task)
118
+ tasks.push(task);
119
+ }
120
+ return tasks;
121
+ }
122
+ //# sourceMappingURL=scheduleLoader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduleLoader.js","sourceRoot":"","sources":["../../../src/schedules/scheduleLoader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * JSON-based schedule definition (no cron strings).
3
+ * Supports: every minute/hour, every day at, every week day at, every month date at, or interval (e.g. "5m", "10s").
4
+ */
5
+ export type ScheduleDef = {
6
+ every: "minute";
7
+ } | {
8
+ every: "hour";
9
+ } | {
10
+ every: "day";
11
+ at?: string;
12
+ } | {
13
+ every: "week";
14
+ day?: string;
15
+ at?: string;
16
+ } | {
17
+ every: "month";
18
+ date?: number;
19
+ at?: string;
20
+ } | {
21
+ every: string;
22
+ };
23
+ /** One task can have multiple schedules. */
24
+ export type Schedule = ScheduleDef | ScheduleDef[];
25
+ export type TaskContext = {
26
+ /** Reserved for app-specific services (e.g. db, reportService). */
27
+ services?: Record<string, unknown>;
28
+ /** Set when the schedule is triggered via ctx.schedule(name, payload). */
29
+ payload?: unknown;
30
+ };
31
+ export type TaskRunFn = (ctx: TaskContext) => void | Promise<void>;
32
+ export type LoadedTask = {
33
+ name: string;
34
+ schedule: ScheduleDef[];
35
+ run: TaskRunFn;
36
+ };
37
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/schedules/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,WAAW,GACnB;IAAE,KAAK,EAAE,QAAQ,CAAA;CAAE,GACnB;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GACjB;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7B;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5C;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9C;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtB,4CAA4C;AAC5C,MAAM,MAAM,QAAQ,GAAG,WAAW,GAAG,WAAW,EAAE,CAAC;AAEnD,MAAM,MAAM,WAAW,GAAG;IACxB,mEAAmE;IACnE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,0EAA0E;IAC1E,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE,WAAW,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnE,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,GAAG,EAAE,SAAS,CAAC;CAChB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/schedules/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ import type { ErrorHandlerResult } from "../config/loadConfig";
2
+ import type { LegonodeContext } from "../core/context";
3
+ export declare function defaultErrorHandler({ logger }: LegonodeContext, err?: unknown): ErrorHandlerResult;
4
+ //# sourceMappingURL=errorHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errorHandler.d.ts","sourceRoot":"","sources":["../../../src/server/errorHandler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEvD,wBAAgB,mBAAmB,CACjC,EAAE,MAAM,EAAE,EAAE,eAAe,EAC3B,GAAG,CAAC,EAAE,OAAO,GACZ,kBAAkB,CAQpB"}
@@ -0,0 +1,10 @@
1
+ export function defaultErrorHandler({ logger }, err) {
2
+ if (err) {
3
+ const message = err instanceof Error ? err.message : "Unknown error";
4
+ const status = err.status ?? 500;
5
+ logger.error(err);
6
+ return { status, json: { error: message } };
7
+ }
8
+ return { status: 500, json: { error: "Internal Server Error" } };
9
+ }
10
+ //# sourceMappingURL=errorHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errorHandler.js","sourceRoot":"","sources":["../../../src/server/errorHandler.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,mBAAmB,CACjC,EAAE,MAAM,EAAmB,EAC3B,GAAa;IAEb,IAAI,GAAG,EAAE,CAAC;QACR,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;QACrE,MAAM,MAAM,GAAI,GAA2B,CAAC,MAAM,IAAI,GAAG,CAAC;QAC1D,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAClB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC;IAC9C,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,uBAAuB,EAAE,EAAE,CAAC;AACnE,CAAC"}