@emcy/openapi-to-mcp 0.2.0 → 0.3.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 +144 -127
- package/dist/__tests__/cli-config.test.d.ts +2 -0
- package/dist/__tests__/cli-config.test.d.ts.map +1 -0
- package/dist/__tests__/cli-config.test.js +73 -0
- package/dist/__tests__/cli-config.test.js.map +1 -0
- package/dist/__tests__/generator.test.d.ts +1 -1
- package/dist/__tests__/generator.test.js +175 -201
- package/dist/__tests__/generator.test.js.map +1 -1
- package/dist/__tests__/integration.test.js +11 -11
- package/dist/__tests__/integration.test.js.map +1 -1
- package/dist/__tests__/mapper.test.js +20 -6
- package/dist/__tests__/mapper.test.js.map +1 -1
- package/dist/__tests__/tool-identity.test.d.ts +2 -0
- package/dist/__tests__/tool-identity.test.d.ts.map +1 -0
- package/dist/__tests__/tool-identity.test.js +15 -0
- package/dist/__tests__/tool-identity.test.js.map +1 -0
- package/dist/cli-config.d.ts +28 -0
- package/dist/cli-config.d.ts.map +1 -0
- package/dist/cli-config.js +124 -0
- package/dist/cli-config.js.map +1 -0
- package/dist/cli.js +56 -3
- package/dist/cli.js.map +1 -1
- package/dist/generator.d.ts +8 -3
- package/dist/generator.d.ts.map +1 -1
- package/dist/generator.js +681 -327
- package/dist/generator.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/mapper.d.ts.map +1 -1
- package/dist/mapper.js +3 -1
- package/dist/mapper.js.map +1 -1
- package/dist/parser.d.ts.map +1 -1
- package/dist/parser.js +14 -5
- package/dist/parser.js.map +1 -1
- package/dist/tool-identity.d.ts +6 -0
- package/dist/tool-identity.d.ts.map +1 -0
- package/dist/tool-identity.js +67 -0
- package/dist/tool-identity.js.map +1 -0
- package/dist/types.d.ts +98 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,35 +1,61 @@
|
|
|
1
1
|
# @emcy/openapi-to-mcp
|
|
2
2
|
|
|
3
|
-
Convert OpenAPI specifications
|
|
3
|
+
Convert OpenAPI specifications into MCP runtimes.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@emcy/openapi-to-mcp)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
7
|
|
|
8
|
-
## What
|
|
8
|
+
## What it generates
|
|
9
9
|
|
|
10
|
-
This
|
|
10
|
+
This package now supports three runtime shapes only:
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
12
|
+
1. `standalone_no_auth`
|
|
13
|
+
- Public MCP server
|
|
14
|
+
- No built-in upstream auth logic
|
|
15
|
+
- Good for public or already-open APIs
|
|
16
|
+
|
|
17
|
+
2. `standalone_headers`
|
|
18
|
+
- Public MCP server
|
|
19
|
+
- Injects static/custom headers into every upstream API request
|
|
20
|
+
- Good for API keys, static bearer tokens, tenant headers, and similar patterns
|
|
21
|
+
|
|
22
|
+
3. `emcy_hosted_worker`
|
|
23
|
+
- Private worker runtime behind Emcy
|
|
24
|
+
- Emcy hosts the public MCP and OAuth surface
|
|
25
|
+
- Good for OAuth-protected APIs where Emcy brokers user auth and forwards short-lived downstream access per execution
|
|
26
|
+
|
|
27
|
+
The generator no longer produces standalone public OAuth resource servers and no longer supports bearer-token passthrough.
|
|
16
28
|
|
|
17
29
|
## Quick Start
|
|
18
30
|
|
|
19
31
|
```bash
|
|
20
|
-
#
|
|
21
|
-
npx @emcy/openapi-to-mcp generate
|
|
32
|
+
# Standalone MCP server for a public API
|
|
33
|
+
npx @emcy/openapi-to-mcp generate \
|
|
34
|
+
--url https://petstore.swagger.io/v2/swagger.json \
|
|
35
|
+
--mode standalone-no-auth
|
|
22
36
|
|
|
23
|
-
#
|
|
24
|
-
npx @emcy/openapi-to-mcp generate
|
|
37
|
+
# Standalone MCP server that injects an API key header upstream
|
|
38
|
+
npx @emcy/openapi-to-mcp generate \
|
|
39
|
+
--url ./openapi.yaml \
|
|
40
|
+
--name my-api \
|
|
41
|
+
--mode standalone-headers \
|
|
42
|
+
--header X-API-Key=UPSTREAM_API_KEY
|
|
25
43
|
|
|
26
|
-
#
|
|
27
|
-
npx @emcy/openapi-to-mcp generate
|
|
44
|
+
# Emcy-hosted worker for an OAuth-protected app
|
|
45
|
+
npx @emcy/openapi-to-mcp generate \
|
|
46
|
+
--url ./openapi.yaml \
|
|
47
|
+
--name my-app \
|
|
48
|
+
--mode emcy-hosted-worker \
|
|
49
|
+
--hosted-provider sqlos \
|
|
50
|
+
--hosted-auth-server-url https://auth.example.com/sqlos/auth \
|
|
51
|
+
--hosted-client-id todo-mcp-local \
|
|
52
|
+
--hosted-resource https://api.example.com/todos \
|
|
53
|
+
--hosted-scopes "openid profile email offline_access todos.read todos.write"
|
|
28
54
|
```
|
|
29
55
|
|
|
30
56
|
## Installation
|
|
31
57
|
|
|
32
|
-
|
|
58
|
+
Use it directly with `npx` or install globally:
|
|
33
59
|
|
|
34
60
|
```bash
|
|
35
61
|
npm install -g @emcy/openapi-to-mcp
|
|
@@ -39,169 +65,160 @@ npm install -g @emcy/openapi-to-mcp
|
|
|
39
65
|
|
|
40
66
|
### `generate`
|
|
41
67
|
|
|
42
|
-
Generate an MCP server from an OpenAPI specification.
|
|
43
|
-
|
|
44
68
|
```bash
|
|
45
69
|
npx @emcy/openapi-to-mcp generate [options]
|
|
46
70
|
```
|
|
47
71
|
|
|
48
|
-
**Options:**
|
|
49
|
-
|
|
50
72
|
| Option | Short | Description |
|
|
51
|
-
|
|
52
|
-
| `--url` | `-u` | URL or file path to OpenAPI
|
|
53
|
-
| `--name` | `-n` | Name for the generated
|
|
54
|
-
| `--output` | `-o` | Output directory
|
|
55
|
-
| `--
|
|
56
|
-
| `--
|
|
57
|
-
| `--
|
|
58
|
-
| `--
|
|
73
|
+
| --- | --- | --- |
|
|
74
|
+
| `--url` | `-u` | URL or file path to OpenAPI spec |
|
|
75
|
+
| `--name` | `-n` | Name for the generated runtime |
|
|
76
|
+
| `--output` | `-o` | Output directory |
|
|
77
|
+
| `--base-url` | `-b` | Override the upstream API base URL |
|
|
78
|
+
| `--version` | | Runtime version string |
|
|
79
|
+
| `--emcy` | `-e` | Include `@emcy/sdk` telemetry |
|
|
80
|
+
| `--local-sdk` | | Use a local `@emcy/sdk` path |
|
|
81
|
+
| `--prompts-json` | | JSON array of MCP prompt definitions |
|
|
82
|
+
| `--tool-instructions-json` | | JSON object keyed by tool key for tool-specific AI guidance |
|
|
83
|
+
| `--mode` | | `standalone-no-auth`, `standalone-headers`, or `emcy-hosted-worker` |
|
|
84
|
+
| `--header` | | Repeatable `Header-Name=ENV_VAR` mapping for upstream requests |
|
|
85
|
+
| `--hosted-provider` | | Hosted OAuth provider recipe label for `emcy-hosted-worker` |
|
|
86
|
+
| `--hosted-auth-server-url` | | Downstream authorization server issuer or metadata base URL |
|
|
87
|
+
| `--hosted-client-id` | | Downstream client ID Emcy should use |
|
|
88
|
+
| `--hosted-resource` | | Downstream API resource / audience |
|
|
89
|
+
| `--hosted-scopes` | | Comma or space separated downstream scopes |
|
|
90
|
+
| `--force` | `-f` | Overwrite the output directory |
|
|
59
91
|
|
|
60
92
|
### `validate`
|
|
61
93
|
|
|
62
|
-
Validate an OpenAPI specification.
|
|
63
|
-
|
|
64
94
|
```bash
|
|
65
95
|
npx @emcy/openapi-to-mcp validate --url https://api.example.com/openapi.json
|
|
66
96
|
```
|
|
67
97
|
|
|
68
|
-
##
|
|
69
|
-
|
|
70
|
-
The generated MCP server includes:
|
|
98
|
+
## Runtime Modes
|
|
71
99
|
|
|
72
|
-
|
|
73
|
-
- **HTTP transport** - For Cursor and web-based clients
|
|
74
|
-
- **Stdio transport** - For Claude Desktop
|
|
75
|
-
- **Security support** - API keys, Bearer tokens, OAuth2
|
|
76
|
-
- **Environment-based config** - `.env.example` with all settings
|
|
77
|
-
- **README** - Usage instructions
|
|
100
|
+
### `standalone_no_auth`
|
|
78
101
|
|
|
79
|
-
|
|
102
|
+
Use this when the upstream API is public or already reachable without adding credentials from the MCP runtime.
|
|
80
103
|
|
|
81
104
|
```bash
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
105
|
+
npx @emcy/openapi-to-mcp generate \
|
|
106
|
+
--url ./openapi.json \
|
|
107
|
+
--mode standalone-no-auth
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### `standalone_headers`
|
|
85
111
|
|
|
86
|
-
|
|
87
|
-
npm run start:http
|
|
112
|
+
Use this when every upstream request needs static headers.
|
|
88
113
|
|
|
89
|
-
|
|
90
|
-
|
|
114
|
+
```bash
|
|
115
|
+
npx @emcy/openapi-to-mcp generate \
|
|
116
|
+
--url ./openapi.json \
|
|
117
|
+
--mode standalone-headers \
|
|
118
|
+
--header X-API-Key=UPSTREAM_API_KEY \
|
|
119
|
+
--header X-Tenant-Id=UPSTREAM_TENANT_ID
|
|
91
120
|
```
|
|
92
121
|
|
|
93
|
-
|
|
122
|
+
If your upstream API needs `Authorization: Bearer ...`, either:
|
|
94
123
|
|
|
95
|
-
|
|
124
|
+
- model it as a bearer security scheme in the OpenAPI document, or
|
|
125
|
+
- pass the full header value through an env var:
|
|
96
126
|
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
127
|
+
```bash
|
|
128
|
+
npx @emcy/openapi-to-mcp generate \
|
|
129
|
+
--url ./openapi.json \
|
|
130
|
+
--mode standalone-headers \
|
|
131
|
+
--header Authorization=UPSTREAM_AUTHORIZATION
|
|
105
132
|
```
|
|
106
133
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
Add to your Claude Desktop config:
|
|
134
|
+
Then set:
|
|
110
135
|
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
"mcpServers": {
|
|
114
|
-
"my-api": {
|
|
115
|
-
"command": "node",
|
|
116
|
-
"args": ["/path/to/my-api-mcp-server/build/index.js"]
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
136
|
+
```bash
|
|
137
|
+
UPSTREAM_AUTHORIZATION=Bearer eyJ...
|
|
120
138
|
```
|
|
121
139
|
|
|
122
|
-
|
|
140
|
+
### `emcy_hosted_worker`
|
|
123
141
|
|
|
124
|
-
|
|
142
|
+
Use this when the upstream API is protected by OAuth and you want Emcy to host the MCP and OAuth surface.
|
|
125
143
|
|
|
126
|
-
|
|
127
|
-
- **Error monitoring** - Failures are captured with context
|
|
128
|
-
- **Performance metrics** - Latency and success rates
|
|
129
|
-
- **Dashboard** - View analytics at [emcy.ai](https://emcy.ai)
|
|
144
|
+
The generated runtime is not the public MCP server. It is the private worker Emcy calls after it has already:
|
|
130
145
|
|
|
131
|
-
|
|
146
|
+
- authenticated the MCP client
|
|
147
|
+
- completed the downstream app OAuth flow
|
|
148
|
+
- stored the downstream grant server-side
|
|
149
|
+
- minted or loaded the short-lived downstream access token for the execution
|
|
132
150
|
|
|
133
151
|
```bash
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
152
|
+
npx @emcy/openapi-to-mcp generate \
|
|
153
|
+
--url ./openapi.json \
|
|
154
|
+
--mode emcy-hosted-worker \
|
|
155
|
+
--hosted-provider sqlos \
|
|
156
|
+
--hosted-auth-server-url https://auth.example.com/sqlos/auth \
|
|
157
|
+
--hosted-client-id todo-mcp-local \
|
|
158
|
+
--hosted-resource https://api.example.com/todos \
|
|
159
|
+
--hosted-scopes "openid profile email offline_access todos.read todos.write"
|
|
137
160
|
```
|
|
138
161
|
|
|
139
|
-
|
|
162
|
+
This is the right mode for apps protected by systems like:
|
|
140
163
|
|
|
141
|
-
|
|
164
|
+
- Auth0
|
|
165
|
+
- WorkOS AuthKit
|
|
166
|
+
- SqlOS AuthServer/AuthPage
|
|
167
|
+
- Entra
|
|
168
|
+
- generic OAuth/OIDC authorization servers
|
|
142
169
|
|
|
143
|
-
|
|
144
|
-
import { parseOpenAPI, mapToMcpTools, generateMcpServer } from '@emcy/openapi-to-mcp';
|
|
170
|
+
## Generated Runtime
|
|
145
171
|
|
|
146
|
-
|
|
147
|
-
const parsed = await parseOpenAPI('https://api.example.com/openapi.json');
|
|
172
|
+
Every generated runtime includes:
|
|
148
173
|
|
|
149
|
-
|
|
150
|
-
|
|
174
|
+
- TypeScript source
|
|
175
|
+
- MCP tool bindings for the selected OpenAPI operations
|
|
176
|
+
- Streamable HTTP transport
|
|
177
|
+
- `.env.example`
|
|
178
|
+
- generated README
|
|
151
179
|
|
|
152
|
-
|
|
153
|
-
const files = generateMcpServer(tools, {
|
|
154
|
-
name: 'my-api',
|
|
155
|
-
version: '1.0.0',
|
|
156
|
-
baseUrl: 'https://api.example.com',
|
|
157
|
-
emcyEnabled: true,
|
|
158
|
-
}, parsed.securitySchemes);
|
|
180
|
+
Standalone modes also support stdio for desktop clients.
|
|
159
181
|
|
|
160
|
-
|
|
161
|
-
```
|
|
182
|
+
## Programmatic Usage
|
|
162
183
|
|
|
163
|
-
|
|
184
|
+
```ts
|
|
185
|
+
import { parseOpenAPI, mapToMcpTools, generateMcpServer } from "@emcy/openapi-to-mcp";
|
|
164
186
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
- ✅ Request bodies (JSON)
|
|
168
|
-
- ✅ API key authentication
|
|
169
|
-
- ✅ Bearer token authentication
|
|
170
|
-
- ✅ OAuth2 (client credentials)
|
|
171
|
-
- ✅ Multiple security schemes
|
|
172
|
-
- ⏳ File uploads (coming soon)
|
|
173
|
-
- ⏳ Webhooks (coming soon)
|
|
187
|
+
const parsed = await parseOpenAPI("https://api.example.com/openapi.json");
|
|
188
|
+
const tools = mapToMcpTools(parsed.endpoints);
|
|
174
189
|
|
|
175
|
-
|
|
190
|
+
const files = generateMcpServer(
|
|
191
|
+
tools,
|
|
192
|
+
{
|
|
193
|
+
name: "my-api",
|
|
194
|
+
version: "1.0.0",
|
|
195
|
+
baseUrl: "https://api.example.com",
|
|
196
|
+
runtimeMode: "standalone_headers",
|
|
197
|
+
upstreamHeaders: [
|
|
198
|
+
{ name: "X-API-Key", envVar: "UPSTREAM_API_KEY" },
|
|
199
|
+
],
|
|
200
|
+
},
|
|
201
|
+
parsed.securitySchemes
|
|
202
|
+
);
|
|
203
|
+
```
|
|
176
204
|
|
|
177
|
-
|
|
205
|
+
## What this package does not do
|
|
178
206
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
--name petstore
|
|
183
|
-
```
|
|
207
|
+
- It does not host a public OAuth authorization server for MCP clients.
|
|
208
|
+
- It does not support forwarding end-user bearer tokens from the MCP client to the upstream API.
|
|
209
|
+
- It does not try to replace Emcy's hosted auth/runtime layer for OAuth-protected apps.
|
|
184
210
|
|
|
185
|
-
|
|
211
|
+
## Emcy
|
|
186
212
|
|
|
187
|
-
|
|
188
|
-
npx @emcy/openapi-to-mcp generate \
|
|
189
|
-
--url http://localhost:5000/swagger/v1/swagger.json \
|
|
190
|
-
--name my-local-api \
|
|
191
|
-
--base-url http://localhost:5000
|
|
192
|
-
```
|
|
213
|
+
Use Emcy when you want to turn an OAuth-protected API into:
|
|
193
214
|
|
|
194
|
-
|
|
215
|
+
- a hosted MCP server
|
|
216
|
+
- an embedded agent
|
|
217
|
+
- a workspace integration
|
|
218
|
+
- an external client surface for tools like VS Code or Claude
|
|
195
219
|
|
|
196
|
-
|
|
197
|
-
npx @emcy/openapi-to-mcp generate \
|
|
198
|
-
--url ./openapi.yaml \
|
|
199
|
-
--name my-api \
|
|
200
|
-
--emcy \
|
|
201
|
-
--output ./mcp-servers/my-api
|
|
202
|
-
```
|
|
220
|
+
The open-source generator handles the runtime. Emcy handles the hosted auth and orchestration layer.
|
|
203
221
|
|
|
204
222
|
## License
|
|
205
223
|
|
|
206
224
|
MIT © [Emcy](https://emcy.ai)
|
|
207
|
-
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-config.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/cli-config.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { normalizeRuntimeMode, parseGeneratorCliConfig, parseHostedOauthConfig, parseToolInstructions, } from "../cli-config.js";
|
|
3
|
+
describe("cli-config", () => {
|
|
4
|
+
it("normalizes supported runtime modes", () => {
|
|
5
|
+
expect(normalizeRuntimeMode("standalone-no-auth")).toBe("standalone_no_auth");
|
|
6
|
+
expect(normalizeRuntimeMode("standalone_headers")).toBe("standalone_headers");
|
|
7
|
+
expect(normalizeRuntimeMode("emcy-hosted-worker")).toBe("emcy_hosted_worker");
|
|
8
|
+
});
|
|
9
|
+
it("parses hosted oauth config from explicit flags", () => {
|
|
10
|
+
const config = parseHostedOauthConfig({
|
|
11
|
+
"hosted-provider": "auth0",
|
|
12
|
+
"hosted-auth-server-url": "https://auth.example.com",
|
|
13
|
+
"hosted-client-id": "client_123",
|
|
14
|
+
"hosted-resource": "https://api.example.com",
|
|
15
|
+
"hosted-scopes": "openid profile email offline_access todos.read",
|
|
16
|
+
});
|
|
17
|
+
expect(config).toEqual({
|
|
18
|
+
provider: "auth0",
|
|
19
|
+
authorizationServerUrl: "https://auth.example.com",
|
|
20
|
+
clientId: "client_123",
|
|
21
|
+
resource: "https://api.example.com",
|
|
22
|
+
scopes: ["openid", "profile", "email", "offline_access", "todos.read"],
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
it("parses tool instructions json objects", () => {
|
|
26
|
+
expect(parseToolInstructions(JSON.stringify({
|
|
27
|
+
get_api_todos: {
|
|
28
|
+
customInstructions: "Use this for current todos only.",
|
|
29
|
+
},
|
|
30
|
+
}))).toEqual({
|
|
31
|
+
get_api_todos: {
|
|
32
|
+
customInstructions: "Use this for current todos only.",
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
it("builds generator CLI config for hosted workers", () => {
|
|
37
|
+
const parsed = parseGeneratorCliConfig({
|
|
38
|
+
mode: "emcy-hosted-worker",
|
|
39
|
+
"prompts-json": JSON.stringify([
|
|
40
|
+
{
|
|
41
|
+
name: "todo-summary",
|
|
42
|
+
description: "Summarize todos",
|
|
43
|
+
content: "Summarize {{topic}}",
|
|
44
|
+
},
|
|
45
|
+
]),
|
|
46
|
+
"tool-instructions-json": JSON.stringify({
|
|
47
|
+
get_api_todos: {
|
|
48
|
+
whenToUse: "When the user asks to list todos.",
|
|
49
|
+
},
|
|
50
|
+
}),
|
|
51
|
+
"hosted-provider": "sqlos",
|
|
52
|
+
"hosted-auth-server-url": "https://auth.example.com/sqlos/auth",
|
|
53
|
+
"hosted-client-id": "todo-mcp-local",
|
|
54
|
+
"hosted-resource": "https://api.example.com/todos",
|
|
55
|
+
"hosted-scopes": "openid profile todos.read todos.write",
|
|
56
|
+
});
|
|
57
|
+
expect(parsed.runtimeMode).toBe("emcy_hosted_worker");
|
|
58
|
+
expect(parsed.prompts).toHaveLength(1);
|
|
59
|
+
expect(parsed.toolInstructions).toEqual({
|
|
60
|
+
get_api_todos: {
|
|
61
|
+
whenToUse: "When the user asks to list todos.",
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
expect(parsed.hostedOauthConfig).toEqual({
|
|
65
|
+
provider: "sqlos",
|
|
66
|
+
authorizationServerUrl: "https://auth.example.com/sqlos/auth",
|
|
67
|
+
clientId: "todo-mcp-local",
|
|
68
|
+
resource: "https://api.example.com/todos",
|
|
69
|
+
scopes: ["openid", "profile", "todos.read", "todos.write"],
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
//# sourceMappingURL=cli-config.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-config.test.js","sourceRoot":"","sources":["../../src/__tests__/cli-config.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EACL,oBAAoB,EACpB,uBAAuB,EACvB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAE1B,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,MAAM,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9E,MAAM,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9E,MAAM,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IAChF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,MAAM,MAAM,GAAG,sBAAsB,CAAC;YACpC,iBAAiB,EAAE,OAAO;YAC1B,wBAAwB,EAAE,0BAA0B;YACpD,kBAAkB,EAAE,YAAY;YAChC,iBAAiB,EAAE,yBAAyB;YAC5C,eAAe,EAAE,gDAAgD;SAClE,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACrB,QAAQ,EAAE,OAAO;YACjB,sBAAsB,EAAE,0BAA0B;YAClD,QAAQ,EAAE,YAAY;YACtB,QAAQ,EAAE,yBAAyB;YACnC,MAAM,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,gBAAgB,EAAE,YAAY,CAAC;SACvE,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,CACJ,qBAAqB,CACnB,IAAI,CAAC,SAAS,CAAC;YACb,aAAa,EAAE;gBACb,kBAAkB,EAAE,kCAAkC;aACvD;SACF,CAAC,CACH,CACF,CAAC,OAAO,CAAC;YACR,aAAa,EAAE;gBACb,kBAAkB,EAAE,kCAAkC;aACvD;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,MAAM,MAAM,GAAG,uBAAuB,CAAC;YACrC,IAAI,EAAE,oBAAoB;YAC1B,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC;gBAC7B;oBACE,IAAI,EAAE,cAAc;oBACpB,WAAW,EAAE,iBAAiB;oBAC9B,OAAO,EAAE,qBAAqB;iBAC/B;aACF,CAAC;YACF,wBAAwB,EAAE,IAAI,CAAC,SAAS,CAAC;gBACvC,aAAa,EAAE;oBACb,SAAS,EAAE,mCAAmC;iBAC/C;aACF,CAAC;YACF,iBAAiB,EAAE,OAAO;YAC1B,wBAAwB,EAAE,qCAAqC;YAC/D,kBAAkB,EAAE,gBAAgB;YACpC,iBAAiB,EAAE,+BAA+B;YAClD,eAAe,EAAE,uCAAuC;SACzD,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QACtD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACvC,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,OAAO,CAAC;YACtC,aAAa,EAAE;gBACb,SAAS,EAAE,mCAAmC;aAC/C;SACF,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,OAAO,CAAC;YACvC,QAAQ,EAAE,OAAO;YACjB,sBAAsB,EAAE,qCAAqC;YAC7D,QAAQ,EAAE,gBAAgB;YAC1B,QAAQ,EAAE,+BAA+B;YACzC,MAAM,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,CAAC;SAC3D,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|