wfu-migrate 0.1.1
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 +199 -0
- package/dist/commands/cleanup.d.ts +10 -0
- package/dist/commands/cleanup.d.ts.map +1 -0
- package/dist/commands/cleanup.js +231 -0
- package/dist/commands/cleanup.js.map +1 -0
- package/dist/commands/config.d.ts +15 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +285 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/doctor.d.ts +15 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +234 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/env-migrate.d.ts +37 -0
- package/dist/commands/env-migrate.d.ts.map +1 -0
- package/dist/commands/env-migrate.js +703 -0
- package/dist/commands/env-migrate.js.map +1 -0
- package/dist/commands/migrate.d.ts +19 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +374 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/compress.d.ts +86 -0
- package/dist/lib/compress.d.ts.map +1 -0
- package/dist/lib/compress.js +203 -0
- package/dist/lib/compress.js.map +1 -0
- package/dist/lib/config-manager.d.ts +34 -0
- package/dist/lib/config-manager.d.ts.map +1 -0
- package/dist/lib/config-manager.js +332 -0
- package/dist/lib/config-manager.js.map +1 -0
- package/dist/lib/database.d.ts +460 -0
- package/dist/lib/database.d.ts.map +1 -0
- package/dist/lib/database.js +1267 -0
- package/dist/lib/database.js.map +1 -0
- package/dist/lib/docker.d.ts +240 -0
- package/dist/lib/docker.d.ts.map +1 -0
- package/dist/lib/docker.js +653 -0
- package/dist/lib/docker.js.map +1 -0
- package/dist/lib/health.d.ts +99 -0
- package/dist/lib/health.d.ts.map +1 -0
- package/dist/lib/health.js +139 -0
- package/dist/lib/health.js.map +1 -0
- package/dist/lib/logger.d.ts +105 -0
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/logger.js +259 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/migration-engine.d.ts +130 -0
- package/dist/lib/migration-engine.d.ts.map +1 -0
- package/dist/lib/migration-engine.js +1175 -0
- package/dist/lib/migration-engine.js.map +1 -0
- package/dist/lib/parallel.d.ts +85 -0
- package/dist/lib/parallel.d.ts.map +1 -0
- package/dist/lib/parallel.js +138 -0
- package/dist/lib/parallel.js.map +1 -0
- package/dist/lib/progress.d.ts +101 -0
- package/dist/lib/progress.d.ts.map +1 -0
- package/dist/lib/progress.js +179 -0
- package/dist/lib/progress.js.map +1 -0
- package/dist/lib/prompt.d.ts +71 -0
- package/dist/lib/prompt.d.ts.map +1 -0
- package/dist/lib/prompt.js +116 -0
- package/dist/lib/prompt.js.map +1 -0
- package/dist/lib/retry.d.ts +61 -0
- package/dist/lib/retry.d.ts.map +1 -0
- package/dist/lib/retry.js +136 -0
- package/dist/lib/retry.js.map +1 -0
- package/dist/lib/s3.d.ts +238 -0
- package/dist/lib/s3.d.ts.map +1 -0
- package/dist/lib/s3.js +507 -0
- package/dist/lib/s3.js.map +1 -0
- package/dist/lib/serialized.d.ts +114 -0
- package/dist/lib/serialized.d.ts.map +1 -0
- package/dist/lib/serialized.js +236 -0
- package/dist/lib/serialized.js.map +1 -0
- package/dist/lib/shutdown.d.ts +78 -0
- package/dist/lib/shutdown.d.ts.map +1 -0
- package/dist/lib/shutdown.js +153 -0
- package/dist/lib/shutdown.js.map +1 -0
- package/dist/lib/site-filter.d.ts +98 -0
- package/dist/lib/site-filter.d.ts.map +1 -0
- package/dist/lib/site-filter.js +213 -0
- package/dist/lib/site-filter.js.map +1 -0
- package/dist/lib/spinner.d.ts +174 -0
- package/dist/lib/spinner.d.ts.map +1 -0
- package/dist/lib/spinner.js +273 -0
- package/dist/lib/spinner.js.map +1 -0
- package/dist/lib/state.d.ts +363 -0
- package/dist/lib/state.d.ts.map +1 -0
- package/dist/lib/state.js +905 -0
- package/dist/lib/state.js.map +1 -0
- package/dist/lib/system.d.ts +227 -0
- package/dist/lib/system.d.ts.map +1 -0
- package/dist/lib/system.js +636 -0
- package/dist/lib/system.js.map +1 -0
- package/dist/lib/url-patterns.d.ts +46 -0
- package/dist/lib/url-patterns.d.ts.map +1 -0
- package/dist/lib/url-patterns.js +259 -0
- package/dist/lib/url-patterns.js.map +1 -0
- package/dist/lib/wp-tables.d.ts +139 -0
- package/dist/lib/wp-tables.d.ts.map +1 -0
- package/dist/lib/wp-tables.js +296 -0
- package/dist/lib/wp-tables.js.map +1 -0
- package/dist/types/index.d.ts +96 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +46 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prompt utilities for WFU-Migrate
|
|
3
|
+
*
|
|
4
|
+
* Handles:
|
|
5
|
+
* - Confirmation prompts for destructive operations
|
|
6
|
+
* - Migration summary display
|
|
7
|
+
* - Interactive user input
|
|
8
|
+
* - Terminal bell for attention-grabbing prompts
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* ASCII BEL character for terminal bell.
|
|
12
|
+
* Produces an audible alert when output to terminal.
|
|
13
|
+
*/
|
|
14
|
+
export declare const TERMINAL_BELL = "\u0007";
|
|
15
|
+
/**
|
|
16
|
+
* Ring the terminal bell.
|
|
17
|
+
* Outputs the BEL character to stdout.
|
|
18
|
+
*/
|
|
19
|
+
export declare function ringBell(output?: NodeJS.WritableStream): void;
|
|
20
|
+
/**
|
|
21
|
+
* Build a prompt message with terminal bell prefix.
|
|
22
|
+
* The bell sounds immediately when the message is displayed.
|
|
23
|
+
*/
|
|
24
|
+
export declare function withBell(message: string): string;
|
|
25
|
+
export interface MigrationSummary {
|
|
26
|
+
siteId: number;
|
|
27
|
+
siteName: string;
|
|
28
|
+
source: string;
|
|
29
|
+
target: string;
|
|
30
|
+
tableCount: number;
|
|
31
|
+
estimatedSize?: string;
|
|
32
|
+
fileSync?: boolean;
|
|
33
|
+
backupTarget?: boolean;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Format a migration summary for display.
|
|
37
|
+
*/
|
|
38
|
+
export declare function formatMigrationSummary(summary: MigrationSummary): string;
|
|
39
|
+
/**
|
|
40
|
+
* Build the confirmation prompt message.
|
|
41
|
+
* Includes terminal bell to alert user that confirmation is needed.
|
|
42
|
+
*/
|
|
43
|
+
export declare function buildConfirmationMessage(summary: MigrationSummary, includeBell?: boolean): string;
|
|
44
|
+
export interface ConfirmationResult {
|
|
45
|
+
confirmed: boolean;
|
|
46
|
+
response?: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Prompt for confirmation (async).
|
|
50
|
+
* Returns true if user confirms, false otherwise.
|
|
51
|
+
*/
|
|
52
|
+
export declare function confirmMigration(summary: MigrationSummary, input?: NodeJS.ReadableStream, output?: NodeJS.WritableStream): Promise<ConfirmationResult>;
|
|
53
|
+
/**
|
|
54
|
+
* Parse user confirmation response.
|
|
55
|
+
* Returns true for 'y', 'yes', 'Y', 'YES', etc.
|
|
56
|
+
*/
|
|
57
|
+
export declare function parseConfirmation(response: string): boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Check if running in interactive mode.
|
|
60
|
+
* Returns false if stdin is not a TTY (e.g., piped input).
|
|
61
|
+
*/
|
|
62
|
+
export declare function isInteractive(): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Build the abort message when user declines.
|
|
65
|
+
*/
|
|
66
|
+
export declare function buildAbortMessage(): string;
|
|
67
|
+
/**
|
|
68
|
+
* Build the proceed message when user confirms.
|
|
69
|
+
*/
|
|
70
|
+
export declare function buildProceedMessage(summary: MigrationSummary): string;
|
|
71
|
+
//# sourceMappingURL=prompt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/lib/prompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH;;;GAGG;AACH,eAAO,MAAM,aAAa,WAAS,CAAC;AAEpC;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,MAAM,GAAE,MAAM,CAAC,cAA+B,GAAG,IAAI,CAE7E;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,CAyBxE;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,gBAAgB,EAAE,WAAW,GAAE,OAAc,GAAG,MAAM,CAIvG;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,gBAAgB,EACzB,KAAK,GAAE,MAAM,CAAC,cAA8B,EAC5C,MAAM,GAAE,MAAM,CAAC,cAA+B,GAC7C,OAAO,CAAC,kBAAkB,CAAC,CAgB7B;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAG3D;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,CAErE"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prompt utilities for WFU-Migrate
|
|
3
|
+
*
|
|
4
|
+
* Handles:
|
|
5
|
+
* - Confirmation prompts for destructive operations
|
|
6
|
+
* - Migration summary display
|
|
7
|
+
* - Interactive user input
|
|
8
|
+
* - Terminal bell for attention-grabbing prompts
|
|
9
|
+
*/
|
|
10
|
+
import { createInterface } from 'readline';
|
|
11
|
+
/**
|
|
12
|
+
* ASCII BEL character for terminal bell.
|
|
13
|
+
* Produces an audible alert when output to terminal.
|
|
14
|
+
*/
|
|
15
|
+
export const TERMINAL_BELL = '\x07';
|
|
16
|
+
/**
|
|
17
|
+
* Ring the terminal bell.
|
|
18
|
+
* Outputs the BEL character to stdout.
|
|
19
|
+
*/
|
|
20
|
+
export function ringBell(output = process.stdout) {
|
|
21
|
+
output.write(TERMINAL_BELL);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Build a prompt message with terminal bell prefix.
|
|
25
|
+
* The bell sounds immediately when the message is displayed.
|
|
26
|
+
*/
|
|
27
|
+
export function withBell(message) {
|
|
28
|
+
return TERMINAL_BELL + message;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Format a migration summary for display.
|
|
32
|
+
*/
|
|
33
|
+
export function formatMigrationSummary(summary) {
|
|
34
|
+
const lines = [
|
|
35
|
+
'',
|
|
36
|
+
'╔══════════════════════════════════════════════════════════════════╗',
|
|
37
|
+
'║ MIGRATION SUMMARY ║',
|
|
38
|
+
'╠══════════════════════════════════════════════════════════════════╣',
|
|
39
|
+
`║ Site: ${summary.siteName} (ID: ${summary.siteId})`.padEnd(68) + '║',
|
|
40
|
+
`║ Source: ${summary.source.toUpperCase()}`.padEnd(68) + '║',
|
|
41
|
+
`║ Target: ${summary.target.toUpperCase()}`.padEnd(68) + '║',
|
|
42
|
+
`║ Tables: ${summary.tableCount} tables`.padEnd(68) + '║',
|
|
43
|
+
];
|
|
44
|
+
if (summary.estimatedSize) {
|
|
45
|
+
lines.push(`║ Est. Size: ${summary.estimatedSize}`.padEnd(68) + '║');
|
|
46
|
+
}
|
|
47
|
+
if (summary.fileSync !== undefined) {
|
|
48
|
+
lines.push(`║ File Sync: ${summary.fileSync ? 'Yes' : 'No'}`.padEnd(68) + '║');
|
|
49
|
+
}
|
|
50
|
+
if (summary.backupTarget !== undefined) {
|
|
51
|
+
lines.push(`║ Backup: ${summary.backupTarget ? 'Yes' : 'No'}`.padEnd(68) + '║');
|
|
52
|
+
}
|
|
53
|
+
lines.push('╠══════════════════════════════════════════════════════════════════╣');
|
|
54
|
+
lines.push('║ WARNING: This will overwrite data in the target environment! ║');
|
|
55
|
+
lines.push('╚══════════════════════════════════════════════════════════════════╝');
|
|
56
|
+
lines.push('');
|
|
57
|
+
return lines.join('\n');
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Build the confirmation prompt message.
|
|
61
|
+
* Includes terminal bell to alert user that confirmation is needed.
|
|
62
|
+
*/
|
|
63
|
+
export function buildConfirmationMessage(summary, includeBell = true) {
|
|
64
|
+
const prompt = formatMigrationSummary(summary) +
|
|
65
|
+
`Proceed with migration from ${summary.source.toUpperCase()} to ${summary.target.toUpperCase()}? (y/n): `;
|
|
66
|
+
return includeBell ? withBell(prompt) : prompt;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Prompt for confirmation (async).
|
|
70
|
+
* Returns true if user confirms, false otherwise.
|
|
71
|
+
*/
|
|
72
|
+
export async function confirmMigration(summary, input = process.stdin, output = process.stdout) {
|
|
73
|
+
return new Promise((resolve) => {
|
|
74
|
+
const rl = createInterface({
|
|
75
|
+
input,
|
|
76
|
+
output,
|
|
77
|
+
});
|
|
78
|
+
const message = buildConfirmationMessage(summary);
|
|
79
|
+
rl.question(message, (answer) => {
|
|
80
|
+
rl.close();
|
|
81
|
+
const normalized = answer.trim().toLowerCase();
|
|
82
|
+
resolve({
|
|
83
|
+
confirmed: normalized === 'y' || normalized === 'yes',
|
|
84
|
+
response: answer,
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Parse user confirmation response.
|
|
91
|
+
* Returns true for 'y', 'yes', 'Y', 'YES', etc.
|
|
92
|
+
*/
|
|
93
|
+
export function parseConfirmation(response) {
|
|
94
|
+
const normalized = response.trim().toLowerCase();
|
|
95
|
+
return normalized === 'y' || normalized === 'yes';
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Check if running in interactive mode.
|
|
99
|
+
* Returns false if stdin is not a TTY (e.g., piped input).
|
|
100
|
+
*/
|
|
101
|
+
export function isInteractive() {
|
|
102
|
+
return process.stdin.isTTY === true;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Build the abort message when user declines.
|
|
106
|
+
*/
|
|
107
|
+
export function buildAbortMessage() {
|
|
108
|
+
return '\nMigration aborted by user.\n';
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Build the proceed message when user confirms.
|
|
112
|
+
*/
|
|
113
|
+
export function buildProceedMessage(summary) {
|
|
114
|
+
return `\nStarting migration of ${summary.siteName} from ${summary.source} to ${summary.target}...\n`;
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/lib/prompt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retry utilities for WFU-Migrate
|
|
3
|
+
*
|
|
4
|
+
* Handles:
|
|
5
|
+
* - Exponential backoff delay calculation
|
|
6
|
+
* - Automatic retry of failed operations
|
|
7
|
+
* - Configurable max retries and delays
|
|
8
|
+
* - Error filtering for retryable errors
|
|
9
|
+
*/
|
|
10
|
+
export declare const DEFAULT_MAX_RETRIES = 3;
|
|
11
|
+
export declare const DEFAULT_INITIAL_DELAY_MS = 1000;
|
|
12
|
+
export declare const DEFAULT_MAX_DELAY_MS = 30000;
|
|
13
|
+
export declare const DEFAULT_BACKOFF_MULTIPLIER = 2;
|
|
14
|
+
export interface RetryOptions {
|
|
15
|
+
maxRetries: number;
|
|
16
|
+
initialDelayMs: number;
|
|
17
|
+
maxDelayMs: number;
|
|
18
|
+
backoffMultiplier: number;
|
|
19
|
+
onRetry?: (attempt: number, error: Error, delay: number) => void;
|
|
20
|
+
shouldRetryError?: (error: Error) => boolean;
|
|
21
|
+
}
|
|
22
|
+
export declare const DEFAULT_RETRY_OPTIONS: RetryOptions;
|
|
23
|
+
export declare const RETRYABLE_ERROR_CODES: readonly ["ECONNRESET", "ETIMEDOUT", "ECONNREFUSED", "ENOTFOUND", "EAI_AGAIN", "EPIPE", "ECONNABORTED", "ENETUNREACH", "EHOSTUNREACH"];
|
|
24
|
+
export interface BackoffOptions {
|
|
25
|
+
initialDelayMs: number;
|
|
26
|
+
backoffMultiplier: number;
|
|
27
|
+
maxDelayMs: number;
|
|
28
|
+
}
|
|
29
|
+
export declare function calculateBackoffDelay(attempt: number, options: BackoffOptions): number;
|
|
30
|
+
export interface RetryContext {
|
|
31
|
+
attempt: number;
|
|
32
|
+
maxRetries: number;
|
|
33
|
+
initialDelayMs: number;
|
|
34
|
+
maxDelayMs: number;
|
|
35
|
+
backoffMultiplier: number;
|
|
36
|
+
errors: string[];
|
|
37
|
+
startTime: number;
|
|
38
|
+
}
|
|
39
|
+
export declare function createRetryContext(options?: Partial<RetryOptions>): RetryContext;
|
|
40
|
+
export declare function shouldRetry(ctx: RetryContext): boolean;
|
|
41
|
+
export declare function getNextDelay(ctx: RetryContext): number;
|
|
42
|
+
export declare function isRetryableError(error: Error): boolean;
|
|
43
|
+
export declare function formatRetryMessage(attempt: number, maxRetries: number, delayMs: number): string;
|
|
44
|
+
export interface RetryResult<T> {
|
|
45
|
+
success: boolean;
|
|
46
|
+
value?: T;
|
|
47
|
+
attempts: number;
|
|
48
|
+
errors: string[];
|
|
49
|
+
totalTimeMs: number;
|
|
50
|
+
}
|
|
51
|
+
export declare function withRetry<T>(operation: () => Promise<T>, options?: Partial<RetryOptions>): Promise<RetryResult<T>>;
|
|
52
|
+
export interface RetryStats {
|
|
53
|
+
totalAttempts: number;
|
|
54
|
+
successfulAttempts: number;
|
|
55
|
+
failedAttempts: number;
|
|
56
|
+
totalDelayMs: number;
|
|
57
|
+
}
|
|
58
|
+
export declare function createRetryStats(): RetryStats;
|
|
59
|
+
export declare function updateRetryStats(stats: RetryStats, result: RetryResult<unknown>): void;
|
|
60
|
+
export declare function formatRetryStats(stats: RetryStats): string;
|
|
61
|
+
//# sourceMappingURL=retry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/lib/retry.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,mBAAmB,IAAI,CAAC;AACrC,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAC7C,eAAO,MAAM,oBAAoB,QAAQ,CAAC;AAC1C,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAE5C,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjE,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC;CAC9C;AAED,eAAO,MAAM,qBAAqB,EAAE,YAKnC,CAAC;AAEF,eAAO,MAAM,qBAAqB,wIAUxB,CAAC;AAEX,MAAM,WAAW,cAAc;IAC7B,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,MAAM,CAGtF;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,kBAAkB,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY,CAUhF;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAEtD;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CAMtD;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAItD;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAE/F;AAED,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,CAAC,CAAC;IACV,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAMD,wBAAsB,SAAS,CAAC,CAAC,EAC/B,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAC3B,OAAO,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAC9B,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CA0CzB;AAED,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,gBAAgB,IAAI,UAAU,CAO7C;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,GAAG,IAAI,CAQtF;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAK1D"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retry utilities for WFU-Migrate
|
|
3
|
+
*
|
|
4
|
+
* Handles:
|
|
5
|
+
* - Exponential backoff delay calculation
|
|
6
|
+
* - Automatic retry of failed operations
|
|
7
|
+
* - Configurable max retries and delays
|
|
8
|
+
* - Error filtering for retryable errors
|
|
9
|
+
*/
|
|
10
|
+
export const DEFAULT_MAX_RETRIES = 3;
|
|
11
|
+
export const DEFAULT_INITIAL_DELAY_MS = 1000;
|
|
12
|
+
export const DEFAULT_MAX_DELAY_MS = 30000;
|
|
13
|
+
export const DEFAULT_BACKOFF_MULTIPLIER = 2;
|
|
14
|
+
export const DEFAULT_RETRY_OPTIONS = {
|
|
15
|
+
maxRetries: DEFAULT_MAX_RETRIES,
|
|
16
|
+
initialDelayMs: DEFAULT_INITIAL_DELAY_MS,
|
|
17
|
+
maxDelayMs: DEFAULT_MAX_DELAY_MS,
|
|
18
|
+
backoffMultiplier: DEFAULT_BACKOFF_MULTIPLIER,
|
|
19
|
+
};
|
|
20
|
+
export const RETRYABLE_ERROR_CODES = [
|
|
21
|
+
'ECONNRESET',
|
|
22
|
+
'ETIMEDOUT',
|
|
23
|
+
'ECONNREFUSED',
|
|
24
|
+
'ENOTFOUND',
|
|
25
|
+
'EAI_AGAIN',
|
|
26
|
+
'EPIPE',
|
|
27
|
+
'ECONNABORTED',
|
|
28
|
+
'ENETUNREACH',
|
|
29
|
+
'EHOSTUNREACH',
|
|
30
|
+
];
|
|
31
|
+
export function calculateBackoffDelay(attempt, options) {
|
|
32
|
+
const delay = options.initialDelayMs * Math.pow(options.backoffMultiplier, attempt);
|
|
33
|
+
return Math.min(delay, options.maxDelayMs);
|
|
34
|
+
}
|
|
35
|
+
export function createRetryContext(options) {
|
|
36
|
+
return {
|
|
37
|
+
attempt: 0,
|
|
38
|
+
maxRetries: options?.maxRetries ?? DEFAULT_MAX_RETRIES,
|
|
39
|
+
initialDelayMs: options?.initialDelayMs ?? DEFAULT_INITIAL_DELAY_MS,
|
|
40
|
+
maxDelayMs: options?.maxDelayMs ?? DEFAULT_MAX_DELAY_MS,
|
|
41
|
+
backoffMultiplier: options?.backoffMultiplier ?? DEFAULT_BACKOFF_MULTIPLIER,
|
|
42
|
+
errors: [],
|
|
43
|
+
startTime: Date.now(),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
export function shouldRetry(ctx) {
|
|
47
|
+
return ctx.attempt < ctx.maxRetries;
|
|
48
|
+
}
|
|
49
|
+
export function getNextDelay(ctx) {
|
|
50
|
+
return calculateBackoffDelay(ctx.attempt, {
|
|
51
|
+
initialDelayMs: ctx.initialDelayMs,
|
|
52
|
+
backoffMultiplier: ctx.backoffMultiplier,
|
|
53
|
+
maxDelayMs: ctx.maxDelayMs,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
export function isRetryableError(error) {
|
|
57
|
+
const code = error.code;
|
|
58
|
+
if (!code)
|
|
59
|
+
return false;
|
|
60
|
+
return RETRYABLE_ERROR_CODES.includes(code);
|
|
61
|
+
}
|
|
62
|
+
export function formatRetryMessage(attempt, maxRetries, delayMs) {
|
|
63
|
+
return `Retry ${attempt}/${maxRetries} in ${delayMs}ms`;
|
|
64
|
+
}
|
|
65
|
+
function sleep(ms) {
|
|
66
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
67
|
+
}
|
|
68
|
+
export async function withRetry(operation, options) {
|
|
69
|
+
const opts = { ...DEFAULT_RETRY_OPTIONS, ...options };
|
|
70
|
+
const errors = [];
|
|
71
|
+
const startTime = Date.now();
|
|
72
|
+
let attempts = 0;
|
|
73
|
+
while (attempts <= opts.maxRetries) {
|
|
74
|
+
attempts++;
|
|
75
|
+
try {
|
|
76
|
+
const value = await operation();
|
|
77
|
+
return {
|
|
78
|
+
success: true,
|
|
79
|
+
value,
|
|
80
|
+
attempts,
|
|
81
|
+
errors,
|
|
82
|
+
totalTimeMs: Date.now() - startTime,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
const error = err;
|
|
87
|
+
errors.push(error.message);
|
|
88
|
+
if (attempts > opts.maxRetries) {
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
if (opts.shouldRetryError && !opts.shouldRetryError(error)) {
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
const delay = calculateBackoffDelay(attempts - 1, {
|
|
95
|
+
initialDelayMs: opts.initialDelayMs,
|
|
96
|
+
backoffMultiplier: opts.backoffMultiplier,
|
|
97
|
+
maxDelayMs: opts.maxDelayMs,
|
|
98
|
+
});
|
|
99
|
+
if (opts.onRetry) {
|
|
100
|
+
opts.onRetry(attempts, error, delay);
|
|
101
|
+
}
|
|
102
|
+
await sleep(delay);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
success: false,
|
|
107
|
+
attempts,
|
|
108
|
+
errors,
|
|
109
|
+
totalTimeMs: Date.now() - startTime,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
export function createRetryStats() {
|
|
113
|
+
return {
|
|
114
|
+
totalAttempts: 0,
|
|
115
|
+
successfulAttempts: 0,
|
|
116
|
+
failedAttempts: 0,
|
|
117
|
+
totalDelayMs: 0,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
export function updateRetryStats(stats, result) {
|
|
121
|
+
stats.totalAttempts += result.attempts;
|
|
122
|
+
if (result.success) {
|
|
123
|
+
stats.successfulAttempts++;
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
stats.failedAttempts++;
|
|
127
|
+
}
|
|
128
|
+
stats.totalDelayMs += result.totalTimeMs;
|
|
129
|
+
}
|
|
130
|
+
export function formatRetryStats(stats) {
|
|
131
|
+
const successRate = stats.totalAttempts > 0
|
|
132
|
+
? Math.round((stats.successfulAttempts / (stats.successfulAttempts + stats.failedAttempts)) * 100)
|
|
133
|
+
: 0;
|
|
134
|
+
return `Retries: ${stats.totalAttempts} attempts, ${successRate}% success rate`;
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/lib/retry.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/s3.d.ts
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* S3 utilities for WFU-Migrate
|
|
3
|
+
*
|
|
4
|
+
* Handles:
|
|
5
|
+
* - File sync between S3 buckets
|
|
6
|
+
* - Backup archival to S3
|
|
7
|
+
* - Metadata upload
|
|
8
|
+
*
|
|
9
|
+
* All operations use the configured AWS region from config.s3.region.
|
|
10
|
+
*
|
|
11
|
+
* AWS Authentication:
|
|
12
|
+
* The AWS CLI automatically handles authentication using the standard credential
|
|
13
|
+
* chain. Credentials can be provided via:
|
|
14
|
+
* 1. Environment variables: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY
|
|
15
|
+
* 2. AWS credentials file: ~/.aws/credentials
|
|
16
|
+
* 3. IAM role (when running on EC2)
|
|
17
|
+
*
|
|
18
|
+
* This module does NOT manage credentials - it relies on the AWS CLI's built-in
|
|
19
|
+
* credential resolution, which is the recommended approach.
|
|
20
|
+
*/
|
|
21
|
+
import type { S3Config, MigrationMetadata } from '../types/index.js';
|
|
22
|
+
export interface S3SyncResult {
|
|
23
|
+
success: boolean;
|
|
24
|
+
error?: string;
|
|
25
|
+
filesTransferred?: number;
|
|
26
|
+
}
|
|
27
|
+
export interface S3UploadResult {
|
|
28
|
+
success: boolean;
|
|
29
|
+
error?: string;
|
|
30
|
+
s3Path?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Build AWS CLI arguments with region and optional profile configuration.
|
|
34
|
+
* The region is passed using --region flag to ensure correct S3 endpoint is used.
|
|
35
|
+
* If a profile is specified, the --profile flag is added.
|
|
36
|
+
*/
|
|
37
|
+
export declare function buildAwsArgs(region: string, profile?: string, ...additionalArgs: string[]): string[];
|
|
38
|
+
/**
|
|
39
|
+
* Sync files from one S3 path to another.
|
|
40
|
+
* Used for syncing WordPress uploads between environments.
|
|
41
|
+
*/
|
|
42
|
+
export declare function s3Sync(config: S3Config, sourcePath: string, targetPath: string, options?: {
|
|
43
|
+
dryRun?: boolean;
|
|
44
|
+
delete?: boolean;
|
|
45
|
+
}): Promise<S3SyncResult>;
|
|
46
|
+
/**
|
|
47
|
+
* Upload a file to S3 with the configured region and profile.
|
|
48
|
+
*/
|
|
49
|
+
export declare function s3Upload(config: S3Config, localPath: string, s3Key: string): Promise<S3UploadResult>;
|
|
50
|
+
/**
|
|
51
|
+
* Upload migration metadata to S3.
|
|
52
|
+
*/
|
|
53
|
+
export declare function uploadMigrationMetadata(config: S3Config, metadata: MigrationMetadata, archivePath: string): Promise<S3UploadResult>;
|
|
54
|
+
/**
|
|
55
|
+
* Build the S3 archive path for a migration.
|
|
56
|
+
*/
|
|
57
|
+
export declare function buildArchivePath(siteName: string, siteId: number, source: string, target: string, timestamp: string): string;
|
|
58
|
+
/**
|
|
59
|
+
* Get the WordPress uploads S3 path for a site.
|
|
60
|
+
*/
|
|
61
|
+
export declare function getSiteUploadsPath(bucket: string, siteId: number): string;
|
|
62
|
+
/**
|
|
63
|
+
* Build S3 sync command arguments.
|
|
64
|
+
* Used for testing and dry-run previews.
|
|
65
|
+
*
|
|
66
|
+
* The --delete flag is critical for migrations to ensure:
|
|
67
|
+
* 1. Files deleted from source are removed from target
|
|
68
|
+
* 2. No orphaned files remain in target after migration
|
|
69
|
+
* 3. Target exactly mirrors source directory structure
|
|
70
|
+
*/
|
|
71
|
+
export declare function buildS3SyncArgs(region: string, profile: string | undefined, sourcePath: string, targetPath: string, options?: {
|
|
72
|
+
dryRun?: boolean;
|
|
73
|
+
delete?: boolean;
|
|
74
|
+
exclude?: string[];
|
|
75
|
+
}): string[];
|
|
76
|
+
/**
|
|
77
|
+
* Check if S3 sync args include --delete flag.
|
|
78
|
+
* This is critical for migrations to ensure extra files are removed.
|
|
79
|
+
*/
|
|
80
|
+
export declare function syncArgsIncludeDelete(args: string[]): boolean;
|
|
81
|
+
/**
|
|
82
|
+
* Build the source S3 path for a site's files.
|
|
83
|
+
* WordPress multisite stores files at: bucket/sites/{siteId}/
|
|
84
|
+
*/
|
|
85
|
+
export declare function buildSiteSourcePath(bucket: string, siteId: number): string;
|
|
86
|
+
/**
|
|
87
|
+
* Build the target S3 path for a site's files.
|
|
88
|
+
* Matches the same structure as source.
|
|
89
|
+
*/
|
|
90
|
+
export declare function buildSiteTargetPath(bucket: string, siteId: number): string;
|
|
91
|
+
/**
|
|
92
|
+
* Build S3 sync arguments for migrating a site's files.
|
|
93
|
+
* This syncs WordPress uploads from source bucket to target bucket.
|
|
94
|
+
*
|
|
95
|
+
* WordPress multisite file structure:
|
|
96
|
+
* - Main site (ID 1): bucket/uploads/
|
|
97
|
+
* - Subsites: bucket/sites/{siteId}/
|
|
98
|
+
*
|
|
99
|
+
* By default, --delete is used to ensure the target mirrors source exactly.
|
|
100
|
+
*/
|
|
101
|
+
export declare function buildSiteSyncArgs(region: string, profile: string | undefined, sourceBucket: string, targetBucket: string, siteId: number, options?: {
|
|
102
|
+
dryRun?: boolean;
|
|
103
|
+
delete?: boolean;
|
|
104
|
+
}): string[];
|
|
105
|
+
export interface SiteSyncResult {
|
|
106
|
+
success: boolean;
|
|
107
|
+
sourcePath?: string;
|
|
108
|
+
targetPath?: string;
|
|
109
|
+
filesTransferred?: number;
|
|
110
|
+
error?: string;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Sync a site's files from source bucket to target bucket.
|
|
114
|
+
* This is used during migration to copy WordPress uploads.
|
|
115
|
+
*
|
|
116
|
+
* @param config S3 configuration (region, profile)
|
|
117
|
+
* @param sourceBucket Source environment's S3 bucket
|
|
118
|
+
* @param targetBucket Target environment's S3 bucket
|
|
119
|
+
* @param siteId Site ID being migrated
|
|
120
|
+
*/
|
|
121
|
+
export declare function syncSiteFiles(config: S3Config, sourceBucket: string, targetBucket: string, siteId: number, options?: {
|
|
122
|
+
dryRun?: boolean;
|
|
123
|
+
}): Promise<SiteSyncResult>;
|
|
124
|
+
/**
|
|
125
|
+
* Archive file names used in S3 archival.
|
|
126
|
+
*/
|
|
127
|
+
export declare const ARCHIVE_FILES: {
|
|
128
|
+
readonly SOURCE_EXPORT: "source-export.sql.gz";
|
|
129
|
+
readonly TARGET_BACKUP: "target-backup.sql.gz";
|
|
130
|
+
readonly MIGRATED_EXPORT: "migrated-export.sql.gz";
|
|
131
|
+
readonly METADATA: "metadata.json";
|
|
132
|
+
};
|
|
133
|
+
export interface ArchiveFilesOptions {
|
|
134
|
+
siteName: string;
|
|
135
|
+
siteId: number;
|
|
136
|
+
source: string;
|
|
137
|
+
target: string;
|
|
138
|
+
timestamp: string;
|
|
139
|
+
sourceExportFile?: string;
|
|
140
|
+
targetBackupFile?: string;
|
|
141
|
+
migratedExportFile?: string;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Build the full S3 archive path for migration files.
|
|
145
|
+
* Format: s3://{bucket}/{prefix}/{siteName}-{siteId}-{source}-to-{target}-{timestamp}/
|
|
146
|
+
*/
|
|
147
|
+
export declare function buildArchiveS3Path(config: S3Config, options: ArchiveFilesOptions): string;
|
|
148
|
+
/**
|
|
149
|
+
* Get the S3 key for an archive file.
|
|
150
|
+
* Format: {prefix}/{archivePath}/{filename}
|
|
151
|
+
*/
|
|
152
|
+
export declare function getArchiveFileKey(prefix: string, archivePath: string, filename: string): string;
|
|
153
|
+
/**
|
|
154
|
+
* Build the list of files to archive.
|
|
155
|
+
* Returns array of { localPath, s3Key } pairs.
|
|
156
|
+
*/
|
|
157
|
+
export declare function buildArchiveFileList(config: S3Config, options: ArchiveFilesOptions): Array<{
|
|
158
|
+
localPath: string;
|
|
159
|
+
s3Key: string;
|
|
160
|
+
filename: string;
|
|
161
|
+
}>;
|
|
162
|
+
export interface ArchiveResult {
|
|
163
|
+
success: boolean;
|
|
164
|
+
archivePath?: string;
|
|
165
|
+
filesArchived?: number;
|
|
166
|
+
error?: string;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Create migration metadata object.
|
|
170
|
+
* This is saved as metadata.json in the S3 archive.
|
|
171
|
+
*/
|
|
172
|
+
export declare function createMigrationMetadata(siteId: number, siteName: string, source: string, target: string, timestamp: string, duration: number, files: string[], tablesCount: number, replacementsCount: number): MigrationMetadata;
|
|
173
|
+
/**
|
|
174
|
+
* Validate that metadata contains all required fields.
|
|
175
|
+
*/
|
|
176
|
+
export declare function isValidMetadata(metadata: unknown): metadata is MigrationMetadata;
|
|
177
|
+
/**
|
|
178
|
+
* Format metadata as JSON string for S3 upload.
|
|
179
|
+
*/
|
|
180
|
+
export declare function formatMetadataJson(metadata: MigrationMetadata): string;
|
|
181
|
+
/**
|
|
182
|
+
* Parse metadata JSON string.
|
|
183
|
+
*/
|
|
184
|
+
export declare function parseMetadataJson(json: string): MigrationMetadata | null;
|
|
185
|
+
/**
|
|
186
|
+
* Get the S3 key for the metadata file.
|
|
187
|
+
*/
|
|
188
|
+
export declare function getMetadataS3Key(prefix: string, archivePath: string): string;
|
|
189
|
+
/**
|
|
190
|
+
* S3 error codes that indicate permission issues.
|
|
191
|
+
*/
|
|
192
|
+
export declare const S3_PERMISSION_ERROR_CODES: readonly ["AccessDenied", "AccessDeniedException", "InvalidAccessKeyId", "SignatureDoesNotMatch", "ExpiredToken", "InvalidToken", "UnauthorizedAccess"];
|
|
193
|
+
/**
|
|
194
|
+
* S3 error codes that indicate connectivity issues.
|
|
195
|
+
*/
|
|
196
|
+
export declare const S3_CONNECTIVITY_ERROR_CODES: readonly ["NetworkingError", "TimeoutError", "RequestTimeout", "ConnectionReset"];
|
|
197
|
+
/**
|
|
198
|
+
* S3 error codes that indicate bucket/path issues.
|
|
199
|
+
*/
|
|
200
|
+
export declare const S3_BUCKET_ERROR_CODES: readonly ["NoSuchBucket", "NoSuchKey", "BucketNotFound"];
|
|
201
|
+
export type S3ErrorType = 'permission' | 'connectivity' | 'bucket' | 'unknown';
|
|
202
|
+
/**
|
|
203
|
+
* Check if an error message indicates a permission issue.
|
|
204
|
+
*/
|
|
205
|
+
export declare function isS3PermissionError(error: string): boolean;
|
|
206
|
+
/**
|
|
207
|
+
* Check if an error message indicates a connectivity issue.
|
|
208
|
+
*/
|
|
209
|
+
export declare function isS3ConnectivityError(error: string): boolean;
|
|
210
|
+
/**
|
|
211
|
+
* Check if an error message indicates a bucket/path issue.
|
|
212
|
+
*/
|
|
213
|
+
export declare function isS3BucketError(error: string): boolean;
|
|
214
|
+
/**
|
|
215
|
+
* Classify an S3 error by its type.
|
|
216
|
+
*/
|
|
217
|
+
export declare function classifyS3Error(error: string): S3ErrorType;
|
|
218
|
+
/**
|
|
219
|
+
* Format a user-friendly error message for S3 errors.
|
|
220
|
+
*/
|
|
221
|
+
export declare function formatS3ErrorMessage(error: string): string;
|
|
222
|
+
/**
|
|
223
|
+
* Build a helpful suggestion for S3 permission errors.
|
|
224
|
+
*/
|
|
225
|
+
export declare function buildS3PermissionHint(): string;
|
|
226
|
+
/**
|
|
227
|
+
* Archive migration SQL files to S3.
|
|
228
|
+
* Creates an archive directory with:
|
|
229
|
+
* - source-export.sql.gz (original export from source)
|
|
230
|
+
* - target-backup.sql.gz (backup of target before import)
|
|
231
|
+
* - migrated-export.sql.gz (transformed data that was imported)
|
|
232
|
+
* - metadata.json (migration details)
|
|
233
|
+
*
|
|
234
|
+
* @param config S3 configuration
|
|
235
|
+
* @param options Archive file paths and metadata
|
|
236
|
+
*/
|
|
237
|
+
export declare function archiveMigrationFiles(config: S3Config, options: ArchiveFilesOptions): Promise<ArchiveResult>;
|
|
238
|
+
//# sourceMappingURL=s3.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3.d.ts","sourceRoot":"","sources":["../../src/lib/s3.ts"],"names":[],"mappings":"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"}
|