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.
- package/dist/commands/databaseUpgrade.d.ts +25 -0
- package/dist/commands/databaseUpgrade.d.ts.map +1 -0
- package/dist/commands/databaseUpgrade.js +136 -0
- package/dist/commands/databaseUpgrade.js.map +1 -0
- package/dist/commands/importApply.d.ts +114 -0
- package/dist/commands/importApply.d.ts.map +1 -0
- package/dist/commands/importApply.js +403 -0
- package/dist/commands/importApply.js.map +1 -0
- package/dist/commands/importCutover.d.ts +95 -0
- package/dist/commands/importCutover.d.ts.map +1 -0
- package/dist/commands/importCutover.js +293 -0
- package/dist/commands/importCutover.js.map +1 -0
- package/dist/commands/importData.d.ts +60 -0
- package/dist/commands/importData.d.ts.map +1 -0
- package/dist/commands/importData.js +286 -0
- package/dist/commands/importData.js.map +1 -0
- package/dist/commands/importPlan.d.ts +32 -0
- package/dist/commands/importPlan.d.ts.map +1 -0
- package/dist/commands/importPlan.js +138 -0
- package/dist/commands/importPlan.js.map +1 -0
- package/dist/commands/importVolumes.d.ts +38 -0
- package/dist/commands/importVolumes.d.ts.map +1 -0
- package/dist/commands/importVolumes.js +161 -0
- package/dist/commands/importVolumes.js.map +1 -0
- package/dist/index.js +59 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/importers/caprover.d.ts +13 -0
- package/dist/lib/importers/caprover.d.ts.map +1 -0
- package/dist/lib/importers/caprover.js +150 -0
- package/dist/lib/importers/caprover.js.map +1 -0
- package/dist/lib/importers/connections.d.ts +39 -0
- package/dist/lib/importers/connections.d.ts.map +1 -0
- package/dist/lib/importers/connections.js +119 -0
- package/dist/lib/importers/connections.js.map +1 -0
- package/dist/lib/importers/coolify.d.ts +10 -0
- package/dist/lib/importers/coolify.d.ts.map +1 -0
- package/dist/lib/importers/coolify.js +174 -0
- package/dist/lib/importers/coolify.js.map +1 -0
- package/dist/lib/importers/dokploy.d.ts +13 -0
- package/dist/lib/importers/dokploy.d.ts.map +1 -0
- package/dist/lib/importers/dokploy.js +183 -0
- package/dist/lib/importers/dokploy.js.map +1 -0
- package/dist/lib/importers/heroku.d.ts +50 -0
- package/dist/lib/importers/heroku.d.ts.map +1 -0
- package/dist/lib/importers/heroku.js +159 -0
- package/dist/lib/importers/heroku.js.map +1 -0
- package/dist/lib/importers/plan.d.ts +137 -0
- package/dist/lib/importers/plan.d.ts.map +1 -0
- package/dist/lib/importers/plan.js +110 -0
- package/dist/lib/importers/plan.js.map +1 -0
- package/dist/lib/importers/shell.d.ts +24 -0
- package/dist/lib/importers/shell.d.ts.map +1 -0
- package/dist/lib/importers/shell.js +45 -0
- package/dist/lib/importers/shell.js.map +1 -0
- package/dist/lib/importers/sources.d.ts +26 -0
- package/dist/lib/importers/sources.d.ts.map +1 -0
- package/dist/lib/importers/sources.js +100 -0
- package/dist/lib/importers/sources.js.map +1 -0
- package/package.json +3 -3
- package/src/commands/databaseUpgrade.ts +124 -0
- package/src/commands/importApply.ts +445 -0
- package/src/commands/importCutover.ts +329 -0
- package/src/commands/importData.ts +302 -0
- package/src/commands/importPlan.ts +143 -0
- package/src/commands/importVolumes.ts +168 -0
- package/src/index.ts +61 -0
- package/src/lib/importers/caprover.ts +141 -0
- package/src/lib/importers/connections.ts +133 -0
- package/src/lib/importers/coolify.ts +164 -0
- package/src/lib/importers/dokploy.ts +167 -0
- package/src/lib/importers/heroku.ts +168 -0
- package/src/lib/importers/plan.ts +209 -0
- package/src/lib/importers/shell.ts +56 -0
- 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"}
|