ninedeploy 0.18.26 → 0.18.27

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 (74) hide show
  1. package/dist/commands/databaseUpgrade.d.ts +25 -0
  2. package/dist/commands/databaseUpgrade.d.ts.map +1 -0
  3. package/dist/commands/databaseUpgrade.js +136 -0
  4. package/dist/commands/databaseUpgrade.js.map +1 -0
  5. package/dist/commands/importApply.d.ts +114 -0
  6. package/dist/commands/importApply.d.ts.map +1 -0
  7. package/dist/commands/importApply.js +403 -0
  8. package/dist/commands/importApply.js.map +1 -0
  9. package/dist/commands/importCutover.d.ts +95 -0
  10. package/dist/commands/importCutover.d.ts.map +1 -0
  11. package/dist/commands/importCutover.js +293 -0
  12. package/dist/commands/importCutover.js.map +1 -0
  13. package/dist/commands/importData.d.ts +60 -0
  14. package/dist/commands/importData.d.ts.map +1 -0
  15. package/dist/commands/importData.js +286 -0
  16. package/dist/commands/importData.js.map +1 -0
  17. package/dist/commands/importPlan.d.ts +32 -0
  18. package/dist/commands/importPlan.d.ts.map +1 -0
  19. package/dist/commands/importPlan.js +138 -0
  20. package/dist/commands/importPlan.js.map +1 -0
  21. package/dist/commands/importVolumes.d.ts +38 -0
  22. package/dist/commands/importVolumes.d.ts.map +1 -0
  23. package/dist/commands/importVolumes.js +161 -0
  24. package/dist/commands/importVolumes.js.map +1 -0
  25. package/dist/index.js +59 -0
  26. package/dist/index.js.map +1 -1
  27. package/dist/lib/importers/caprover.d.ts +13 -0
  28. package/dist/lib/importers/caprover.d.ts.map +1 -0
  29. package/dist/lib/importers/caprover.js +150 -0
  30. package/dist/lib/importers/caprover.js.map +1 -0
  31. package/dist/lib/importers/connections.d.ts +39 -0
  32. package/dist/lib/importers/connections.d.ts.map +1 -0
  33. package/dist/lib/importers/connections.js +119 -0
  34. package/dist/lib/importers/connections.js.map +1 -0
  35. package/dist/lib/importers/coolify.d.ts +10 -0
  36. package/dist/lib/importers/coolify.d.ts.map +1 -0
  37. package/dist/lib/importers/coolify.js +174 -0
  38. package/dist/lib/importers/coolify.js.map +1 -0
  39. package/dist/lib/importers/dokploy.d.ts +13 -0
  40. package/dist/lib/importers/dokploy.d.ts.map +1 -0
  41. package/dist/lib/importers/dokploy.js +183 -0
  42. package/dist/lib/importers/dokploy.js.map +1 -0
  43. package/dist/lib/importers/heroku.d.ts +50 -0
  44. package/dist/lib/importers/heroku.d.ts.map +1 -0
  45. package/dist/lib/importers/heroku.js +159 -0
  46. package/dist/lib/importers/heroku.js.map +1 -0
  47. package/dist/lib/importers/plan.d.ts +137 -0
  48. package/dist/lib/importers/plan.d.ts.map +1 -0
  49. package/dist/lib/importers/plan.js +110 -0
  50. package/dist/lib/importers/plan.js.map +1 -0
  51. package/dist/lib/importers/shell.d.ts +24 -0
  52. package/dist/lib/importers/shell.d.ts.map +1 -0
  53. package/dist/lib/importers/shell.js +45 -0
  54. package/dist/lib/importers/shell.js.map +1 -0
  55. package/dist/lib/importers/sources.d.ts +26 -0
  56. package/dist/lib/importers/sources.d.ts.map +1 -0
  57. package/dist/lib/importers/sources.js +100 -0
  58. package/dist/lib/importers/sources.js.map +1 -0
  59. package/package.json +3 -3
  60. package/src/commands/databaseUpgrade.ts +124 -0
  61. package/src/commands/importApply.ts +445 -0
  62. package/src/commands/importCutover.ts +329 -0
  63. package/src/commands/importData.ts +302 -0
  64. package/src/commands/importPlan.ts +143 -0
  65. package/src/commands/importVolumes.ts +168 -0
  66. package/src/index.ts +61 -0
  67. package/src/lib/importers/caprover.ts +141 -0
  68. package/src/lib/importers/connections.ts +133 -0
  69. package/src/lib/importers/coolify.ts +164 -0
  70. package/src/lib/importers/dokploy.ts +167 -0
  71. package/src/lib/importers/heroku.ts +168 -0
  72. package/src/lib/importers/plan.ts +209 -0
  73. package/src/lib/importers/shell.ts +56 -0
  74. package/src/lib/importers/sources.ts +96 -0
@@ -0,0 +1,293 @@
1
+ /**
2
+ * `ninedeploy import cutover <plan.json> [--yes]`
3
+ *
4
+ * A1 step 3, domain half (docs/plans/COMPETITIVE_ROADMAP_2026-11.md). Adds
5
+ * each planned domain to the service `import apply` created, but only once
6
+ * that service is ready and the hostname's DNS already points at this panel.
7
+ *
8
+ * - Ready means the service is `running` and its latest deployment is
9
+ * `running` (succeeded). It is not an HTTP probe of the app, and this
10
+ * command never deploys.
11
+ * - The DNS gate resolves each host here, with a direct DNS query (not the
12
+ * OS cache or hosts file), and passes when every A/AAAA address is one this
13
+ * panel expects: --expect, else Settings → DNS records' content. It stays
14
+ * strict because adding a domain makes Traefik request a certificate, and
15
+ * Let's Encrypt limits failed validations per hostname.
16
+ * - --skip-dns-check <host> is for records behind a proxy (Cloudflare's
17
+ * orange cloud resolves to Cloudflare). It is refused unless the panel's
18
+ * Cloudflare integration is known to be off: that integration POSTs a new
19
+ * A record on every domain add, which next to a record that still points
20
+ * at the source would split traffic between the two hosts.
21
+ * - It never adds the source's own generated hosts (sourceDefault) and
22
+ * reports wildcard hosts for a person: HTTP-01 cannot issue them.
23
+ * - The panel is the truth for what exists: every run lists the service's
24
+ * domains first, so a domain added by hand or by a run that stopped counts
25
+ * as done. A `pending` domain (ownership proof outstanding) is verified
26
+ * once its DNS passes; the TXT challenge is printed, never stored.
27
+ */
28
+ import { existsSync, readFileSync } from 'node:fs';
29
+ import { Resolver } from 'node:dns/promises';
30
+ import { isIP } from 'node:net';
31
+ import { getClient } from '../client.js';
32
+ import { loadConfig } from '../config.js';
33
+ import { c, error, header, info, success } from '../lib/format.js';
34
+ import { renderReceipt, validatePlan, writeReceipt } from './importApply.js';
35
+ export function dnsLookup(server) {
36
+ const r = new Resolver({ timeout: 5000, tries: 2 });
37
+ if (server)
38
+ r.setServers([server]);
39
+ return { resolve4: (h) => r.resolve4(h), resolve6: (h) => r.resolve6(h), servers: () => r.getServers() };
40
+ }
41
+ /** A and AAAA of a host; a name with no record of a type gives none of it. */
42
+ export async function resolveHost(dns, host) {
43
+ const none = (err) => {
44
+ const code = err.code;
45
+ if (code === 'ENOTFOUND' || code === 'ENODATA')
46
+ return [];
47
+ throw err;
48
+ };
49
+ const [a, aaaa] = await Promise.all([dns.resolve4(host).catch(none), dns.resolve6(host).catch(none)]);
50
+ return [...a, ...aaaa];
51
+ }
52
+ /**
53
+ * The addresses a host must resolve to. --expect wins; else the content the
54
+ * panel writes into DNS records (Settings → DNS records), an admin-only read.
55
+ * A hostname (CNAME mode) is resolved here; the panel's own DNS check
56
+ * compares it literally, so it can never match there.
57
+ */
58
+ export async function expectedAddresses(client, dns, expect) {
59
+ let settings = null;
60
+ try {
61
+ settings = await client.settings.dnsRecords.get();
62
+ }
63
+ catch (err) {
64
+ const status = err.status;
65
+ if (status !== 401 && status !== 403)
66
+ throw err;
67
+ }
68
+ const cloudflare = settings ? (settings.enabled ? 'on' : 'off') : 'unknown';
69
+ const wanted = expect.length > 0 ? expect : settings?.content ? [settings.content] : [];
70
+ const source = expect.length > 0 ? '--expect' : 'Settings → DNS records';
71
+ if (wanted.length === 0) {
72
+ throw new Error(settings
73
+ ? 'This panel has no DNS records address set (Settings → DNS records), so there is nothing to compare DNS with. Pass --expect <this panel\'s public IP>.'
74
+ : 'Only an admin can read the panel\'s DNS records address. Pass --expect <this panel\'s public IP>.');
75
+ }
76
+ const addresses = [];
77
+ for (const w of wanted) {
78
+ if (isIP(w))
79
+ addresses.push(canonicalIp(w));
80
+ else {
81
+ const resolved = await resolveHost(dns, w);
82
+ if (resolved.length === 0)
83
+ throw new Error(`The expected address ${w} (${source}) does not resolve.`);
84
+ addresses.push(...resolved.map(canonicalIp));
85
+ }
86
+ }
87
+ return { addresses: [...new Set(addresses)], source: wanted.some((w) => !isIP(w)) ? `${source}, ${wanted.join(', ')} resolved` : source, cloudflare };
88
+ }
89
+ const lower = (h) => h.toLowerCase().replace(/\.$/, '');
90
+ /** One spelling per address, so `2001:DB8:0::1` and `2001:db8::1` compare equal. */
91
+ export function canonicalIp(ip) {
92
+ return isIP(ip) === 6 ? new URL(`http://[${ip}]/`).hostname.slice(1, -1) : ip;
93
+ }
94
+ /**
95
+ * Why a host's DNS is not ready for a certificate, or null. Every A and AAAA
96
+ * must be this panel's: Let's Encrypt validates over IPv6 first when an AAAA
97
+ * exists, so a leftover record that still names the source fails the
98
+ * certificate even when another record already points here.
99
+ */
100
+ export function dnsProblem(resolved, expected) {
101
+ if (resolved.length === 0)
102
+ return 'does not resolve';
103
+ const stray = resolved.map(canonicalIp).filter((a) => !expected.includes(a));
104
+ if (stray.length === 0)
105
+ return null;
106
+ const which = stray.map((a) => `${isIP(a) === 6 ? 'AAAA' : 'A'} ${a}`).join(', ');
107
+ return stray.length === resolved.length
108
+ ? `resolves to ${which}, not ${expected.join(', ')}`
109
+ : `${which} ${stray.length === 1 ? 'is' : 'are'} not this panel (expected ${expected.join(', ')}): remove ${stray.length === 1 ? 'it' : 'them'}, or pass --expect with ${stray.length === 1 ? 'it' : 'them'} if ${stray.length === 1 ? 'it is' : 'they are'} this panel's`;
110
+ }
111
+ /** Check readiness and DNS for every planned domain; with yes, add or verify those that pass. */
112
+ export async function cutover(plan, opts, deps) {
113
+ const { client, dns, expected, receipt } = deps;
114
+ const now = deps.now ?? (() => new Date());
115
+ const skip = new Set(opts.skipDnsCheck.map(lower));
116
+ const out = [];
117
+ const planned = new Set(plan.services.flatMap((s) => s.domains.map((d) => lower(d.host))));
118
+ for (const h of skip)
119
+ if (!planned.has(h))
120
+ out.push(` ! --skip-dns-check ${h}: no planned domain has that host`);
121
+ const res = { lines: out, added: 0, waiting: 0, failed: 0 };
122
+ const put = (item) => {
123
+ receipt.items[`domain:${item.ref}`] = { ...item, at: now().toISOString() };
124
+ deps.save(receipt);
125
+ };
126
+ for (const s of plan.services) {
127
+ const hosts = [];
128
+ const seen = new Set();
129
+ for (const d of s.domains) {
130
+ if (d.sourceDefault || seen.has(lower(d.host)))
131
+ continue;
132
+ seen.add(lower(d.host));
133
+ hosts.push(d);
134
+ }
135
+ if (hosts.length === 0)
136
+ continue;
137
+ const created = receipt.items[`service:${s.ref}`];
138
+ if (!created || created.state !== 'done' || created.id === undefined) {
139
+ out.push(` – ${s.name}: not created yet (run import apply first)`);
140
+ res.waiting += hosts.length;
141
+ continue;
142
+ }
143
+ const serviceId = created.id;
144
+ const existing = new Map((await client.domains.list(serviceId)).map((d) => [lower(d.hostname), d]));
145
+ const svc = await client.services.get(serviceId);
146
+ const last = (await client.deploys.list(serviceId))[0];
147
+ const ready = svc.status === 'running' && last?.status === 'running';
148
+ out.push(` ${s.name} (#${serviceId}): service ${svc.status}, last deploy ${last ? last.status : 'none'}`);
149
+ for (const d of hosts) {
150
+ const host = lower(d.host);
151
+ const ref = `${s.ref}:${host}`;
152
+ const row = existing.get(host);
153
+ if (row?.status === 'active') {
154
+ out.push(` ✓ ${host}: added (#${row.id})`);
155
+ const prev = receipt.items[`domain:${ref}`];
156
+ if (opts.yes && (prev?.state !== 'done' || prev.id !== row.id))
157
+ put({ kind: 'domain', ref, name: host, state: 'done', id: row.id, notes: [] });
158
+ continue;
159
+ }
160
+ if (host.startsWith('*.')) {
161
+ out.push(` – ${host}: a wildcard needs a DNS-01 certificate; add it by hand`);
162
+ res.waiting++;
163
+ continue;
164
+ }
165
+ if (!ready) {
166
+ out.push(` – ${host}: waits until the service runs a successful deploy (deploy it and check it first)`);
167
+ res.waiting++;
168
+ continue;
169
+ }
170
+ // DNS gate.
171
+ let note = null;
172
+ if (skip.has(host)) {
173
+ if (expected.cloudflare !== 'off') {
174
+ out.push(` ✗ ${host}: --skip-dns-check refused: ${expected.cloudflare === 'on'
175
+ ? 'the panel\'s Cloudflare integration is on and would add a second A record next to the source\'s'
176
+ : 'only an admin can see whether the panel\'s Cloudflare integration is on (it would add a second A record next to the source\'s)'}`);
177
+ res.waiting++;
178
+ continue;
179
+ }
180
+ note = 'DNS check skipped (--skip-dns-check)';
181
+ }
182
+ else {
183
+ const gate = dnsProblem(await resolveHost(dns, host), expected.addresses);
184
+ if (gate) {
185
+ out.push(` ✗ ${host}: ${gate}; fix DNS first`);
186
+ res.waiting++;
187
+ continue;
188
+ }
189
+ }
190
+ if (!opts.yes) {
191
+ out.push(` + ${host}: ${note ?? 'DNS points here'}; would ${row ? 'verify the pending domain' : `add it (${d.https ? 'https' : 'http'})`}`);
192
+ continue;
193
+ }
194
+ const notes = note ? [note] : [];
195
+ if (row) {
196
+ // Pending ownership proof: verifying flips it live, so it waited for the gate too.
197
+ let v;
198
+ try {
199
+ v = await client.domains.verify(serviceId, row.id);
200
+ }
201
+ catch (err) {
202
+ out.push(` ✗ ${host}: verify failed: ${err instanceof Error ? err.message : String(err)}`);
203
+ res.failed++;
204
+ continue;
205
+ }
206
+ if (v.verified) {
207
+ if (v.dnsWarning)
208
+ notes.push(`DNS provider: ${v.dnsWarning}`);
209
+ put({ kind: 'domain', ref, name: host, state: 'done', id: row.id, notes });
210
+ out.push(` ✓ ${host}: verified and live (#${row.id})`);
211
+ res.added++;
212
+ }
213
+ else {
214
+ out.push(` – ${host}: ownership not proven yet${v.error ? ` (${v.error})` : ''}`);
215
+ if (v.verification)
216
+ out.push(` publish TXT ${v.verification.recordName} = ${v.verification.recordValue}, then run this again`);
217
+ res.waiting++;
218
+ }
219
+ continue;
220
+ }
221
+ put({ kind: 'domain', ref, name: host, state: 'pending', notes });
222
+ let made;
223
+ try {
224
+ made = await client.domains.create(serviceId, { hostname: host, ssl: d.https });
225
+ }
226
+ catch (err) {
227
+ const msg = err instanceof Error ? err.message : String(err);
228
+ put({ kind: 'domain', ref, name: host, state: 'failed', notes: [...notes, msg] });
229
+ out.push(` ✗ ${host}: ${msg}`);
230
+ res.failed++;
231
+ continue;
232
+ }
233
+ if (made.dnsWarning)
234
+ notes.push(`DNS provider: ${made.dnsWarning}`);
235
+ if (made.status === 'pending')
236
+ notes.push('ownership proof pending (TXT)');
237
+ put({ kind: 'domain', ref, name: host, state: 'done', id: made.id, notes });
238
+ // A pending domain is not routed yet: it waits for its TXT proof.
239
+ if (made.status === 'pending')
240
+ res.waiting++;
241
+ else
242
+ res.added++;
243
+ out.push(` ✓ ${host}: added (#${made.id}, ${made.status})`);
244
+ if (made.verification) {
245
+ out.push(` publish TXT ${made.verification.recordName} = ${made.verification.recordValue}, then run this again to verify`);
246
+ }
247
+ }
248
+ }
249
+ return res;
250
+ }
251
+ export async function importCutoverAction(planPath, opts, deps = {}) {
252
+ try {
253
+ const plan = validatePlan(JSON.parse(readFileSync(planPath, 'utf8')));
254
+ const receiptPath = opts.receipt ?? `${planPath.replace(/\.json$/i, '')}.receipt.json`;
255
+ if (!existsSync(receiptPath))
256
+ throw new Error(`No receipt at ${receiptPath}: run \`ninedeploy import apply ${planPath} --yes\` first.`);
257
+ const receipt = JSON.parse(readFileSync(receiptPath, 'utf8'));
258
+ const panel = (deps.panel ?? loadConfig().baseUrl).replace(/\/+$/, '');
259
+ if (receipt.panel !== panel)
260
+ throw new Error(`The receipt is for ${receipt.panel}, but the CLI is signed in to ${panel}.`);
261
+ if (opts.resolver && !isIP(opts.resolver))
262
+ throw new Error(`--resolver takes an IP address, got "${opts.resolver}".`);
263
+ const client = deps.client ?? getClient();
264
+ const dns = deps.dns ?? dnsLookup(opts.resolver);
265
+ const expected = await expectedAddresses(client, dns, opts.expect ?? []);
266
+ header(`Cutover into ${panel}`);
267
+ info(`Expected address: ${expected.addresses.join(', ')} (${expected.source})`);
268
+ info(`Resolver: ${dns.servers().join(', ') || 'system default'}`);
269
+ if (expected.cloudflare === 'on')
270
+ info('The Cloudflare integration is on: each domain added here also gets an A record created in Cloudflare.');
271
+ const result = await cutover(plan, { yes: !!opts.yes, skipDnsCheck: opts.skipDnsCheck ?? [] }, {
272
+ client, dns, expected, receipt, save: (r) => writeReceipt(receiptPath, r),
273
+ });
274
+ console.log(result.lines.length ? result.lines.join('\n') : ' No domains to move (the plan has none besides the source\'s own hosts).');
275
+ if (!opts.yes) {
276
+ info(`${c.dim('Nothing was added.')} Run again with --yes to add the domains marked +.`);
277
+ return;
278
+ }
279
+ const items = Object.values(receipt.items).filter((i) => i.kind === 'domain');
280
+ if (items.length)
281
+ console.log(renderReceipt({ ...receipt, items: Object.fromEntries(items.map((i) => [`domain:${i.ref}`, i])) }));
282
+ if (result.failed)
283
+ error(`${result.failed} domain(s) failed. Fix the cause and run the same command again. Receipt: ${receiptPath}`);
284
+ else if (result.waiting)
285
+ info(`${result.added} added, ${result.waiting} waiting. Run the same command again once they are ready. Receipt: ${receiptPath}`);
286
+ else
287
+ success(`Done: every planned domain is on this panel. Receipt: ${receiptPath}`);
288
+ }
289
+ catch (err) {
290
+ error(err instanceof Error ? err.message : String(err));
291
+ }
292
+ }
293
+ //# sourceMappingURL=importCutover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"importCutover.js","sourceRoot":"","sources":["../../src/commands/importCutover.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ import { type NineDeployClient } from '../client.js';
2
+ import type { ImportPlan, PlanDatabase } from '../lib/importers/plan.js';
3
+ import { type ImportReceipt } from './importApply.js';
4
+ import { type VolumeClient } from './importVolumes.js';
5
+ /** The panel calls `import data` makes; NineDeployClient satisfies it. */
6
+ export interface DataClient extends VolumeClient {
7
+ databases: {
8
+ importFile: NineDeployClient['databases']['importFile'];
9
+ imports: {
10
+ get: NineDeployClient['databases']['imports']['get'];
11
+ wait: NineDeployClient['databases']['imports']['wait'];
12
+ };
13
+ };
14
+ }
15
+ /**
16
+ * The command, run on the source host, that writes a dump the panel's import
17
+ * accepts: pg_dump custom format, mysqldump/mariadb-dump SQL of the app
18
+ * database (not the system schemas, which the import refuses), a gzipped
19
+ * mongodump archive, an RDB snapshot.
20
+ *
21
+ * The MySQL/MariaDB dump names the database positionally, never with
22
+ * --databases: that form writes `CREATE DATABASE shopdb; USE shopdb;`, and
23
+ * the panel feeds the file to `mysql … app` as it is, so the rows would land
24
+ * in `shopdb` instead of the managed `app` database (and the panel refuses
25
+ * any `USE` other than `USE app` from a non-operator).
26
+ */
27
+ export declare function dumpCommand(db: PlanDatabase): {
28
+ command: string;
29
+ file: string;
30
+ notes: string[];
31
+ } | null;
32
+ /** The order that loses no writes, and the steps this command does not do. */
33
+ export declare const CUTOVER_ORDER: string[];
34
+ export declare function renderDataPreview(plan: ImportPlan, receipt: ImportReceipt | null): string;
35
+ export interface DataDeps {
36
+ client: DataClient;
37
+ receipt: ImportReceipt;
38
+ save: (receipt: ImportReceipt) => void;
39
+ /** sha256 and size of a local file. */
40
+ hashFile: (file: string) => Promise<{
41
+ sha256: string;
42
+ bytes: number;
43
+ }>;
44
+ /** Stream of the file from a byte offset (for a resumed upload). */
45
+ open: (file: string) => (offset: number) => AsyncIterable<Uint8Array>;
46
+ now?: () => Date;
47
+ }
48
+ /** Import each named dump, recording every step in the receipt. */
49
+ export declare function importData(plan: ImportPlan, dumps: Record<string, string>, deps: DataDeps): Promise<ImportReceipt>;
50
+ export interface ImportDataOpts {
51
+ receipt?: string;
52
+ dump?: string[];
53
+ volume?: string[];
54
+ yes?: boolean;
55
+ }
56
+ export declare function importDataAction(planPath: string, opts: ImportDataOpts, deps?: {
57
+ client?: DataClient;
58
+ panel?: string;
59
+ }): Promise<void>;
60
+ //# sourceMappingURL=importData.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"importData.d.ts","sourceRoot":"","sources":["../../src/commands/importData.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAa,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGhE,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAA0B,MAAM,0BAA0B,CAAC;AAEjG,OAAO,EAAE,KAAK,aAAa,EAA6C,MAAM,kBAAkB,CAAC;AACjG,OAAO,EAAsC,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAE3F,0EAA0E;AAC1E,MAAM,WAAW,UAAW,SAAQ,YAAY;IAC9C,SAAS,EAAE;QACT,UAAU,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC,YAAY,CAAC,CAAC;QACxD,OAAO,EAAE;YACP,GAAG,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC;YACrD,IAAI,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;SACxD,CAAC;KACH,CAAC;CACH;AAaD;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,YAAY,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,IAAI,CA6CvG;AAED,8EAA8E;AAC9E,eAAO,MAAM,aAAa,UAOzB,CAAC;AAIF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,aAAa,GAAG,IAAI,GAAG,MAAM,CAkCzF;AAED,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,EAAE,aAAa,CAAC;IACvB,IAAI,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAC;IACvC,uCAAuC;IACvC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACvE,oEAAoE;IACpE,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,CAAC,MAAM,EAAE,MAAM,KAAK,aAAa,CAAC,UAAU,CAAC,CAAC;IACtE,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CAClB;AAID,mEAAmE;AACnE,wBAAsB,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,aAAa,CAAC,CAwExH;AAUD,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,UAAU,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAwChJ"}