diff --git a/pgpm/cli/src/commands/export.ts b/pgpm/cli/src/commands/export.ts index e962dc5d3..b98e7dd3f 100644 --- a/pgpm/cli/src/commands/export.ts +++ b/pgpm/cli/src/commands/export.ts @@ -18,9 +18,11 @@ Options: --extensionName Extension name --metaExtensionName Meta extension name (default: svc) --cwd Working directory (default: current directory) + --clobber Overwrite existing deploy/revert/verify directories if module exists Examples: pgpm export Export migrations from selected database + pgpm export --clobber Export and overwrite existing module directories `; export default async ( @@ -139,7 +141,8 @@ export default async ( schema_names, outdir, extensionName, - metaExtensionName + metaExtensionName, + clobber: argv.clobber ?? false }); console.log(` diff --git a/pgpm/core/src/export/export-migrations.ts b/pgpm/core/src/export/export-migrations.ts index a5cb23c04..803a186f8 100644 --- a/pgpm/core/src/export/export-migrations.ts +++ b/pgpm/core/src/export/export-migrations.ts @@ -22,6 +22,7 @@ interface ExportMigrationsToDiskOptions { extensionDesc?: string; metaExtensionName: string; metaExtensionDesc?: string; + clobber?: boolean; } interface ExportOptions { @@ -39,6 +40,7 @@ interface ExportOptions { extensionDesc?: string; metaExtensionName: string; metaExtensionDesc?: string; + clobber?: boolean; } const exportMigrationsToDisk = async ({ @@ -53,7 +55,8 @@ const exportMigrationsToDisk = async ({ extensionName, extensionDesc, metaExtensionName, - metaExtensionDesc + metaExtensionDesc, + clobber = false }: ExportMigrationsToDiskOptions): Promise => { outdir = outdir + '/'; @@ -130,7 +133,8 @@ const exportMigrationsToDisk = async ({ 'pgpm-base32', 'pgpm-totp', 'pgpm-types' - ] + ], + clobber }); writePgpmPlan(results.rows, opts); @@ -153,7 +157,8 @@ const exportMigrationsToDisk = async ({ outdir, name: metaExtensionName, description: metaDesc, - extensions: ['plpgsql', 'db-meta-schema', 'db-meta-modules'] + extensions: ['plpgsql', 'db-meta-schema', 'db-meta-modules'], + clobber }); const metaReplacer = makeReplacer({ @@ -220,7 +225,8 @@ export const exportMigrations = async ({ extensionName, extensionDesc, metaExtensionName, - metaExtensionDesc + metaExtensionDesc, + clobber = false }: ExportOptions): Promise => { for (let v = 0; v < dbInfo.database_ids.length; v++) { const databaseId = dbInfo.database_ids[v]; @@ -236,7 +242,8 @@ export const exportMigrations = async ({ databaseId, schema_names, author, - outdir + outdir, + clobber }); } }; @@ -249,6 +256,7 @@ interface PreparePackageOptions { name: string; description: string; extensions: string[]; + clobber?: boolean; } interface Schema { @@ -268,6 +276,9 @@ interface ReplacerResult { /** * Creates a PGPM package directory or resets the deploy/revert/verify directories if it exists. + * + * @param clobber - If true, allows overwriting existing deploy/revert/verify directories. + * If false (default), throws an error if the module already exists. */ const preparePackage = async ({ project, @@ -275,7 +286,8 @@ const preparePackage = async ({ outdir, name, description, - extensions + extensions, + clobber = false }: PreparePackageOptions): Promise => { const curDir = process.cwd(); const pgpmDir = path.resolve(path.join(outdir, name)); @@ -297,6 +309,13 @@ const preparePackage = async ({ } }); } else { + if (!clobber) { + process.chdir(curDir); + throw new Error( + `Module "${name}" already exists at ${pgpmDir}. ` + + `Use --clobber flag to overwrite existing deploy/revert/verify directories.` + ); + } rmSync(path.resolve(pgpmDir, 'deploy'), { recursive: true, force: true }); rmSync(path.resolve(pgpmDir, 'revert'), { recursive: true, force: true }); rmSync(path.resolve(pgpmDir, 'verify'), { recursive: true, force: true });