@pixpilot/supabase-backup 0.0.0 → 1.6.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 +77 -2
- package/dist/cli.cjs +40 -0
- package/dist/cli.d.cts +6 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.js +40 -0
- package/dist/index.cjs +17 -5
- package/dist/index.d.cts +144 -3
- package/dist/index.d.ts +144 -3
- package/dist/index.js +2 -4
- package/dist/status-Ba7xyZV8.js +594 -0
- package/dist/status-DgmkvmrB.cjs +719 -0
- package/package.json +37 -31
package/README.md
CHANGED
|
@@ -1,3 +1,78 @@
|
|
|
1
|
-
# supabase-backup
|
|
1
|
+
# @pixpilot/supabase-backup
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Encrypted backups of application schemas plus `auth.users` and `auth.identities`.
|
|
4
|
+
It is deliberately not full Supabase-project disaster recovery. Requires Node
|
|
5
|
+
22+, `pg_dump`, `pg_restore`, and `age`; direct PostgreSQL or the Supabase
|
|
6
|
+
Session Pooler on port 5432 is supported, while Transaction Pooler port 6543 is rejected.
|
|
7
|
+
|
|
8
|
+
## Backup
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
SOURCE_DATABASE_URL='postgresql://…' BACKUP_AGE_RECIPIENT='age1…' \
|
|
12
|
+
R2_ACCESS_KEY_ID=… R2_SECRET_ACCESS_KEY=… R2_ENDPOINT='https://<account>.r2.cloudflarestorage.com' \
|
|
13
|
+
R2_BUCKET='myapp-production-backups' BACKUP_PREFIX='production/database' \
|
|
14
|
+
npx @pixpilot/supabase-backup@1 backup
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`APP_SCHEMAS` is comma-separated and defaults to `public`; `auth` is never an
|
|
18
|
+
application schema. Backups fail if non-empty `auth.mfa_factors`,
|
|
19
|
+
`auth.sso_providers`, or `auth.saml_providers` would be omitted. R2 must be a
|
|
20
|
+
private bucket with bucket-scoped credentials; configure retention/bucket lock
|
|
21
|
+
in R2, not the CLI.
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npx @pixpilot/supabase-backup@1 status --max-age-hours 36
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Restore drill
|
|
28
|
+
|
|
29
|
+
Keep `AGE_IDENTITY` outside GitHub Actions and R2 credentials. Restore verifies
|
|
30
|
+
hashes, decrypts in a private temporary directory, inspects both archives, and
|
|
31
|
+
does nothing unless `--apply` is present. Apply only to a fresh recovery project.
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
AGE_IDENTITY='AGE-SECRET-KEY-…' R2_ACCESS_KEY_ID=… R2_SECRET_ACCESS_KEY=… \
|
|
35
|
+
R2_ENDPOINT=… R2_BUCKET=… TARGET_DATABASE_URL='postgresql://…' \
|
|
36
|
+
npx @pixpilot/supabase-backup@1 restore --key <manifest-key> --apply \
|
|
37
|
+
--confirm-target '<host>:5432/<database>'
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Apply restores Auth data before application data, never cleans `auth`, requires
|
|
41
|
+
empty target Auth tables, and rejects a target matching `SOURCE_DATABASE_URL`.
|
|
42
|
+
Verify user login and a representative application workflow manually afterward.
|
|
43
|
+
|
|
44
|
+
## Reusable workflow
|
|
45
|
+
|
|
46
|
+
`.github/workflows/backup.yml` is `workflow_call`, has no schedule, and never
|
|
47
|
+
receives `AGE_IDENTITY`. Consumers own schedule, concurrency, configuration,
|
|
48
|
+
and notifications:
|
|
49
|
+
|
|
50
|
+
```yaml
|
|
51
|
+
name: Database Backup
|
|
52
|
+
on:
|
|
53
|
+
workflow_dispatch:
|
|
54
|
+
schedule:
|
|
55
|
+
- cron: '17 3 * * *'
|
|
56
|
+
permissions:
|
|
57
|
+
contents: read
|
|
58
|
+
concurrency:
|
|
59
|
+
group: production-database-backup
|
|
60
|
+
cancel-in-progress: false
|
|
61
|
+
jobs:
|
|
62
|
+
backup:
|
|
63
|
+
uses: pixpilot/supabase-toolkit/.github/workflows/backup.yml@main
|
|
64
|
+
with:
|
|
65
|
+
backup-prefix: production/database
|
|
66
|
+
age-recipient: ${{ vars.BACKUP_AGE_RECIPIENT }}
|
|
67
|
+
r2-endpoint: ${{ vars.R2_ENDPOINT }}
|
|
68
|
+
r2-bucket: ${{ vars.R2_BUCKET }}
|
|
69
|
+
max-age-hours: 36
|
|
70
|
+
package-version: '1'
|
|
71
|
+
secrets:
|
|
72
|
+
database-url: ${{ secrets.SOURCE_DATABASE_URL }}
|
|
73
|
+
r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }}
|
|
74
|
+
r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Do not use `secrets: inherit`. Publish matching npm and `v1` workflow releases;
|
|
78
|
+
run a recovery drill immediately, quarterly, and after material Auth changes.
|
package/dist/cli.cjs
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const require_status = require('./status-DgmkvmrB.cjs');
|
|
3
|
+
|
|
4
|
+
//#region src/cli.ts
|
|
5
|
+
function valueAfter(args, flag) {
|
|
6
|
+
const index = args.indexOf(flag);
|
|
7
|
+
return index === -1 ? void 0 : args[index + 1];
|
|
8
|
+
}
|
|
9
|
+
/** Executes the package CLI commands. */
|
|
10
|
+
async function runCli(args = process.argv.slice(2)) {
|
|
11
|
+
const [command] = args;
|
|
12
|
+
if (command === "backup") {
|
|
13
|
+
await require_status.backup();
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (command === "status") {
|
|
17
|
+
const raw = valueAfter(args, "--max-age-hours");
|
|
18
|
+
await require_status.status(raw === void 0 ? void 0 : Number(raw));
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (command === "restore") {
|
|
22
|
+
const key = valueAfter(args, "--key");
|
|
23
|
+
if (!key) throw new require_status.BackupError("restore requires --key <manifest-key>.");
|
|
24
|
+
const confirmTarget = valueAfter(args, "--confirm-target");
|
|
25
|
+
await require_status.restore({
|
|
26
|
+
key,
|
|
27
|
+
apply: args.includes("--apply"),
|
|
28
|
+
...confirmTarget ? { confirmTarget } : {}
|
|
29
|
+
});
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
throw new require_status.BackupError("Usage: supabase-backup <backup|status|restore> [options]");
|
|
33
|
+
}
|
|
34
|
+
runCli().catch((error) => {
|
|
35
|
+
process.stderr.write(`${require_status.redact(error instanceof Error ? error.message : "Unexpected backup failure.")}\n`);
|
|
36
|
+
process.exitCode = 1;
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
//#endregion
|
|
40
|
+
exports.runCli = runCli;
|
package/dist/cli.d.cts
ADDED
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { a as backup, g as BackupError, i as redact, n as status, r as restore } from "./status-Ba7xyZV8.js";
|
|
3
|
+
|
|
4
|
+
//#region src/cli.ts
|
|
5
|
+
function valueAfter(args, flag) {
|
|
6
|
+
const index = args.indexOf(flag);
|
|
7
|
+
return index === -1 ? void 0 : args[index + 1];
|
|
8
|
+
}
|
|
9
|
+
/** Executes the package CLI commands. */
|
|
10
|
+
async function runCli(args = process.argv.slice(2)) {
|
|
11
|
+
const [command] = args;
|
|
12
|
+
if (command === "backup") {
|
|
13
|
+
await backup();
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (command === "status") {
|
|
17
|
+
const raw = valueAfter(args, "--max-age-hours");
|
|
18
|
+
await status(raw === void 0 ? void 0 : Number(raw));
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (command === "restore") {
|
|
22
|
+
const key = valueAfter(args, "--key");
|
|
23
|
+
if (!key) throw new BackupError("restore requires --key <manifest-key>.");
|
|
24
|
+
const confirmTarget = valueAfter(args, "--confirm-target");
|
|
25
|
+
await restore({
|
|
26
|
+
key,
|
|
27
|
+
apply: args.includes("--apply"),
|
|
28
|
+
...confirmTarget ? { confirmTarget } : {}
|
|
29
|
+
});
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
throw new BackupError("Usage: supabase-backup <backup|status|restore> [options]");
|
|
33
|
+
}
|
|
34
|
+
runCli().catch((error) => {
|
|
35
|
+
process.stderr.write(`${redact(error instanceof Error ? error.message : "Unexpected backup failure.")}\n`);
|
|
36
|
+
process.exitCode = 1;
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
//#endregion
|
|
40
|
+
export { runCli };
|
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
1
|
+
const require_status = require('./status-DgmkvmrB.cjs');
|
|
1
2
|
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
exports.
|
|
3
|
+
exports.BackupError = require_status.BackupError;
|
|
4
|
+
exports.backup = require_status.backup;
|
|
5
|
+
exports.backupObjectKeys = require_status.backupObjectKeys;
|
|
6
|
+
exports.backupWithConfig = require_status.backupWithConfig;
|
|
7
|
+
exports.databaseLabel = require_status.databaseLabel;
|
|
8
|
+
exports.ensureDifferentDatabases = require_status.ensureDifferentDatabases;
|
|
9
|
+
exports.getBackupStatus = require_status.getBackupStatus;
|
|
10
|
+
exports.loadBackupConfig = require_status.loadBackupConfig;
|
|
11
|
+
exports.loadRestoreConfig = require_status.loadRestoreConfig;
|
|
12
|
+
exports.loadStatusConfig = require_status.loadStatusConfig;
|
|
13
|
+
exports.parseDatabaseUrl = require_status.parseDatabaseUrl;
|
|
14
|
+
exports.parseManifest = require_status.parseManifest;
|
|
15
|
+
exports.redact = require_status.redact;
|
|
16
|
+
exports.restore = require_status.restore;
|
|
17
|
+
exports.status = require_status.status;
|
|
18
|
+
exports.toLibpqEnvironment = require_status.toLibpqEnvironment;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,145 @@
|
|
|
1
|
-
//#region src/
|
|
2
|
-
|
|
1
|
+
//#region src/config.d.ts
|
|
2
|
+
interface R2Config {
|
|
3
|
+
accessKeyId: string;
|
|
4
|
+
bucket: string;
|
|
5
|
+
endpoint: string;
|
|
6
|
+
secretAccessKey: string;
|
|
7
|
+
}
|
|
8
|
+
interface BackupConfig extends R2Config {
|
|
9
|
+
ageRecipient: string;
|
|
10
|
+
appSchemas: string[];
|
|
11
|
+
prefix: string;
|
|
12
|
+
sourceDatabaseUrl: string;
|
|
13
|
+
}
|
|
14
|
+
interface RestoreConfig extends R2Config {
|
|
15
|
+
ageIdentity: string;
|
|
16
|
+
sourceDatabaseUrl?: string;
|
|
17
|
+
targetDatabaseUrl?: string;
|
|
18
|
+
}
|
|
19
|
+
interface StatusConfig extends R2Config {
|
|
20
|
+
prefix: string;
|
|
21
|
+
}
|
|
22
|
+
/** Loads and validates backup-only environment configuration. */
|
|
23
|
+
declare function loadBackupConfig(env?: NodeJS.ProcessEnv): BackupConfig;
|
|
24
|
+
/** Loads restore credentials while allowing dry-run archive checks without a target. */
|
|
25
|
+
declare function loadRestoreConfig(env?: NodeJS.ProcessEnv, requireTarget?: boolean): RestoreConfig;
|
|
26
|
+
/** Loads the R2 prefix and credentials required by the read-only health check. */
|
|
27
|
+
declare function loadStatusConfig(env?: NodeJS.ProcessEnv): StatusConfig;
|
|
3
28
|
//#endregion
|
|
4
|
-
|
|
29
|
+
//#region src/manifest.d.ts
|
|
30
|
+
declare const authTables: readonly ["auth.users", "auth.identities"];
|
|
31
|
+
type AuthTable = (typeof authTables)[number];
|
|
32
|
+
interface Column {
|
|
33
|
+
dataType: string;
|
|
34
|
+
name: string;
|
|
35
|
+
}
|
|
36
|
+
interface TableCount {
|
|
37
|
+
table: string;
|
|
38
|
+
count: number;
|
|
39
|
+
}
|
|
40
|
+
interface BackupManifest {
|
|
41
|
+
appChecksumObjectKey: string;
|
|
42
|
+
appEncryptedBytes: number;
|
|
43
|
+
appObjectKey: string;
|
|
44
|
+
appSchemas: string[];
|
|
45
|
+
appSha256: string;
|
|
46
|
+
appTableCounts: TableCount[];
|
|
47
|
+
authColumns: Record<AuthTable, Column[]>;
|
|
48
|
+
authChecksumObjectKey: string;
|
|
49
|
+
authEncryptedBytes: number;
|
|
50
|
+
authObjectKey: string;
|
|
51
|
+
authRowCounts: TableCount[];
|
|
52
|
+
authSha256: string;
|
|
53
|
+
authTables: AuthTable[];
|
|
54
|
+
cliVersion: string;
|
|
55
|
+
createdAt: string;
|
|
56
|
+
environment: string;
|
|
57
|
+
pgDumpVersion: string;
|
|
58
|
+
postgresServerVersion: string;
|
|
59
|
+
}
|
|
60
|
+
/** Generates immutable object names for one UTC backup timestamp. */
|
|
61
|
+
declare function backupObjectKeys(prefix: string, createdAt: Date): Record<'app' | 'auth' | 'appChecksum' | 'authChecksum' | 'manifest', string>;
|
|
62
|
+
/** Rejects malformed manifests before they can guide a restore. */
|
|
63
|
+
declare function parseManifest(value: string): BackupManifest;
|
|
64
|
+
//#endregion
|
|
65
|
+
//#region src/process.d.ts
|
|
66
|
+
interface ProgramRunner {
|
|
67
|
+
run: (command: string, args: string[], options?: {
|
|
68
|
+
env?: NodeJS.ProcessEnv;
|
|
69
|
+
}) => Promise<string>;
|
|
70
|
+
}
|
|
71
|
+
//#endregion
|
|
72
|
+
//#region src/r2.d.ts
|
|
73
|
+
interface ObjectStore {
|
|
74
|
+
get: (key: string) => Promise<Uint8Array>;
|
|
75
|
+
has: (key: string) => Promise<boolean>;
|
|
76
|
+
list: (prefix: string) => Promise<string[]>;
|
|
77
|
+
putImmutable: (key: string, body: Uint8Array) => Promise<void>;
|
|
78
|
+
}
|
|
79
|
+
//#endregion
|
|
80
|
+
//#region src/backup.d.ts
|
|
81
|
+
/** Creates encrypted, immutable app/Auth archives and publishes their manifest last. */
|
|
82
|
+
declare function backup(env?: NodeJS.ProcessEnv, dependencies?: {
|
|
83
|
+
now?: Date;
|
|
84
|
+
runner?: ProgramRunner;
|
|
85
|
+
store?: ObjectStore;
|
|
86
|
+
}): Promise<BackupManifest>;
|
|
87
|
+
/** Implements backup with injected dependencies for deterministic tests. */
|
|
88
|
+
declare function backupWithConfig(config: BackupConfig, dependencies?: {
|
|
89
|
+
now?: Date;
|
|
90
|
+
runner?: ProgramRunner;
|
|
91
|
+
store?: ObjectStore;
|
|
92
|
+
}): Promise<BackupManifest>;
|
|
93
|
+
//#endregion
|
|
94
|
+
//#region src/database-url.d.ts
|
|
95
|
+
interface DatabaseConnection {
|
|
96
|
+
database: string;
|
|
97
|
+
host: string;
|
|
98
|
+
password: string;
|
|
99
|
+
port: string;
|
|
100
|
+
sslmode: string;
|
|
101
|
+
user: string;
|
|
102
|
+
}
|
|
103
|
+
/** Parses a PostgreSQL URL without retaining it in process arguments. */
|
|
104
|
+
declare function parseDatabaseUrl(value: string): DatabaseConnection;
|
|
105
|
+
/** Converts a parsed URL to the libpq environment passed to PostgreSQL tools. */
|
|
106
|
+
declare function toLibpqEnvironment(connection: DatabaseConnection): NodeJS.ProcessEnv;
|
|
107
|
+
/** Produces a non-secret target label used for typed restore confirmation. */
|
|
108
|
+
declare function databaseLabel(connection: DatabaseConnection): string;
|
|
109
|
+
/** Prevents a configured source database from also being used as a restore target. */
|
|
110
|
+
declare function ensureDifferentDatabases(source: DatabaseConnection | undefined, target: DatabaseConnection): void;
|
|
111
|
+
//#endregion
|
|
112
|
+
//#region src/errors.d.ts
|
|
113
|
+
/** Error whose message is safe to display from the CLI. */
|
|
114
|
+
declare class BackupError extends Error {
|
|
115
|
+
constructor(message: string);
|
|
116
|
+
}
|
|
117
|
+
//#endregion
|
|
118
|
+
//#region src/redact.d.ts
|
|
119
|
+
/** Removes connection strings, age identities, and common credential values from text. */
|
|
120
|
+
declare function redact(value: string): string;
|
|
121
|
+
//#endregion
|
|
122
|
+
//#region src/restore.d.ts
|
|
123
|
+
interface RestoreOptions {
|
|
124
|
+
apply: boolean;
|
|
125
|
+
confirmTarget?: string;
|
|
126
|
+
key: string;
|
|
127
|
+
}
|
|
128
|
+
/** Downloads, verifies, decrypts, and optionally restores a single manifest. */
|
|
129
|
+
declare function restore(options: RestoreOptions, env?: NodeJS.ProcessEnv, dependencies?: {
|
|
130
|
+
runner?: ProgramRunner;
|
|
131
|
+
store?: ObjectStore;
|
|
132
|
+
}): Promise<BackupManifest>;
|
|
133
|
+
//#endregion
|
|
134
|
+
//#region src/status.d.ts
|
|
135
|
+
interface BackupStatus {
|
|
136
|
+
ageHours: number;
|
|
137
|
+
manifest: BackupManifest;
|
|
138
|
+
manifestKey: string;
|
|
139
|
+
}
|
|
140
|
+
/** Finds the latest complete manifest and checks its referenced archives remain available. */
|
|
141
|
+
declare function getBackupStatus(prefix: string, store: ObjectStore, now?: Date): Promise<BackupStatus>;
|
|
142
|
+
/** Prints a machine-safe health result and fails when no recent valid backup exists. */
|
|
143
|
+
declare function status(maxAgeHours: number | undefined, env?: NodeJS.ProcessEnv): Promise<BackupStatus>;
|
|
144
|
+
//#endregion
|
|
145
|
+
export { BackupError, type BackupManifest, backup, backupObjectKeys, backupWithConfig, databaseLabel, ensureDifferentDatabases, getBackupStatus, loadBackupConfig, loadRestoreConfig, loadStatusConfig, parseDatabaseUrl, parseManifest, redact, restore, status, toLibpqEnvironment };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,145 @@
|
|
|
1
|
-
//#region src/
|
|
2
|
-
|
|
1
|
+
//#region src/config.d.ts
|
|
2
|
+
interface R2Config {
|
|
3
|
+
accessKeyId: string;
|
|
4
|
+
bucket: string;
|
|
5
|
+
endpoint: string;
|
|
6
|
+
secretAccessKey: string;
|
|
7
|
+
}
|
|
8
|
+
interface BackupConfig extends R2Config {
|
|
9
|
+
ageRecipient: string;
|
|
10
|
+
appSchemas: string[];
|
|
11
|
+
prefix: string;
|
|
12
|
+
sourceDatabaseUrl: string;
|
|
13
|
+
}
|
|
14
|
+
interface RestoreConfig extends R2Config {
|
|
15
|
+
ageIdentity: string;
|
|
16
|
+
sourceDatabaseUrl?: string;
|
|
17
|
+
targetDatabaseUrl?: string;
|
|
18
|
+
}
|
|
19
|
+
interface StatusConfig extends R2Config {
|
|
20
|
+
prefix: string;
|
|
21
|
+
}
|
|
22
|
+
/** Loads and validates backup-only environment configuration. */
|
|
23
|
+
declare function loadBackupConfig(env?: NodeJS.ProcessEnv): BackupConfig;
|
|
24
|
+
/** Loads restore credentials while allowing dry-run archive checks without a target. */
|
|
25
|
+
declare function loadRestoreConfig(env?: NodeJS.ProcessEnv, requireTarget?: boolean): RestoreConfig;
|
|
26
|
+
/** Loads the R2 prefix and credentials required by the read-only health check. */
|
|
27
|
+
declare function loadStatusConfig(env?: NodeJS.ProcessEnv): StatusConfig;
|
|
3
28
|
//#endregion
|
|
4
|
-
|
|
29
|
+
//#region src/manifest.d.ts
|
|
30
|
+
declare const authTables: readonly ["auth.users", "auth.identities"];
|
|
31
|
+
type AuthTable = (typeof authTables)[number];
|
|
32
|
+
interface Column {
|
|
33
|
+
dataType: string;
|
|
34
|
+
name: string;
|
|
35
|
+
}
|
|
36
|
+
interface TableCount {
|
|
37
|
+
table: string;
|
|
38
|
+
count: number;
|
|
39
|
+
}
|
|
40
|
+
interface BackupManifest {
|
|
41
|
+
appChecksumObjectKey: string;
|
|
42
|
+
appEncryptedBytes: number;
|
|
43
|
+
appObjectKey: string;
|
|
44
|
+
appSchemas: string[];
|
|
45
|
+
appSha256: string;
|
|
46
|
+
appTableCounts: TableCount[];
|
|
47
|
+
authColumns: Record<AuthTable, Column[]>;
|
|
48
|
+
authChecksumObjectKey: string;
|
|
49
|
+
authEncryptedBytes: number;
|
|
50
|
+
authObjectKey: string;
|
|
51
|
+
authRowCounts: TableCount[];
|
|
52
|
+
authSha256: string;
|
|
53
|
+
authTables: AuthTable[];
|
|
54
|
+
cliVersion: string;
|
|
55
|
+
createdAt: string;
|
|
56
|
+
environment: string;
|
|
57
|
+
pgDumpVersion: string;
|
|
58
|
+
postgresServerVersion: string;
|
|
59
|
+
}
|
|
60
|
+
/** Generates immutable object names for one UTC backup timestamp. */
|
|
61
|
+
declare function backupObjectKeys(prefix: string, createdAt: Date): Record<'app' | 'auth' | 'appChecksum' | 'authChecksum' | 'manifest', string>;
|
|
62
|
+
/** Rejects malformed manifests before they can guide a restore. */
|
|
63
|
+
declare function parseManifest(value: string): BackupManifest;
|
|
64
|
+
//#endregion
|
|
65
|
+
//#region src/process.d.ts
|
|
66
|
+
interface ProgramRunner {
|
|
67
|
+
run: (command: string, args: string[], options?: {
|
|
68
|
+
env?: NodeJS.ProcessEnv;
|
|
69
|
+
}) => Promise<string>;
|
|
70
|
+
}
|
|
71
|
+
//#endregion
|
|
72
|
+
//#region src/r2.d.ts
|
|
73
|
+
interface ObjectStore {
|
|
74
|
+
get: (key: string) => Promise<Uint8Array>;
|
|
75
|
+
has: (key: string) => Promise<boolean>;
|
|
76
|
+
list: (prefix: string) => Promise<string[]>;
|
|
77
|
+
putImmutable: (key: string, body: Uint8Array) => Promise<void>;
|
|
78
|
+
}
|
|
79
|
+
//#endregion
|
|
80
|
+
//#region src/backup.d.ts
|
|
81
|
+
/** Creates encrypted, immutable app/Auth archives and publishes their manifest last. */
|
|
82
|
+
declare function backup(env?: NodeJS.ProcessEnv, dependencies?: {
|
|
83
|
+
now?: Date;
|
|
84
|
+
runner?: ProgramRunner;
|
|
85
|
+
store?: ObjectStore;
|
|
86
|
+
}): Promise<BackupManifest>;
|
|
87
|
+
/** Implements backup with injected dependencies for deterministic tests. */
|
|
88
|
+
declare function backupWithConfig(config: BackupConfig, dependencies?: {
|
|
89
|
+
now?: Date;
|
|
90
|
+
runner?: ProgramRunner;
|
|
91
|
+
store?: ObjectStore;
|
|
92
|
+
}): Promise<BackupManifest>;
|
|
93
|
+
//#endregion
|
|
94
|
+
//#region src/database-url.d.ts
|
|
95
|
+
interface DatabaseConnection {
|
|
96
|
+
database: string;
|
|
97
|
+
host: string;
|
|
98
|
+
password: string;
|
|
99
|
+
port: string;
|
|
100
|
+
sslmode: string;
|
|
101
|
+
user: string;
|
|
102
|
+
}
|
|
103
|
+
/** Parses a PostgreSQL URL without retaining it in process arguments. */
|
|
104
|
+
declare function parseDatabaseUrl(value: string): DatabaseConnection;
|
|
105
|
+
/** Converts a parsed URL to the libpq environment passed to PostgreSQL tools. */
|
|
106
|
+
declare function toLibpqEnvironment(connection: DatabaseConnection): NodeJS.ProcessEnv;
|
|
107
|
+
/** Produces a non-secret target label used for typed restore confirmation. */
|
|
108
|
+
declare function databaseLabel(connection: DatabaseConnection): string;
|
|
109
|
+
/** Prevents a configured source database from also being used as a restore target. */
|
|
110
|
+
declare function ensureDifferentDatabases(source: DatabaseConnection | undefined, target: DatabaseConnection): void;
|
|
111
|
+
//#endregion
|
|
112
|
+
//#region src/errors.d.ts
|
|
113
|
+
/** Error whose message is safe to display from the CLI. */
|
|
114
|
+
declare class BackupError extends Error {
|
|
115
|
+
constructor(message: string);
|
|
116
|
+
}
|
|
117
|
+
//#endregion
|
|
118
|
+
//#region src/redact.d.ts
|
|
119
|
+
/** Removes connection strings, age identities, and common credential values from text. */
|
|
120
|
+
declare function redact(value: string): string;
|
|
121
|
+
//#endregion
|
|
122
|
+
//#region src/restore.d.ts
|
|
123
|
+
interface RestoreOptions {
|
|
124
|
+
apply: boolean;
|
|
125
|
+
confirmTarget?: string;
|
|
126
|
+
key: string;
|
|
127
|
+
}
|
|
128
|
+
/** Downloads, verifies, decrypts, and optionally restores a single manifest. */
|
|
129
|
+
declare function restore(options: RestoreOptions, env?: NodeJS.ProcessEnv, dependencies?: {
|
|
130
|
+
runner?: ProgramRunner;
|
|
131
|
+
store?: ObjectStore;
|
|
132
|
+
}): Promise<BackupManifest>;
|
|
133
|
+
//#endregion
|
|
134
|
+
//#region src/status.d.ts
|
|
135
|
+
interface BackupStatus {
|
|
136
|
+
ageHours: number;
|
|
137
|
+
manifest: BackupManifest;
|
|
138
|
+
manifestKey: string;
|
|
139
|
+
}
|
|
140
|
+
/** Finds the latest complete manifest and checks its referenced archives remain available. */
|
|
141
|
+
declare function getBackupStatus(prefix: string, store: ObjectStore, now?: Date): Promise<BackupStatus>;
|
|
142
|
+
/** Prints a machine-safe health result and fails when no recent valid backup exists. */
|
|
143
|
+
declare function status(maxAgeHours: number | undefined, env?: NodeJS.ProcessEnv): Promise<BackupStatus>;
|
|
144
|
+
//#endregion
|
|
145
|
+
export { BackupError, type BackupManifest, backup, backupObjectKeys, backupWithConfig, databaseLabel, ensureDifferentDatabases, getBackupStatus, loadBackupConfig, loadRestoreConfig, loadStatusConfig, parseDatabaseUrl, parseManifest, redact, restore, status, toLibpqEnvironment };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
const name = "supabase-backup";
|
|
1
|
+
import { a as backup, c as parseManifest, d as parseDatabaseUrl, f as toLibpqEnvironment, g as BackupError, h as loadStatusConfig, i as redact, l as databaseLabel, m as loadRestoreConfig, n as status, o as backupWithConfig, p as loadBackupConfig, r as restore, s as backupObjectKeys, t as getBackupStatus, u as ensureDifferentDatabases } from "./status-Ba7xyZV8.js";
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
export { name };
|
|
3
|
+
export { BackupError, backup, backupObjectKeys, backupWithConfig, databaseLabel, ensureDifferentDatabases, getBackupStatus, loadBackupConfig, loadRestoreConfig, loadStatusConfig, parseDatabaseUrl, parseManifest, redact, restore, status, toLibpqEnvironment };
|