@codemarc/blt 1.6.5 → 1.8.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 +192 -0
- package/dist/blt +4 -0
- package/dist/blt.d.ts.map +1 -1
- package/dist/blt.js.map +1 -1
- package/dist/commands/data/apply.d.ts +6 -0
- package/dist/commands/data/apply.d.ts.map +1 -0
- package/dist/commands/data/apply.js +363 -0
- package/dist/commands/data/apply.js.map +1 -0
- package/dist/commands/data/helpers.d.ts +15 -0
- package/dist/commands/data/helpers.d.ts.map +1 -0
- package/dist/commands/data/helpers.js +53 -0
- package/dist/commands/data/helpers.js.map +1 -0
- package/dist/commands/data/pull.d.ts +11 -0
- package/dist/commands/data/pull.d.ts.map +1 -0
- package/dist/commands/data/pull.js +101 -0
- package/dist/commands/data/pull.js.map +1 -0
- package/dist/commands/data/remove.d.ts +7 -0
- package/dist/commands/data/remove.d.ts.map +1 -0
- package/dist/commands/data/remove.js +29 -0
- package/dist/commands/data/remove.js.map +1 -0
- package/dist/commands/data.d.ts +3 -0
- package/dist/commands/data.d.ts.map +1 -0
- package/dist/commands/data.js +115 -0
- package/dist/commands/data.js.map +1 -0
- package/dist/commands/spin/dns.d.ts +7 -0
- package/dist/commands/spin/dns.d.ts.map +1 -0
- package/dist/commands/spin/dns.js +42 -0
- package/dist/commands/spin/dns.js.map +1 -0
- package/dist/commands/spin/down.d.ts +3 -0
- package/dist/commands/spin/down.d.ts.map +1 -0
- package/dist/commands/spin/down.js +17 -0
- package/dist/commands/spin/down.js.map +1 -0
- package/dist/commands/spin/helpers.d.ts +7 -0
- package/dist/commands/spin/helpers.d.ts.map +1 -0
- package/dist/commands/spin/helpers.js +38 -0
- package/dist/commands/spin/helpers.js.map +1 -0
- package/dist/commands/spin/list.d.ts +3 -0
- package/dist/commands/spin/list.d.ts.map +1 -0
- package/dist/commands/spin/list.js +20 -0
- package/dist/commands/spin/list.js.map +1 -0
- package/dist/commands/spin/setup.d.ts +3 -0
- package/dist/commands/spin/setup.d.ts.map +1 -0
- package/dist/commands/spin/setup.js +32 -0
- package/dist/commands/spin/setup.js.map +1 -0
- package/dist/commands/spin/ssh.d.ts +3 -0
- package/dist/commands/spin/ssh.d.ts.map +1 -0
- package/dist/commands/spin/ssh.js +14 -0
- package/dist/commands/spin/ssh.js.map +1 -0
- package/dist/commands/spin/status.d.ts +3 -0
- package/dist/commands/spin/status.d.ts.map +1 -0
- package/dist/commands/spin/status.js +21 -0
- package/dist/commands/spin/status.js.map +1 -0
- package/dist/commands/spin/up.d.ts +11 -0
- package/dist/commands/spin/up.d.ts.map +1 -0
- package/dist/commands/spin/up.js +34 -0
- package/dist/commands/spin/up.js.map +1 -0
- package/dist/commands/spin.d.ts +3 -0
- package/dist/commands/spin.d.ts.map +1 -0
- package/dist/commands/spin.js +166 -0
- package/dist/commands/spin.js.map +1 -0
- package/dist/lib/data-pull-extra-tables.d.ts +26 -0
- package/dist/lib/data-pull-extra-tables.d.ts.map +1 -0
- package/dist/lib/data-pull-extra-tables.js +212 -0
- package/dist/lib/data-pull-extra-tables.js.map +1 -0
- package/dist/lib/data-pull-manifest.d.ts +97 -0
- package/dist/lib/data-pull-manifest.d.ts.map +1 -0
- package/dist/lib/data-pull-manifest.js +603 -0
- package/dist/lib/data-pull-manifest.js.map +1 -0
- package/dist/lib/database-runner.d.ts +28 -2
- package/dist/lib/database-runner.d.ts.map +1 -1
- package/dist/lib/database-runner.js +112 -49
- package/dist/lib/database-runner.js.map +1 -1
- package/dist/lib/digitalocean.d.ts +60 -0
- package/dist/lib/digitalocean.d.ts.map +1 -0
- package/dist/lib/digitalocean.js +108 -0
- package/dist/lib/digitalocean.js.map +1 -0
- package/dist/lib/yaml-converter.d.ts +25 -1
- package/dist/lib/yaml-converter.d.ts.map +1 -1
- package/dist/lib/yaml-converter.js +98 -15
- package/dist/lib/yaml-converter.js.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssh.d.ts","sourceRoot":"","sources":["../../../src/commands/spin/ssh.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAK5C,wBAAsB,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAc3F"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { getDroplet } from "../../lib/digitalocean";
|
|
3
|
+
import { getPublicIp } from "./helpers";
|
|
4
|
+
export async function spinSsh(nameOrId, user, logger) {
|
|
5
|
+
const droplet = await getDroplet(nameOrId);
|
|
6
|
+
const ip = getPublicIp(droplet);
|
|
7
|
+
if (!ip) {
|
|
8
|
+
throw new Error(`Droplet "${droplet.name}" has no public IP yet (status: ${droplet.status})`);
|
|
9
|
+
}
|
|
10
|
+
logger.info(`Connecting to ${user}@${ip} (${droplet.name})…`);
|
|
11
|
+
const result = spawnSync("ssh", ["-o", "StrictHostKeyChecking=accept-new", `${user}@${ip}`], { stdio: "inherit" });
|
|
12
|
+
process.exit(result.status ?? 0);
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=ssh.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssh.js","sourceRoot":"","sources":["../../../src/commands/spin/ssh.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,QAAgB,EAAE,IAAY,EAAE,MAAc;IAC3E,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC3C,MAAM,EAAE,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IAChC,IAAI,CAAC,EAAE,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CAAC,YAAY,OAAO,CAAC,IAAI,mCAAmC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IAC/F,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,iBAAiB,IAAI,IAAI,EAAE,KAAK,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC;IAC9D,MAAM,MAAM,GAAG,SAAS,CACvB,KAAK,EACL,CAAC,IAAI,EAAE,kCAAkC,EAAE,GAAG,IAAI,IAAI,EAAE,EAAE,CAAC,EAC3D,EAAE,KAAK,EAAE,SAAS,EAAE,CACpB,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/commands/spin/status.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAI5C,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBjF"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { getDroplet } from "../../lib/digitalocean";
|
|
2
|
+
import { formatTable, getPublicIp } from "./helpers";
|
|
3
|
+
export async function spinStatus(nameOrId, _logger) {
|
|
4
|
+
const d = await getDroplet(nameOrId);
|
|
5
|
+
const ip = getPublicIp(d) ?? "pending";
|
|
6
|
+
console.log(formatTable([
|
|
7
|
+
["Name", d.name],
|
|
8
|
+
["ID", String(d.id)],
|
|
9
|
+
["Status", d.status],
|
|
10
|
+
["IP", ip],
|
|
11
|
+
["Region", `${d.region.slug} (${d.region.name})`],
|
|
12
|
+
["Size", d.size_slug],
|
|
13
|
+
["Image", `${d.image.slug} (${d.image.name})`],
|
|
14
|
+
["vCPUs", String(d.vcpus)],
|
|
15
|
+
["Memory", `${d.memory} MB`],
|
|
16
|
+
["Disk", `${d.disk} GB`],
|
|
17
|
+
["Tags", d.tags.join(", ") || "none"],
|
|
18
|
+
["Created", d.created_at],
|
|
19
|
+
]));
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/commands/spin/status.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAErD,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAAgB,EAAE,OAAe;IACjE,MAAM,CAAC,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAC;IACrC,MAAM,EAAE,GAAG,WAAW,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC;IAEvC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;QACvB,CAAC,MAAM,EAAK,CAAC,CAAC,IAAI,CAAC;QACnB,CAAC,IAAI,EAAO,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACzB,CAAC,QAAQ,EAAG,CAAC,CAAC,MAAM,CAAC;QACrB,CAAC,IAAI,EAAO,EAAE,CAAC;QACf,CAAC,QAAQ,EAAG,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC;QAClD,CAAC,MAAM,EAAK,CAAC,CAAC,SAAS,CAAC;QACxB,CAAC,OAAO,EAAI,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC;QAChD,CAAC,OAAO,EAAI,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC,QAAQ,EAAG,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC;QAC7B,CAAC,MAAM,EAAK,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC;QAC3B,CAAC,MAAM,EAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC;QACxC,CAAC,SAAS,EAAE,CAAC,CAAC,UAAU,CAAC;KACzB,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Logger } from "@caporal/core";
|
|
2
|
+
export type SpinUpOpts = {
|
|
3
|
+
name: string;
|
|
4
|
+
size: string;
|
|
5
|
+
region: string;
|
|
6
|
+
image: string;
|
|
7
|
+
sshKeys: string[];
|
|
8
|
+
tag: string;
|
|
9
|
+
};
|
|
10
|
+
export declare function spinUp(opts: SpinUpOpts, logger: Logger): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=up.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"up.d.ts","sourceRoot":"","sources":["../../../src/commands/spin/up.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAI5C,MAAM,MAAM,UAAU,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF,wBAAsB,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsC5E"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { createDroplet, listSshKeys } from "../../lib/digitalocean";
|
|
2
|
+
import { getPublicIp, waitForActive } from "./helpers";
|
|
3
|
+
export async function spinUp(opts, logger) {
|
|
4
|
+
if (opts.sshKeys.length === 0) {
|
|
5
|
+
const keys = await listSshKeys();
|
|
6
|
+
const bltKeys = keys.filter((k) => k.name.toLowerCase().includes("blt"));
|
|
7
|
+
if (bltKeys.length > 0) {
|
|
8
|
+
opts.sshKeys = bltKeys.map((k) => String(k.id));
|
|
9
|
+
logger.info(`Auto-selected SSH keys: ${bltKeys.map((k) => k.name).join(", ")}`);
|
|
10
|
+
}
|
|
11
|
+
else if (keys.length > 0) {
|
|
12
|
+
opts.sshKeys = keys.map((k) => String(k.id));
|
|
13
|
+
logger.info(`No 'blt' SSH keys found — using all account keys: ${keys.map((k) => k.name).join(", ")}`);
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
logger.warn("No SSH keys found in DO account. Droplet will use password auth (check email for root password).");
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
logger.info(`Creating droplet "${opts.name}" (${opts.size}) in ${opts.region}…`);
|
|
20
|
+
const droplet = await createDroplet({
|
|
21
|
+
name: opts.name,
|
|
22
|
+
size: opts.size,
|
|
23
|
+
region: opts.region,
|
|
24
|
+
image: opts.image,
|
|
25
|
+
sshKeys: opts.sshKeys,
|
|
26
|
+
tags: [opts.tag],
|
|
27
|
+
});
|
|
28
|
+
logger.info(`Droplet created — id: ${droplet.id}, status: ${droplet.status}`);
|
|
29
|
+
logger.info("Waiting for droplet to become active…");
|
|
30
|
+
const ready = await waitForActive(String(droplet.id), logger);
|
|
31
|
+
const ip = getPublicIp(ready) ?? "unknown";
|
|
32
|
+
logger.info(`Droplet ready — id: ${ready.id}, ip: ${ip}`);
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=up.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"up.js","sourceRoot":"","sources":["../../../src/commands/spin/up.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAWvD,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAgB,EAAE,MAAc;IAC5D,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,MAAM,WAAW,EAAE,CAAC;QACjC,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAC1B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAC3C,CAAC;QACF,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAChD,MAAM,CAAC,IAAI,CACV,2BAA2B,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAClE,CAAC;QACH,CAAC;aAAM,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAC7C,MAAM,CAAC,IAAI,CACV,qDAAqD,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACzF,CAAC;QACH,CAAC;aAAM,CAAC;YACP,MAAM,CAAC,IAAI,CACV,kGAAkG,CAClG,CAAC;QACH,CAAC;IACF,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,qBAAqB,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,IAAI,QAAQ,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;IACjF,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC;QACnC,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC;KAChB,CAAC,CAAC;IACH,MAAM,CAAC,IAAI,CAAC,yBAAyB,OAAO,CAAC,EAAE,aAAa,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAE9E,MAAM,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC;IACrD,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;IAC9D,MAAM,EAAE,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,SAAS,CAAC;IAC3C,MAAM,CAAC,IAAI,CAAC,uBAAuB,KAAK,CAAC,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;AAC3D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spin.d.ts","sourceRoot":"","sources":["../../src/commands/spin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAiC,MAAM,eAAe,CAAC;AAwB5E,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,OAAO,EAAE,OAAO,QAuNnD"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { spinUp } from "./spin/up";
|
|
2
|
+
import { spinDown } from "./spin/down";
|
|
3
|
+
import { spinList } from "./spin/list";
|
|
4
|
+
import { spinStatus } from "./spin/status";
|
|
5
|
+
import { spinSsh } from "./spin/ssh";
|
|
6
|
+
import { spinDns } from "./spin/dns";
|
|
7
|
+
import { spinSetup } from "./spin/setup";
|
|
8
|
+
const spinHelp = `
|
|
9
|
+
Manage DigitalOcean droplets for BLT test environments
|
|
10
|
+
|
|
11
|
+
Usage:
|
|
12
|
+
blt spin up --name <name> [--size slug] [--region slug] [--image slug] [--ssh-keys ids] [--tag tag]
|
|
13
|
+
blt spin down <name> [--force]
|
|
14
|
+
blt spin list [--tag tag]
|
|
15
|
+
blt spin status <name>
|
|
16
|
+
blt spin ssh <name> [--user user]
|
|
17
|
+
blt spin dns <action> --domain <domain> [--name sub] [--ip addr] [--record-id id]
|
|
18
|
+
blt spin setup <name>
|
|
19
|
+
|
|
20
|
+
Requires DIGITALOCEAN_ACCESS_TOKEN env var.
|
|
21
|
+
`;
|
|
22
|
+
export default function spinCommand(program) {
|
|
23
|
+
program
|
|
24
|
+
.command("spin", "Manage DigitalOcean droplets for BLT environments")
|
|
25
|
+
.help(spinHelp)
|
|
26
|
+
.action(() => {
|
|
27
|
+
console.log(spinHelp);
|
|
28
|
+
});
|
|
29
|
+
// -- spin up ---------------------------------------------------------------
|
|
30
|
+
program
|
|
31
|
+
.command("spin up", "Create a new droplet")
|
|
32
|
+
.hide()
|
|
33
|
+
.option("--name <name>", "Droplet name", { required: true })
|
|
34
|
+
.option("--size <size>", "Droplet size slug", {
|
|
35
|
+
default: "s-1vcpu-512mb-10gb",
|
|
36
|
+
})
|
|
37
|
+
.option("--region <region>", "Region slug", { default: "nyc3" })
|
|
38
|
+
.option("--image <image>", "OS image slug", {
|
|
39
|
+
default: "ubuntu-24-04-x64",
|
|
40
|
+
})
|
|
41
|
+
.option("--ssh-keys <keys>", "Comma-separated SSH key IDs or fingerprints")
|
|
42
|
+
.option("--tag <tag>", "Tag for the droplet", { default: "blt" })
|
|
43
|
+
.action(async ({ options, logger, }) => {
|
|
44
|
+
try {
|
|
45
|
+
const sshKeysRaw = options.sshKeys;
|
|
46
|
+
const sshKeys = sshKeysRaw
|
|
47
|
+
? String(sshKeysRaw).split(",").map((k) => k.trim()).filter(Boolean)
|
|
48
|
+
: [];
|
|
49
|
+
await spinUp({
|
|
50
|
+
name: String(options.name),
|
|
51
|
+
size: String(options.size),
|
|
52
|
+
region: String(options.region),
|
|
53
|
+
image: String(options.image),
|
|
54
|
+
tag: String(options.tag),
|
|
55
|
+
sshKeys,
|
|
56
|
+
}, logger);
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
60
|
+
logger.error(`spin up failed: ${message}`);
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
// -- spin down -------------------------------------------------------------
|
|
65
|
+
program
|
|
66
|
+
.command("spin down", "Destroy a droplet")
|
|
67
|
+
.hide()
|
|
68
|
+
.argument("<name>", "Droplet name or ID")
|
|
69
|
+
.option("--force", "Skip confirmation", { default: false })
|
|
70
|
+
.action(async ({ args, options, logger, }) => {
|
|
71
|
+
try {
|
|
72
|
+
await spinDown(args.name, !!options.force, logger);
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
76
|
+
logger.error(`spin down failed: ${message}`);
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
// -- spin list -------------------------------------------------------------
|
|
81
|
+
program
|
|
82
|
+
.command("spin list", "List BLT droplets")
|
|
83
|
+
.hide()
|
|
84
|
+
.option("--tag <tag>", "Filter by tag", { default: "blt" })
|
|
85
|
+
.action(async ({ options, logger, }) => {
|
|
86
|
+
try {
|
|
87
|
+
await spinList(options.tag, logger);
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
91
|
+
logger.error(`spin list failed: ${message}`);
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
// -- spin status -----------------------------------------------------------
|
|
96
|
+
program
|
|
97
|
+
.command("spin status", "Check droplet status")
|
|
98
|
+
.hide()
|
|
99
|
+
.argument("<name>", "Droplet name or ID")
|
|
100
|
+
.action(async ({ args, logger, }) => {
|
|
101
|
+
try {
|
|
102
|
+
await spinStatus(args.name, logger);
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
106
|
+
logger.error(`spin status failed: ${message}`);
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
// -- spin ssh --------------------------------------------------------------
|
|
111
|
+
program
|
|
112
|
+
.command("spin ssh", "SSH into a droplet")
|
|
113
|
+
.hide()
|
|
114
|
+
.argument("<name>", "Droplet name or ID")
|
|
115
|
+
.option("--user <user>", "SSH user", { default: "blt" })
|
|
116
|
+
.action(async ({ args, options, logger, }) => {
|
|
117
|
+
try {
|
|
118
|
+
await spinSsh(args.name, options.user, logger);
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
122
|
+
logger.error(`spin ssh failed: ${message}`);
|
|
123
|
+
process.exit(1);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
// -- spin dns --------------------------------------------------------------
|
|
127
|
+
program
|
|
128
|
+
.command("spin dns", "Manage DNS records for a domain")
|
|
129
|
+
.hide()
|
|
130
|
+
.argument("<action>", "Action: create, list, delete")
|
|
131
|
+
.option("--domain <domain>", "Domain name", { default: "bltcore.com" })
|
|
132
|
+
.option("--name <name>", "Record name (subdomain)")
|
|
133
|
+
.option("--ip <ip>", "IP address for A record")
|
|
134
|
+
.option("--record-id <id>", "Record ID (for delete)")
|
|
135
|
+
.action(async ({ args, options, logger, }) => {
|
|
136
|
+
try {
|
|
137
|
+
await spinDns(args.action, options.domain, {
|
|
138
|
+
name: options.name,
|
|
139
|
+
ip: options.ip,
|
|
140
|
+
recordId: options.recordId,
|
|
141
|
+
}, logger);
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
145
|
+
logger.error(`spin dns failed: ${message}`);
|
|
146
|
+
process.exit(1);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
// -- spin setup ------------------------------------------------------------
|
|
150
|
+
program
|
|
151
|
+
.command("spin setup", "Bootstrap a fresh droplet (Docker, users, dirs)")
|
|
152
|
+
.hide()
|
|
153
|
+
.argument("<name>", "Droplet name or ID")
|
|
154
|
+
.option("--user <user>", "SSH user for bootstrap", { default: "root" })
|
|
155
|
+
.action(async ({ args, options, logger, }) => {
|
|
156
|
+
try {
|
|
157
|
+
await spinSetup(args.name, options.user, logger);
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
161
|
+
logger.error(`spin setup failed: ${message}`);
|
|
162
|
+
process.exit(1);
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=spin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spin.js","sourceRoot":"","sources":["../../src/commands/spin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pull remaining `public` base tables not covered by the curated snapshot manifest
|
|
3
|
+
* (everything in `schema/public/sql` should exist as a table in a live DB — we discover via catalog).
|
|
4
|
+
*/
|
|
5
|
+
import type { Client } from "pg";
|
|
6
|
+
import type { PullContext, PullPartition } from "./data-pull-manifest";
|
|
7
|
+
export declare function listPublicBaseTables(client: Client): Promise<string[]>;
|
|
8
|
+
/** Insert-safe order: parents before children (FK targets first). */
|
|
9
|
+
export declare function topoSortTables(client: Client, tables: string[]): Promise<string[]>;
|
|
10
|
+
/** Column `udt_name` map for snapshot apply (json/jsonb-aware literals). */
|
|
11
|
+
export declare function fetchPublicTableColumnUdts(client: Client, table: string): Promise<Record<string, string>>;
|
|
12
|
+
/** Columns that are `GENERATED ALWAYS AS IDENTITY` — inserts need `OVERRIDING SYSTEM VALUE` when values are supplied. */
|
|
13
|
+
export declare function fetchPublicTableIdentityAlwaysColumns(client: Client, table: string): Promise<string[]>;
|
|
14
|
+
/** Columns that are `STORED` generated (`GENERATED ALWAYS AS (...)`); inserts must omit them (values are computed). */
|
|
15
|
+
export declare function fetchPublicTableGeneratedStoredColumnNames(client: Client, table: string): Promise<string[]>;
|
|
16
|
+
export declare function pullExtraPublicTablePartition(client: Client, table: string): Promise<PullPartition>;
|
|
17
|
+
/** Full-row pull for curated manifest assets that need stable PKs (e.g. `items.id` for `order_items` FKs). */
|
|
18
|
+
export declare function dumpPublicTableForCuratedPull(client: Client, table: string): Promise<{
|
|
19
|
+
rows: {
|
|
20
|
+
row: Record<string, unknown>;
|
|
21
|
+
}[];
|
|
22
|
+
columnUdts: Record<string, string>;
|
|
23
|
+
primaryKey: string[];
|
|
24
|
+
}>;
|
|
25
|
+
export declare function discoverAndSortExtraPublicTables(client: Client, ctx: PullContext): Promise<string[]>;
|
|
26
|
+
//# sourceMappingURL=data-pull-extra-tables.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-pull-extra-tables.d.ts","sourceRoot":"","sources":["../../src/lib/data-pull-extra-tables.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AACjC,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AA2BvE,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAa5E;AAmBD,qEAAqE;AACrE,wBAAsB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAiCxF;AAeD,4EAA4E;AAC5E,wBAAsB,0BAA0B,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAG/G;AAED,yHAAyH;AACzH,wBAAsB,qCAAqC,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAW5G;AAED,uHAAuH;AACvH,wBAAsB,0CAA0C,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAejH;AA2CD,wBAAsB,6BAA6B,CAClD,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACX,OAAO,CAAC,aAAa,CAAC,CAoCxB;AAED,8GAA8G;AAC9G,wBAAsB,6BAA6B,CAClD,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACX,OAAO,CAAC;IACV,IAAI,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,EAAE,CAAC;IACzC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,UAAU,EAAE,MAAM,EAAE,CAAC;CACrB,CAAC,CAOD;AAED,wBAAsB,gCAAgC,CACrD,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,WAAW,GACd,OAAO,CAAC,MAAM,EAAE,CAAC,CAOnB"}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pull remaining `public` base tables not covered by the curated snapshot manifest
|
|
3
|
+
* (everything in `schema/public/sql` should exist as a table in a live DB — we discover via catalog).
|
|
4
|
+
*/
|
|
5
|
+
import { MANIFEST_COVERED_PUBLIC_TABLES } from "./data-pull-manifest";
|
|
6
|
+
/** Never auto-pull these (noise, huge, or not data). */
|
|
7
|
+
const EXTRA_TABLE_BLOCKLIST = new Set([
|
|
8
|
+
"spatial_ref_sys",
|
|
9
|
+
"geometry_columns",
|
|
10
|
+
"geography_columns",
|
|
11
|
+
"raster_columns",
|
|
12
|
+
"raster_overviews",
|
|
13
|
+
]);
|
|
14
|
+
function slugTableForFilename(table) {
|
|
15
|
+
return table.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
16
|
+
}
|
|
17
|
+
/** Tables handled by FULL_PULL_SEQUENCE (same physical table as curated assets). */
|
|
18
|
+
function coveredPublicTablesForPull(ctx) {
|
|
19
|
+
const s = new Set(MANIFEST_COVERED_PUBLIC_TABLES);
|
|
20
|
+
/** User-shaped assets map to profiles / profile_roles; avoid duplicate apply. */
|
|
21
|
+
if (ctx.includeUsers) {
|
|
22
|
+
s.add("profiles");
|
|
23
|
+
s.add("profile_roles");
|
|
24
|
+
}
|
|
25
|
+
return s;
|
|
26
|
+
}
|
|
27
|
+
export async function listPublicBaseTables(client) {
|
|
28
|
+
const { rows } = await client.query(`SELECT c.relname AS t
|
|
29
|
+
FROM pg_class c
|
|
30
|
+
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
31
|
+
WHERE n.nspname = 'public'
|
|
32
|
+
AND (
|
|
33
|
+
(c.relkind = 'r' AND NOT c.relispartition)
|
|
34
|
+
OR c.relkind = 'p'
|
|
35
|
+
)
|
|
36
|
+
ORDER BY c.relname ASC`);
|
|
37
|
+
return rows.map((r) => r.t);
|
|
38
|
+
}
|
|
39
|
+
async function publicFkEdgesAmong(client, tableSet) {
|
|
40
|
+
const { rows } = await client.query(`SELECT cl.relname AS child, pf.relname AS parent
|
|
41
|
+
FROM pg_constraint con
|
|
42
|
+
JOIN pg_class cl ON cl.oid = con.conrelid
|
|
43
|
+
JOIN pg_namespace nl ON nl.oid = cl.relnamespace
|
|
44
|
+
JOIN pg_class pf ON pf.oid = con.confrelid
|
|
45
|
+
JOIN pg_namespace nf ON nf.oid = pf.relnamespace
|
|
46
|
+
WHERE con.contype = 'f'
|
|
47
|
+
AND nl.nspname = 'public'
|
|
48
|
+
AND nf.nspname = 'public'`);
|
|
49
|
+
return rows.filter((e) => tableSet.has(e.child) && tableSet.has(e.parent));
|
|
50
|
+
}
|
|
51
|
+
/** Insert-safe order: parents before children (FK targets first). */
|
|
52
|
+
export async function topoSortTables(client, tables) {
|
|
53
|
+
const set = new Set(tables);
|
|
54
|
+
if (tables.length <= 1)
|
|
55
|
+
return [...tables];
|
|
56
|
+
const edges = await publicFkEdgesAmong(client, set);
|
|
57
|
+
const inDeg = new Map();
|
|
58
|
+
for (const t of tables)
|
|
59
|
+
inDeg.set(t, 0);
|
|
60
|
+
for (const e of edges) {
|
|
61
|
+
if (set.has(e.child))
|
|
62
|
+
inDeg.set(e.child, (inDeg.get(e.child) ?? 0) + 1);
|
|
63
|
+
}
|
|
64
|
+
const q = tables.filter((t) => (inDeg.get(t) ?? 0) === 0).sort((a, b) => a.localeCompare(b));
|
|
65
|
+
const out = [];
|
|
66
|
+
while (q.length > 0) {
|
|
67
|
+
const t = q.shift();
|
|
68
|
+
if (t === undefined)
|
|
69
|
+
break;
|
|
70
|
+
out.push(t);
|
|
71
|
+
for (const e of edges) {
|
|
72
|
+
if (e.parent === t && set.has(e.child)) {
|
|
73
|
+
const d = (inDeg.get(e.child) ?? 1) - 1;
|
|
74
|
+
inDeg.set(e.child, d);
|
|
75
|
+
if (d === 0) {
|
|
76
|
+
q.push(e.child);
|
|
77
|
+
q.sort((a, b) => a.localeCompare(b));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (out.length !== tables.length) {
|
|
83
|
+
const seen = new Set(out);
|
|
84
|
+
for (const t of tables.sort((a, b) => a.localeCompare(b))) {
|
|
85
|
+
if (!seen.has(t))
|
|
86
|
+
out.push(t);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return out;
|
|
90
|
+
}
|
|
91
|
+
async function listTableColumns(client, table) {
|
|
92
|
+
const { rows } = await client.query(`SELECT column_name, udt_name
|
|
93
|
+
FROM information_schema.columns
|
|
94
|
+
WHERE table_schema = 'public' AND table_name = $1
|
|
95
|
+
ORDER BY ordinal_position ASC`, [table]);
|
|
96
|
+
return rows.map((r) => ({ name: r.column_name, udt: r.udt_name }));
|
|
97
|
+
}
|
|
98
|
+
/** Column `udt_name` map for snapshot apply (json/jsonb-aware literals). */
|
|
99
|
+
export async function fetchPublicTableColumnUdts(client, table) {
|
|
100
|
+
const cols = await listTableColumns(client, table);
|
|
101
|
+
return Object.fromEntries(cols.map((c) => [c.name, c.udt]));
|
|
102
|
+
}
|
|
103
|
+
/** Columns that are `GENERATED ALWAYS AS IDENTITY` — inserts need `OVERRIDING SYSTEM VALUE` when values are supplied. */
|
|
104
|
+
export async function fetchPublicTableIdentityAlwaysColumns(client, table) {
|
|
105
|
+
const { rows } = await client.query(`SELECT column_name
|
|
106
|
+
FROM information_schema.columns
|
|
107
|
+
WHERE table_schema = 'public'
|
|
108
|
+
AND table_name = $1
|
|
109
|
+
AND is_identity = 'YES'
|
|
110
|
+
AND identity_generation = 'ALWAYS'`, [table]);
|
|
111
|
+
return rows.map((r) => r.column_name);
|
|
112
|
+
}
|
|
113
|
+
/** Columns that are `STORED` generated (`GENERATED ALWAYS AS (...)`); inserts must omit them (values are computed). */
|
|
114
|
+
export async function fetchPublicTableGeneratedStoredColumnNames(client, table) {
|
|
115
|
+
const { rows } = await client.query(`SELECT a.attname AS column_name
|
|
116
|
+
FROM pg_attribute a
|
|
117
|
+
JOIN pg_class c ON c.oid = a.attrelid
|
|
118
|
+
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
119
|
+
WHERE n.nspname = 'public'
|
|
120
|
+
AND c.relname = $1
|
|
121
|
+
AND a.attnum > 0
|
|
122
|
+
AND NOT a.attisdropped
|
|
123
|
+
AND a.attgenerated = 's'
|
|
124
|
+
ORDER BY a.attnum`, [table]);
|
|
125
|
+
return rows.map((r) => r.column_name);
|
|
126
|
+
}
|
|
127
|
+
async function primaryKeyColumns(client, table) {
|
|
128
|
+
const { rows } = await client.query(`SELECT a.attname
|
|
129
|
+
FROM pg_index i
|
|
130
|
+
JOIN pg_class c ON c.oid = i.indrelid
|
|
131
|
+
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
132
|
+
JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY (i.indkey)
|
|
133
|
+
WHERE n.nspname = 'public' AND c.relname = $1 AND i.indisprimary
|
|
134
|
+
ORDER BY array_position(i.indkey, a.attnum)`, [table]);
|
|
135
|
+
return rows.map((r) => r.attname);
|
|
136
|
+
}
|
|
137
|
+
function buildSelectList(cols) {
|
|
138
|
+
const parts = [];
|
|
139
|
+
for (const c of cols) {
|
|
140
|
+
const q = `"${c.name.replace(/"/g, '""')}"`;
|
|
141
|
+
if (c.udt === "bytea") {
|
|
142
|
+
parts.push(`encode(${q}, 'base64') AS ${q}`);
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
parts.push(q);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return parts.join(", ");
|
|
149
|
+
}
|
|
150
|
+
function normalizeCell(column, value, udtByCol) {
|
|
151
|
+
if (value === null || value === undefined)
|
|
152
|
+
return value;
|
|
153
|
+
if (typeof value === "bigint")
|
|
154
|
+
return value.toString();
|
|
155
|
+
if (value instanceof Date)
|
|
156
|
+
return value.toISOString();
|
|
157
|
+
if (Buffer.isBuffer(value)) {
|
|
158
|
+
return value.toString("base64");
|
|
159
|
+
}
|
|
160
|
+
/** After SELECT encode(..., 'base64') for bytea, driver returns string. */
|
|
161
|
+
if (udtByCol.get(column) === "bytea" && typeof value === "string") {
|
|
162
|
+
return { __blt_bytea_b64: value };
|
|
163
|
+
}
|
|
164
|
+
return value;
|
|
165
|
+
}
|
|
166
|
+
export async function pullExtraPublicTablePartition(client, table) {
|
|
167
|
+
const cols = await listTableColumns(client, table);
|
|
168
|
+
if (cols.length === 0) {
|
|
169
|
+
return {
|
|
170
|
+
assetId: `10-900-public-${slugTableForFilename(table)}`,
|
|
171
|
+
snapshotStem: `10-900-public-${slugTableForFilename(table)}`,
|
|
172
|
+
rows: [],
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
const pk = await primaryKeyColumns(client, table);
|
|
176
|
+
const udtByCol = new Map(cols.map((c) => [c.name, c.udt]));
|
|
177
|
+
const selectList = buildSelectList(cols);
|
|
178
|
+
const orderBy = pk.length > 0 ? pk.map((c) => `"${c.replace(/"/g, '""')}" ASC`).join(", ") : `"${cols[0].name.replace(/"/g, '""')}" ASC`;
|
|
179
|
+
const { rows: data } = await client.query(`SELECT ${selectList} FROM public."${table.replace(/"/g, '""')}" ORDER BY ${orderBy}`);
|
|
180
|
+
const rrows = data.map((r) => {
|
|
181
|
+
const row = {};
|
|
182
|
+
for (const c of cols) {
|
|
183
|
+
row[c.name] = normalizeCell(c.name, r[c.name], udtByCol);
|
|
184
|
+
}
|
|
185
|
+
return { row };
|
|
186
|
+
});
|
|
187
|
+
const stem = `10-900-public-${slugTableForFilename(table)}`;
|
|
188
|
+
const columnUdts = Object.fromEntries(cols.map((c) => [c.name, c.udt]));
|
|
189
|
+
return {
|
|
190
|
+
assetId: stem,
|
|
191
|
+
snapshotStem: stem,
|
|
192
|
+
rows: rrows,
|
|
193
|
+
primaryKey: pk.length > 0 ? pk : undefined,
|
|
194
|
+
columnUdts,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
/** Full-row pull for curated manifest assets that need stable PKs (e.g. `items.id` for `order_items` FKs). */
|
|
198
|
+
export async function dumpPublicTableForCuratedPull(client, table) {
|
|
199
|
+
const part = await pullExtraPublicTablePartition(client, table);
|
|
200
|
+
return {
|
|
201
|
+
rows: part.rows,
|
|
202
|
+
columnUdts: part.columnUdts ?? {},
|
|
203
|
+
primaryKey: part.primaryKey ?? [],
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
export async function discoverAndSortExtraPublicTables(client, ctx) {
|
|
207
|
+
const covered = coveredPublicTablesForPull(ctx);
|
|
208
|
+
const all = await listPublicBaseTables(client);
|
|
209
|
+
const candidates = all.filter((t) => !covered.has(t) && !EXTRA_TABLE_BLOCKLIST.has(t) && !t.startsWith("pg_"));
|
|
210
|
+
return topoSortTables(client, candidates);
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=data-pull-extra-tables.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-pull-extra-tables.js","sourceRoot":"","sources":["../../src/lib/data-pull-extra-tables.ts"],"names":[],"mappings":"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"}
|