@mandujs/core 0.9.3 โ†’ 0.9.4

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.
@@ -1,3 +1,3 @@
1
- export * from "./generate";
2
- export * from "./templates";
3
- export * from "./contract-glue";
1
+ export * from "./generate";
2
+ export * from "./templates";
3
+ export * from "./contract-glue";
@@ -1 +1 @@
1
- export * from "./build";
1
+ export * from "./build";
@@ -1,222 +1,222 @@
1
- /**
2
- * Mandu Middleware Compose ๐Ÿ”—
3
- * Hono ์Šคํƒ€์ผ ๋ฏธ๋“ค์›จ์–ด ์กฐํ•ฉ ํŒจํ„ด
4
- *
5
- * @see https://github.com/honojs/hono/blob/main/src/compose.ts
6
- */
7
-
8
- import type { ManduContext } from "../filling/context";
9
-
10
- /**
11
- * Next ํ•จ์ˆ˜ ํƒ€์ž…
12
- */
13
- export type Next = () => Promise<void>;
14
-
15
- /**
16
- * ๋ฏธ๋“ค์›จ์–ด ํ•จ์ˆ˜ ํƒ€์ž…
17
- * - Response ๋ฐ˜ํ™˜: ์ฒด์ธ ์ค‘๋‹จ (Guard ์—ญํ• )
18
- * - void ๋ฐ˜ํ™˜: ๋‹ค์Œ ๋ฏธ๋“ค์›จ์–ด ์‹คํ–‰
19
- */
20
- export type Middleware = (
21
- ctx: ManduContext,
22
- next: Next
23
- ) => Response | void | Promise<Response | void>;
24
-
25
- /**
26
- * ์—๋Ÿฌ ํ•ธ๋“ค๋Ÿฌ ํƒ€์ž…
27
- */
28
- export type ErrorHandler = (
29
- error: Error,
30
- ctx: ManduContext
31
- ) => Response | Promise<Response>;
32
-
33
- /**
34
- * NotFound ํ•ธ๋“ค๋Ÿฌ ํƒ€์ž…
35
- */
36
- export type NotFoundHandler = (ctx: ManduContext) => Response | Promise<Response>;
37
-
38
- /**
39
- * ๋ฏธ๋“ค์›จ์–ด ์—”ํŠธ๋ฆฌ (๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ํฌํ•จ)
40
- */
41
- export interface MiddlewareEntry {
42
- fn: Middleware;
43
- name?: string;
44
- isAsync?: boolean;
45
- }
46
-
47
- /**
48
- * Compose ์˜ต์…˜
49
- */
50
- export interface ComposeOptions {
51
- onError?: ErrorHandler;
52
- onNotFound?: NotFoundHandler;
53
- }
54
-
55
- /**
56
- * ๋ฏธ๋“ค์›จ์–ด ํ•จ์ˆ˜๋“ค์„ ํ•˜๋‚˜์˜ ์‹คํ–‰ ํ•จ์ˆ˜๋กœ ์กฐํ•ฉ
57
- *
58
- * @example
59
- * ```typescript
60
- * const middleware = [
61
- * { fn: async (ctx, next) => { console.log('before'); await next(); console.log('after'); } },
62
- * { fn: async (ctx, next) => { return ctx.ok({ data: 'hello' }); } },
63
- * ];
64
- *
65
- * const handler = compose(middleware, {
66
- * onError: (err, ctx) => ctx.json({ error: err.message }, 500),
67
- * onNotFound: (ctx) => ctx.notFound(),
68
- * });
69
- *
70
- * const response = await handler(context);
71
- * ```
72
- */
73
- export function compose(
74
- middleware: MiddlewareEntry[],
75
- options: ComposeOptions = {}
76
- ): (ctx: ManduContext) => Promise<Response> {
77
- const { onError, onNotFound } = options;
78
-
79
- return async (ctx: ManduContext): Promise<Response> => {
80
- let index = -1;
81
- let finalResponse: Response | undefined;
82
-
83
- /**
84
- * ๋ฏธ๋“ค์›จ์–ด ์ˆœ์ฐจ ์‹คํ–‰
85
- * @param i ํ˜„์žฌ ์ธ๋ฑ์Šค
86
- */
87
- async function dispatch(i: number): Promise<void> {
88
- // next() ์ด์ค‘ ํ˜ธ์ถœ ๋ฐฉ์ง€
89
- if (i <= index) {
90
- throw new Error("next() called multiple times");
91
- }
92
- index = i;
93
-
94
- const entry = middleware[i];
95
-
96
- if (!entry) {
97
- // ๋ชจ๋“  ๋ฏธ๋“ค์›จ์–ด ํ†ต๊ณผ ํ›„ ํ•ธ๋“ค๋Ÿฌ ์—†์Œ
98
- if (!finalResponse && onNotFound) {
99
- finalResponse = await onNotFound(ctx);
100
- }
101
- return;
102
- }
103
-
104
- try {
105
- const result = await entry.fn(ctx, () => dispatch(i + 1));
106
-
107
- // Response ๋ฐ˜ํ™˜ ์‹œ ์ฒด์ธ ์ค‘๋‹จ
108
- if (result instanceof Response) {
109
- finalResponse = result;
110
- return;
111
- }
112
- } catch (err) {
113
- if (err instanceof Error && onError) {
114
- finalResponse = await onError(err, ctx);
115
- return;
116
- }
117
- throw err;
118
- }
119
- }
120
-
121
- await dispatch(0);
122
-
123
- // ์‘๋‹ต์ด ์—†์œผ๋ฉด 404
124
- if (!finalResponse) {
125
- if (onNotFound) {
126
- finalResponse = await onNotFound(ctx);
127
- } else {
128
- finalResponse = new Response("Not Found", { status: 404 });
129
- }
130
- }
131
-
132
- return finalResponse;
133
- };
134
- }
135
-
136
- /**
137
- * ๋ฏธ๋“ค์›จ์–ด ๋ฐฐ์—ด ์ƒ์„ฑ ํ—ฌํผ
138
- *
139
- * @example
140
- * ```typescript
141
- * const mw = createMiddleware([
142
- * authGuard,
143
- * rateLimitGuard,
144
- * mainHandler,
145
- * ]);
146
- * ```
147
- */
148
- export function createMiddleware(
149
- fns: Middleware[]
150
- ): MiddlewareEntry[] {
151
- return fns.map((fn, i) => ({
152
- fn,
153
- name: fn.name || `middleware_${i}`,
154
- isAsync: fn.constructor.name === "AsyncFunction",
155
- }));
156
- }
157
-
158
- /**
159
- * ๋ฏธ๋“ค์›จ์–ด ์ฒด์ธ ๋นŒ๋”
160
- *
161
- * @example
162
- * ```typescript
163
- * const chain = new MiddlewareChain()
164
- * .use(authGuard)
165
- * .use(rateLimitGuard)
166
- * .use(mainHandler)
167
- * .onError((err, ctx) => ctx.json({ error: err.message }, 500))
168
- * .build();
169
- *
170
- * const response = await chain(ctx);
171
- * ```
172
- */
173
- export class MiddlewareChain {
174
- private middleware: MiddlewareEntry[] = [];
175
- private errorHandler?: ErrorHandler;
176
- private notFoundHandler?: NotFoundHandler;
177
-
178
- /**
179
- * ๋ฏธ๋“ค์›จ์–ด ์ถ”๊ฐ€
180
- */
181
- use(fn: Middleware, name?: string): this {
182
- this.middleware.push({
183
- fn,
184
- name: name || fn.name || `middleware_${this.middleware.length}`,
185
- isAsync: fn.constructor.name === "AsyncFunction",
186
- });
187
- return this;
188
- }
189
-
190
- /**
191
- * ์—๋Ÿฌ ํ•ธ๋“ค๋Ÿฌ ์„ค์ •
192
- */
193
- onError(handler: ErrorHandler): this {
194
- this.errorHandler = handler;
195
- return this;
196
- }
197
-
198
- /**
199
- * NotFound ํ•ธ๋“ค๋Ÿฌ ์„ค์ •
200
- */
201
- onNotFound(handler: NotFoundHandler): this {
202
- this.notFoundHandler = handler;
203
- return this;
204
- }
205
-
206
- /**
207
- * ๋ฏธ๋“ค์›จ์–ด ์ฒด์ธ ๋นŒ๋“œ
208
- */
209
- build(): (ctx: ManduContext) => Promise<Response> {
210
- return compose(this.middleware, {
211
- onError: this.errorHandler,
212
- onNotFound: this.notFoundHandler,
213
- });
214
- }
215
-
216
- /**
217
- * ๋ฏธ๋“ค์›จ์–ด ๋ชฉ๋ก ์กฐํšŒ
218
- */
219
- getMiddleware(): MiddlewareEntry[] {
220
- return [...this.middleware];
221
- }
222
- }
1
+ /**
2
+ * Mandu Middleware Compose ๐Ÿ”—
3
+ * Hono ์Šคํƒ€์ผ ๋ฏธ๋“ค์›จ์–ด ์กฐํ•ฉ ํŒจํ„ด
4
+ *
5
+ * @see https://github.com/honojs/hono/blob/main/src/compose.ts
6
+ */
7
+
8
+ import type { ManduContext } from "../filling/context";
9
+
10
+ /**
11
+ * Next ํ•จ์ˆ˜ ํƒ€์ž…
12
+ */
13
+ export type Next = () => Promise<void>;
14
+
15
+ /**
16
+ * ๋ฏธ๋“ค์›จ์–ด ํ•จ์ˆ˜ ํƒ€์ž…
17
+ * - Response ๋ฐ˜ํ™˜: ์ฒด์ธ ์ค‘๋‹จ (Guard ์—ญํ• )
18
+ * - void ๋ฐ˜ํ™˜: ๋‹ค์Œ ๋ฏธ๋“ค์›จ์–ด ์‹คํ–‰
19
+ */
20
+ export type Middleware = (
21
+ ctx: ManduContext,
22
+ next: Next
23
+ ) => Response | void | Promise<Response | void>;
24
+
25
+ /**
26
+ * ์—๋Ÿฌ ํ•ธ๋“ค๋Ÿฌ ํƒ€์ž…
27
+ */
28
+ export type ErrorHandler = (
29
+ error: Error,
30
+ ctx: ManduContext
31
+ ) => Response | Promise<Response>;
32
+
33
+ /**
34
+ * NotFound ํ•ธ๋“ค๋Ÿฌ ํƒ€์ž…
35
+ */
36
+ export type NotFoundHandler = (ctx: ManduContext) => Response | Promise<Response>;
37
+
38
+ /**
39
+ * ๋ฏธ๋“ค์›จ์–ด ์—”ํŠธ๋ฆฌ (๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ํฌํ•จ)
40
+ */
41
+ export interface MiddlewareEntry {
42
+ fn: Middleware;
43
+ name?: string;
44
+ isAsync?: boolean;
45
+ }
46
+
47
+ /**
48
+ * Compose ์˜ต์…˜
49
+ */
50
+ export interface ComposeOptions {
51
+ onError?: ErrorHandler;
52
+ onNotFound?: NotFoundHandler;
53
+ }
54
+
55
+ /**
56
+ * ๋ฏธ๋“ค์›จ์–ด ํ•จ์ˆ˜๋“ค์„ ํ•˜๋‚˜์˜ ์‹คํ–‰ ํ•จ์ˆ˜๋กœ ์กฐํ•ฉ
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * const middleware = [
61
+ * { fn: async (ctx, next) => { console.log('before'); await next(); console.log('after'); } },
62
+ * { fn: async (ctx, next) => { return ctx.ok({ data: 'hello' }); } },
63
+ * ];
64
+ *
65
+ * const handler = compose(middleware, {
66
+ * onError: (err, ctx) => ctx.json({ error: err.message }, 500),
67
+ * onNotFound: (ctx) => ctx.notFound(),
68
+ * });
69
+ *
70
+ * const response = await handler(context);
71
+ * ```
72
+ */
73
+ export function compose(
74
+ middleware: MiddlewareEntry[],
75
+ options: ComposeOptions = {}
76
+ ): (ctx: ManduContext) => Promise<Response> {
77
+ const { onError, onNotFound } = options;
78
+
79
+ return async (ctx: ManduContext): Promise<Response> => {
80
+ let index = -1;
81
+ let finalResponse: Response | undefined;
82
+
83
+ /**
84
+ * ๋ฏธ๋“ค์›จ์–ด ์ˆœ์ฐจ ์‹คํ–‰
85
+ * @param i ํ˜„์žฌ ์ธ๋ฑ์Šค
86
+ */
87
+ async function dispatch(i: number): Promise<void> {
88
+ // next() ์ด์ค‘ ํ˜ธ์ถœ ๋ฐฉ์ง€
89
+ if (i <= index) {
90
+ throw new Error("next() called multiple times");
91
+ }
92
+ index = i;
93
+
94
+ const entry = middleware[i];
95
+
96
+ if (!entry) {
97
+ // ๋ชจ๋“  ๋ฏธ๋“ค์›จ์–ด ํ†ต๊ณผ ํ›„ ํ•ธ๋“ค๋Ÿฌ ์—†์Œ
98
+ if (!finalResponse && onNotFound) {
99
+ finalResponse = await onNotFound(ctx);
100
+ }
101
+ return;
102
+ }
103
+
104
+ try {
105
+ const result = await entry.fn(ctx, () => dispatch(i + 1));
106
+
107
+ // Response ๋ฐ˜ํ™˜ ์‹œ ์ฒด์ธ ์ค‘๋‹จ
108
+ if (result instanceof Response) {
109
+ finalResponse = result;
110
+ return;
111
+ }
112
+ } catch (err) {
113
+ if (err instanceof Error && onError) {
114
+ finalResponse = await onError(err, ctx);
115
+ return;
116
+ }
117
+ throw err;
118
+ }
119
+ }
120
+
121
+ await dispatch(0);
122
+
123
+ // ์‘๋‹ต์ด ์—†์œผ๋ฉด 404
124
+ if (!finalResponse) {
125
+ if (onNotFound) {
126
+ finalResponse = await onNotFound(ctx);
127
+ } else {
128
+ finalResponse = new Response("Not Found", { status: 404 });
129
+ }
130
+ }
131
+
132
+ return finalResponse;
133
+ };
134
+ }
135
+
136
+ /**
137
+ * ๋ฏธ๋“ค์›จ์–ด ๋ฐฐ์—ด ์ƒ์„ฑ ํ—ฌํผ
138
+ *
139
+ * @example
140
+ * ```typescript
141
+ * const mw = createMiddleware([
142
+ * authGuard,
143
+ * rateLimitGuard,
144
+ * mainHandler,
145
+ * ]);
146
+ * ```
147
+ */
148
+ export function createMiddleware(
149
+ fns: Middleware[]
150
+ ): MiddlewareEntry[] {
151
+ return fns.map((fn, i) => ({
152
+ fn,
153
+ name: fn.name || `middleware_${i}`,
154
+ isAsync: fn.constructor.name === "AsyncFunction",
155
+ }));
156
+ }
157
+
158
+ /**
159
+ * ๋ฏธ๋“ค์›จ์–ด ์ฒด์ธ ๋นŒ๋”
160
+ *
161
+ * @example
162
+ * ```typescript
163
+ * const chain = new MiddlewareChain()
164
+ * .use(authGuard)
165
+ * .use(rateLimitGuard)
166
+ * .use(mainHandler)
167
+ * .onError((err, ctx) => ctx.json({ error: err.message }, 500))
168
+ * .build();
169
+ *
170
+ * const response = await chain(ctx);
171
+ * ```
172
+ */
173
+ export class MiddlewareChain {
174
+ private middleware: MiddlewareEntry[] = [];
175
+ private errorHandler?: ErrorHandler;
176
+ private notFoundHandler?: NotFoundHandler;
177
+
178
+ /**
179
+ * ๋ฏธ๋“ค์›จ์–ด ์ถ”๊ฐ€
180
+ */
181
+ use(fn: Middleware, name?: string): this {
182
+ this.middleware.push({
183
+ fn,
184
+ name: name || fn.name || `middleware_${this.middleware.length}`,
185
+ isAsync: fn.constructor.name === "AsyncFunction",
186
+ });
187
+ return this;
188
+ }
189
+
190
+ /**
191
+ * ์—๋Ÿฌ ํ•ธ๋“ค๋Ÿฌ ์„ค์ •
192
+ */
193
+ onError(handler: ErrorHandler): this {
194
+ this.errorHandler = handler;
195
+ return this;
196
+ }
197
+
198
+ /**
199
+ * NotFound ํ•ธ๋“ค๋Ÿฌ ์„ค์ •
200
+ */
201
+ onNotFound(handler: NotFoundHandler): this {
202
+ this.notFoundHandler = handler;
203
+ return this;
204
+ }
205
+
206
+ /**
207
+ * ๋ฏธ๋“ค์›จ์–ด ์ฒด์ธ ๋นŒ๋“œ
208
+ */
209
+ build(): (ctx: ManduContext) => Promise<Response> {
210
+ return compose(this.middleware, {
211
+ onError: this.errorHandler,
212
+ onNotFound: this.notFoundHandler,
213
+ });
214
+ }
215
+
216
+ /**
217
+ * ๋ฏธ๋“ค์›จ์–ด ๋ชฉ๋ก ์กฐํšŒ
218
+ */
219
+ getMiddleware(): MiddlewareEntry[] {
220
+ return [...this.middleware];
221
+ }
222
+ }
@@ -3,6 +3,6 @@ export * from "./router";
3
3
  export * from "./server";
4
4
  export * from "./cors";
5
5
  export * from "./env";
6
- export * from "./compose";
7
- export * from "./lifecycle";
8
- export * from "./trace";
6
+ export * from "./compose";
7
+ export * from "./lifecycle";
8
+ export * from "./trace";