@fluojs/http 2.0.1 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ko.md +417 -16
- package/README.md +424 -16
- package/dist/access-log-observer.d.ts +77 -0
- package/dist/access-log-observer.d.ts.map +1 -0
- package/dist/access-log-observer.js +171 -0
- package/dist/adapter.d.ts +9 -0
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +15 -1
- package/dist/adapters/binding.d.ts.map +1 -1
- package/dist/adapters/binding.js +18 -16
- package/dist/adapters/dto-binding-plan.d.ts +2 -2
- package/dist/adapters/dto-binding-plan.d.ts.map +1 -1
- package/dist/adapters/dto-binding-plan.js +13 -4
- package/dist/adapters/dto-validation-adapter.d.ts +2 -1
- package/dist/adapters/dto-validation-adapter.d.ts.map +1 -1
- package/dist/adapters/dto-validation-adapter.js +2 -2
- package/dist/byte-range-response.d.ts +71 -0
- package/dist/byte-range-response.d.ts.map +1 -0
- package/dist/byte-range-response.js +347 -0
- package/dist/client-identity.d.ts +8 -4
- package/dist/client-identity.d.ts.map +1 -1
- package/dist/client-identity.js +12 -93
- package/dist/compiled-route-identity.d.ts +17 -0
- package/dist/compiled-route-identity.d.ts.map +1 -0
- package/dist/compiled-route-identity.js +29 -0
- package/dist/connection.d.ts +67 -0
- package/dist/connection.d.ts.map +1 -0
- package/dist/connection.js +480 -0
- package/dist/context/request-context-node-store.d.ts +6 -0
- package/dist/context/request-context-node-store.d.ts.map +1 -1
- package/dist/context/request-context-node-store.js +14 -0
- package/dist/context/request-context.d.ts +5 -5
- package/dist/context/request-context.d.ts.map +1 -1
- package/dist/context/request-context.js +8 -83
- package/dist/context/request-id.d.ts +10 -0
- package/dist/context/request-id.d.ts.map +1 -0
- package/dist/context/request-id.js +27 -0
- package/dist/context/sse.d.ts +13 -0
- package/dist/context/sse.d.ts.map +1 -1
- package/dist/context/sse.js +36 -6
- package/dist/cookie-helpers.d.ts +47 -0
- package/dist/cookie-helpers.d.ts.map +1 -0
- package/dist/cookie-helpers.js +166 -0
- package/dist/decorators.d.ts +52 -19
- package/dist/decorators.d.ts.map +1 -1
- package/dist/decorators.js +57 -10
- package/dist/dispatch/conditional-request-policy.d.ts +67 -0
- package/dist/dispatch/conditional-request-policy.d.ts.map +1 -0
- package/dist/dispatch/conditional-request-policy.js +297 -0
- package/dist/dispatch/dispatch-content-negotiation.d.ts +8 -0
- package/dist/dispatch/dispatch-content-negotiation.d.ts.map +1 -1
- package/dist/dispatch/dispatch-content-negotiation.js +89 -42
- package/dist/dispatch/dispatch-error-negotiation.d.ts +26 -0
- package/dist/dispatch/dispatch-error-negotiation.d.ts.map +1 -0
- package/dist/dispatch/dispatch-error-negotiation.js +110 -0
- package/dist/dispatch/dispatch-error-policy.d.ts +1 -10
- package/dist/dispatch/dispatch-error-policy.d.ts.map +1 -1
- package/dist/dispatch/dispatch-error-policy.js +1 -33
- package/dist/dispatch/dispatch-error-representation.d.ts +18 -0
- package/dist/dispatch/dispatch-error-representation.d.ts.map +1 -0
- package/dist/dispatch/dispatch-error-representation.js +125 -0
- package/dist/dispatch/dispatch-response-metadata.d.ts +10 -0
- package/dist/dispatch/dispatch-response-metadata.d.ts.map +1 -0
- package/dist/dispatch/dispatch-response-metadata.js +12 -0
- package/dist/dispatch/dispatch-response-policy.d.ts +30 -3
- package/dist/dispatch/dispatch-response-policy.d.ts.map +1 -1
- package/dist/dispatch/dispatch-response-policy.js +104 -15
- package/dist/dispatch/dispatcher.d.ts +5 -1
- package/dist/dispatch/dispatcher.d.ts.map +1 -1
- package/dist/dispatch/dispatcher.js +140 -100
- package/dist/dispatch/fast-path/debug-visibility.d.ts.map +1 -1
- package/dist/dispatch/fast-path/debug-visibility.js +6 -3
- package/dist/dispatch/fast-path/dispatcher-state.d.ts +10 -0
- package/dist/dispatch/fast-path/dispatcher-state.d.ts.map +1 -0
- package/dist/dispatch/fast-path/dispatcher-state.js +52 -0
- package/dist/dispatch/fast-path/eligibility-checker.d.ts.map +1 -1
- package/dist/dispatch/fast-path/eligibility-checker.js +27 -15
- package/dist/dispatch/fast-path/eligibility.d.ts +16 -10
- package/dist/dispatch/fast-path/eligibility.d.ts.map +1 -1
- package/dist/dispatch/fast-path/eligibility.js +10 -4
- package/dist/dispatch/fast-path/fast-path-executor.d.ts +1 -1
- package/dist/dispatch/fast-path/fast-path-executor.d.ts.map +1 -1
- package/dist/dispatch/fast-path/fast-path-executor.js +8 -5
- package/dist/dispatch/request-abort.d.ts +22 -0
- package/dist/dispatch/request-abort.d.ts.map +1 -0
- package/dist/dispatch/request-abort.js +30 -0
- package/dist/dispatch/response-integration.d.ts +55 -0
- package/dist/dispatch/response-integration.d.ts.map +1 -0
- package/dist/dispatch/response-integration.js +57 -0
- package/dist/errors.d.ts +10 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +19 -0
- package/dist/guards.d.ts +1 -1
- package/dist/guards.d.ts.map +1 -1
- package/dist/header-helpers.d.ts +59 -0
- package/dist/header-helpers.d.ts.map +1 -0
- package/dist/header-helpers.js +185 -0
- package/dist/index.d.ts +1 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -15
- package/dist/index.portable.d.ts +25 -0
- package/dist/index.portable.d.ts.map +1 -0
- package/dist/index.portable.js +21 -0
- package/dist/internal.d.ts +3 -1
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +2 -0
- package/dist/mapping.d.ts.map +1 -1
- package/dist/mapping.js +100 -15
- package/dist/middleware/correlation.d.ts +9 -1
- package/dist/middleware/correlation.d.ts.map +1 -1
- package/dist/middleware/correlation.js +25 -14
- package/dist/middleware/cors.d.ts.map +1 -1
- package/dist/middleware/cors.js +5 -8
- package/dist/middleware/middleware.d.ts +3 -3
- package/dist/middleware/middleware.d.ts.map +1 -1
- package/dist/middleware/rate-limit.d.ts +13 -2
- package/dist/middleware/rate-limit.d.ts.map +1 -1
- package/dist/middleware/rate-limit.js +1 -0
- package/dist/static-assets.d.ts +77 -0
- package/dist/static-assets.d.ts.map +1 -0
- package/dist/static-assets.js +270 -0
- package/dist/types.d.ts +209 -16
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +69 -1
- package/package.json +19 -9
|
@@ -1,6 +1,31 @@
|
|
|
1
|
+
import { appendVaryHeader } from '../header-helpers.js';
|
|
2
|
+
import { applyResponseValidators } from './conditional-request-policy.js';
|
|
1
3
|
import { resolveContentNegotiation, selectResponseFormatter } from './dispatch-content-negotiation.js';
|
|
2
4
|
import { writeErrorResponse } from './dispatch-error-policy.js';
|
|
3
|
-
|
|
5
|
+
import { applyRouteHeaders } from './dispatch-response-metadata.js';
|
|
6
|
+
import { createByteRangeResponse, isByteRangeByteSource, shouldApplyByteRange } from '../byte-range-response.js';
|
|
7
|
+
import { FRAMEWORK_RESPONSE_VALUE_FINALIZER, FRAMEWORK_RESPONSE_WRITER } from './response-integration.js';
|
|
8
|
+
const BINARY_CONTENT_TYPE = 'application/octet-stream';
|
|
9
|
+
const JSON_CONTENT_TYPE = 'application/json; charset=utf-8';
|
|
10
|
+
const TEXT_CONTENT_TYPE = 'text/plain; charset=utf-8';
|
|
11
|
+
|
|
12
|
+
/** Selected representation metadata shared by success and conditional response writers. */
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Resolves the representation policy before conditional request evaluation.
|
|
16
|
+
*
|
|
17
|
+
* @param handler Matched route descriptor.
|
|
18
|
+
* @param request Adapter-normalized request.
|
|
19
|
+
* @param contentNegotiation Configured response formatters.
|
|
20
|
+
* @returns Formatter selection and representation variance metadata.
|
|
21
|
+
*/
|
|
22
|
+
export function resolveResponsePolicy(handler, request, contentNegotiation) {
|
|
23
|
+
const formatter = contentNegotiation ? selectResponseFormatter(handler, request, contentNegotiation) : undefined;
|
|
24
|
+
return {
|
|
25
|
+
formatter,
|
|
26
|
+
variesByAccept: formatter !== undefined
|
|
27
|
+
};
|
|
28
|
+
}
|
|
4
29
|
function resolveDefaultSuccessStatus(handler, value) {
|
|
5
30
|
switch (handler.route.method) {
|
|
6
31
|
case 'POST':
|
|
@@ -28,9 +53,16 @@ function readFrameworkResponseWriter(value) {
|
|
|
28
53
|
if (typeof value !== 'object' || value === null) {
|
|
29
54
|
return undefined;
|
|
30
55
|
}
|
|
31
|
-
const writer = Reflect.get(value,
|
|
56
|
+
const writer = Reflect.get(value, FRAMEWORK_RESPONSE_WRITER);
|
|
32
57
|
return typeof writer === 'function' ? writer : undefined;
|
|
33
58
|
}
|
|
59
|
+
function readFrameworkResponseValueFinalizer(requestContext) {
|
|
60
|
+
const finalizer = requestContext.metadata[FRAMEWORK_RESPONSE_VALUE_FINALIZER];
|
|
61
|
+
if (typeof finalizer !== 'function') {
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
return context => Reflect.apply(finalizer, undefined, [context]);
|
|
65
|
+
}
|
|
34
66
|
function isResponseBodyForbidden(status) {
|
|
35
67
|
return status === 204 || status === 205 || status === 304;
|
|
36
68
|
}
|
|
@@ -54,9 +86,7 @@ function applySuccessResponseMetadata(context) {
|
|
|
54
86
|
response,
|
|
55
87
|
value
|
|
56
88
|
} = context;
|
|
57
|
-
|
|
58
|
-
response.setHeader(header.name, header.value);
|
|
59
|
-
}
|
|
89
|
+
applyRouteHeaders(handler, response);
|
|
60
90
|
if (formatter) {
|
|
61
91
|
response.setHeader('Content-Type', formatter.mediaType);
|
|
62
92
|
}
|
|
@@ -66,6 +96,16 @@ function applySuccessResponseMetadata(context) {
|
|
|
66
96
|
response.setStatus(resolveDefaultSuccessStatus(handler, value));
|
|
67
97
|
}
|
|
68
98
|
}
|
|
99
|
+
function applyImplicitHeadContentType(response, value) {
|
|
100
|
+
if (readHeader(response.headers, 'content-type') !== undefined || value === undefined) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (value instanceof Uint8Array || value instanceof ArrayBuffer) {
|
|
104
|
+
response.setHeader('Content-Type', BINARY_CONTENT_TYPE);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
response.setHeader('Content-Type', typeof value === 'string' ? TEXT_CONTENT_TYPE : JSON_CONTENT_TYPE);
|
|
108
|
+
}
|
|
69
109
|
|
|
70
110
|
/**
|
|
71
111
|
* Write success response.
|
|
@@ -74,11 +114,13 @@ function applySuccessResponseMetadata(context) {
|
|
|
74
114
|
* @param request The request.
|
|
75
115
|
* @param response The response.
|
|
76
116
|
* @param value The value.
|
|
77
|
-
* @param contentNegotiation The
|
|
117
|
+
* @param contentNegotiation The configured response formatters.
|
|
78
118
|
* @param requestContext The active request context passed to custom response writers.
|
|
119
|
+
* @param validators Validators resolved before the route handler executes.
|
|
120
|
+
* @param conditionalOutcome Matched conditional outcome for formatter-managed responses.
|
|
79
121
|
* @returns The write success response result.
|
|
80
122
|
*/
|
|
81
|
-
export function writeSuccessResponse(handler, request, response, value, contentNegotiation, requestContext) {
|
|
123
|
+
export async function writeSuccessResponse(handler, request, response, value, contentNegotiation, requestContext, validators, conditionalOutcome) {
|
|
82
124
|
if (response.committed) {
|
|
83
125
|
return;
|
|
84
126
|
}
|
|
@@ -87,11 +129,22 @@ export function writeSuccessResponse(handler, request, response, value, contentN
|
|
|
87
129
|
url,
|
|
88
130
|
statusCode = 302
|
|
89
131
|
} = handler.route.redirect;
|
|
132
|
+
applyResponseValidators(response, validators);
|
|
90
133
|
response.redirect(statusCode, url);
|
|
91
134
|
return;
|
|
92
135
|
}
|
|
93
|
-
const
|
|
136
|
+
const responseValueFinalizer = readFrameworkResponseValueFinalizer(requestContext);
|
|
137
|
+
const responseValue = responseValueFinalizer ? await responseValueFinalizer({
|
|
138
|
+
handler,
|
|
139
|
+
request,
|
|
140
|
+
requestContext,
|
|
141
|
+
response,
|
|
142
|
+
value
|
|
143
|
+
}) : value;
|
|
144
|
+
const writerValue = readFrameworkResponseWriter(responseValue) ? responseValue : isByteRangeByteSource(responseValue) && shouldApplyByteRange(request, validators) ? createByteRangeResponse(responseValue) : undefined;
|
|
145
|
+
const responseWriter = writerValue ? readFrameworkResponseWriter(writerValue) : undefined;
|
|
94
146
|
if (responseWriter) {
|
|
147
|
+
applyResponseValidators(response, validators);
|
|
95
148
|
let successResponseMetadataApplied = false;
|
|
96
149
|
const applyWriterSuccessResponseMetadata = () => {
|
|
97
150
|
if (successResponseMetadataApplied) {
|
|
@@ -102,28 +155,64 @@ export function writeSuccessResponse(handler, request, response, value, contentN
|
|
|
102
155
|
formatter: undefined,
|
|
103
156
|
handler,
|
|
104
157
|
response,
|
|
105
|
-
value
|
|
158
|
+
value: responseValue
|
|
106
159
|
});
|
|
160
|
+
applyResponseValidators(response, validators);
|
|
107
161
|
};
|
|
108
162
|
return responseWriter({
|
|
109
163
|
applySuccessResponseMetadata: applyWriterSuccessResponseMetadata,
|
|
110
164
|
handler,
|
|
111
165
|
request,
|
|
112
166
|
requestContext,
|
|
113
|
-
response
|
|
167
|
+
response,
|
|
168
|
+
validators,
|
|
169
|
+
value: writerValue
|
|
114
170
|
});
|
|
115
171
|
}
|
|
116
|
-
const
|
|
172
|
+
const responsePolicy = resolveResponsePolicy(handler, request, contentNegotiation);
|
|
173
|
+
const {
|
|
174
|
+
formatter
|
|
175
|
+
} = responsePolicy;
|
|
176
|
+
if (conditionalOutcome !== undefined) {
|
|
177
|
+
applyRouteHeaders(handler, response);
|
|
178
|
+
return writeConditionalResponse(response, conditionalOutcome, validators, responsePolicy);
|
|
179
|
+
}
|
|
117
180
|
applySuccessResponseMetadata({
|
|
118
181
|
formatter,
|
|
119
182
|
handler,
|
|
120
183
|
response,
|
|
121
|
-
value
|
|
184
|
+
value: responseValue
|
|
122
185
|
});
|
|
123
|
-
if (
|
|
124
|
-
|
|
186
|
+
if (responsePolicy.variesByAccept) {
|
|
187
|
+
appendVaryHeader(response, 'Accept');
|
|
125
188
|
}
|
|
126
|
-
|
|
189
|
+
applyResponseValidators(response, validators);
|
|
190
|
+
if (request.method.toUpperCase() === 'HEAD') {
|
|
191
|
+
applyImplicitHeadContentType(response, responseValue);
|
|
192
|
+
return response.send(undefined);
|
|
193
|
+
}
|
|
194
|
+
if (!formatter && hasSimpleJsonResponseWriter(response) && canUseSimpleJsonFastPath(response, responseValue)) {
|
|
195
|
+
return response.sendSimpleJson(responseValue);
|
|
196
|
+
}
|
|
197
|
+
const responseBody = formatter ? formatter.format(responseValue) : responseValue;
|
|
127
198
|
return response.send(responseBody);
|
|
128
199
|
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Writes a bodyless conditional response through every supported adapter facade.
|
|
203
|
+
*
|
|
204
|
+
* @param response Mutable adapter-normalized response.
|
|
205
|
+
* @param outcome Selected non-proceed conditional request outcome.
|
|
206
|
+
* @param validators Current representation validators.
|
|
207
|
+
* @param responsePolicy Selected representation metadata.
|
|
208
|
+
* @returns A promise that settles after the adapter accepts the bodyless response.
|
|
209
|
+
*/
|
|
210
|
+
export async function writeConditionalResponse(response, outcome, validators, responsePolicy) {
|
|
211
|
+
applyResponseValidators(response, validators);
|
|
212
|
+
if (responsePolicy.variesByAccept) {
|
|
213
|
+
appendVaryHeader(response, 'Accept');
|
|
214
|
+
}
|
|
215
|
+
response.setStatus(outcome === 'not-modified' ? 304 : 412);
|
|
216
|
+
await response.send(undefined);
|
|
217
|
+
}
|
|
129
218
|
export { resolveContentNegotiation, writeErrorResponse };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Container } from '@fluojs/di';
|
|
2
|
-
import type { Binder, ContentNegotiationOptions, ConverterLike, Dispatcher, DispatcherLogger, FrameworkRequest, FrameworkResponse, HandlerMapping, InterceptorLike, MiddlewareLike, RequestObserverLike } from '../types.js';
|
|
2
|
+
import type { Binder, ConditionalRequestOptions, ContentNegotiationOptions, ConverterLike, Dispatcher, DispatcherLogger, FrameworkRequest, FrameworkResponse, HandlerMapping, HttpErrorRepresentationOptions, InterceptorLike, MiddlewareLike, RequestObserverLike } from '../types.js';
|
|
3
3
|
import { type FastPathStats } from './fast-path/index.js';
|
|
4
4
|
export type { FastPathEligibility, FastPathStats } from './fast-path/index.js';
|
|
5
5
|
export { FAST_PATH_ELIGIBILITY_SYMBOL, FAST_PATH_STATS_SYMBOL } from './fast-path/index.js';
|
|
@@ -13,6 +13,8 @@ export interface CreateDispatcherOptions {
|
|
|
13
13
|
binder?: Binder;
|
|
14
14
|
/** Optional content negotiation configuration. */
|
|
15
15
|
contentNegotiation?: ContentNegotiationOptions;
|
|
16
|
+
/** Optional dispatcher-owned HTTP conditional request policy. */
|
|
17
|
+
conditionalRequest?: ConditionalRequestOptions;
|
|
16
18
|
/** Mapping of routes to their respective handlers. */
|
|
17
19
|
handlerMapping: HandlerMapping;
|
|
18
20
|
/** Global interceptors applied to all matched handlers. */
|
|
@@ -23,6 +25,8 @@ export interface CreateDispatcherOptions {
|
|
|
23
25
|
fastPathDebugHeaders?: boolean;
|
|
24
26
|
/** Optional global error handler. */
|
|
25
27
|
onError?: ErrorHandler;
|
|
28
|
+
/** Optional application-owned HTML representation for HTTP-classified errors. */
|
|
29
|
+
errorRepresentation?: HttpErrorRepresentationOptions;
|
|
26
30
|
/** Request-scope optimization hints supplied by runtime bootstrap. */
|
|
27
31
|
requestScope?: {
|
|
28
32
|
/** Global DTO converters used by the default binder. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/dispatch/dispatcher.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAyB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/dispatch/dispatcher.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAyB,MAAM,YAAY,CAAC;AAUnE,OAAO,KAAK,EACV,MAAM,EACN,yBAAyB,EACzB,yBAAyB,EACzB,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EAKjB,cAAc,EAEd,8BAA8B,EAC9B,eAAe,EAEf,cAAc,EAKd,mBAAmB,EAEpB,MAAM,aAAa,CAAC;AAgBrB,OAAO,EAKL,KAAK,aAAa,EAEnB,MAAM,sBAAsB,CAAC;AAK9B,YAAY,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC/E,OAAO,EAAE,4BAA4B,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE5F,gEAAgE;AAChE,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,iBAAiB,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,OAAO,GAAG,IAAI,CAAC;AAEpK,uDAAuD;AACvD,MAAM,WAAW,uBAAuB;IACtC,iDAAiD;IACjD,aAAa,CAAC,EAAE,cAAc,EAAE,CAAC;IACjC,kFAAkF;IAClF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,kBAAkB,CAAC,EAAE,yBAAyB,CAAC;IAC/C,iEAAiE;IACjE,kBAAkB,CAAC,EAAE,yBAAyB,CAAC;IAC/C,sDAAsD;IACtD,cAAc,EAAE,cAAc,CAAC;IAC/B,2DAA2D;IAC3D,YAAY,CAAC,EAAE,eAAe,EAAE,CAAC;IACjC,0DAA0D;IAC1D,SAAS,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAClC,+DAA+D;IAC/D,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qCAAqC;IACrC,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,iFAAiF;IACjF,mBAAmB,CAAC,EAAE,8BAA8B,CAAC;IACrD,sEAAsE;IACtE,YAAY,CAAC,EAAE;QACb,wDAAwD;QACxD,oBAAoB,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;KACjD,CAAC;IACF,qDAAqD;IACrD,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,qDAAqD;IACrD,aAAa,EAAE,SAAS,CAAC;IACzB,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAgjCD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,UAAU,CAiG7E;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,UAAU,GAAG,aAAa,GAAG,SAAS,CAE5F;AAED,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC"}
|