@ozanarslan/corpus 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 (87) hide show
  1. package/LICENSE.txt +20 -0
  2. package/README.md +337 -0
  3. package/dist/App/index.d.ts +377 -0
  4. package/dist/App/index.d.ts.map +1 -0
  5. package/dist/C.namespace.d.ts +27 -0
  6. package/dist/C.namespace.d.ts.map +1 -0
  7. package/dist/Config/index.d.ts +163 -0
  8. package/dist/Config/index.d.ts.map +1 -0
  9. package/dist/Context/ContextAccess/index.d.ts +50 -0
  10. package/dist/Context/ContextAccess/index.d.ts.map +1 -0
  11. package/dist/Context/index.d.ts +162 -0
  12. package/dist/Context/index.d.ts.map +1 -0
  13. package/dist/Controller/index.d.ts +164 -0
  14. package/dist/Controller/index.d.ts.map +1 -0
  15. package/dist/Cookies/index.d.ts +81 -0
  16. package/dist/Cookies/index.d.ts.map +1 -0
  17. package/dist/Cors/index.d.ts +135 -0
  18. package/dist/Cors/index.d.ts.map +1 -0
  19. package/dist/Exception/index.d.ts +85 -0
  20. package/dist/Exception/index.d.ts.map +1 -0
  21. package/dist/Globals/AppsRegistry/index.d.ts +48 -0
  22. package/dist/Globals/AppsRegistry/index.d.ts.map +1 -0
  23. package/dist/Globals/ParsersRegistry/index.d.ts +93 -0
  24. package/dist/Globals/ParsersRegistry/index.d.ts.map +1 -0
  25. package/dist/Globals/index.d.ts +109 -0
  26. package/dist/Globals/index.d.ts.map +1 -0
  27. package/dist/Headers/index.d.ts +208 -0
  28. package/dist/Headers/index.d.ts.map +1 -0
  29. package/dist/Middleware/index.d.ts +125 -0
  30. package/dist/Middleware/index.d.ts.map +1 -0
  31. package/dist/ParserBase/BodyParser/index.d.ts +138 -0
  32. package/dist/ParserBase/BodyParser/index.d.ts.map +1 -0
  33. package/dist/ParserBase/FormDataParser/index.d.ts +57 -0
  34. package/dist/ParserBase/FormDataParser/index.d.ts.map +1 -0
  35. package/dist/ParserBase/SchemaParser/index.d.ts +143 -0
  36. package/dist/ParserBase/SchemaParser/index.d.ts.map +1 -0
  37. package/dist/ParserBase/SearchParamsParser/index.d.ts +61 -0
  38. package/dist/ParserBase/SearchParamsParser/index.d.ts.map +1 -0
  39. package/dist/ParserBase/URLParamsParser/index.d.ts +32 -0
  40. package/dist/ParserBase/URLParamsParser/index.d.ts.map +1 -0
  41. package/dist/ParserBase/index.d.ts +92 -0
  42. package/dist/ParserBase/index.d.ts.map +1 -0
  43. package/dist/RateLimiter/index.d.ts +321 -0
  44. package/dist/RateLimiter/index.d.ts.map +1 -0
  45. package/dist/Request/index.d.ts +81 -0
  46. package/dist/Request/index.d.ts.map +1 -0
  47. package/dist/Res/index.d.ts +353 -0
  48. package/dist/Res/index.d.ts.map +1 -0
  49. package/dist/RouteBase/BundleRoute/index.d.ts +268 -0
  50. package/dist/RouteBase/BundleRoute/index.d.ts.map +1 -0
  51. package/dist/RouteBase/FileRoute/index.d.ts +121 -0
  52. package/dist/RouteBase/FileRoute/index.d.ts.map +1 -0
  53. package/dist/RouteBase/Route/index.d.ts +83 -0
  54. package/dist/RouteBase/Route/index.d.ts.map +1 -0
  55. package/dist/RouteBase/StaticRoute/index.d.ts +149 -0
  56. package/dist/RouteBase/StaticRoute/index.d.ts.map +1 -0
  57. package/dist/RouteBase/WebSocketRoute/index.d.ts +117 -0
  58. package/dist/RouteBase/WebSocketRoute/index.d.ts.map +1 -0
  59. package/dist/RouteBase/index.d.ts +206 -0
  60. package/dist/RouteBase/index.d.ts.map +1 -0
  61. package/dist/Server/index.d.ts +44 -0
  62. package/dist/Server/index.d.ts.map +1 -0
  63. package/dist/XFile/index.d.ts +202 -0
  64. package/dist/XFile/index.d.ts.map +1 -0
  65. package/dist/exports.d.ts +11 -0
  66. package/dist/exports.d.ts.map +1 -0
  67. package/dist/index.d.ts +5 -0
  68. package/dist/index.d.ts.map +1 -0
  69. package/dist/index.js +12 -0
  70. package/dist/index.js.map +47 -0
  71. package/dist/initialize.d.ts +22 -0
  72. package/dist/initialize.d.ts.map +1 -0
  73. package/dist/utils/assert.d.ts +7 -0
  74. package/dist/utils/assert.d.ts.map +1 -0
  75. package/dist/utils/is.d.ts +17 -0
  76. package/dist/utils/is.d.ts.map +1 -0
  77. package/dist/utils/lazy.d.ts +27 -0
  78. package/dist/utils/lazy.d.ts.map +1 -0
  79. package/dist/utils/logger.d.ts +31 -0
  80. package/dist/utils/logger.d.ts.map +1 -0
  81. package/dist/utils/object.d.ts +20 -0
  82. package/dist/utils/object.d.ts.map +1 -0
  83. package/dist/utils/path.d.ts +6 -0
  84. package/dist/utils/path.d.ts.map +1 -0
  85. package/dist/utils/tuple.d.ts +3 -0
  86. package/dist/utils/tuple.d.ts.map +1 -0
  87. package/package.json +57 -0
@@ -0,0 +1,162 @@
1
+ /**
2
+ * The per-request object every handler receives.
3
+ *
4
+ * A {@link Context} carries the incoming request alongside the parsed views of
5
+ * it — {@link Context.body}, {@link Context.params}, {@link Context.search} —
6
+ * and the {@link Res} being built up in reply. It is created once per request by
7
+ * the {@link ContextFactory} on {@link App.contextFactory} and threaded through
8
+ * the whole {@link Middleware} chain, so it is also the place to hang state that
9
+ * one handler produces and another consumes.
10
+ *
11
+ * The parsed fields start out empty and are filled by {@link App} during the
12
+ * request lifecycle, but only for the surfaces a route's handlers actually read
13
+ * — {@link getContextAccess} decides that, so an untouched body is never parsed.
14
+ *
15
+ * @module Context
16
+ */
17
+ import { Res } from "../Res";
18
+ import type { Server } from "../Server";
19
+ import type { Maybe, MaybePromise } from "../utils/is";
20
+ /**
21
+ * Declaration target for {@link Context.data}, the request-scoped state shared
22
+ * between {@link Middleware} and route handlers.
23
+ *
24
+ * Empty by design. Augment it from your own code so everything a middleware sets
25
+ * is typed where a handler reads it:
26
+ *
27
+ * ```ts
28
+ * declare module "@ozanarslan/corpus" {
29
+ * interface ContextDataInterface {
30
+ * user: User;
31
+ * }
32
+ * }
33
+ * ```
34
+ */
35
+ interface ContextDataInterface {
36
+ }
37
+ /**
38
+ * Builds the {@link Context} for an incoming request. Assigned to
39
+ * {@link App.contextFactory}; replace it to have an app construct a
40
+ * {@link Context} subclass.
41
+ *
42
+ * @param request - The incoming request.
43
+ * @param server - The {@link Server} that accepted it, absent when the request
44
+ * was dispatched without one.
45
+ * @returns The context the request will be handled with.
46
+ * @typeParam B - Parsed {@link Context.body} type.
47
+ * @typeParam S - Parsed {@link Context.search} type.
48
+ * @typeParam P - Parsed {@link Context.params} type.
49
+ * @typeParam R - Response body type carried by {@link Context.res}.
50
+ */
51
+ type ContextFactory<B = unknown, S = unknown, P = unknown, R = unknown> = (request: Request, server: Maybe<Server>) => Context<B, S, P, R>;
52
+ /**
53
+ * A function that handles a request given its {@link Context}. This is the shape
54
+ * of a {@link RouteBase} handler and of the app-level hooks
55
+ * {@link App.handleNotFound} and {@link App.handlePreflight}.
56
+ *
57
+ * A {@link Middleware} handler is a {@link MiddlewareHandler} instead, since it
58
+ * additionally receives `next`.
59
+ *
60
+ * @param context - The {@link Context} for the request.
61
+ * @returns The response body, a {@link Res}, or a promise of either. Returning
62
+ * `undefined` leaves {@link Context.res} as the handler mutated it.
63
+ * @typeParam B - Parsed {@link Context.body} type.
64
+ * @typeParam S - Parsed {@link Context.search} type.
65
+ * @typeParam P - Parsed {@link Context.params} type.
66
+ * @typeParam R - Response body type.
67
+ */
68
+ type ContextHandler<B = unknown, S = unknown, P = unknown, R = unknown> = (context: Context<B, S, P, R>) => MaybePromise<R>;
69
+ /**
70
+ * Everything a handler needs to know about one request, and everything it uses
71
+ * to answer it.
72
+ *
73
+ * The type parameters are supplied by the route the context belongs to, so a
74
+ * handler sees its own validated shapes rather than `unknown`.
75
+ *
76
+ * {@link Context.res} and {@link Context.url} are lazy: neither the response
77
+ * object nor the parsed URL is constructed until something reads it, so a
78
+ * handler that returns a body without touching either pays for neither.
79
+ *
80
+ * The parsed containers are created with {@link createSafeObject}, so a payload
81
+ * carrying a `__proto__` key cannot reach `Object.prototype` through them.
82
+ *
83
+ * @typeParam B - Parsed {@link Context.body} type.
84
+ * @typeParam S - Parsed {@link Context.search} type.
85
+ * @typeParam P - Parsed {@link Context.params} type.
86
+ * @typeParam R - Response body type carried by {@link Context.res}.
87
+ */
88
+ declare class Context<B = unknown, S = unknown, P = unknown, R = unknown> {
89
+ /**
90
+ * Creates a context with empty parsed containers; {@link App} fills them
91
+ * during the request lifecycle.
92
+ *
93
+ * @param req - The incoming request.
94
+ * @param server - The {@link Server} that accepted it. Absent when the request
95
+ * was dispatched without one, which is why {@link Context.server} is optional
96
+ * at every use site — including the WebSocket upgrade.
97
+ */
98
+ constructor(req: Request, server: Maybe<Server>);
99
+ /**
100
+ * The parsed request body, decoded by {@link BodyParser} and validated against
101
+ * the route's {@link RouteConfig} body schema.
102
+ *
103
+ * Empty for {@link Method.GET} and {@link Method.HEAD} requests, and for any
104
+ * route whose handlers never read it.
105
+ */
106
+ body: B;
107
+ /**
108
+ * The path parameters matched by the route, parsed by
109
+ * {@link ParsersRegistry.urlParamsParser} and validated against the route's
110
+ * params schema. A wildcard segment is available under the `*` key.
111
+ */
112
+ params: P;
113
+ /**
114
+ * The query string, parsed by {@link ParsersRegistry.searchParamsParser} and
115
+ * validated against the route's search schema. Empty when the request carried
116
+ * no query string.
117
+ */
118
+ search: S;
119
+ /**
120
+ * Free-form request-scoped state, shared across the whole
121
+ * {@link Middleware} chain and the route handler. This is how a middleware
122
+ * hands something — an authenticated user, a request id — to what runs after
123
+ * it. Type it by augmenting {@link ContextDataInterface}.
124
+ */
125
+ data: ContextDataInterface;
126
+ /**
127
+ * The {@link Server} that accepted the request. Needed to upgrade a connection
128
+ * to a {@link WebSocketRoute}; absent when the request was dispatched without
129
+ * a server.
130
+ */
131
+ readonly server: Maybe<Server>;
132
+ /**
133
+ * The untouched incoming request. Read it for headers and for the raw body;
134
+ * the parsed views live on {@link Context.body} and its siblings.
135
+ */
136
+ readonly req: Request;
137
+ /** Backing store for {@link Context.res}, constructed on first access. */
138
+ private _res;
139
+ /**
140
+ * The response under construction. Mutate it to set status, headers or body
141
+ * before returning, or assign a whole new {@link Res} to replace it.
142
+ *
143
+ * A {@link Middleware} that replaces this after `next()` resolves wins over
144
+ * whatever the downstream handler returned — see {@link composeHandlerChain}.
145
+ *
146
+ * @returns The response object, created on first access.
147
+ */
148
+ get res(): Res<R>;
149
+ set res(value: Res<R>);
150
+ /** Backing store for {@link Context.url}, parsed on first access. */
151
+ private _url;
152
+ /**
153
+ * The request URL, parsed once and reused.
154
+ *
155
+ * @returns The parsed `URL`. Prefer {@link Context.params} and
156
+ * {@link Context.search} for path and query values; reach for this when you
157
+ * need the pathname or origin itself, as {@link BundleRoute} does.
158
+ */
159
+ get url(): URL;
160
+ }
161
+ export { Context, type ContextDataInterface, type ContextFactory, type ContextHandler };
162
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Context/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAC5B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAItD;;;;;;;;;;;;;;GAcG;AACH,UAAU,oBAAoB;CAAG;AAEjC;;;;;;;;;;;;;GAaG;AACH,KAAK,cAAc,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,IAAI,CACzE,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,KACjB,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAEzB;;;;;;;;;;;;;;;GAeG;AACH,KAAK,cAAc,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,IAAI,CACzE,OAAO,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KACxB,YAAY,CAAC,CAAC,CAAC,CAAC;AAErB;;;;;;;;;;;;;;;;;;GAkBG;AACH,cAAM,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO;IAC/D;;;;;;;;OAQG;gBACS,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC;IAW/C;;;;;;OAMG;IACH,IAAI,EAAE,CAAC,CAAC;IAER;;;;OAIG;IACH,MAAM,EAAE,CAAC,CAAC;IAEV;;;;OAIG;IACH,MAAM,EAAE,CAAC,CAAC;IAEV;;;;;OAKG;IACH,IAAI,EAAE,oBAAoB,CAAC;IAE3B;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAE/B;;;OAGG;IACH,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IAEtB,0EAA0E;IAC1E,OAAO,CAAC,IAAI,CAAkB;IAE9B;;;;;;;;OAQG;IACH,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAEhB;IAED,IAAI,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,EAEpB;IAED,qEAAqE;IACrE,OAAO,CAAC,IAAI,CAAY;IAExB;;;;;;OAMG;IACH,IAAI,GAAG,IAAI,GAAG,CAEb;CACD;AAED,OAAO,EAAE,OAAO,EAAE,KAAK,oBAAoB,EAAE,KAAK,cAAc,EAAE,KAAK,cAAc,EAAE,CAAC"}
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Grouping for routes that share a path prefix and a common preamble.
3
+ *
4
+ * A {@link Controller} is a thin factory: each method constructs the
5
+ * corresponding {@link RouteBase} subclass with the prefix already joined on,
6
+ * records its id, and returns it. The routes are ordinary routes registered on
7
+ * the nearest {@link App} exactly as if they had been constructed directly —
8
+ * a controller adds no dispatch layer of its own.
9
+ *
10
+ * ```ts
11
+ * import { Controller } from "@ozanarslan/corpus";
12
+ *
13
+ * const users = new Controller("/users");
14
+ * users.beforeEach = (c) => authenticate(c);
15
+ *
16
+ * users.route("GET /:id", (c) => findUser(c.params.id));
17
+ * ```
18
+ *
19
+ * @module Controller
20
+ */
21
+ import type { ContextHandler } from "../Context";
22
+ import { BundleRoute } from "../RouteBase/BundleRoute";
23
+ import { FileRoute } from "../RouteBase/FileRoute";
24
+ import { Route } from "../RouteBase/Route";
25
+ import { StaticRoute } from "../RouteBase/StaticRoute";
26
+ import { WebSocketRoute } from "../RouteBase/WebSocketRoute";
27
+ import type { Optional } from "../utils/is";
28
+ import { type WithPrefix } from "../utils/path";
29
+ /**
30
+ * Registers routes under a shared path prefix.
31
+ *
32
+ * Every method mirrors the constructor of the route class it creates, so moving
33
+ * a route into a controller means changing the call site and nothing else. The
34
+ * prefix is folded into the endpoint at construction time and into the endpoint
35
+ * *type* through {@link WithPrefix}, so the returned route stays as narrowly
36
+ * typed as one written out by hand.
37
+ *
38
+ * {@link Controller.beforeEach} runs ahead of the handler for the route kinds
39
+ * that have a user-supplied handler — {@link Controller.route} and
40
+ * {@link Controller.staticRoute}. The other kinds resolve their responses
41
+ * internally and are unaffected.
42
+ *
43
+ * {@link Controller.routeIds} makes the group addressable afterwards, which is
44
+ * how a {@link Middleware} can be attached to every route in a controller at
45
+ * once.
46
+ *
47
+ * @typeParam Px - The literal prefix type, carried into every endpoint type the
48
+ * controller produces.
49
+ */
50
+ declare class Controller<Px extends Optional<string> = Optional<string>> {
51
+ prefix?: Px | undefined;
52
+ /**
53
+ * Creates a controller.
54
+ *
55
+ * @param prefix - Path segment prepended to every endpoint registered through
56
+ * this controller. Omit it to group routes without changing their paths — the
57
+ * shared {@link Controller.beforeEach} and {@link Controller.routeIds} still
58
+ * apply.
59
+ */
60
+ constructor(prefix?: Px | undefined);
61
+ /**
62
+ * Ids of every {@link RouteBase} registered through this controller, in the
63
+ * order they were created.
64
+ *
65
+ * Pass them to a {@link Middleware} to target the whole group:
66
+ *
67
+ * ```ts
68
+ * new Middleware([...users.routeIds], handler);
69
+ * ```
70
+ */
71
+ readonly routeIds: Set<string>;
72
+ /**
73
+ * Runs before the handler of every {@link Controller.route} and
74
+ * {@link Controller.staticRoute} created by this controller.
75
+ *
76
+ * Its return value is discarded — this is for side effects on the
77
+ * {@link Context}, such as authenticating a request or populating
78
+ * {@link Context.data}. Throwing here aborts the request before the handler
79
+ * runs, which is the intended way to reject one.
80
+ *
81
+ * Assign it before registering routes: each route captures the controller, not
82
+ * the function, but a route registered while it is unset still checks it at
83
+ * request time. For behaviour that must wrap the response as well as precede
84
+ * it, use a {@link Middleware} targeting {@link Controller.routeIds} instead.
85
+ */
86
+ beforeEach?: ContextHandler;
87
+ /**
88
+ * Registers a dynamic route under this controller. Behaves identically to {@link Route}
89
+ * but automatically prepends the controller prefix and runs `beforeEach` before the handler.
90
+ *
91
+ * @param args - The {@link Route} constructor arguments: the route address
92
+ * (a `"METHOD /endpoint"` string or a method/endpoint pair), the
93
+ * {@link ContextHandler}, and an optional {@link RouteConfig}.
94
+ * @returns The registered {@link Route}, its endpoint type prefixed.
95
+ * @typeParam B - Parsed {@link Context.body} type.
96
+ * @typeParam S - Parsed {@link Context.search} type.
97
+ * @typeParam P - Parsed {@link Context.params} type.
98
+ * @typeParam R - Response body type.
99
+ * @typeParam E - The endpoint literal, before the prefix is applied.
100
+ */
101
+ route<B = unknown, S = unknown, P = unknown, R = unknown, E extends string = string>(...args: ConstructorParameters<typeof Route<B, S, P, R, E>>): Route<B, S, P, R, WithPrefix<Px, E>>;
102
+ /**
103
+ * Registers a static route under this controller. Behaves identically to {@link StaticRoute}
104
+ * but automatically prepends the controller prefix.
105
+ *
106
+ * {@link Controller.beforeEach} runs only when a callback is supplied, since
107
+ * that is where the controller has a handler to wrap; a static route that just
108
+ * serves its file is left alone.
109
+ *
110
+ * @param args - The {@link StaticRoute} constructor arguments: the route
111
+ * address, the file path, an optional callback receiving the
112
+ * {@link Context} and the file contents, and an optional
113
+ * {@link RouteConfig}.
114
+ * @returns The registered {@link StaticRoute}, its endpoint type prefixed.
115
+ * @typeParam B - Parsed {@link Context.body} type.
116
+ * @typeParam S - Parsed {@link Context.search} type.
117
+ * @typeParam P - Parsed {@link Context.params} type.
118
+ * @typeParam E - The endpoint literal, before the prefix is applied.
119
+ */
120
+ staticRoute<B = unknown, S = unknown, P = unknown, E extends string = string>(...args: ConstructorParameters<typeof StaticRoute<B, S, P, E>>): StaticRoute<B, S, P, WithPrefix<Px, E>>;
121
+ /**
122
+ * Registers a file route under this controller. Behaves identically to {@link FileRoute}
123
+ * but automatically prepends the controller prefix.
124
+ *
125
+ * {@link Controller.beforeEach} does not apply: a file route resolves its
126
+ * response internally and takes no handler to wrap.
127
+ *
128
+ * @param args - The {@link FileRoute} constructor arguments: the route address
129
+ * and the file definition.
130
+ * @returns The registered {@link FileRoute}, its endpoint type prefixed.
131
+ * @typeParam E - The endpoint literal, before the prefix is applied.
132
+ */
133
+ fileRoute<E extends string = string>(...args: ConstructorParameters<typeof FileRoute<E>>): FileRoute<WithPrefix<Px, E>>;
134
+ /**
135
+ * Registers a websocket route under this controller. Behaves identically to {@link WebSocketRoute}
136
+ * but automatically prepends the controller prefix.
137
+ *
138
+ * The address is a plain endpoint rather than a method-and-endpoint pair, since
139
+ * an upgrade is always a {@link Method.GET}.
140
+ * {@link Controller.beforeEach} does not apply — the socket lifecycle
141
+ * callbacks are not a {@link ContextHandler}.
142
+ *
143
+ * @param args - The {@link WebSocketRoute} constructor arguments: the endpoint
144
+ * followed by the socket lifecycle callbacks.
145
+ * @returns The registered {@link WebSocketRoute}, its endpoint type prefixed.
146
+ * @typeParam E - The endpoint literal, before the prefix is applied.
147
+ */
148
+ websocketRoute<E extends string = string>(...args: ConstructorParameters<typeof WebSocketRoute<E>>): WebSocketRoute<WithPrefix<Px, E>>;
149
+ /**
150
+ * Registers a bundle route under this controller. Behaves identically to {@link BundleRoute}
151
+ * but automatically prepends the controller prefix.
152
+ *
153
+ * {@link Controller.beforeEach} does not apply: a bundle route resolves files
154
+ * internally and takes no handler to wrap.
155
+ *
156
+ * @param args - The {@link BundleRoute} constructor arguments: the endpoint,
157
+ * the directory to serve, and an optional {@link BundleRouteDefinition}.
158
+ * @returns The registered {@link BundleRoute}, its endpoint type prefixed.
159
+ * @typeParam E - The endpoint literal, before the prefix is applied.
160
+ */
161
+ bundleRoute<E extends string = string>(...args: ConstructorParameters<typeof BundleRoute<E>>): BundleRoute<WithPrefix<Px, E>>;
162
+ }
163
+ export { Controller };
164
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Controller/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEhD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAEjE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,cAAM,UAAU,CAAC,EAAE,SAAS,QAAQ,CAAC,MAAM,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC;IAS3C,MAAM,CAAC,EAAE,EAAE;IAR9B;;;;;;;OAOG;gBACgB,MAAM,CAAC,EAAE,EAAE,YAAA;IAE9B;;;;;;;;;OASG;IACH,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAqB;IAEnD;;;;;;;;;;;;;OAaG;IACH,UAAU,CAAC,EAAE,cAAc,CAAC;IAE5B;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,EAClF,GAAG,IAAI,EAAE,qBAAqB,CAAC,OAAO,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,GACzD,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAiBvC;;;;;;;;;;;;;;;;;OAiBG;IACH,WAAW,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,EAC3E,GAAG,IAAI,EAAE,qBAAqB,CAAC,OAAO,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,GAC5D,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAoB1C;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAClC,GAAG,IAAI,EAAE,qBAAqB,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,GACjD,SAAS,CAAC,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAU/B;;;;;;;;;;;;;OAaG;IACH,cAAc,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EACvC,GAAG,IAAI,EAAE,qBAAqB,CAAC,OAAO,cAAc,CAAC,CAAC,CAAC,CAAC,GACtD,cAAc,CAAC,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAQpC;;;;;;;;;;;OAWG;IACH,WAAW,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EACpC,GAAG,IAAI,EAAE,qBAAqB,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,GACnD,WAAW,CAAC,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;CAOjC;AAED,OAAO,EAAE,UAAU,EAAE,CAAC"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Cookie reading and writing, built on Bun's native cookie primitives.
3
+ *
4
+ * {@link Cookies} extends `Bun.CookieMap`, so it keeps the whole native API —
5
+ * `get`, `set`, `delete`, iteration — and adds the two constructions the
6
+ * framework needs: parsing an inbound `Cookie` header and parsing outbound
7
+ * `Set-Cookie` headers back into a map.
8
+ *
9
+ * The two header formats are not interchangeable, which is why they get separate
10
+ * entry points: a `Cookie` header is a list of name/value pairs on one line with
11
+ * no attributes, while each `Set-Cookie` header is a single cookie carrying its
12
+ * own `Path`, `Max-Age`, `HttpOnly` and the rest.
13
+ *
14
+ * @module Cookies
15
+ */
16
+ /**
17
+ * Parses an inbound `Cookie` header into individual cookies.
18
+ *
19
+ * The header is a semicolon-separated list of name/value pairs with no
20
+ * attributes, so each pair is re-serialised on its own before being handed to
21
+ * Bun's parser. Malformed fragments that yield no name are skipped rather than
22
+ * throwing — a single bad pair from a client should not fail the request.
23
+ *
24
+ * @param cookieHeader - The raw `Cookie` header value.
25
+ * @returns The parsed cookies, in header order. Values keep whatever encoding
26
+ * the client sent.
27
+ */
28
+ declare function parseCookieHeader(cookieHeader: string): Array<Bun.Cookie>;
29
+ /**
30
+ * Parses `Set-Cookie` header values into individual cookies, attributes
31
+ * included.
32
+ *
33
+ * Each header carries exactly one cookie, so no splitting is needed — unlike
34
+ * {@link parseCookieHeader}, which has to break one header into many pairs.
35
+ *
36
+ * @param headers - The raw `Set-Cookie` header values, one per cookie. Use
37
+ * `Headers.getSetCookie()` to obtain them; a plain `get` collapses repeated
38
+ * headers into one string and loses the boundaries.
39
+ * @returns The parsed cookies, in the order given.
40
+ */
41
+ declare function parseSetCookieHeaders(headers: string[]): Array<Bun.Cookie>;
42
+ /**
43
+ * A cookie map with header-parsing constructors.
44
+ *
45
+ * Everything `Bun.CookieMap` offers is available unchanged; the two static
46
+ * methods are the additions. Use {@link Cookies.fromHeader} for what a client
47
+ * sent and {@link Cookies.fromSetCookieHeaders} for what a server is sending
48
+ * back — reading a response's own cookies, or following them in a client.
49
+ */
50
+ declare class Cookies extends Bun.CookieMap {
51
+ /**
52
+ * Creates a cookie map, forwarding to the native constructor.
53
+ *
54
+ * `Bun.CookieMap` is a native class that ignores `new.target`, so instances
55
+ * come back with the base prototype and none of the subclass members attached.
56
+ * The prototype is reattached here, which is what makes subclassing work at
57
+ * all.
58
+ *
59
+ * @param args - The native {@link Bun.CookieMap} constructor arguments.
60
+ */
61
+ constructor(...args: ConstructorParameters<typeof Bun.CookieMap>);
62
+ /**
63
+ * Builds a map from an inbound `Cookie` header.
64
+ *
65
+ * @param cookieHeader - The raw `Cookie` header value, as sent by the client.
66
+ * @returns The cookies it carried. Repeated names resolve to the last
67
+ * occurrence.
68
+ */
69
+ static fromHeader(cookieHeader: string): Cookies;
70
+ /**
71
+ * Builds a map from outbound `Set-Cookie` headers, preserving each cookie's
72
+ * attributes.
73
+ *
74
+ * @param headers - The raw `Set-Cookie` values, one per cookie.
75
+ * @returns The cookies they describe. Repeated names resolve to the last
76
+ * occurrence.
77
+ */
78
+ static fromSetCookieHeaders(headers: string[]): Cookies;
79
+ }
80
+ export { Cookies, parseCookieHeader, parseSetCookieHeaders };
81
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Cookies/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;;;;;GAWG;AACH,iBAAS,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAQlE;AAED;;;;;;;;;;;GAWG;AACH,iBAAS,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAMnE;AAED;;;;;;;GAOG;AACH,cAAM,OAAQ,SAAQ,GAAG,CAAC,SAAS;IAClC;;;;;;;;;OASG;gBACS,GAAG,IAAI,EAAE,qBAAqB,CAAC,OAAO,GAAG,CAAC,SAAS,CAAC;IAOhE;;;;;;OAMG;IACH,MAAM,CAAC,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAMhD;;;;;;;OAOG;IACH,MAAM,CAAC,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO;CAKvD;AAED,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,CAAC"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Cross-origin resource sharing.
3
+ *
4
+ * Constructing a {@link Cors} attaches it to the nearest {@link App}, which then
5
+ * calls it from two places: {@link App.respond} runs {@link Cors.handler} on
6
+ * every outgoing response, after the {@link Middleware} chain has finished, and
7
+ * {@link App.handlePreflight} delegates to {@link Cors.handlePreflight} for
8
+ * `OPTIONS` requests carrying
9
+ * {@link HeaderKey.AccessControlRequestMethod}. Running last is deliberate — a
10
+ * middleware that short-circuits the chain cannot drop the CORS headers.
11
+ *
12
+ * With no {@link Cors} attached, an app answers preflights with
13
+ * {@link Status.NO_CONTENT} and sends no CORS headers at all.
14
+ *
15
+ * ```ts
16
+ * import { Cors } from "@ozanarslan/corpus";
17
+ *
18
+ * new Cors({ allowedOrigins: ["https://example.com"], credentials: true });
19
+ * ```
20
+ *
21
+ * @module Cors
22
+ */
23
+ import type { ContextHandler } from "../Context";
24
+ import { HeaderKey } from "../Headers";
25
+ /**
26
+ * The CORS policy. Every field is optional; an omitted field means the
27
+ * corresponding header is not sent, with the exception of the origin, which
28
+ * falls back to a wildcard.
29
+ */
30
+ type CorsOptions = {
31
+ /** Which origins are allowed to access the resource. Use ["*"] for any origin, or specific domains. */
32
+ allowedOrigins?: string[];
33
+ /** Which HTTP methods are allowed (GET, POST, etc.) */
34
+ allowedMethods?: string[];
35
+ /** Which headers can be sent in the request */
36
+ allowedHeaders?: HeaderKey[];
37
+ /** Which headers should be exposed to the client/browser JavaScript
38
+ * These are response headers that the client can read
39
+ * @example ['RateLimit-Limit', 'RateLimit-Remaining', 'X-Custom-Header']
40
+ */
41
+ exposedHeaders?: HeaderKey[];
42
+ /** Whether to expose cookies and auth headers to the client */
43
+ credentials?: boolean;
44
+ /** How long (in seconds) browsers can cache preflight results. Default: 86400 (24 hours) */
45
+ maxAge?: number;
46
+ /**
47
+ * Whether {@link HeaderKey.AccessControlMaxAge} is sent on ordinary responses
48
+ * as well as on preflights. Preflights always carry it; browsers ignore it
49
+ * elsewhere.
50
+ */
51
+ includeMaxAgeResponseHeader?: boolean;
52
+ };
53
+ /**
54
+ * The public shape of a CORS policy, implemented by {@link Cors}. This is the
55
+ * type {@link App.cors} holds, so a custom policy only has to satisfy the
56
+ * contract.
57
+ */
58
+ interface CorsInterface {
59
+ /** The configured {@link CorsOptions}. */
60
+ opts?: CorsOptions;
61
+ /** Preflight handler for OPTIONS requests. */
62
+ handlePreflight: ContextHandler;
63
+ /** Applies CORS headers to an outgoing response. */
64
+ handler: ContextHandler;
65
+ }
66
+ /**
67
+ * Default {@link CorsInterface} implementation.
68
+ *
69
+ * Both entry points share {@link Cors.applyHeaders}, so a preflight and a real
70
+ * response describe the same policy. The preflight builds a fresh
71
+ * {@link Status.NO_CONTENT} {@link Res} — it never reaches a route handler —
72
+ * while the response path writes onto the {@link Res} that is already being
73
+ * returned.
74
+ */
75
+ declare class Cors implements CorsInterface {
76
+ opts?: CorsOptions | undefined;
77
+ /**
78
+ * Creates a policy and attaches it to the nearest {@link App}.
79
+ *
80
+ * @param opts - The {@link CorsOptions} to enforce. Omitting them yields a
81
+ * permissive wildcard origin with no method, header or exposure restrictions.
82
+ */
83
+ constructor(opts?: CorsOptions | undefined);
84
+ /**
85
+ * Attaches this policy to the nearest {@link App}, replacing any policy
86
+ * already set. Called by the constructor; an app holds exactly one.
87
+ */
88
+ register(): void;
89
+ /**
90
+ * Adds the CORS headers to an outgoing response.
91
+ *
92
+ * Called by {@link App.respond} for every response, after the handler chain
93
+ * has produced its result.
94
+ *
95
+ * @param c - The {@link Context} for the request, read for its `Origin` header
96
+ * and written to through {@link Context.res}.
97
+ */
98
+ handler: ContextHandler;
99
+ /**
100
+ * Preflight handler for OPTIONS requests.
101
+ *
102
+ * Answers with an empty {@link Status.NO_CONTENT} response carrying the full
103
+ * policy, including {@link HeaderKey.AccessControlMaxAge} so the browser can
104
+ * cache the result and skip the round trip on subsequent requests.
105
+ *
106
+ * @param c - The {@link Context} for the preflight request.
107
+ * @returns The preflight {@link Res}.
108
+ */
109
+ handlePreflight: ContextHandler;
110
+ /**
111
+ * Applies CORS headers to a Headers object given the request origin.
112
+ *
113
+ * Origin resolution has three outcomes. A wildcard policy sends `*`. A policy
114
+ * listing origins sends the request's own origin when it is listed, and no
115
+ * origin header at all when it is not — an unlisted origin is rejected by
116
+ * omission rather than by an error status. A wildcard policy combined with
117
+ * `credentials` reflects the request origin instead of `*`, because the spec
118
+ * forbids the wildcard in credentialed mode. Whenever the origin is reflected,
119
+ * {@link HeaderKey.Vary} is appended so caches key on it.
120
+ *
121
+ * The remaining list headers are written only when their option is a non-empty
122
+ * array, so an unset method or header list leaves the browser's defaults
123
+ * alone.
124
+ *
125
+ * @param headers - The response headers to write into.
126
+ * @param reqOrigin - The request's `Origin` header, or an empty string when it
127
+ * sent none.
128
+ * @param includeMaxAge - Whether to send
129
+ * {@link HeaderKey.AccessControlMaxAge}. Set for preflights, where it governs
130
+ * how long the browser caches the result. Defaults to `false`.
131
+ */
132
+ protected applyHeaders(headers: Headers, reqOrigin: string, includeMaxAge?: boolean): void;
133
+ }
134
+ export { Cors, type CorsInterface };
135
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Cors/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEhD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAItC;;;;GAIG;AACH,KAAK,WAAW,GAAG;IAClB,uGAAuG;IACvG,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,uDAAuD;IACvD,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,+CAA+C;IAC/C,cAAc,CAAC,EAAE,SAAS,EAAE,CAAC;IAC7B;;;OAGG;IACH,cAAc,CAAC,EAAE,SAAS,EAAE,CAAC;IAC7B,+DAA+D;IAC/D,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,4FAA4F;IAC5F,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,2BAA2B,CAAC,EAAE,OAAO,CAAC;CACtC,CAAC;AAEF;;;;GAIG;AACH,UAAU,aAAa;IACtB,0CAA0C;IAC1C,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,8CAA8C;IAC9C,eAAe,EAAE,cAAc,CAAC;IAChC,oDAAoD;IACpD,OAAO,EAAE,cAAc,CAAC;CACxB;AAED;;;;;;;;GAQG;AACH,cAAM,IAAK,YAAW,aAAa;IAOf,IAAI,CAAC,EAAE,WAAW;IANrC;;;;;OAKG;gBACgB,IAAI,CAAC,EAAE,WAAW,YAAA;IAIrC;;;OAGG;IACH,QAAQ,IAAI,IAAI;IAIhB;;;;;;;;OAQG;IACH,OAAO,EAAE,cAAc,CAErB;IAEF;;;;;;;;;OASG;IACH,eAAe,EAAE,cAAc,CAI7B;IAEF;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,SAAS,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,UAAQ,GAAG,IAAI;CA2CxF;AAED,OAAO,EAAE,IAAI,EAAE,KAAK,aAAa,EAAE,CAAC"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Throwing HTTP errors with a status attached.
3
+ *
4
+ * All errors are caught by {@link App.handleError}, whatever their type. What an
5
+ * {@link Exception} adds is the {@link Status} to answer with: it is rendered
6
+ * through {@link Exception.toRes}, message and detail intact, while an ordinary
7
+ * error becomes an opaque {@link Status.INTERNAL_SERVER_ERROR} so an accidental
8
+ * `TypeError` does not leak its message to the client.
9
+ *
10
+ * Throwing one is the intended way to end a request early:
11
+ *
12
+ * ```ts
13
+ * import { Exception, Status } from "@ozanarslan/corpus";
14
+ *
15
+ * if (!user) throw new Exception("User not found", Status.NOT_FOUND);
16
+ * ```
17
+ *
18
+ * Subclass it for errors you raise often, so the status and message live in one
19
+ * place rather than at every throw site.
20
+ *
21
+ * @module Exception
22
+ */
23
+ import { Res, Status } from "../Res";
24
+ /**
25
+ * An error carrying the {@link Status} it should be answered with.
26
+ *
27
+ * Beyond a status, an exception can carry {@link Exception.data} — either
28
+ * arbitrary detail to include in the error body, or a fully formed {@link Res}
29
+ * when the error response needs its own headers or shape.
30
+ */
31
+ declare class Exception extends Error {
32
+ /**
33
+ * Creates an exception for subclasses, which assign
34
+ * {@link Exception.message}, {@link Exception.status} and
35
+ * {@link Exception.data} themselves.
36
+ */
37
+ constructor();
38
+ /**
39
+ * Creates an exception to throw from a handler.
40
+ *
41
+ * @param message - Human-readable description. It is sent to the client, so
42
+ * write it for whoever receives the response.
43
+ * @param status - The {@link Status} to answer with.
44
+ * @param data - Optional detail attached to the response body under `error`,
45
+ * such as validation failures. Pass a {@link Res} instead to control the whole
46
+ * error response — see {@link Exception.toRes}.
47
+ */
48
+ constructor(message: string, status: Status, data?: unknown);
49
+ /** Human-readable description, sent to the client in the error body. */
50
+ message: string;
51
+ /** The {@link Status} the response is sent with. */
52
+ status: Status;
53
+ /**
54
+ * Optional detail. An arbitrary value is placed under `error` in the response
55
+ * body; a {@link Res} is used as the response itself.
56
+ */
57
+ data?: unknown;
58
+ /**
59
+ * Renders the exception as the response to send.
60
+ *
61
+ * When {@link Exception.data} is a {@link Res}, that response is used directly:
62
+ * its status is overwritten with {@link Exception.status}, the Exception
63
+ * message gets discarded. Otherwise a fresh {@link Res} is built with the
64
+ * message and the detail under `error`.
65
+ *
66
+ * @returns The {@link Res} for this error. Called by
67
+ * {@link App.handleError}.
68
+ */
69
+ toRes(): Res;
70
+ /**
71
+ * Checks the exception's status, by numeric value or by {@link Status} name.
72
+ *
73
+ * Useful when catching an exception to branch on what went wrong:
74
+ *
75
+ * ```ts
76
+ * if (err instanceof Exception && err.isStatusOf("NOT_FOUND")) { … }
77
+ * ```
78
+ *
79
+ * @param status - A {@link Status} value or one of its keys.
80
+ * @returns `true` when {@link Exception.status} matches.
81
+ */
82
+ isStatusOf(status: Status | keyof typeof Status): boolean;
83
+ }
84
+ export { Exception };
85
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Exception/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAGpC;;;;;;GAMG;AACH,cAAM,SAAU,SAAQ,KAAK;IAC5B;;;;OAIG;;IAEH;;;;;;;;;OASG;gBACS,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO;IAY3D,wEAAwE;IAC/D,OAAO,EAAG,MAAM,CAAC;IAE1B,oDAAoD;IACpD,MAAM,EAAG,MAAM,CAAC;IAEhB;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf;;;;;;;;;;OAUG;IACH,KAAK,IAAI,GAAG;IAQZ;;;;;;;;;;;OAWG;IACH,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,OAAO,MAAM,GAAG,OAAO;CAGzD;AAED,OAAO,EAAE,SAAS,EAAE,CAAC"}