@nxgt/graphql-codegen-zod 0.1.0 → 0.2.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.md +98 -10
- package/dist/collect-fields.d.ts +24 -0
- package/dist/collect-fields.d.ts.map +1 -0
- package/dist/config.d.ts +10 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/cycles.d.ts +7 -0
- package/dist/cycles.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +530 -133
- package/dist/index.js.map +12 -7
- package/dist/naming.d.ts +4 -0
- package/dist/naming.d.ts.map +1 -1
- package/dist/objects-output.d.ts +16 -0
- package/dist/objects-output.d.ts.map +1 -0
- package/dist/output-types.d.ts +15 -0
- package/dist/output-types.d.ts.map +1 -0
- package/dist/results-output.d.ts +16 -0
- package/dist/results-output.d.ts.map +1 -0
- package/dist/results-selections.d.ts +21 -0
- package/dist/results-selections.d.ts.map +1 -0
- package/docs/README.md +1 -1
- package/docs/guide/output.md +279 -7
- package/docs/roadmap.md +8 -5
- package/docs/troubleshooting.md +53 -6
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
A [graphql-codegen](https://the-guild.dev/graphql/codegen) plugin that writes
|
|
4
4
|
Zod 4 schemas, and their TypeScript types, from your SDL: one per enum and per
|
|
5
5
|
input type, one per field that takes arguments, one per named operation's
|
|
6
|
-
variables
|
|
6
|
+
variables, one per object type, interface and union, and one per named
|
|
7
|
+
operation's result and per fragment. It carries every `@constraint` of
|
|
7
8
|
[`@nxgt/graphql-validation`](https://www.npmjs.com/package/@nxgt/graphql-validation),
|
|
8
9
|
through that package's own rules, so the server (`withValidation`) and the
|
|
9
10
|
generated code accept and refuse the same values. For graphql-codegen 5 to 7
|
|
@@ -29,18 +30,37 @@ run `withValidation` on a server.
|
|
|
29
30
|
|
|
30
31
|
## Setup
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
Write the SDL files codegen reads: `@constraint` from
|
|
34
|
+
`@nxgt/graphql-validation` and the custom scalars from `@nxgt/graphql-scalars`.
|
|
35
|
+
Install both, so their bins are yours, whatever the package manager links:
|
|
36
|
+
`bun add @nxgt/graphql-validation @nxgt/graphql-scalars` (the generated file
|
|
37
|
+
imports `@nxgt/graphql-scalars` at run time anyway). Without the directive
|
|
38
|
+
nothing is constrained; plain types are still generated.
|
|
35
39
|
|
|
36
|
-
|
|
40
|
+
```sh
|
|
41
|
+
bunx nxgt-graphql-validation typedefs --out # generated/graphql/constraint.graphqls
|
|
42
|
+
bunx nxgt-graphql-scalars typedefs --out # generated/graphql/scalars.graphqls
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Both bins are described in the
|
|
46
|
+
[validation](https://www.npmjs.com/package/@nxgt/graphql-validation#ide-support)
|
|
47
|
+
and [scalars](https://www.npmjs.com/package/@nxgt/graphql-scalars#the-sdl-as-a-file)
|
|
48
|
+
READMEs. `typedefs DateTime Long --out` keeps only the scalars you use. Or skip the CLI and list
|
|
49
|
+
`node_modules/@nxgt/graphql-validation/graphql/constraint.graphqls` and
|
|
50
|
+
`node_modules/@nxgt/graphql-scalars/graphql/scalars.graphqls` in `schema`.
|
|
51
|
+
|
|
52
|
+
Then add the plugin, writing to **its own file**, with those files in `schema`:
|
|
37
53
|
|
|
38
54
|
```ts
|
|
39
55
|
// codegen.ts
|
|
40
56
|
import type { CodegenConfig } from '@graphql-codegen/cli';
|
|
41
57
|
|
|
42
58
|
const config: CodegenConfig = {
|
|
43
|
-
schema:
|
|
59
|
+
schema: [
|
|
60
|
+
'generated/graphql/constraint.graphqls',
|
|
61
|
+
'generated/graphql/scalars.graphqls',
|
|
62
|
+
'src/schema/**/*.graphql',
|
|
63
|
+
],
|
|
44
64
|
documents: 'src/operations/**/*.graphql',
|
|
45
65
|
generates: {
|
|
46
66
|
'src/generated/zod.ts': {
|
|
@@ -55,11 +75,24 @@ export default config;
|
|
|
55
75
|
The plugin writes types named as `@graphql-codegen/typescript` names them
|
|
56
76
|
(`SignUpInput`, `MutationSignUpArgs`), which would collide with that plugin's
|
|
57
77
|
in one file. Its `*Args` and `*Variables` types can replace the typescript
|
|
58
|
-
plugin's
|
|
78
|
+
plugin's; so can its object types, interfaces and unions (`User`), or
|
|
79
|
+
`objects: false` leaves them to that plugin. Its `*Query`, `*Mutation` and
|
|
80
|
+
`*Fragment` types can replace typescript-operations' (`SearchQuery`,
|
|
81
|
+
`UserFieldsFragment`), or `operations: false` leaves them to it.
|
|
59
82
|
|
|
60
83
|
`scalarSchemas` supplies a Zod schema for each custom scalar of the schema;
|
|
61
84
|
see [Scalars](docs/guide/output.md#scalars).
|
|
62
85
|
|
|
86
|
+
Run codegen, once or on every change:
|
|
87
|
+
|
|
88
|
+
```sh
|
|
89
|
+
bunx graphql-codegen --config codegen.ts
|
|
90
|
+
bunx graphql-codegen --config codegen.ts --watch
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
or add `"codegen": "graphql-codegen"` to the `scripts` of `package.json` and
|
|
94
|
+
run `bun run codegen`.
|
|
95
|
+
|
|
63
96
|
## Usage
|
|
64
97
|
|
|
65
98
|
### On the server: type the resolvers
|
|
@@ -76,6 +109,24 @@ export const signUp = (_: unknown, { input }: MutationSignUpArgs) => {
|
|
|
76
109
|
};
|
|
77
110
|
```
|
|
78
111
|
|
|
112
|
+
### On the server: type what a resolver returns
|
|
113
|
+
|
|
114
|
+
Object types, interfaces and unions are typed
|
|
115
|
+
`z.output`: custom scalars decoded, `__typename` optional, nullable fields
|
|
116
|
+
optional.
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
import type { User } from './generated/zod';
|
|
120
|
+
|
|
121
|
+
export const me = (): User => ({ id: 'u_1', name: 'Al', joined: new Date() });
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
`zUser.parse(value)` reads a wire value: a `DateTime` string becomes a
|
|
125
|
+
`Date`, and a field the schema does not declare is dropped. To check what a
|
|
126
|
+
resolver returns, which holds a `Date`, encode it back to the wire form:
|
|
127
|
+
`z.encode(zUser, value)`, or `z.safeEncode(zUser, value)` for a result. A
|
|
128
|
+
resolver's string for a `DateTime` is refused.
|
|
129
|
+
|
|
79
130
|
### On the client: check before sending
|
|
80
131
|
|
|
81
132
|
Variables are typed `z.input`: what a client sends. A schema per named
|
|
@@ -92,6 +143,32 @@ if (!result.success) {
|
|
|
92
143
|
}
|
|
93
144
|
```
|
|
94
145
|
|
|
146
|
+
### On the client: parse the response
|
|
147
|
+
|
|
148
|
+
An operation's result is typed `z.output`: what the response holds, custom
|
|
149
|
+
scalars decoded. An abstract type's selection is a union on `__typename` when
|
|
150
|
+
its members select different fields, so checking it narrows.
|
|
151
|
+
|
|
152
|
+
```graphql
|
|
153
|
+
query Search($text: String!) {
|
|
154
|
+
search(text: $text) {
|
|
155
|
+
__typename
|
|
156
|
+
... on User { id joined }
|
|
157
|
+
... on Post { id title }
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
import { zSearchQuery } from './generated/zod';
|
|
164
|
+
|
|
165
|
+
const search = zSearchQuery.parse(response.data).search;
|
|
166
|
+
for (const hit of search) {
|
|
167
|
+
if (hit.__typename === 'User') hit.joined.getFullYear(); // a Date
|
|
168
|
+
else hit.title; // Post
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
95
172
|
What is generated, how it is named, defaults, recursion, `@oneOf` and scalars
|
|
96
173
|
are in [Output](docs/guide/output.md).
|
|
97
174
|
|
|
@@ -106,6 +183,8 @@ are in [Output](docs/guide/output.md).
|
|
|
106
183
|
| `typesPrefix`, `typesSuffix` | `string` | none | around each type's name |
|
|
107
184
|
| `addUnderscoreToArgsType` | `boolean` | `false` | `Query_FindUserArgs` |
|
|
108
185
|
| `dedupeOperationSuffix`, `omitOperationSuffix` | `boolean` | `false` | as in `typescript-operations` |
|
|
186
|
+
| `objects` | `boolean` | `true` | write the object types, interfaces and unions; `false` writes no object types, interfaces or unions; results are still written unless `operations: false` |
|
|
187
|
+
| `operations` | `boolean` | `true` | write each named operation's result and each fragment; `false` writes none, the variables stay |
|
|
109
188
|
|
|
110
189
|
Each is detailed in [Output](docs/guide/output.md).
|
|
111
190
|
|
|
@@ -128,10 +207,19 @@ Each is detailed in [Output](docs/guide/output.md).
|
|
|
128
207
|
[validation troubleshooting](https://github.com/softistx/nxgt-graphql/blob/develop/packages/graphql-validation/docs/troubleshooting.md).
|
|
129
208
|
- A custom scalar mapped nowhere fails generation, naming it, rather than
|
|
130
209
|
becoming an unchecked `z.unknown()`.
|
|
210
|
+
- An abstract type whose possible types select different fields is a union on
|
|
211
|
+
`__typename`: select it, under one key for every member, or generation
|
|
212
|
+
fails. When they all select the same fields, no `__typename` is needed.
|
|
213
|
+
- A field under `@skip`, `@include` or `@defer` may be absent: it is
|
|
214
|
+
`.optional()`.
|
|
131
215
|
- Generate into a file of its own: the type names collide with the typescript
|
|
132
|
-
plugins'.
|
|
133
|
-
|
|
134
|
-
|
|
216
|
+
plugins', `*Query` and `*Fragment` with typescript-operations'. Take them from
|
|
217
|
+
this plugin, or set `objects: false` and `operations: false`.
|
|
218
|
+
- An input type in a cycle also declares `<Type>Input`, and an object type in a
|
|
219
|
+
cycle `<Type>Wire`: a GraphQL type of that name fails generation. Rename it,
|
|
220
|
+
or set `typesSuffix`.
|
|
221
|
+
- 0.1.0's output needs both `objects: false` and `operations: false`: a custom
|
|
222
|
+
scalar an operation selects needs a schema, whichever option is set alone.
|
|
135
223
|
|
|
136
224
|
Every error and its fix is in [Troubleshooting](docs/troubleshooting.md).
|
|
137
225
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type FieldNode, type FragmentDefinitionNode, type GraphQLObjectType, type GraphQLSchema, type SelectionSetNode } from 'graphql';
|
|
2
|
+
/** A selection set, and whether the response may leave it out. */
|
|
3
|
+
export interface Selected {
|
|
4
|
+
readonly set: SelectionSetNode;
|
|
5
|
+
readonly conditional: boolean;
|
|
6
|
+
}
|
|
7
|
+
/** A response key: its field, every node selecting it, if it may be absent. */
|
|
8
|
+
export interface Collected {
|
|
9
|
+
readonly name: string;
|
|
10
|
+
readonly nodes: {
|
|
11
|
+
readonly node: FieldNode;
|
|
12
|
+
readonly conditional: boolean;
|
|
13
|
+
}[];
|
|
14
|
+
optional: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The fields `sets` select on `type`, by response key, as graphql's
|
|
18
|
+
* CollectFields gathers them for every value of the variables: inline
|
|
19
|
+
* fragments and spreads whose type condition `type` satisfies, the same
|
|
20
|
+
* key's nodes merged, each node keeping whether it may be left out, so a
|
|
21
|
+
* sub-field only a conditional node selects stays optional.
|
|
22
|
+
*/
|
|
23
|
+
export declare function collectFields(schema: GraphQLSchema, fragments: ReadonlyMap<string, FragmentDefinitionNode>, type: GraphQLObjectType, sets: readonly Selected[]): Map<string, Collected>;
|
|
24
|
+
//# sourceMappingURL=collect-fields.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collect-fields.d.ts","sourceRoot":"","sources":["../src/collect-fields.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,SAAS,EACd,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAIlB,KAAK,gBAAgB,EACrB,MAAM,SAAS,CAAC;AAEjB,kEAAkE;AAClE,MAAM,WAAW,QAAQ;IACxB,QAAQ,CAAC,GAAG,EAAE,gBAAgB,CAAC;IAC/B,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;CAC9B;AAED,+EAA+E;AAC/E,MAAM,WAAW,SAAS;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;QAAC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;IAC9E,QAAQ,EAAE,OAAO,CAAC;CAClB;AAKD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC5B,MAAM,EAAE,aAAa,EACrB,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,sBAAsB,CAAC,EACtD,IAAI,EAAE,iBAAiB,EACvB,IAAI,EAAE,SAAS,QAAQ,EAAE,GACvB,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CA8CxB"}
|
package/dist/config.d.ts
CHANGED
|
@@ -34,6 +34,16 @@ export interface CodegenZodConfig {
|
|
|
34
34
|
readonly addUnderscoreToArgsType?: boolean;
|
|
35
35
|
readonly dedupeOperationSuffix?: boolean;
|
|
36
36
|
readonly omitOperationSuffix?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* The SDL's object types, interfaces and unions, as what a resolver
|
|
39
|
+
* returns: `zUser`, `User`. Default `true`.
|
|
40
|
+
*/
|
|
41
|
+
readonly objects?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Each named operation's result and each fragment, as the response
|
|
44
|
+
* holds them: `zUserQuery`, `UserFieldsFragment`. Default `true`.
|
|
45
|
+
*/
|
|
46
|
+
readonly operations?: boolean;
|
|
37
47
|
}
|
|
38
48
|
/** A file of `documents`, as graphql-codegen hands it to a plugin. */
|
|
39
49
|
export interface DocumentFile {
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAChC;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACvD,gEAAgE;IAChE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EACvB,MAAM,GACN,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,GAC1B;QACA,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC;QACzD,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;QAC9B,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC;KACtC,CAAC;IACL,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAC3C,QAAQ,CAAC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IACzC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAChC;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACvD,gEAAgE;IAChE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EACvB,MAAM,GACN,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,GAC1B;QACA,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC;QACzD,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;QAC9B,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC;KACtC,CAAC;IACL,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAC3C,QAAQ,CAAC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IACzC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IACvC;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,sEAAsE;AACtE,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;IAC7C,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACvC"}
|
package/dist/cycles.d.ts
CHANGED
|
@@ -6,4 +6,11 @@ import { type GraphQLSchema } from 'graphql';
|
|
|
6
6
|
* types out.
|
|
7
7
|
*/
|
|
8
8
|
export declare function inputCycles(schema: GraphQLSchema): ReadonlySet<string>;
|
|
9
|
+
/**
|
|
10
|
+
* The object types that reach themselves through their fields, an
|
|
11
|
+
* interface's or a union's members included: TypeScript infers such a
|
|
12
|
+
* schema only so deep (TS2589 past a loop of ten), so the plugin writes
|
|
13
|
+
* their types out.
|
|
14
|
+
*/
|
|
15
|
+
export declare function outputCycles(schema: GraphQLSchema): ReadonlySet<string>;
|
|
9
16
|
//# sourceMappingURL=cycles.d.ts.map
|
package/dist/cycles.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cycles.d.ts","sourceRoot":"","sources":["../src/cycles.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,KAAK,aAAa,
|
|
1
|
+
{"version":3,"file":"cycles.d.ts","sourceRoot":"","sources":["../src/cycles.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,KAAK,aAAa,EAMlB,MAAM,SAAS,CAAC;AAEjB;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,aAAa,GAAG,WAAW,CAAC,MAAM,CAAC,CAUtE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,WAAW,CAAC,MAAM,CAAC,CAavE"}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,8 +3,8 @@ import type { CodegenZodConfig, DocumentFile } from './config';
|
|
|
3
3
|
export type { CodegenZodConfig, DocumentFile } from './config';
|
|
4
4
|
/**
|
|
5
5
|
* The graphql-codegen plugin: Zod schemas, and their types, for the
|
|
6
|
-
* schema's enums, input types
|
|
7
|
-
* each operation in `documents`, with every `@constraint` of
|
|
6
|
+
* schema's enums, input types, field arguments, object types, interfaces and
|
|
7
|
+
* unions, and for the variables of each operation in `documents`, with every `@constraint` of
|
|
8
8
|
* `@nxgt/graphql-validation`. It refuses a schema `withValidation` would
|
|
9
9
|
* refuse, with the same message.
|
|
10
10
|
*/
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACN,KAAK,aAAa,EAIlB,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACN,KAAK,aAAa,EAIlB,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAU/D,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE/D;;;;;;GAMG;AACH,wBAAsB,MAAM,CAC3B,MAAM,EAAE,aAAa,EACrB,SAAS,EAAE,SAAS,YAAY,EAAE,EAClC,MAAM,GAAE,gBAAqB,EAC7B,IAAI,CAAC,EAAE;IAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,GACjD,OAAO,CAAC,MAAM,CAAC,CAqCjB"}
|