@routepact/core 0.1.2 → 0.1.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.
- package/README.md +72 -114
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +29 -21
- package/dist/types.d.ts.map +1 -1
- package/dist/utils.d.ts +20 -2
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +27 -4
- package/dist/utils.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,82 +8,77 @@ Shared types and utilities for defining type-safe route pacts. This package is t
|
|
|
8
8
|
npm install @routepact/core zod
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
## Defining a
|
|
11
|
+
## Defining a pact
|
|
12
12
|
|
|
13
|
-
A
|
|
13
|
+
A pact describes a single endpoint: its path, HTTP method, and optional Zod schemas for the request body, response body, query parameters, path parameters, and response metadata.
|
|
14
|
+
|
|
15
|
+
Use `definePact` to get full type inference while keeping literal types (exact path strings, method literals):
|
|
14
16
|
|
|
15
17
|
```ts
|
|
16
18
|
import { z } from "zod";
|
|
17
|
-
import
|
|
19
|
+
import { definePact } from "@routepact/core";
|
|
18
20
|
|
|
19
21
|
export const PostPacts = {
|
|
20
|
-
list: {
|
|
22
|
+
list: definePact({
|
|
21
23
|
method: "get",
|
|
22
24
|
path: "/posts",
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
response: z.object({
|
|
26
|
+
items: z.object({ id: z.string(), title: z.string() }).array(),
|
|
27
|
+
total: z.number(),
|
|
28
|
+
page: z.number(),
|
|
29
|
+
}),
|
|
30
|
+
query: z.object({ page: z.string().optional(), limit: z.string().optional() }),
|
|
31
|
+
}),
|
|
32
|
+
getById: definePact({
|
|
29
33
|
method: "get",
|
|
30
34
|
path: "/posts/:id",
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
},
|
|
39
|
-
create: {
|
|
35
|
+
response: z.object({
|
|
36
|
+
id: z.string(),
|
|
37
|
+
title: z.string(),
|
|
38
|
+
body: z.string(),
|
|
39
|
+
}),
|
|
40
|
+
}),
|
|
41
|
+
create: definePact({
|
|
40
42
|
method: "post",
|
|
41
43
|
path: "/posts",
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
},
|
|
51
|
-
update: {
|
|
44
|
+
request: z.object({ title: z.string(), body: z.string() }),
|
|
45
|
+
response: z.object({
|
|
46
|
+
id: z.string(),
|
|
47
|
+
title: z.string(),
|
|
48
|
+
body: z.string(),
|
|
49
|
+
}),
|
|
50
|
+
}),
|
|
51
|
+
update: definePact({
|
|
52
52
|
method: "patch",
|
|
53
53
|
path: "/posts/:id",
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
},
|
|
66
|
-
delete: {
|
|
54
|
+
request: z.object({
|
|
55
|
+
title: z.string().optional(),
|
|
56
|
+
body: z.string().optional(),
|
|
57
|
+
}),
|
|
58
|
+
response: z.object({
|
|
59
|
+
id: z.string(),
|
|
60
|
+
title: z.string(),
|
|
61
|
+
body: z.string(),
|
|
62
|
+
}),
|
|
63
|
+
}),
|
|
64
|
+
delete: definePact({
|
|
67
65
|
method: "delete",
|
|
68
66
|
path: "/posts/:id",
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
} satisfies Record<string, RoutePact>;
|
|
67
|
+
}),
|
|
68
|
+
};
|
|
72
69
|
```
|
|
73
70
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
## Validation rules
|
|
71
|
+
## Validation schemas
|
|
77
72
|
|
|
78
|
-
| Field
|
|
79
|
-
|
|
|
80
|
-
| `
|
|
81
|
-
| `
|
|
82
|
-
| `
|
|
73
|
+
| Field | Required for | Description |
|
|
74
|
+
| ---------- | ------------------------------- | ----------------------------------------------------------------- |
|
|
75
|
+
| `request` | Only for `post`, `patch`, `put` | Zod schema for `req.body` on the server |
|
|
76
|
+
| `response` | Optional | Zod schema for the full response body sent via `res.json(...)` |
|
|
77
|
+
| `query` | Optional | Zod schema for query parameters — typed on both server and client |
|
|
83
78
|
|
|
84
79
|
## Path parameters
|
|
85
80
|
|
|
86
|
-
Parameters in the path are extracted as a type-safe object. If a path contains `:id`, the `params` option is required and typed as `{ id: string }`.
|
|
81
|
+
Parameters in the path (`:param`) are extracted as a type-safe object. If a path contains `:id`, the `params` option is required and typed as `{ id: string }`.
|
|
87
82
|
|
|
88
83
|
```ts
|
|
89
84
|
// TypeScript requires params when the path has parameters
|
|
@@ -93,71 +88,34 @@ await request(PostPacts.getById, { params: { id: "abc" } });
|
|
|
93
88
|
await request(PostPacts.list);
|
|
94
89
|
```
|
|
95
90
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
All endpoints follow the same envelope:
|
|
99
|
-
|
|
100
|
-
```ts
|
|
101
|
-
// Response body sent from the server
|
|
102
|
-
interface ApiResponse<TResource, TMeta> {
|
|
103
|
-
resource: TResource;
|
|
104
|
-
meta?: TMeta;
|
|
105
|
-
message?: string;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// Request body sent to the server
|
|
109
|
-
interface ApiRequest<TResource> {
|
|
110
|
-
resource: TResource;
|
|
111
|
-
}
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
## Utilities
|
|
115
|
-
|
|
116
|
-
### `buildEndpoint(spec, options)`
|
|
117
|
-
|
|
118
|
-
Interpolates path params and appends a query string.
|
|
119
|
-
|
|
120
|
-
```ts
|
|
121
|
-
import { buildEndpoint } from "@routepact/core";
|
|
122
|
-
|
|
123
|
-
buildEndpoint(PostPacts.getById, { params: { id: "42" } });
|
|
124
|
-
// → "/posts/42"
|
|
125
|
-
|
|
126
|
-
buildEndpoint(PostPacts.list, { queries: { page: "2", limit: "10" } });
|
|
127
|
-
// → "/posts?page=2&limit=10"
|
|
128
|
-
```
|
|
91
|
+
On the server, `req.parsedParams` is automatically populated from `req.params` and typed as `{ [key: string]: string }` based on the path string — no Zod schema needed.
|
|
129
92
|
|
|
130
|
-
|
|
93
|
+
## Query parameters
|
|
131
94
|
|
|
132
|
-
|
|
95
|
+
Add a `query` Zod schema to make query parameters type-safe on both server and client. If any field in the schema is required, TypeScript will require the `queries` option at the call site:
|
|
133
96
|
|
|
134
97
|
```ts
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
// ... etc
|
|
144
|
-
default:
|
|
145
|
-
exhaustiveGuard(method); // TypeScript errors if a case is missing
|
|
146
|
-
}
|
|
147
|
-
}
|
|
98
|
+
const list = definePact({
|
|
99
|
+
method: "get",
|
|
100
|
+
path: "/posts",
|
|
101
|
+
query: z.object({ page: z.string().optional(), sort: z.string() }), // sort is required
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// TypeScript requires queries.sort
|
|
105
|
+
await request(list, { queries: { sort: "createdAt" } });
|
|
148
106
|
```
|
|
149
107
|
|
|
150
108
|
## Type reference
|
|
151
109
|
|
|
152
|
-
| Type | Description
|
|
153
|
-
| ----------------------------- |
|
|
154
|
-
| `RoutePact` |
|
|
155
|
-
| `
|
|
156
|
-
| `
|
|
157
|
-
| `
|
|
158
|
-
| `
|
|
159
|
-
| `
|
|
160
|
-
| `
|
|
161
|
-
| `
|
|
162
|
-
| `
|
|
163
|
-
| `
|
|
110
|
+
| Type | Description |
|
|
111
|
+
| ----------------------------- | ---------------------------------------------------------------------------------- |
|
|
112
|
+
| `RoutePact` | Generic type for a single pact definition |
|
|
113
|
+
| `AnyRoutePact` | Widened pact type — used internally and in package integrations |
|
|
114
|
+
| `AnyRouteValidation` | The set of optional Zod schemas that can be attached to a pact |
|
|
115
|
+
| `HttpMethod` | `"get" \| "post" \| "patch" \| "put" \| "delete"` |
|
|
116
|
+
| `RouteOptions<TPact>` | Inferred call-site options (params, payload, queries) for a pact |
|
|
117
|
+
| `RouteOptionsRequired<TPact>` | `true` if options are required (pact has params or a request schema) |
|
|
118
|
+
| `QueryOption<TPact>` | Inferred `queries` option — required if the query schema has required fields |
|
|
119
|
+
| `PactResponse<TPact>` | Inferred return type when calling a pact from the client — `z.infer<response>` or `undefined` |
|
|
120
|
+
| `ExtractParams<TPath>` | Extracts parameter names from a path string |
|
|
121
|
+
| `ExpectedParams<TPath>` | Maps extracted param names to `string` values |
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,41 +1,49 @@
|
|
|
1
1
|
import type z from "zod/v4";
|
|
2
|
-
import type { ApiResponse } from "./api.js";
|
|
3
2
|
export type HttpMethod = "get" | "post" | "patch" | "put" | "delete";
|
|
4
|
-
export type
|
|
3
|
+
export type QueryParam = Record<string, string | number | boolean | undefined>;
|
|
4
|
+
export type AnyRouteValidation = {
|
|
5
5
|
response?: z.ZodType<unknown>;
|
|
6
6
|
request?: z.ZodType<unknown>;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
export type RoutePact = {
|
|
10
|
-
path: string;
|
|
11
|
-
method: HttpMethod;
|
|
12
|
-
validation: RouteValidation;
|
|
7
|
+
query?: z.ZodType<QueryParam>;
|
|
8
|
+
params?: z.ZodType<Record<string, unknown>>;
|
|
13
9
|
};
|
|
10
|
+
export type RoutePact<TPath extends string, TMethod extends HttpMethod, TValidation extends AnyRouteValidation> = {
|
|
11
|
+
path: TPath;
|
|
12
|
+
method: TMethod;
|
|
13
|
+
} & TValidation;
|
|
14
|
+
export type AnyRoutePact = RoutePact<string, HttpMethod, AnyRouteValidation>;
|
|
14
15
|
export type ExtractParams<T extends string> = T extends `${string}/:${infer Param}/${infer Rest}` ? Param | ExtractParams<`/${Rest}`> : T extends `${string}:${infer Param}` ? Param : never;
|
|
15
16
|
export type ExpectedParams<T extends string> = {
|
|
16
17
|
[Key in ExtractParams<T>]: string;
|
|
17
18
|
};
|
|
18
|
-
type
|
|
19
|
-
|
|
20
|
-
}
|
|
19
|
+
type RequiredKeys<T> = {
|
|
20
|
+
[K in keyof T]-?: {} extends Pick<T, K> ? never : K;
|
|
21
|
+
}[keyof T];
|
|
22
|
+
type RequiredOnly<T> = Pick<T, RequiredKeys<T>>;
|
|
23
|
+
type HasParams<TPath extends string> = [ExtractParams<TPath>] extends [never] ? false : true;
|
|
24
|
+
type ParamsOption<TPath extends string> = HasParams<TPath> extends true ? {
|
|
21
25
|
params: ExpectedParams<TPath>;
|
|
26
|
+
} : {
|
|
27
|
+
params?: never;
|
|
22
28
|
};
|
|
23
|
-
type PayloadOption<TPact extends
|
|
24
|
-
payload: z.infer<TPact["
|
|
29
|
+
type PayloadOption<TPact extends AnyRoutePact> = TPact["method"] extends "post" | "patch" | "put" ? TPact["request"] extends z.ZodType<unknown> ? {
|
|
30
|
+
payload: z.infer<TPact["request"]>;
|
|
25
31
|
} : {
|
|
26
32
|
payload?: never;
|
|
27
33
|
} : {
|
|
28
34
|
payload?: never;
|
|
29
35
|
};
|
|
30
|
-
export type
|
|
31
|
-
queries?:
|
|
36
|
+
export type QueryOption<TPact extends AnyRoutePact> = TPact["query"] extends z.ZodType<infer TQuery> ? {} extends RequiredOnly<TQuery> ? {
|
|
37
|
+
queries?: TQuery;
|
|
38
|
+
} : {
|
|
39
|
+
queries: TQuery;
|
|
40
|
+
} : {
|
|
41
|
+
queries?: never;
|
|
32
42
|
};
|
|
33
|
-
export type
|
|
34
|
-
export type
|
|
35
|
-
|
|
36
|
-
} ? z.infer<TPact["validation"]["response"]> : undefined, TPact["validation"] extends {
|
|
43
|
+
export type RouteOptions<TPact extends AnyRoutePact> = ParamsOption<TPact["path"]> & PayloadOption<TPact> & QueryOption<TPact>;
|
|
44
|
+
export type RouteOptionsRequired<TPact extends AnyRoutePact> = {} extends RouteOptions<TPact> ? false : true;
|
|
45
|
+
export type PactResponse<TPact extends AnyRoutePact> = TPact extends {
|
|
37
46
|
response: z.ZodType<unknown>;
|
|
38
|
-
|
|
39
|
-
} ? z.infer<TPact["validation"]["meta"]> : undefined>;
|
|
47
|
+
} ? z.infer<TPact["response"]> : undefined;
|
|
40
48
|
export {};
|
|
41
49
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,4 +1,22 @@
|
|
|
1
|
-
import type { RouteOptions, RoutePact } from "./types.js";
|
|
1
|
+
import type { AnyRoutePact, AnyRouteValidation, HttpMethod, RouteOptions, RoutePact } from "./types.js";
|
|
2
2
|
export declare function exhaustiveGuard(_value: never): never;
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Builds a full endpoint path from a pact, substituting path parameters and
|
|
5
|
+
* appending a query string. Path param values are URL-encoded automatically.
|
|
6
|
+
* Throws if a required path parameter is missing from `options.params`.
|
|
7
|
+
*/
|
|
8
|
+
export declare function buildEndpoint<TPact extends AnyRoutePact>(pact: TPact, options?: RouteOptions<TPact>): string;
|
|
9
|
+
/**
|
|
10
|
+
* Defines a type-safe route pact
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* const getUser = definePact({
|
|
14
|
+
* path: "/users/:id",
|
|
15
|
+
* method: "get",
|
|
16
|
+
* response: z.object({ id: z.string(), name: z.string() }),
|
|
17
|
+
* params: z.object({ param: z.string() }),
|
|
18
|
+
* query: z.object({ query: z.string() }),
|
|
19
|
+
* });
|
|
20
|
+
*/
|
|
21
|
+
export declare function definePact<const TPath extends string, TMethod extends HttpMethod, TValidation extends AnyRouteValidation>(pact: RoutePact<TPath, TMethod, TValidation>): RoutePact<TPath, TMethod, TValidation>;
|
|
4
22
|
//# sourceMappingURL=utils.d.ts.map
|
package/dist/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,kBAAkB,EAElB,UAAU,EACV,YAAY,EACZ,SAAS,EACV,MAAM,YAAY,CAAC;AAEpB,wBAAgB,eAAe,CAAC,MAAM,EAAE,KAAK,GAAG,KAAK,CAIpD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,SAAS,YAAY,EACtD,IAAI,EAAE,KAAK,EACX,OAAO,CAAC,EAAE,YAAY,CAAC,KAAK,CAAC,GAC5B,MAAM,CAiBR;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CACxB,KAAK,CAAC,KAAK,SAAS,MAAM,EAC1B,OAAO,SAAS,UAAU,EAC1B,WAAW,SAAS,kBAAkB,EAEtC,IAAI,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,WAAW,CAAC,GAC3C,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,WAAW,CAAC,CAExC"}
|
package/dist/utils.js
CHANGED
|
@@ -1,14 +1,37 @@
|
|
|
1
1
|
export function exhaustiveGuard(_value) {
|
|
2
2
|
throw new Error(`Reached forbidden guard function with unexpected value: ${JSON.stringify(_value)}`);
|
|
3
3
|
}
|
|
4
|
+
/**
|
|
5
|
+
* Builds a full endpoint path from a pact, substituting path parameters and
|
|
6
|
+
* appending a query string. Path param values are URL-encoded automatically.
|
|
7
|
+
* Throws if a required path parameter is missing from `options.params`.
|
|
8
|
+
*/
|
|
4
9
|
export function buildEndpoint(pact, options) {
|
|
5
|
-
const replacedEndpoint = pact.path.replace(/:(\w+)/g, (
|
|
10
|
+
const replacedEndpoint = pact.path.replace(/:(\w+)/g, (_match, key) => {
|
|
6
11
|
if (options?.params && key in options.params) {
|
|
7
|
-
return options.params[key];
|
|
12
|
+
return encodeURIComponent(options.params[key]);
|
|
8
13
|
}
|
|
9
|
-
|
|
14
|
+
throw new Error(`Missing required path parameter: ${key}`);
|
|
10
15
|
});
|
|
11
|
-
const
|
|
16
|
+
const queryEntries = Object.entries(options?.queries ?? {})
|
|
17
|
+
.filter(([, value]) => value !== undefined)
|
|
18
|
+
.map(([key, value]) => [key, String(value)]);
|
|
19
|
+
const queryString = new URLSearchParams(queryEntries).toString();
|
|
12
20
|
return queryString ? `${replacedEndpoint}?${queryString}` : replacedEndpoint;
|
|
13
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Defines a type-safe route pact
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* const getUser = definePact({
|
|
27
|
+
* path: "/users/:id",
|
|
28
|
+
* method: "get",
|
|
29
|
+
* response: z.object({ id: z.string(), name: z.string() }),
|
|
30
|
+
* params: z.object({ param: z.string() }),
|
|
31
|
+
* query: z.object({ query: z.string() }),
|
|
32
|
+
* });
|
|
33
|
+
*/
|
|
34
|
+
export function definePact(pact) {
|
|
35
|
+
return pact;
|
|
36
|
+
}
|
|
14
37
|
//# sourceMappingURL=utils.js.map
|
package/dist/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AASA,MAAM,UAAU,eAAe,CAAC,MAAa;IAC3C,MAAM,IAAI,KAAK,CACb,2DAA2D,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CACpF,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC3B,IAAW,EACX,OAA6B;IAE7B,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE;QACpE,IAAI,OAAO,EAAE,MAAM,IAAI,GAAG,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YAC7C,OAAO,kBAAkB,CACvB,OAAO,CAAC,MAAM,CAAC,GAA0C,CAAC,CAC3D,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,oCAAoC,GAAG,EAAE,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,IAAI,EAAE,CAAC;SACxD,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC;SAC1C,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAE/C,MAAM,WAAW,GAAG,IAAI,eAAe,CAAC,YAAY,CAAC,CAAC,QAAQ,EAAE,CAAC;IAEjE,OAAO,WAAW,CAAC,CAAC,CAAC,GAAG,gBAAgB,IAAI,WAAW,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC;AAC/E,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,UAAU,CAKxB,IAA4C;IAE5C,OAAO,IAAI,CAAC;AACd,CAAC"}
|