@buenojs/bueno 0.8.4 → 0.8.5

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 (218) hide show
  1. package/README.md +136 -16
  2. package/dist/cli/{index.js → bin.js} +412 -331
  3. package/dist/container/index.js +250 -0
  4. package/dist/context/index.js +219 -0
  5. package/dist/database/index.js +493 -0
  6. package/dist/frontend/index.js +7697 -0
  7. package/dist/health/index.js +364 -0
  8. package/dist/i18n/index.js +345 -0
  9. package/dist/index.js +11043 -6482
  10. package/dist/jobs/index.js +819 -0
  11. package/dist/lock/index.js +367 -0
  12. package/dist/logger/index.js +281 -0
  13. package/dist/metrics/index.js +289 -0
  14. package/dist/middleware/index.js +77 -0
  15. package/dist/migrations/index.js +571 -0
  16. package/dist/modules/index.js +3346 -0
  17. package/dist/notification/index.js +484 -0
  18. package/dist/observability/index.js +331 -0
  19. package/dist/openapi/index.js +776 -0
  20. package/dist/orm/index.js +1356 -0
  21. package/dist/router/index.js +886 -0
  22. package/dist/rpc/index.js +691 -0
  23. package/dist/schema/index.js +400 -0
  24. package/dist/telemetry/index.js +595 -0
  25. package/dist/template/index.js +640 -0
  26. package/dist/templates/index.js +640 -0
  27. package/dist/testing/index.js +1111 -0
  28. package/dist/types/index.js +60 -0
  29. package/package.json +121 -27
  30. package/src/cache/index.ts +2 -1
  31. package/src/cli/bin.ts +2 -2
  32. package/src/cli/commands/build.ts +183 -165
  33. package/src/cli/commands/dev.ts +96 -89
  34. package/src/cli/commands/generate.ts +142 -111
  35. package/src/cli/commands/help.ts +20 -16
  36. package/src/cli/commands/index.ts +3 -6
  37. package/src/cli/commands/migration.ts +124 -105
  38. package/src/cli/commands/new.ts +294 -232
  39. package/src/cli/commands/start.ts +81 -79
  40. package/src/cli/core/args.ts +68 -50
  41. package/src/cli/core/console.ts +89 -95
  42. package/src/cli/core/index.ts +4 -4
  43. package/src/cli/core/prompt.ts +65 -62
  44. package/src/cli/core/spinner.ts +23 -20
  45. package/src/cli/index.ts +46 -38
  46. package/src/cli/templates/database/index.ts +37 -18
  47. package/src/cli/templates/database/mysql.ts +3 -3
  48. package/src/cli/templates/database/none.ts +2 -2
  49. package/src/cli/templates/database/postgresql.ts +3 -3
  50. package/src/cli/templates/database/sqlite.ts +3 -3
  51. package/src/cli/templates/deploy.ts +29 -26
  52. package/src/cli/templates/docker.ts +41 -30
  53. package/src/cli/templates/frontend/index.ts +33 -15
  54. package/src/cli/templates/frontend/none.ts +2 -2
  55. package/src/cli/templates/frontend/react.ts +18 -18
  56. package/src/cli/templates/frontend/solid.ts +15 -15
  57. package/src/cli/templates/frontend/svelte.ts +17 -17
  58. package/src/cli/templates/frontend/vue.ts +15 -15
  59. package/src/cli/templates/generators/index.ts +29 -29
  60. package/src/cli/templates/generators/types.ts +21 -21
  61. package/src/cli/templates/index.ts +6 -6
  62. package/src/cli/templates/project/api.ts +37 -36
  63. package/src/cli/templates/project/default.ts +25 -25
  64. package/src/cli/templates/project/fullstack.ts +28 -26
  65. package/src/cli/templates/project/index.ts +55 -16
  66. package/src/cli/templates/project/minimal.ts +17 -12
  67. package/src/cli/templates/project/types.ts +10 -5
  68. package/src/cli/templates/project/website.ts +14 -14
  69. package/src/cli/utils/fs.ts +55 -41
  70. package/src/cli/utils/index.ts +3 -3
  71. package/src/cli/utils/strings.ts +47 -33
  72. package/src/cli/utils/version.ts +14 -8
  73. package/src/config/env-validation.ts +100 -0
  74. package/src/config/env.ts +169 -41
  75. package/src/config/index.ts +28 -20
  76. package/src/config/loader.ts +25 -16
  77. package/src/config/merge.ts +21 -10
  78. package/src/config/types.ts +545 -25
  79. package/src/config/validation.ts +215 -7
  80. package/src/container/forward-ref.ts +22 -22
  81. package/src/container/index.ts +34 -12
  82. package/src/context/index.ts +11 -1
  83. package/src/database/index.ts +7 -190
  84. package/src/database/orm/builder.ts +457 -0
  85. package/src/database/orm/casts/index.ts +130 -0
  86. package/src/database/orm/casts/types.ts +25 -0
  87. package/src/database/orm/compiler.ts +304 -0
  88. package/src/database/orm/hooks/index.ts +114 -0
  89. package/src/database/orm/index.ts +61 -0
  90. package/src/database/orm/model-registry.ts +59 -0
  91. package/src/database/orm/model.ts +821 -0
  92. package/src/database/orm/relationships/base.ts +146 -0
  93. package/src/database/orm/relationships/belongs-to-many.ts +179 -0
  94. package/src/database/orm/relationships/belongs-to.ts +56 -0
  95. package/src/database/orm/relationships/has-many.ts +45 -0
  96. package/src/database/orm/relationships/has-one.ts +41 -0
  97. package/src/database/orm/relationships/index.ts +11 -0
  98. package/src/database/orm/scopes/index.ts +55 -0
  99. package/src/events/__tests__/event-system.test.ts +235 -0
  100. package/src/events/config.ts +238 -0
  101. package/src/events/example-usage.ts +185 -0
  102. package/src/events/index.ts +278 -0
  103. package/src/events/manager.ts +385 -0
  104. package/src/events/registry.ts +182 -0
  105. package/src/events/types.ts +124 -0
  106. package/src/frontend/api-routes.ts +65 -23
  107. package/src/frontend/bundler.ts +76 -34
  108. package/src/frontend/console-client.ts +2 -2
  109. package/src/frontend/console-stream.ts +94 -38
  110. package/src/frontend/dev-server.ts +94 -46
  111. package/src/frontend/file-router.ts +61 -19
  112. package/src/frontend/frameworks/index.ts +37 -10
  113. package/src/frontend/frameworks/react.ts +10 -8
  114. package/src/frontend/frameworks/solid.ts +11 -9
  115. package/src/frontend/frameworks/svelte.ts +15 -9
  116. package/src/frontend/frameworks/vue.ts +13 -11
  117. package/src/frontend/hmr-client.ts +12 -10
  118. package/src/frontend/hmr.ts +146 -103
  119. package/src/frontend/index.ts +14 -5
  120. package/src/frontend/islands.ts +41 -22
  121. package/src/frontend/isr.ts +59 -37
  122. package/src/frontend/layout.ts +36 -21
  123. package/src/frontend/ssr/react.ts +74 -27
  124. package/src/frontend/ssr/solid.ts +54 -20
  125. package/src/frontend/ssr/svelte.ts +48 -14
  126. package/src/frontend/ssr/vue.ts +50 -18
  127. package/src/frontend/ssr.ts +83 -39
  128. package/src/frontend/types.ts +91 -56
  129. package/src/health/index.ts +21 -9
  130. package/src/i18n/engine.ts +305 -0
  131. package/src/i18n/index.ts +38 -0
  132. package/src/i18n/loader.ts +218 -0
  133. package/src/i18n/middleware.ts +164 -0
  134. package/src/i18n/negotiator.ts +162 -0
  135. package/src/i18n/types.ts +158 -0
  136. package/src/index.ts +179 -27
  137. package/src/jobs/drivers/memory.ts +315 -0
  138. package/src/jobs/drivers/redis.ts +459 -0
  139. package/src/jobs/index.ts +30 -0
  140. package/src/jobs/queue.ts +281 -0
  141. package/src/jobs/types.ts +295 -0
  142. package/src/jobs/worker.ts +380 -0
  143. package/src/logger/index.ts +1 -3
  144. package/src/logger/transports/index.ts +62 -22
  145. package/src/metrics/index.ts +25 -16
  146. package/src/migrations/index.ts +9 -0
  147. package/src/modules/filters.ts +13 -17
  148. package/src/modules/guards.ts +49 -26
  149. package/src/modules/index.ts +409 -298
  150. package/src/modules/interceptors.ts +58 -20
  151. package/src/modules/lazy.ts +11 -19
  152. package/src/modules/lifecycle.ts +15 -7
  153. package/src/modules/metadata.ts +15 -5
  154. package/src/modules/pipes.ts +94 -72
  155. package/src/notification/channels/base.ts +68 -0
  156. package/src/notification/channels/email.ts +105 -0
  157. package/src/notification/channels/push.ts +104 -0
  158. package/src/notification/channels/sms.ts +105 -0
  159. package/src/notification/channels/whatsapp.ts +104 -0
  160. package/src/notification/index.ts +48 -0
  161. package/src/notification/service.ts +354 -0
  162. package/src/notification/types.ts +344 -0
  163. package/src/observability/__tests__/observability.test.ts +483 -0
  164. package/src/observability/breadcrumbs.ts +114 -0
  165. package/src/observability/index.ts +136 -0
  166. package/src/observability/interceptor.ts +85 -0
  167. package/src/observability/service.ts +303 -0
  168. package/src/observability/trace.ts +37 -0
  169. package/src/observability/types.ts +196 -0
  170. package/src/openapi/__tests__/decorators.test.ts +335 -0
  171. package/src/openapi/__tests__/document-builder.test.ts +285 -0
  172. package/src/openapi/__tests__/route-scanner.test.ts +334 -0
  173. package/src/openapi/__tests__/schema-generator.test.ts +275 -0
  174. package/src/openapi/decorators.ts +328 -0
  175. package/src/openapi/document-builder.ts +274 -0
  176. package/src/openapi/index.ts +112 -0
  177. package/src/openapi/metadata.ts +112 -0
  178. package/src/openapi/route-scanner.ts +289 -0
  179. package/src/openapi/schema-generator.ts +256 -0
  180. package/src/openapi/swagger-module.ts +166 -0
  181. package/src/openapi/types.ts +398 -0
  182. package/src/orm/index.ts +10 -0
  183. package/src/rpc/index.ts +3 -1
  184. package/src/schema/index.ts +9 -0
  185. package/src/security/index.ts +15 -6
  186. package/src/ssg/index.ts +9 -8
  187. package/src/telemetry/index.ts +76 -22
  188. package/src/template/index.ts +7 -0
  189. package/src/templates/engine.ts +224 -0
  190. package/src/templates/index.ts +9 -0
  191. package/src/templates/loader.ts +331 -0
  192. package/src/templates/renderers/markdown.ts +212 -0
  193. package/src/templates/renderers/simple.ts +269 -0
  194. package/src/templates/types.ts +154 -0
  195. package/src/testing/index.ts +100 -27
  196. package/src/types/optional-deps.d.ts +347 -187
  197. package/src/validation/index.ts +92 -2
  198. package/src/validation/schemas.ts +536 -0
  199. package/tests/integration/fullstack.test.ts +4 -4
  200. package/tests/unit/database.test.ts +2 -72
  201. package/tests/unit/env-validation.test.ts +166 -0
  202. package/tests/unit/events.test.ts +910 -0
  203. package/tests/unit/i18n.test.ts +455 -0
  204. package/tests/unit/jobs.test.ts +493 -0
  205. package/tests/unit/notification.test.ts +988 -0
  206. package/tests/unit/observability.test.ts +453 -0
  207. package/tests/unit/orm/builder.test.ts +323 -0
  208. package/tests/unit/orm/casts.test.ts +179 -0
  209. package/tests/unit/orm/compiler.test.ts +220 -0
  210. package/tests/unit/orm/eager-loading.test.ts +285 -0
  211. package/tests/unit/orm/hooks.test.ts +191 -0
  212. package/tests/unit/orm/model.test.ts +373 -0
  213. package/tests/unit/orm/relationships.test.ts +303 -0
  214. package/tests/unit/orm/scopes.test.ts +74 -0
  215. package/tests/unit/templates-simple.test.ts +53 -0
  216. package/tests/unit/templates.test.ts +454 -0
  217. package/tests/unit/validation.test.ts +18 -24
  218. package/tsconfig.json +11 -3
@@ -0,0 +1,182 @@
1
+ import {
2
+ type Event,
3
+ type EventCategory,
4
+ EventContext,
5
+ EventError,
6
+ type EventRegistry,
7
+ type EventRegistryOptions,
8
+ type EventRegistryState,
9
+ type EventStats,
10
+ } from "./types";
11
+
12
+ export class EventRegistryImpl implements EventRegistry {
13
+ private state: EventRegistryState;
14
+
15
+ constructor(options: EventRegistryOptions = {}) {
16
+ this.state = {
17
+ events: new Map(),
18
+ categories: new Map(),
19
+ config: {
20
+ maxEvents: options.maxEvents || 1000,
21
+ retentionPeriod: options.retentionPeriod || 24 * 60 * 60 * 1000, // 24 hours
22
+ cleanupInterval: options.cleanupInterval || 60 * 60 * 1000, // 1 hour
23
+ },
24
+ };
25
+
26
+ this.setupCleanup();
27
+ }
28
+
29
+ registerEvent(event: Event): void {
30
+ if (this.state.events.size >= this.state.config.maxEvents) {
31
+ this.cleanupOldEvents();
32
+ }
33
+
34
+ this.state.events.set(event.id, event);
35
+ }
36
+
37
+ getEvent(id: string): Event | undefined {
38
+ return this.state.events.get(id);
39
+ }
40
+
41
+ getEventsByCategory(category: string): Event[] {
42
+ return Array.from(this.state.events.values()).filter(
43
+ (event) => event.context?.category === category,
44
+ );
45
+ }
46
+
47
+ getAllEvents(): Event[] {
48
+ return Array.from(this.state.events.values());
49
+ }
50
+
51
+ getEventCategories(): EventCategory[] {
52
+ return Array.from(this.state.categories.values());
53
+ }
54
+
55
+ registerEventCategory(category: EventCategory): void {
56
+ this.state.categories.set(category.name, category);
57
+ }
58
+
59
+ getEventStats(): EventStats {
60
+ return {
61
+ totalEvents: this.state.events.size,
62
+ eventsPerSecond: this.calculateEventsPerSecond(),
63
+ listenersCount: 0, // Not tracked in registry
64
+ errorsCount: 0, // Not tracked in registry
65
+ averageProcessingTime: 0, // Not tracked in registry
66
+ };
67
+ }
68
+
69
+ clearEvents(): void {
70
+ this.state.events.clear();
71
+ }
72
+
73
+ private setupCleanup(): void {
74
+ setInterval(() => {
75
+ this.cleanupOldEvents();
76
+ }, this.state.config.cleanupInterval);
77
+ }
78
+
79
+ private cleanupOldEvents(): void {
80
+ const now = Date.now();
81
+ const retentionTime = now - this.state.config.retentionPeriod;
82
+
83
+ for (const [id, event] of this.state.events.entries()) {
84
+ if (event.timestamp.getTime() < retentionTime) {
85
+ this.state.events.delete(id);
86
+ }
87
+ }
88
+ }
89
+
90
+ private calculateEventsPerSecond(): number {
91
+ const now = Date.now();
92
+ const oneSecondAgo = now - 1000;
93
+ let count = 0;
94
+
95
+ for (const event of this.state.events.values()) {
96
+ if (event.timestamp.getTime() > oneSecondAgo) {
97
+ count++;
98
+ }
99
+ }
100
+
101
+ return count;
102
+ }
103
+
104
+ getEventHistory(options: {
105
+ category?: string;
106
+ startTime?: Date;
107
+ endTime?: Date;
108
+ limit?: number;
109
+ }): Event[] {
110
+ let events = Array.from(this.state.events.values());
111
+
112
+ if (options.category) {
113
+ events = events.filter(
114
+ (event) => event.context?.category === options.category,
115
+ );
116
+ }
117
+
118
+ if (options.startTime) {
119
+ events = events.filter((event) => event.timestamp >= options.startTime);
120
+ }
121
+
122
+ if (options.endTime) {
123
+ events = events.filter((event) => event.timestamp <= options.endTime);
124
+ }
125
+
126
+ // Sort first before applying limit
127
+ events = events.sort(
128
+ (a, b) => b.timestamp.getTime() - a.timestamp.getTime(),
129
+ );
130
+
131
+ if (options.limit) {
132
+ events = events.slice(0, options.limit);
133
+ }
134
+
135
+ return events;
136
+ }
137
+
138
+ searchEvents(query: string): Event[] {
139
+ const lowerQuery = query.toLowerCase();
140
+ return Array.from(this.state.events.values()).filter(
141
+ (event) =>
142
+ event.name.toLowerCase().includes(lowerQuery) ||
143
+ (event.data &&
144
+ JSON.stringify(event.data).toLowerCase().includes(lowerQuery)),
145
+ );
146
+ }
147
+
148
+ exportEvents(): Event[] {
149
+ return Array.from(this.state.events.values());
150
+ }
151
+
152
+ importEvents(events: Event[]): void {
153
+ events.forEach((event) => this.registerEvent(event));
154
+ }
155
+
156
+ getEventTimeline(): { timestamp: Date; eventCount: number }[] {
157
+ const timeline: { timestamp: Date; eventCount: number }[] = [];
158
+ const eventsByTime = new Map();
159
+
160
+ for (const event of this.state.events.values()) {
161
+ const timeKey = new Date(
162
+ event.timestamp.getTime() - (event.timestamp.getTime() % (60 * 1000)),
163
+ );
164
+ const count = eventsByTime.get(timeKey) || 0;
165
+ eventsByTime.set(timeKey, count + 1);
166
+ }
167
+
168
+ for (const [time, count] of eventsByTime.entries()) {
169
+ timeline.push({ timestamp: time, eventCount: count });
170
+ }
171
+
172
+ return timeline.sort(
173
+ (a, b) => a.timestamp.getTime() - b.timestamp.getTime(),
174
+ );
175
+ }
176
+ }
177
+
178
+ export function createEventRegistry(
179
+ options?: EventRegistryOptions,
180
+ ): EventRegistry {
181
+ return new EventRegistryImpl(options);
182
+ }
@@ -0,0 +1,124 @@
1
+ export interface Event {
2
+ id: string;
3
+ name: string;
4
+ timestamp: Date;
5
+ data: Record<string, any>;
6
+ context?: EventContext;
7
+ }
8
+
9
+ export interface EventContext {
10
+ userId?: string;
11
+ sessionId?: string;
12
+ requestId?: string;
13
+ ipAddress?: string;
14
+ userAgent?: string;
15
+ }
16
+
17
+ export interface EventListener {
18
+ id: string;
19
+ name: string;
20
+ handler: EventHandler;
21
+ filter?: EventFilter;
22
+ priority?: number;
23
+ once?: boolean;
24
+ }
25
+
26
+ export type EventHandler = (event: Event) => Promise<void> | void;
27
+
28
+ export type EventFilter = (event: Event) => boolean;
29
+
30
+ export interface EventCategory {
31
+ name: string;
32
+ description: string;
33
+ events: string[];
34
+ }
35
+
36
+ export interface EventManagerConfig {
37
+ maxListeners?: number;
38
+ eventCategories?: EventCategory[];
39
+ middleware?: EventMiddleware[];
40
+ }
41
+
42
+ export type EventMiddleware = (
43
+ event: Event,
44
+ next: () => Promise<void>,
45
+ ) => Promise<void>;
46
+
47
+ export interface EventRegistry {
48
+ registerEvent(event: Event): void;
49
+ getEvent(id: string): Event | undefined;
50
+ getEventsByCategory(category: string): Event[];
51
+ getAllEvents(): Event[];
52
+ }
53
+
54
+ export interface EventManager {
55
+ emit(event: Event): Promise<void>;
56
+ emitSync(event: Event): void;
57
+ on(event: string, listener: EventHandler): () => void;
58
+ once(event: string, listener: EventHandler): () => void;
59
+ off(event: string, listener: EventHandler): void;
60
+ addListener(listener: EventListener): void;
61
+ removeListener(listener: EventListener): void;
62
+ addFilter(filter: EventFilter): void;
63
+ removeFilter(filter: EventFilter): void;
64
+ addMiddleware(middleware: EventMiddleware): void;
65
+ removeMiddleware(middleware: EventMiddleware): void;
66
+ getListeners(event: string): EventListener[];
67
+ hasListeners(event: string): boolean;
68
+ clearListeners(event?: string): void;
69
+ getEventCategories(): EventCategory[];
70
+ registerEventCategory(category: EventCategory): void;
71
+ }
72
+
73
+ export interface EventError extends Error {
74
+ event: Event;
75
+ originalError?: Error;
76
+ }
77
+
78
+ export interface EventStats {
79
+ totalEvents: number;
80
+ eventsPerSecond: number;
81
+ listenersCount: number;
82
+ errorsCount: number;
83
+ averageProcessingTime: number;
84
+ }
85
+
86
+ export interface EventOptions {
87
+ context?: EventContext;
88
+ timestamp?: Date;
89
+ id?: string;
90
+ }
91
+
92
+ export interface EventListenerOptions {
93
+ priority?: number;
94
+ once?: boolean;
95
+ filter?: EventFilter;
96
+ }
97
+
98
+ export interface EventManagerOptions {
99
+ maxListeners?: number;
100
+ eventCategories?: EventCategory[];
101
+ middleware?: EventMiddleware[];
102
+ errorHandling?: "throw" | "log" | "ignore";
103
+ }
104
+
105
+ export interface EventRegistryOptions {
106
+ maxEvents?: number;
107
+ retentionPeriod?: number;
108
+ cleanupInterval?: number;
109
+ }
110
+
111
+ export interface EventManagerState {
112
+ listeners: Map<string, EventListener[]>;
113
+ filters: EventFilter[];
114
+ middleware: EventMiddleware[];
115
+ categories: EventCategory[];
116
+ stats: EventStats;
117
+ config: EventManagerConfig;
118
+ }
119
+
120
+ export interface EventRegistryState {
121
+ events: Map<string, Event>;
122
+ categories: Map<string, EventCategory>;
123
+ config: EventRegistryOptions;
124
+ }
@@ -9,24 +9,32 @@
9
9
  * - Type-safe response helpers
10
10
  */
11
11
 
12
- import { createLogger, type Logger } from "../logger/index.js";
12
+ import { type Logger, createLogger } from "../logger/index.js";
13
13
  import type {
14
+ APIContext,
15
+ APIMiddleware,
16
+ APIResponse,
14
17
  APIRouteConfig,
15
- PartialAPIRouteConfig,
16
18
  APIRouteDefinition,
17
19
  APIRouteHandler,
18
- APIContext,
19
- APIResponse,
20
- APIMiddleware,
21
20
  APIRouteModule,
22
21
  HTTPMethod,
22
+ PartialAPIRouteConfig,
23
23
  } from "./types.js";
24
24
 
25
25
  // ============= Constants =============
26
26
 
27
27
  const DEFAULT_API_DIR = "pages/api";
28
28
  const SUPPORTED_EXTENSIONS = [".ts", ".js"];
29
- const SUPPORTED_METHODS: HTTPMethod[] = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
29
+ const SUPPORTED_METHODS: HTTPMethod[] = [
30
+ "GET",
31
+ "POST",
32
+ "PUT",
33
+ "PATCH",
34
+ "DELETE",
35
+ "HEAD",
36
+ "OPTIONS",
37
+ ];
30
38
 
31
39
  // ============= API Route Manager Class =============
32
40
 
@@ -102,7 +110,10 @@ export class APIRouteManager {
102
110
  /**
103
111
  * Process a single API file
104
112
  */
105
- private async processAPIFile(filePath: string, basePath: string): Promise<void> {
113
+ private async processAPIFile(
114
+ filePath: string,
115
+ basePath: string,
116
+ ): Promise<void> {
106
117
  const fullPath = `${basePath}/${filePath}`;
107
118
  const routePath = this.filePathToRoute(filePath);
108
119
 
@@ -136,14 +147,18 @@ export class APIRouteManager {
136
147
  };
137
148
 
138
149
  this.routes.set(routePath, route);
139
- this.logger.debug(`Processed API route: ${routePath} [${methods.join(", ")}]`);
150
+ this.logger.debug(
151
+ `Processed API route: ${routePath} [${methods.join(", ")}]`,
152
+ );
140
153
  }
141
154
 
142
155
  /**
143
156
  * Load middlewares from _middleware.ts files
144
157
  */
145
158
  private async loadMiddlewares(basePath: string): Promise<void> {
146
- const glob = new Bun.Glob(`**/_middleware{${this.config.extensions.join(",")}}`);
159
+ const glob = new Bun.Glob(
160
+ `**/_middleware{${this.config.extensions.join(",")}}`,
161
+ );
147
162
 
148
163
  try {
149
164
  for await (const file of glob.scan(basePath)) {
@@ -261,7 +276,10 @@ export class APIRouteManager {
261
276
  /**
262
277
  * Match a request to an API route
263
278
  */
264
- match(method: string, pathname: string): { route: APIRouteDefinition; params: Record<string, string> } | null {
279
+ match(
280
+ method: string,
281
+ pathname: string,
282
+ ): { route: APIRouteDefinition; params: Record<string, string> } | null {
265
283
  for (const route of this.routes.values()) {
266
284
  const match = pathname.match(route.regex);
267
285
  if (match) {
@@ -316,8 +334,11 @@ export class APIRouteManager {
316
334
  } catch (error) {
317
335
  this.logger.error(`API error: ${pathname}`, error);
318
336
  return this.jsonResponse(
319
- { error: "Internal Server Error", message: error instanceof Error ? error.message : "Unknown error" },
320
- 500
337
+ {
338
+ error: "Internal Server Error",
339
+ message: error instanceof Error ? error.message : "Unknown error",
340
+ },
341
+ 500,
321
342
  );
322
343
  }
323
344
  }
@@ -339,7 +360,7 @@ export class APIRouteManager {
339
360
  */
340
361
  private async createContext(
341
362
  request: Request,
342
- params: Record<string, string>
363
+ params: Record<string, string>,
343
364
  ): Promise<APIContext> {
344
365
  const url = new URL(request.url);
345
366
 
@@ -361,7 +382,10 @@ export class APIRouteManager {
361
382
  body = await request.text();
362
383
  }
363
384
  } catch (error) {
364
- this.logger.warn("Failed to parse request body", error as Record<string, unknown>);
385
+ this.logger.warn(
386
+ "Failed to parse request body",
387
+ error as Record<string, unknown>,
388
+ );
365
389
  }
366
390
  }
367
391
 
@@ -419,7 +443,7 @@ export class APIRouteManager {
419
443
  context: APIContext,
420
444
  middlewares: APIMiddleware[],
421
445
  route: APIRouteDefinition,
422
- method: HTTPMethod
446
+ method: HTTPMethod,
423
447
  ): Promise<Response> {
424
448
  let index = 0;
425
449
 
@@ -509,7 +533,9 @@ export class APIRouteManager {
509
533
  /**
510
534
  * Create an API route manager
511
535
  */
512
- export function createAPIRouteManager(config: PartialAPIRouteConfig = {}): APIRouteManager {
536
+ export function createAPIRouteManager(
537
+ config: PartialAPIRouteConfig = {},
538
+ ): APIRouteManager {
513
539
  return new APIRouteManager(config);
514
540
  }
515
541
 
@@ -518,7 +544,11 @@ export function createAPIRouteManager(config: PartialAPIRouteConfig = {}): APIRo
518
544
  /**
519
545
  * Create a JSON response
520
546
  */
521
- export function json(data: unknown, status = 200, headers?: Record<string, string>): Response {
547
+ export function json(
548
+ data: unknown,
549
+ status = 200,
550
+ headers?: Record<string, string>,
551
+ ): Response {
522
552
  return new Response(JSON.stringify(data), {
523
553
  status,
524
554
  headers: {
@@ -531,7 +561,11 @@ export function json(data: unknown, status = 200, headers?: Record<string, strin
531
561
  /**
532
562
  * Create a text response
533
563
  */
534
- export function text(data: string, status = 200, headers?: Record<string, string>): Response {
564
+ export function text(
565
+ data: string,
566
+ status = 200,
567
+ headers?: Record<string, string>,
568
+ ): Response {
535
569
  return new Response(data, {
536
570
  status,
537
571
  headers: {
@@ -544,7 +578,11 @@ export function text(data: string, status = 200, headers?: Record<string, string
544
578
  /**
545
579
  * Create an HTML response
546
580
  */
547
- export function html(data: string, status = 200, headers?: Record<string, string>): Response {
581
+ export function html(
582
+ data: string,
583
+ status = 200,
584
+ headers?: Record<string, string>,
585
+ ): Response {
548
586
  return new Response(data, {
549
587
  status,
550
588
  headers: {
@@ -621,8 +659,10 @@ export function noContent(): Response {
621
659
  * Check if a file is an API route file
622
660
  */
623
661
  export function isAPIRouteFile(filename: string): boolean {
624
- return SUPPORTED_EXTENSIONS.some(ext => filename.endsWith(ext)) &&
625
- !filename.includes("_middleware");
662
+ return (
663
+ SUPPORTED_EXTENSIONS.some((ext) => filename.endsWith(ext)) &&
664
+ !filename.includes("_middleware")
665
+ );
626
666
  }
627
667
 
628
668
  /**
@@ -636,5 +676,7 @@ export function isMiddlewareFile(filename: string): boolean {
636
676
  * Get HTTP methods from module
637
677
  */
638
678
  export function getModuleMethods(module: APIRouteModule): HTTPMethod[] {
639
- return SUPPORTED_METHODS.filter(method => typeof module[method] === "function");
640
- }
679
+ return SUPPORTED_METHODS.filter(
680
+ (method) => typeof module[method] === "function",
681
+ );
682
+ }