@databrainhq/mcp-server 0.3.0-rc.3 → 0.3.0-rc.5
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 +56 -1
- package/dist/apps/server.d.ts +6 -6
- package/dist/apps/server.js +3 -2
- package/dist/apps/stdio.js +4 -3
- package/dist/apps/stdio.js.map +1 -1
- package/dist/{chunk-CX3CS62P.js → chunk-3GF7WSKK.js} +4 -2
- package/dist/chunk-3GF7WSKK.js.map +1 -0
- package/dist/{chunk-4LIULTLT.js → chunk-4DYPD273.js} +204 -67
- package/dist/chunk-4DYPD273.js.map +1 -0
- package/dist/{chunk-DZOYK5BB.js → chunk-5IQ7MVUH.js} +1044 -1029
- package/dist/chunk-5IQ7MVUH.js.map +1 -0
- package/dist/chunk-PRE4CGOV.js +1903 -0
- package/dist/chunk-PRE4CGOV.js.map +1 -0
- package/dist/{chunk-OHTV24NG.js → chunk-V64ZQINV.js} +2 -2
- package/dist/cli.d.ts +15 -0
- package/dist/cli.js +495 -0
- package/dist/cli.js.map +1 -0
- package/dist/custom-chart/runtime-shim.js +146 -0
- package/dist/custom-chart/template/AGENTS.md +374 -0
- package/dist/custom-chart/template/README.md +374 -0
- package/dist/custom-chart/template/chart.css +28 -0
- package/dist/custom-chart/template/chart.ts +192 -0
- package/dist/custom-chart/template/custom-chart.d.ts +78 -0
- package/dist/custom-chart/template/icon.svg +1 -0
- package/dist/custom-chart/template/manifest.json +23 -0
- package/dist/custom-chart/template/package.json +14 -0
- package/dist/custom-chart/template/sample-data.json +18 -0
- package/dist/custom-chart/template/tsconfig.json +12 -0
- package/dist/index.js +11 -7
- package/dist/index.js.map +1 -1
- package/dist/{main-VPCN2764.js → main-Q6XT4O46.js} +34 -8
- package/dist/main-Q6XT4O46.js.map +1 -0
- package/dist/{test-only-B4EVUNFU.js → test-only-TJ3DQUYW.js} +2 -2
- package/package.json +6 -3
- package/dist/chunk-4LIULTLT.js.map +0 -1
- package/dist/chunk-CX3CS62P.js.map +0 -1
- package/dist/chunk-DZOYK5BB.js.map +0 -1
- package/dist/main-VPCN2764.js.map +0 -1
- /package/dist/{chunk-OHTV24NG.js.map → chunk-V64ZQINV.js.map} +0 -0
- /package/dist/{test-only-B4EVUNFU.js.map → test-only-TJ3DQUYW.js.map} +0 -0
package/README.md
CHANGED
|
@@ -280,6 +280,27 @@ At least one of `DATABRAIN_SERVICE_TOKEN` or `DATABRAIN_API_TOKEN` must be set.
|
|
|
280
280
|
|
|
281
281
|
---
|
|
282
282
|
|
|
283
|
+
## Hosted (HTTPS) deployment
|
|
284
|
+
|
|
285
|
+
`node dist/index.js --http` starts the same server as a hosted Streamable HTTP endpoint at `/mcp`. Callers authenticate with an OAuth bearer token on every request; the server never reads `DATABRAIN_SERVICE_TOKEN` or `DATABRAIN_API_TOKEN` in this mode. Full design notes are in [`specs/hosted-http.md`](specs/hosted-http.md).
|
|
286
|
+
|
|
287
|
+
| Variable | Required | Default | Description |
|
|
288
|
+
|----------|----------|---------|-------------|
|
|
289
|
+
| `DATABRAIN_HOSTED_PUBLIC_URL` | Yes | — | Exact public HTTPS URL of the endpoint, ending in `/mcp` (e.g. `https://mcp.usedatabrain.com/mcp`). Used for discovery metadata and audience checks. |
|
|
290
|
+
| `DATABRAIN_HOSTED_ISSUER` | Yes | — | HTTPS origin of the trusted authorization server. Bearer tokens are verified against `<issuer>/oauth/principal`. |
|
|
291
|
+
| `DATABRAIN_HOSTED_BIND` | No | `127.0.0.1` | Listener address. Set `0.0.0.0` in a container so the load balancer can reach it. |
|
|
292
|
+
| `DATABRAIN_HOSTED_PORT` | No | `3144` | Listener port. |
|
|
293
|
+
|
|
294
|
+
`GET /health` (or `HEAD`) returns `200 {"status":"ok"}` with no authentication. It is the only route that skips the Host check, so an ALB health check with the target IP:port as Host succeeds. Point the target group health check at `/health`.
|
|
295
|
+
|
|
296
|
+
The `Dockerfile` at the repo root builds the hosted server from source: `docker build -t databrain-mcp-hosted .` then run it with the two required variables and `-p 3144:3144`.
|
|
297
|
+
|
|
298
|
+
The load balancer **must forward the original `Host` header unchanged**. Requests to `/mcp` and the `/.well-known/oauth-protected-resource` metadata are answered only when Host matches the host of `DATABRAIN_HOSTED_PUBLIC_URL`; anything else gets `403 invalid_host`.
|
|
299
|
+
|
|
300
|
+
**Current limits.** Without `DATABRAIN_HOSTED_ADAPTER_MODULE` (an absolute path to a trusted delegated adapter, see the spec), the default adapter verifies identity only. `whoami`, tool/resource/prompt discovery and OAuth verification work today; every data tool answers `503 delegated_backend_adapter_required` until that adapter is configured.
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
283
304
|
## Available Prompts
|
|
284
305
|
|
|
285
306
|
Prompts are guided workflows your AI assistant can follow. Ask for them by name or describe what you want.
|
|
@@ -298,7 +319,7 @@ Prompts are guided workflows your AI assistant can follow. Ask for them by name
|
|
|
298
319
|
|
|
299
320
|
## Tools Reference
|
|
300
321
|
|
|
301
|
-
|
|
322
|
+
44 tools organized by category (plus 6 chart App tools on the opt-in `databrain-mcp-chart-apps` entry). Your AI assistant picks the right tools automatically. You do not need to call them directly.
|
|
302
323
|
|
|
303
324
|
> **Note:** Datasource and workspace creation happen outside MCP. Datamarts can be planned with `create_datamart` in `dry_run` mode and created only with `confirm: "APPLY_TO_PRODUCTION"`. The semantic layer is managed via MCP tools (`get_semantic_layer`, `update_semantic_layer`, `start_semantic_layer_generation`, `get_semantic_layer_generation_status`).
|
|
304
325
|
|
|
@@ -360,6 +381,8 @@ Prompts are guided workflows your AI assistant can follow. Ask for them by name
|
|
|
360
381
|
| `update_semantic_layer` | Improve semantic layer quality (add descriptions, synonyms, example questions) |
|
|
361
382
|
| `start_semantic_layer_generation` | Start semantic-layer generation for a datamart |
|
|
362
383
|
| `get_semantic_layer_generation_status` | Check semantic-layer generation progress |
|
|
384
|
+
|
|
385
|
+
Semantic-layer generation uses the datamart ID returned by `list_datamarts` and calls the service-token API. Pass `datamartId` directly when the ID is already known.
|
|
363
386
|
</details>
|
|
364
387
|
|
|
365
388
|
<details>
|
|
@@ -388,6 +411,38 @@ Production writes through `create_or_update_metric_from_query` default to `dry_r
|
|
|
388
411
|
| `list_scheduled_reports` | List configured scheduled reports for a dashboard/client scope |
|
|
389
412
|
</details>
|
|
390
413
|
|
|
414
|
+
<details>
|
|
415
|
+
<summary><b>Custom chart types</b> (5)</summary>
|
|
416
|
+
|
|
417
|
+
| Tool | Description |
|
|
418
|
+
|------|-------------|
|
|
419
|
+
| `custom_chart_scaffold` | Return the files of a new chart project (manifest, chart.ts, css, icon, sample data, author guide). Nothing is written or persisted |
|
|
420
|
+
| `custom_chart_validate` | Validate a manifest and bundle with the local rules and, when a service token is configured, the server rules. Never persists |
|
|
421
|
+
| `custom_chart_upload` | Dry-run or upload a built bundle as a private chart (version 1) or a preview version; `publish: true` publishes in the same apply |
|
|
422
|
+
| `list_custom_charts` | List the company's custom chart types with status and version ids |
|
|
423
|
+
| `publish_custom_chart` | Dry-run or publish a version so every builder can use chart type `custom:<key>` |
|
|
424
|
+
|
|
425
|
+
`custom_chart_upload` and `publish_custom_chart` default to `dry_run` and apply only with `confirm: "APPLY_TO_PRODUCTION"`. Hosted scopes: `mcp:custom-charts:read` and `mcp:custom-charts:write`. Build the bundle with the CLI below.
|
|
426
|
+
</details>
|
|
427
|
+
|
|
428
|
+
---
|
|
429
|
+
|
|
430
|
+
## Custom chart CLI
|
|
431
|
+
|
|
432
|
+
The package also installs a `databrain` binary for chart authors:
|
|
433
|
+
|
|
434
|
+
```bash
|
|
435
|
+
npx -p @databrainhq/mcp-server databrain custom-chart init my-chart
|
|
436
|
+
cd my-chart # read AGENTS.md, edit chart.ts
|
|
437
|
+
databrain custom-chart validate # manifest, icon, css
|
|
438
|
+
databrain custom-chart build # writes dist/index.js, manifest.json, icon.svg, index.css, bundle.zip
|
|
439
|
+
databrain custom-chart dev # local sandbox page on http://127.0.0.1:4174
|
|
440
|
+
DATABRAIN_SERVICE_TOKEN=... databrain custom-chart upload # build, server validate, plan, confirm, upload
|
|
441
|
+
DATABRAIN_SERVICE_TOKEN=... databrain custom-chart upload --publish --yes
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
Problems print as `path code message` and the exit code is 1 when there is any. `upload` needs `DATABRAIN_SERVICE_TOKEN` and, on self-hosted instances, `DATABRAIN_API_URL`. The template's `AGENTS.md` is the full author guide: manifest reference, data shape, theme, interactions, troubleshooting.
|
|
445
|
+
|
|
391
446
|
---
|
|
392
447
|
|
|
393
448
|
## Built-in Knowledge
|
package/dist/apps/server.d.ts
CHANGED
|
@@ -197,8 +197,8 @@ declare const pageSchema: z.ZodEffects<z.ZodObject<{
|
|
|
197
197
|
drillId: z.ZodOptional<z.ZodString>;
|
|
198
198
|
}, "strict", z.ZodTypeAny, {
|
|
199
199
|
value: string | number | boolean | null;
|
|
200
|
-
label: string;
|
|
201
200
|
key: string;
|
|
201
|
+
label: string;
|
|
202
202
|
x: number;
|
|
203
203
|
y: number;
|
|
204
204
|
width: number;
|
|
@@ -206,8 +206,8 @@ declare const pageSchema: z.ZodEffects<z.ZodObject<{
|
|
|
206
206
|
drillId?: string | undefined;
|
|
207
207
|
}, {
|
|
208
208
|
value: string | number | boolean | null;
|
|
209
|
-
label: string;
|
|
210
209
|
key: string;
|
|
210
|
+
label: string;
|
|
211
211
|
x: number;
|
|
212
212
|
y: number;
|
|
213
213
|
width: number;
|
|
@@ -228,8 +228,8 @@ declare const pageSchema: z.ZodEffects<z.ZodObject<{
|
|
|
228
228
|
rows: Record<string, string | number | boolean | null>[];
|
|
229
229
|
points: {
|
|
230
230
|
value: string | number | boolean | null;
|
|
231
|
-
label: string;
|
|
232
231
|
key: string;
|
|
232
|
+
label: string;
|
|
233
233
|
x: number;
|
|
234
234
|
y: number;
|
|
235
235
|
width: number;
|
|
@@ -251,8 +251,8 @@ declare const pageSchema: z.ZodEffects<z.ZodObject<{
|
|
|
251
251
|
rows: Record<string, string | number | boolean | null>[];
|
|
252
252
|
points: {
|
|
253
253
|
value: string | number | boolean | null;
|
|
254
|
-
label: string;
|
|
255
254
|
key: string;
|
|
255
|
+
label: string;
|
|
256
256
|
x: number;
|
|
257
257
|
y: number;
|
|
258
258
|
width: number;
|
|
@@ -274,8 +274,8 @@ declare const pageSchema: z.ZodEffects<z.ZodObject<{
|
|
|
274
274
|
rows: Record<string, string | number | boolean | null>[];
|
|
275
275
|
points: {
|
|
276
276
|
value: string | number | boolean | null;
|
|
277
|
-
label: string;
|
|
278
277
|
key: string;
|
|
278
|
+
label: string;
|
|
279
279
|
x: number;
|
|
280
280
|
y: number;
|
|
281
281
|
width: number;
|
|
@@ -297,8 +297,8 @@ declare const pageSchema: z.ZodEffects<z.ZodObject<{
|
|
|
297
297
|
rows: Record<string, string | number | boolean | null>[];
|
|
298
298
|
points: {
|
|
299
299
|
value: string | number | boolean | null;
|
|
300
|
-
label: string;
|
|
301
300
|
key: string;
|
|
301
|
+
label: string;
|
|
302
302
|
x: number;
|
|
303
303
|
y: number;
|
|
304
304
|
width: number;
|
package/dist/apps/server.js
CHANGED
package/dist/apps/stdio.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
loadConfig
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-V64ZQINV.js";
|
|
5
5
|
import {
|
|
6
6
|
createChartAppServer
|
|
7
|
-
} from "../chunk-
|
|
8
|
-
import "../chunk-
|
|
7
|
+
} from "../chunk-4DYPD273.js";
|
|
8
|
+
import "../chunk-5IQ7MVUH.js";
|
|
9
|
+
import "../chunk-PRE4CGOV.js";
|
|
9
10
|
|
|
10
11
|
// src/apps/stdio.ts
|
|
11
12
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
package/dist/apps/stdio.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/apps/stdio.ts"],"sourcesContent":["import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { loadConfig } from '../utils/config.js';\nimport { createChartAppServer } from './server.js';\n\n// Separate opt-in command until the owners integrate both shared entrypoints.\nconst server = createChartAppServer(loadConfig());\nawait server.connect(new StdioServerTransport());\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../src/apps/stdio.ts"],"sourcesContent":["import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { loadConfig } from '../utils/config.js';\nimport { createChartAppServer } from './server.js';\n\n// Separate opt-in command until the owners integrate both shared entrypoints.\nconst server = createChartAppServer(loadConfig());\nawait server.connect(new StdioServerTransport());\n"],"mappings":";;;;;;;;;;;AAAA,SAAS,4BAA4B;AAKrC,IAAM,SAAS,qBAAqB,WAAW,CAAC;AAChD,MAAM,OAAO,QAAQ,IAAI,qBAAqB,CAAC;","names":[]}
|
|
@@ -7,7 +7,9 @@ var HOSTED_SCOPES = [
|
|
|
7
7
|
"mcp:datamarts:read",
|
|
8
8
|
"mcp:datamarts:write",
|
|
9
9
|
"mcp:embeds:write",
|
|
10
|
-
"mcp:query"
|
|
10
|
+
"mcp:query",
|
|
11
|
+
"mcp:custom-charts:read",
|
|
12
|
+
"mcp:custom-charts:write"
|
|
11
13
|
];
|
|
12
14
|
var HostedAuthError = class extends Error {
|
|
13
15
|
constructor(status, code) {
|
|
@@ -99,4 +101,4 @@ export {
|
|
|
99
101
|
FilePatStore,
|
|
100
102
|
createBearerVerifier
|
|
101
103
|
};
|
|
102
|
-
//# sourceMappingURL=chunk-
|
|
104
|
+
//# sourceMappingURL=chunk-3GF7WSKK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/hosted/types.ts","../src/hosted/auth.ts"],"sourcesContent":["import type { RequestOptions } from '../client/types.js';\n\nexport const HOSTED_SCOPES = [\n 'mcp:dashboards:read', 'mcp:dashboards:write',\n 'mcp:datamarts:read', 'mcp:datamarts:write', 'mcp:embeds:write', 'mcp:query',\n 'mcp:custom-charts:read', 'mcp:custom-charts:write',\n] as const;\nexport type HostedScope = typeof HOSTED_SCOPES[number];\n\n/** Only the trusted auth adapter may produce this context. Never populate it from MCP input. */\nexport interface HostedPrincipal {\n actorKind: 'user';\n credentialType: 'oauth' | 'pat';\n userId: string;\n companyId: string;\n workspaceId: string;\n workspaceName?: string;\n /** OAuth application ID, NOT the tenant identifier called clientId by legacy tools. */\n clientId: string;\n resource: string;\n scopes: HostedScope[];\n /** Required for stored PATs. OAuth may delegate expiry to fresh provider validation. */\n expiresAt?: number;\n /** Explicit tenant allow-list resolved by the backend; absent means no tenant access. */\n tenantIds?: string[];\n}\n\nexport interface PatRecord {\n hash: string;\n revokedAt: number | null;\n principal: HostedPrincipal;\n}\n\nexport interface PatStore {\n findByHash(hash: string): Promise<PatRecord | undefined>;\n}\n\n/** Production integration must recheck membership, policy and revocation on every call. */\nexport interface HostedAdapter {\n verifyOAuth(token: string, resource: string): Promise<HostedPrincipal>;\n resolvePatGrant(principal: HostedPrincipal): Promise<HostedPrincipal>;\n /**\n * Execute as this user/workspace with backend resource and tenant checks and auditing.\n * Receives NO incoming bearer or server service credential. Credential exchange, if\n * needed, belongs in the trusted adapter. Do not impersonate a static service token.\n * Return the raw API result: the shared client performs its usual data unwrapping.\n */\n executeRequest(options: RequestOptions, principal: HostedPrincipal): Promise<unknown>;\n}\n\nexport interface HostedConfig {\n publicUrl: string;\n issuer: string;\n port: number;\n bind: string;\n testOnly: boolean;\n}\n\nexport class HostedAuthError extends Error {\n constructor(public readonly status: 401 | 403 | 503, public readonly code: string) {\n super(code);\n }\n}\n","import { createHash, timingSafeEqual } from 'node:crypto';\nimport { open } from 'node:fs/promises';\nimport { constants } from 'node:fs';\nimport { z } from 'zod';\nimport { HOSTED_SCOPES, HostedAuthError } from './types.js';\nimport type { HostedAdapter, HostedPrincipal, PatRecord, PatStore } from './types.js';\n\nconst identity = z.string().min(1).max(512).regex(/^[^\\x00-\\x1f\\x7f]+$/);\nexport const principalSchema = z.object({\n actorKind: z.literal('user'), credentialType: z.enum(['oauth', 'pat']),\n userId: identity, companyId: identity, workspaceId: identity, workspaceName: identity.optional(),\n clientId: identity, resource: z.string().url(), scopes: z.array(z.enum(HOSTED_SCOPES)),\n expiresAt: z.number().finite().positive().optional(), tenantIds: z.array(identity).optional(),\n}).strict();\nconst recordSchema = z.object({\n hash: z.string().regex(/^[a-f0-9]{64}$/), revokedAt: z.number().finite().nullable(),\n principal: principalSchema,\n}).strict();\n\nexport function hashCredential(token: string): string {\n return createHash('sha256').update(token).digest('hex');\n}\n\n/** Reread on every request: an atomic file replacement revokes immediately, without restart. */\nexport class FilePatStore implements PatStore {\n constructor(private readonly path: string) {}\n async findByHash(hash: string): Promise<PatRecord | undefined> {\n const handle = await open(this.path, constants.O_RDONLY | constants.O_NOFOLLOW);\n try {\n const stat = await handle.stat();\n if (!stat.isFile() || (stat.mode & 0o077) !== 0 || stat.size > 1_048_576 ||\n (process.getuid && stat.uid !== process.getuid())) throw new Error('Invalid credential store');\n const records = z.array(recordSchema).max(1000).parse(JSON.parse(await handle.readFile('utf8')));\n const matches = records.filter(record => timingSafeEqual(Buffer.from(record.hash, 'hex'), Buffer.from(hash, 'hex')));\n // Duplicate records are ambiguous, including an active/revoked pair.\n if (matches.length > 1) throw new Error('Ambiguous credential store');\n return matches[0];\n } finally { await handle.close(); }\n }\n}\n\nfunction validatePrincipal(value: unknown, resource: string, kind: 'oauth' | 'pat'): HostedPrincipal {\n const parsed = principalSchema.safeParse(value);\n if (!parsed.success || parsed.data.resource !== resource || parsed.data.credentialType !== kind ||\n (parsed.data.expiresAt !== undefined && parsed.data.expiresAt <= Date.now() / 1000) ||\n (kind === 'pat' && parsed.success && parsed.data.expiresAt === undefined)) throw new HostedAuthError(401, 'invalid_token');\n return parsed.data;\n}\n\nexport function createBearerVerifier(adapter: HostedAdapter, resource: string, pats?: PatStore) {\n return async (token: string): Promise<HostedPrincipal> => {\n try {\n if (!/^[A-Za-z0-9._~+\\/-]+=*$/.test(token) || token.length > 8192) throw new HostedAuthError(401, 'invalid_token');\n if (!token.startsWith('dbp_')) {\n return validatePrincipal(await adapter.verifyOAuth(token, resource), resource, 'oauth');\n }\n if (!/^dbp_[A-Za-z0-9_-]{32,}$/.test(token)) throw new HostedAuthError(401, 'invalid_token');\n const record = await pats?.findByHash(hashCredential(token));\n if (!record || record.revokedAt !== null || record.hash !== hashCredential(token)) throw new HostedAuthError(401, 'invalid_token');\n const stored = validatePrincipal(record.principal, resource, 'pat');\n const resolved = validatePrincipal(await adapter.resolvePatGrant(structuredClone(stored)), resource, 'pat');\n // Membership resolution may narrow a stored grant, never move or expand it.\n for (const key of ['userId', 'companyId', 'workspaceId', 'clientId', 'resource'] as const) {\n if (resolved[key] !== stored[key]) throw new HostedAuthError(401, 'invalid_token');\n }\n if (resolved.expiresAt! > stored.expiresAt! || resolved.scopes.some(scope => !stored.scopes.includes(scope)) ||\n resolved.tenantIds?.some(id => !stored.tenantIds?.includes(id))) throw new HostedAuthError(401, 'invalid_token');\n return resolved;\n } catch (error) {\n if (error instanceof HostedAuthError) throw error;\n // No raw verifier, filesystem or remote errors can disclose credential values.\n throw new HostedAuthError(401, 'invalid_token');\n }\n };\n}\n"],"mappings":";;;AAEO,IAAM,gBAAgB;AAAA,EAC3B;AAAA,EAAuB;AAAA,EACvB;AAAA,EAAsB;AAAA,EAAuB;AAAA,EAAoB;AAAA,EACjE;AAAA,EAA0B;AAC5B;AAoDO,IAAM,kBAAN,cAA8B,MAAM;AAAA,EACzC,YAA4B,QAAyC,MAAc;AACjF,UAAM,IAAI;AADgB;AAAyC;AAAA,EAErE;AACF;;;AC9DA,SAAS,YAAY,uBAAuB;AAC5C,SAAS,YAAY;AACrB,SAAS,iBAAiB;AAC1B,SAAS,SAAS;AAIlB,IAAM,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,MAAM,qBAAqB;AAChE,IAAM,kBAAkB,EAAE,OAAO;AAAA,EACtC,WAAW,EAAE,QAAQ,MAAM;AAAA,EAAG,gBAAgB,EAAE,KAAK,CAAC,SAAS,KAAK,CAAC;AAAA,EACrE,QAAQ;AAAA,EAAU,WAAW;AAAA,EAAU,aAAa;AAAA,EAAU,eAAe,SAAS,SAAS;AAAA,EAC/F,UAAU;AAAA,EAAU,UAAU,EAAE,OAAO,EAAE,IAAI;AAAA,EAAG,QAAQ,EAAE,MAAM,EAAE,KAAK,aAAa,CAAC;AAAA,EACrF,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAAG,WAAW,EAAE,MAAM,QAAQ,EAAE,SAAS;AAC9F,CAAC,EAAE,OAAO;AACV,IAAM,eAAe,EAAE,OAAO;AAAA,EAC5B,MAAM,EAAE,OAAO,EAAE,MAAM,gBAAgB;AAAA,EAAG,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA,EAClF,WAAW;AACb,CAAC,EAAE,OAAO;AAEH,SAAS,eAAe,OAAuB;AACpD,SAAO,WAAW,QAAQ,EAAE,OAAO,KAAK,EAAE,OAAO,KAAK;AACxD;AAGO,IAAM,eAAN,MAAuC;AAAA,EAC5C,YAA6B,MAAc;AAAd;AAAA,EAAe;AAAA,EAC5C,MAAM,WAAW,MAA8C;AAC7D,UAAM,SAAS,MAAM,KAAK,KAAK,MAAM,UAAU,WAAW,UAAU,UAAU;AAC9E,QAAI;AACF,YAAM,OAAO,MAAM,OAAO,KAAK;AAC/B,UAAI,CAAC,KAAK,OAAO,MAAM,KAAK,OAAO,QAAW,KAAK,KAAK,OAAO,WAC1D,QAAQ,UAAU,KAAK,QAAQ,QAAQ,OAAO,EAAI,OAAM,IAAI,MAAM,0BAA0B;AACjG,YAAM,UAAU,EAAE,MAAM,YAAY,EAAE,IAAI,GAAI,EAAE,MAAM,KAAK,MAAM,MAAM,OAAO,SAAS,MAAM,CAAC,CAAC;AAC/F,YAAM,UAAU,QAAQ,OAAO,YAAU,gBAAgB,OAAO,KAAK,OAAO,MAAM,KAAK,GAAG,OAAO,KAAK,MAAM,KAAK,CAAC,CAAC;AAEnH,UAAI,QAAQ,SAAS,EAAG,OAAM,IAAI,MAAM,4BAA4B;AACpE,aAAO,QAAQ,CAAC;AAAA,IAClB,UAAE;AAAU,YAAM,OAAO,MAAM;AAAA,IAAG;AAAA,EACpC;AACF;AAEA,SAAS,kBAAkB,OAAgB,UAAkB,MAAwC;AACnG,QAAM,SAAS,gBAAgB,UAAU,KAAK;AAC9C,MAAI,CAAC,OAAO,WAAW,OAAO,KAAK,aAAa,YAAY,OAAO,KAAK,mBAAmB,QACtF,OAAO,KAAK,cAAc,UAAa,OAAO,KAAK,aAAa,KAAK,IAAI,IAAI,OAC7E,SAAS,SAAS,OAAO,WAAW,OAAO,KAAK,cAAc,OAAY,OAAM,IAAI,gBAAgB,KAAK,eAAe;AAC7H,SAAO,OAAO;AAChB;AAEO,SAAS,qBAAqB,SAAwB,UAAkB,MAAiB;AAC9F,SAAO,OAAO,UAA4C;AACxD,QAAI;AACF,UAAI,CAAC,0BAA0B,KAAK,KAAK,KAAK,MAAM,SAAS,KAAM,OAAM,IAAI,gBAAgB,KAAK,eAAe;AACjH,UAAI,CAAC,MAAM,WAAW,MAAM,GAAG;AAC7B,eAAO,kBAAkB,MAAM,QAAQ,YAAY,OAAO,QAAQ,GAAG,UAAU,OAAO;AAAA,MACxF;AACA,UAAI,CAAC,2BAA2B,KAAK,KAAK,EAAG,OAAM,IAAI,gBAAgB,KAAK,eAAe;AAC3F,YAAM,SAAS,MAAM,MAAM,WAAW,eAAe,KAAK,CAAC;AAC3D,UAAI,CAAC,UAAU,OAAO,cAAc,QAAQ,OAAO,SAAS,eAAe,KAAK,EAAG,OAAM,IAAI,gBAAgB,KAAK,eAAe;AACjI,YAAM,SAAS,kBAAkB,OAAO,WAAW,UAAU,KAAK;AAClE,YAAM,WAAW,kBAAkB,MAAM,QAAQ,gBAAgB,gBAAgB,MAAM,CAAC,GAAG,UAAU,KAAK;AAE1G,iBAAW,OAAO,CAAC,UAAU,aAAa,eAAe,YAAY,UAAU,GAAY;AACzF,YAAI,SAAS,GAAG,MAAM,OAAO,GAAG,EAAG,OAAM,IAAI,gBAAgB,KAAK,eAAe;AAAA,MACnF;AACA,UAAI,SAAS,YAAa,OAAO,aAAc,SAAS,OAAO,KAAK,WAAS,CAAC,OAAO,OAAO,SAAS,KAAK,CAAC,KACvG,SAAS,WAAW,KAAK,QAAM,CAAC,OAAO,WAAW,SAAS,EAAE,CAAC,EAAG,OAAM,IAAI,gBAAgB,KAAK,eAAe;AACnH,aAAO;AAAA,IACT,SAAS,OAAO;AACd,UAAI,iBAAiB,gBAAiB,OAAM;AAE5C,YAAM,IAAI,gBAAgB,KAAK,eAAe;AAAA,IAChD;AAAA,EACF;AACF;","names":[]}
|