@hasna/domains 0.0.19 → 0.0.21

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.
Files changed (45) hide show
  1. package/README.md +145 -53
  2. package/dist/cli/commands/config.d.ts.map +1 -1
  3. package/dist/cli/commands/domain.d.ts.map +1 -1
  4. package/dist/cli/commands/provider.d.ts.map +1 -1
  5. package/dist/cli/commands/providers.d.ts.map +1 -1
  6. package/dist/cli/commands/storage.d.ts +3 -0
  7. package/dist/cli/commands/storage.d.ts.map +1 -0
  8. package/dist/cli/commands/wallet.d.ts +2 -2
  9. package/dist/cli/commands/wallet.d.ts.map +1 -1
  10. package/dist/cli/index.js +6958 -516
  11. package/dist/db/database.d.ts +1 -1
  12. package/dist/db/database.d.ts.map +1 -1
  13. package/dist/db/pg-migrations.d.ts +5 -0
  14. package/dist/db/pg-migrations.d.ts.map +1 -0
  15. package/dist/db/remote-storage.d.ts +10 -0
  16. package/dist/db/remote-storage.d.ts.map +1 -0
  17. package/dist/db/storage-sync.d.ts +55 -0
  18. package/dist/db/storage-sync.d.ts.map +1 -0
  19. package/dist/index.d.ts +5 -1
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +5658 -93
  22. package/dist/lib/brandsight.d.ts +2 -3
  23. package/dist/lib/brandsight.d.ts.map +1 -1
  24. package/dist/lib/capability.d.ts.map +1 -1
  25. package/dist/lib/cloudflare-auth.d.ts +2 -3
  26. package/dist/lib/cloudflare-auth.d.ts.map +1 -1
  27. package/dist/lib/creds-check.d.ts +1 -2
  28. package/dist/lib/creds-check.d.ts.map +1 -1
  29. package/dist/lib/env-aliases.d.ts +43 -0
  30. package/dist/lib/env-aliases.d.ts.map +1 -0
  31. package/dist/lib/namecheap.d.ts +13 -0
  32. package/dist/lib/namecheap.d.ts.map +1 -1
  33. package/dist/lib/registrar.d.ts +36 -2
  34. package/dist/lib/registrar.d.ts.map +1 -1
  35. package/dist/lib/route53.d.ts.map +1 -1
  36. package/dist/lib/sedo.d.ts +7 -0
  37. package/dist/lib/sedo.d.ts.map +1 -1
  38. package/dist/mcp/index.d.ts.map +1 -1
  39. package/dist/mcp/index.js +13638 -10230
  40. package/dist/mcp/storage-tools.d.ts +3 -0
  41. package/dist/mcp/storage-tools.d.ts.map +1 -0
  42. package/dist/storage.d.ts +5 -0
  43. package/dist/storage.d.ts.map +1 -0
  44. package/dist/storage.js +5703 -0
  45. package/package.json +11 -5
package/README.md CHANGED
@@ -1,11 +1,17 @@
1
1
  # @hasna/domains
2
2
 
3
- Domain portfolio and DNS management for AI agents — CLI + MCP server with SQLite.
3
+ Domain portfolio, registrar, marketplace, and DNS management for AI agents — CLI + MCP server with SQLite.
4
4
 
5
5
  ## Features
6
6
 
7
- - **Domain portfolio management** — track registrar, expiry, SSL, nameservers, status
7
+ - **Domain portfolio management** — track registrar, expiry, SSL, nameservers, pricing, lifecycle status, and notes
8
+ - **Registrar sync and purchase flows** — direct Route 53 and Namecheap registration plus GoDaddy and Brandsight provider surfaces through a shared provider registry
9
+ - **Nameserver delegation** — Route 53 and Namecheap adapters can update registrar nameservers when the provider API supports it
10
+ - **Cloudflare-first DNS** — create or reuse Cloudflare zones and manage DNS records through the DNS provider layer
8
11
  - **DNS record CRUD** — A, AAAA, CNAME, MX, TXT, NS, SRV records
12
+ - **Sedo marketplace tools** — search, portfolio/listing management, blacklist checks, and recorded Sedo purchases
13
+ - **AWS diagnostics** — sync Route 53 registered domains and report AWS/Beepmedia credential metadata without printing secret values
14
+ - **Credential diagnostics** — redacted checks for Route 53, Beepmedia AWS env aliases, Cloudflare, Namecheap, GoDaddy, Brandsight, and Sedo
9
15
  - **Expiry alerts** — set alerts for domain expiry and SSL certificate expiry
10
16
  - **WHOIS lookup** — query and store registrar/expiry info from WHOIS
11
17
  - **SSL certificate check** — verify SSL issuer and expiry
@@ -14,10 +20,9 @@ Domain portfolio and DNS management for AI agents — CLI + MCP server with SQLi
14
20
  - **Subdomain discovery** — via crt.sh certificate transparency logs
15
21
  - **DNS validation** — detect CNAME conflicts, missing MX, and more
16
22
  - **Portfolio export** — CSV or JSON with all domain data
17
- - **Registrar sync** — Namecheap and GoDaddy integration
18
23
  - **Brand monitoring** — typosquat/threat detection via Brandsight API
19
- - **MCP server** — full Model Context Protocol support for AI agents
20
- - **Interactive TUI** — browse your portfolio in the terminal with `domains interactive`
24
+ - **MCP server** — Model Context Protocol support for AI agents
25
+ - **Interactive TUI** — browse the portfolio in the terminal with `domains interactive`
21
26
 
22
27
  ## Installation
23
28
 
@@ -25,36 +30,97 @@ Domain portfolio and DNS management for AI agents — CLI + MCP server with SQLi
25
30
  npm install -g @hasna/domains
26
31
  ```
27
32
 
28
- Data is stored at `~/.hasna/domains/domains.db`. Override with `HASNA_DOMAINS_DIR` or `DOMAINS_DIR` env var.
33
+ Data is stored at `~/.hasna/domains/domains.db`. Override with `HASNA_DOMAINS_DB_PATH`, `HASNA_DOMAINS_DIR`, or `DOMAINS_DIR`.
34
+
35
+ ## Quick Start
36
+
37
+ ```bash
38
+ # Set defaults used by availability, buy, setup, DNS, and doctor commands
39
+ domains config set default-registrar route53
40
+ domains config set default-dns cloudflare
41
+ domains config set purchase-aws-profile hasna-xyz-infra
42
+
43
+ # Add registrant contact defaults used by registrar purchase APIs
44
+ domains config set contact.first_name Jane
45
+ domains config set contact.last_name Example
46
+ domains config set contact.email jane@example.com
47
+ domains config set contact.phone +1.5555555555
48
+ domains config set contact.address_line_1 "1 Main St"
49
+ domains config set contact.city "New York"
50
+ domains config set contact.state NY
51
+ domains config set contact.country_code US
52
+ domains config set contact.zip_code 10001
53
+
54
+ # Check local health without printing secrets
55
+ domains doctor
56
+ ```
57
+
58
+ ## Provider Matrix
59
+
60
+ | Provider | Type | Availability | Buy/Register | Renew | Nameservers/DNS | Notes |
61
+ |----------|------|--------------|--------------|-------|-----------------|-------|
62
+ | `route53` | registrar + DNS | yes | yes | no | nameservers + Route 53 hosted zones | Primary self-serve registration path. Use `AWS_PROFILE` or AWS keys. |
63
+ | `namecheap` | registrar + DNS | yes | yes | yes | nameservers + Namecheap DNS records | Requires Namecheap API access and whitelisted client IP. |
64
+ | `godaddy` | registrar + DNS | gated | no direct CLI purchase | gated | DNS records when API access qualifies | Retail Domains API access is account-gated; CLI surfaces credentials and capability checks. |
65
+ | `brandsight` | registrar | gated | no direct CLI purchase | yes when contract allows | contract-specific | GoDaddy Corporate Domains / Brandsight APIs are enterprise-contract-only. |
66
+ | `cloudflare` | DNS | no | no | no | DNS zones and records | Preferred DNS provider; not a registrar. |
67
+ | `sedo` | marketplace | marketplace search/status | recorded purchase only | no | no | Sedo is marketplace/listing/portfolio, not registrar DNS in this CLI. |
29
68
 
30
69
  ## CLI Usage
31
70
 
32
71
  ```bash
33
- # Interactive portfolio browser (Ink TUI)
72
+ # Interactive portfolio browser
34
73
  domains interactive
35
74
  domains interactive --status active
36
- ```
37
- domains add --name example.com --registrar Namecheap --expires-at 2025-01-01
38
- domains list
39
- domains list --status active --registrar Namecheap
40
- domains get <id>
41
- domains update <id> --notes "renewed"
42
- domains delete <id>
43
- domains search example
44
- domains stats
75
+
76
+ # Portfolio management
77
+ domains domain add --name example.com --registrar Namecheap --expires-at 2027-01-01
78
+ domains domain list
79
+ domains domain list --status active --registrar Namecheap
80
+ domains domain get example.com
81
+ domains domain update <id> --notes "renewed"
82
+ domains domain delete <id>
83
+ domains domain search example
84
+ domains domain stats
45
85
 
46
86
  # Expiry monitoring
47
- domains expiring --days 30
48
- domains ssl --days 30
87
+ domains domain expiring --days 30
88
+ domains ssl expiring --days 30
49
89
 
50
90
  # WHOIS / SSL checks
51
- domains whois example.com
52
- domains ssl-check example.com
53
- domains check-all
91
+ domains domain whois example.com
92
+ domains ssl check example.com
93
+ domains domain check example.com example.net
54
94
 
55
95
  # Portfolio export
56
- domains export --format csv --output portfolio.csv
57
- domains export --format json
96
+ domains domain export --format csv > portfolio.csv
97
+ domains domain export --format json
98
+
99
+ # Provider registry and diagnostics
100
+ domains providers
101
+ domains provider list
102
+ domains provider test route53
103
+ domains provider test cloudflare
104
+ domains doctor
105
+
106
+ # Registrar sync
107
+ domains sync --provider route53
108
+ domains sync --provider namecheap
109
+ domains sync --provider godaddy
110
+ domains sync --provider brandsight
111
+ domains sync --all
112
+
113
+ # Availability and renewals
114
+ domains check example.com
115
+ domains check --provider route53 example.com
116
+ domains check --provider namecheap example.com
117
+ domains renew example.com --provider namecheap --years 1
118
+
119
+ # Purchases and setup
120
+ domains domain buy example.com --provider route53 --wait
121
+ domains domain buy example.com --provider namecheap --wait
122
+ domains domain buy premium.example --registrar sedo --price 2500 --expires 2027-01-01
123
+ domains domain setup example.com --registrar route53 --dns cloudflare --wait
58
124
 
59
125
  # DNS record management
60
126
  domains dns list <domain-id>
@@ -66,24 +132,17 @@ domains dns export <domain-id>
66
132
  domains dns import <domain-id> --file zone.txt
67
133
  domains dns discover-subdomains example.com
68
134
  domains dns validate <domain-id>
69
-
70
- # Alerts
71
- domains alert set --domain <id> --type expiry --days-before 30
72
- domains alert list <domain-id>
73
- domains alert remove <alert-id>
74
-
75
- # Registrar integration
76
- domains providers
77
- domains sync --provider namecheap
78
- domains sync --provider godaddy
79
- domains sync --all
80
- domains renew example.com --provider namecheap
81
-
82
- # Availability checks — pick the registrar with --provider
83
- domains check example.com # default registrar (config default-registrar, else namecheap)
84
- domains check --provider route53 example.com # AWS Route 53 availability
85
- domains check --provider godaddy example.com
86
- domains r53 check example.com # Route 53-specific subcommand (same backend)
135
+ domains dns pull example.com --provider cloudflare
136
+ domains dns push <domain-id> --provider cloudflare
137
+
138
+ # Sedo marketplace
139
+ domains sedo search example
140
+ domains sedo status example.com
141
+ domains sedo portfolio --limit 25
142
+ domains sedo add example.com --price 2500
143
+ domains sedo edit example.com --price 3000
144
+ domains sedo remove example.com
145
+ domains sedo buy example.com --price 2500 --order-id SEDO-ORDER-ID
87
146
 
88
147
  # Brand monitoring
89
148
  domains monitor mybrand
@@ -91,12 +150,33 @@ domains similar example.com
91
150
  domains threats example.com
92
151
  ```
93
152
 
94
- > **Prefer the `domains` CLI over raw `aws` commands.** For Route 53 availability,
95
- > registration status, and DNS, use `domains check --provider route53`,
96
- > `domains r53 status`, and `domains dns …` instead of `aws route53domains …` /
97
- > `aws route53 …`. The CLI applies the configured purchase profile, records the
98
- > result in the local portfolio DB, and works the same across registrars — raw
99
- > `aws` calls bypass all of that.
153
+ Prefer the `domains` CLI over raw registrar CLIs for Route 53 availability, registration status, local portfolio updates, and DNS delegation. The CLI applies configured defaults, records outcomes in the local portfolio DB, and keeps behavior consistent across providers.
154
+
155
+ ## AWS Domain Discovery
156
+
157
+ ```bash
158
+ # Sync registered domains from specific AWS accounts
159
+ AWS_PROFILE=hasna domains sync --provider route53
160
+ AWS_PROFILE=hasna-xyz-infra domains sync --provider route53
161
+
162
+ # Check all configured providers and redacted credential status
163
+ domains providers --json
164
+ domains doctor --json
165
+ ```
166
+
167
+ Route 53 sync imports registered domains when the selected AWS account permits `route53domains:ListDomains`. Beepmedia AWS metadata can be inspected through redacted diagnostics, but domain-looking SSM/Secrets names should only be imported after review because they do not prove registrar ownership.
168
+
169
+ ## Storage Sync
170
+
171
+ Set one of these environment variables to sync with a remote PostgreSQL storage database:
172
+
173
+ ```bash
174
+ export HASNA_DOMAINS_DATABASE_URL="postgres://..."
175
+
176
+ domains storage status
177
+ domains storage push
178
+ domains storage pull
179
+ ```
100
180
 
101
181
  ## MCP Server
102
182
 
@@ -126,8 +206,8 @@ domains-mcp --http --port 8814
126
206
  MCP_HTTP=1 MCP_HTTP_PORT=8814 domains-mcp
127
207
  ```
128
208
 
129
- - `GET /health` `{"status":"ok","name":"domains"}`
130
- - `POST /mcp` Streamable HTTP MCP endpoint
209
+ - `GET /health` returns `{"status":"ok","name":"domains"}`
210
+ - `POST /mcp` is the Streamable HTTP MCP endpoint
131
211
 
132
212
  Stdio remains the default transport for gradual rollout.
133
213
 
@@ -135,15 +215,27 @@ Stdio remains the default transport for gradual rollout.
135
215
 
136
216
  | Variable | Description |
137
217
  |----------|-------------|
218
+ | `HASNA_DOMAINS_DB_PATH` | Override database file path |
138
219
  | `HASNA_DOMAINS_DIR` | Override database directory |
139
- | `DOMAINS_DIR` | Override database directory (fallback) |
220
+ | `DOMAINS_DIR` | Override database directory fallback |
221
+ | `HASNA_DOMAINS_DATABASE_URL` | Remote storage PostgreSQL database URL |
222
+ | `DOMAINS_DATABASE_URL` | Remote storage PostgreSQL database URL fallback |
223
+ | `HASNA_DOMAINS_STORAGE_MODE` | Storage mode: `local`, `remote`, or `hybrid` |
224
+ | `DOMAINS_STORAGE_MODE` | Storage mode fallback |
225
+ | `AWS_PROFILE` | AWS profile for Route 53 Domains and hosted zones |
226
+ | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_SESSION_TOKEN` | AWS credential fallback |
227
+ | `DOMAINS_PURCHASE_AWS_PROFILE` | Purchase profile fallback when config has no `purchase_aws_profile` |
228
+ | `CLOUDFLARE_API_TOKEN` | Cloudflare API token |
229
+ | `CLOUDFLARE_API_KEY`, `CLOUDFLARE_EMAIL` | Cloudflare global key fallback |
230
+ | `CLOUDFLARE_ACCOUNT_ID` | Cloudflare account ID for zone creation |
140
231
  | `NAMECHEAP_API_KEY` | Namecheap API key |
141
232
  | `NAMECHEAP_USERNAME` | Namecheap account username |
142
233
  | `NAMECHEAP_CLIENT_IP` | Namecheap whitelisted IP |
143
234
  | `NAMECHEAP_SANDBOX` | Use Namecheap sandbox API |
144
- | `GODADDY_API_KEY` | GoDaddy API key |
145
- | `GODADDY_API_SECRET` | GoDaddy API secret |
146
- | `BRANDSIGHT_API_KEY` | Brandsight API key |
235
+ | `GODADDY_API_KEY`, `GODADDY_API_SECRET` | GoDaddy API credentials |
236
+ | `BRANDSIGHT_API_KEY`, `BRANDSIGHT_API_SECRET`, `BRANDSIGHT_CUSTOMER_ID` | Brandsight / GoDaddy Corporate Domains credentials |
237
+ | `SEDO_PARTNER_ID`, `SEDO_API_KEY`, `SEDO_USERNAME`, `SEDO_PASSWORD` | Sedo marketplace API credentials |
238
+ | `HASNAXYZ_*` scoped aliases | Supported for Cloudflare, Brandsight, Sedo, and Beepmedia AWS diagnostics |
147
239
 
148
240
  ## License
149
241
 
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkBzC,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAyD7D"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmBzC,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA0D7D"}
@@ -1 +1 @@
1
- {"version":3,"file":"domain.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/domain.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkDzC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA8vB5D"}
1
+ {"version":3,"file":"domain.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/domain.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkDzC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAq0B5D"}
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAuJ9D"}
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAoK9D"}
@@ -1 +1 @@
1
- {"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/providers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuBzC,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAuM/D"}
1
+ {"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/providers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiCzC,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA0J/D"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerStorageCommand(program: Command): void;
3
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/storage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA2GzC,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAE7D"}
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Wallet payment integration for domain purchases
3
3
  *
4
- * Uses @hasna/wallets virtual cards to pay for domain registrations,
5
- * renewals, and marketplace purchases (Sedo, etc.)
4
+ * Uses an optional wallet module to pay for domain registrations,
5
+ * renewals, and marketplace purchases (Sedo, etc.).
6
6
  */
7
7
  import type { Command } from "commander";
8
8
  export interface WalletCard {
@@ -1 +1 @@
1
- {"version":3,"file":"wallet.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/wallet.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIzC,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AA2BD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAyL5D"}
1
+ {"version":3,"file":"wallet.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/wallet.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIzC,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAwCD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAyL5D"}