From da34db00b021d0b6806d5e4c7c079ebf99bd5a02 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Fri, 26 Dec 2025 21:52:19 +0000 Subject: [PATCH 1/3] feat(pgpm): improve export command UX with smart defaults - Change databases and database_ids prompts from checkbox to list (single-select) - Fix selection bug that mapped all options instead of just selected ones - Update metaExtensionName default to be more descriptive (e.g., 'minimal-service') - Pass answers to initModule to skip boilerplate prompts (moduleName, moduleDesc, packageIdentifier, access) - Add smart descriptions for both db and meta extension packages - Add databaseName to dbInfo for better description generation --- pgpm/cli/src/commands/export.ts | 33 ++++++++----------- pgpm/core/src/export/export-migrations.ts | 40 ++++++++++++++++++++--- 2 files changed, 48 insertions(+), 25 deletions(-) diff --git a/pgpm/cli/src/commands/export.ts b/pgpm/cli/src/commands/export.ts index 3173cb6c7..e962dc5d3 100644 --- a/pgpm/cli/src/commands/export.ts +++ b/pgpm/cli/src/commands/export.ts @@ -1,7 +1,7 @@ import { exportMigrations,PgpmPackage } from '@pgpmjs/core'; import { getEnvOptions } from '@pgpmjs/env'; import { getGitConfigInfo } from '@pgpmjs/types'; -import { CLIOptions, Inquirerer, OptionValue } from 'inquirerer'; +import { CLIOptions, Inquirerer } from 'inquirerer'; import { resolve } from 'path'; import { getPgPool } from 'pg-cache'; @@ -52,18 +52,15 @@ export default async ( AND datname !~ '^pg_'; `); - let databases: OptionValue[]; - ({ databases } = await prompter.prompt(argv, [ + const { databases: dbname } = await prompter.prompt(argv, [ { - type: 'checkbox', + type: 'list', name: 'databases', message: 'Select a database', options: databasesResult.rows.map(row => row.datname), required: true } - ])); - - const dbname = databases.filter(d=>d.selected).map(d=>d.value)[0]; + ]); const selectedDb = await getPgPool({ database: dbname }); @@ -72,26 +69,22 @@ export default async ( SELECT id, name FROM collections_public.database; `); - let database_ids: OptionValue[]; - ({ database_ids } = await prompter.prompt({} as any, [ + const { database_ids: selectedDatabaseName } = await prompter.prompt({} as any, [ { - type: 'checkbox', + type: 'list', name: 'database_ids', - message: 'Select database_id(s)', + message: 'Select database_id', options: dbsResult.rows.map(db => db.name), required: true } - ])); + ]); - const selectedDatabaseNames = database_ids - .filter(did => did.selected) - .map(did => did.name); + const selectedDatabase = dbsResult.rows.find(db => db.name === selectedDatabaseName); const dbInfo = { dbname, - database_ids: database_ids.map(did => - dbsResult.rows.find(db => db.name === did.name)!.id - ) + databaseName: selectedDatabaseName, + database_ids: [selectedDatabase!.id] }; const { author, extensionName, metaExtensionName } = await prompter.prompt(argv, [ @@ -106,14 +99,14 @@ export default async ( type: 'text', name: 'extensionName', message: 'Extension name', - default: selectedDatabaseNames[0] || dbname, + default: selectedDatabaseName || dbname, required: true }, { type: 'text', name: 'metaExtensionName', message: 'Meta extension name', - default: 'svc', + default: `${selectedDatabaseName || dbname}-service`, required: true } ]); diff --git a/pgpm/core/src/export/export-migrations.ts b/pgpm/core/src/export/export-migrations.ts index ba7055f40..e31a20f06 100644 --- a/pgpm/core/src/export/export-migrations.ts +++ b/pgpm/core/src/export/export-migrations.ts @@ -14,11 +14,14 @@ interface ExportMigrationsToDiskOptions { options: PgpmOptions; database: string; databaseId: string; + databaseName: string; author: string; outdir: string; schema_names: string[]; extensionName?: string; + extensionDesc?: string; metaExtensionName: string; + metaExtensionDesc?: string; } interface ExportOptions { @@ -26,13 +29,16 @@ interface ExportOptions { options: PgpmOptions; dbInfo: { dbname: string; + databaseName: string; database_ids: string[]; }; author: string; outdir: string; schema_names: string[]; extensionName?: string; + extensionDesc?: string; metaExtensionName: string; + metaExtensionDesc?: string; } const exportMigrationsToDisk = async ({ @@ -40,11 +46,14 @@ const exportMigrationsToDisk = async ({ options, database, databaseId, + databaseName, author, outdir, schema_names, extensionName, - metaExtensionName + extensionDesc, + metaExtensionName, + metaExtensionDesc }: ExportMigrationsToDiskOptions): Promise => { outdir = outdir + '/'; @@ -93,12 +102,16 @@ const exportMigrationsToDisk = async ({ author }; + // Build description for the database extension package + const dbExtensionDesc = extensionDesc || `${name} database schema for ${databaseName}`; + if (results?.rows?.length > 0) { await preparePackage({ project, author, outdir, name, + description: dbExtensionDesc, extensions: [ 'plpgsql', 'uuid-ossp', @@ -131,12 +144,16 @@ const exportMigrationsToDisk = async ({ meta = replacer(meta); + // Build description for the meta/service extension package + const metaDesc = metaExtensionDesc || `${metaExtensionName} service utilities for managing domains, APIs, and services`; + await preparePackage({ project, author, outdir, - extensions: ['plpgsql', 'db-meta-schema', 'db-meta-modules'], - name: metaExtensionName + name: metaExtensionName, + description: metaDesc, + extensions: ['plpgsql', 'db-meta-schema', 'db-meta-modules'] }); const metaReplacer = makeReplacer({ @@ -197,7 +214,9 @@ export const exportMigrations = async ({ outdir, schema_names, extensionName, - metaExtensionName + extensionDesc, + metaExtensionName, + metaExtensionDesc }: ExportOptions): Promise => { for (let v = 0; v < dbInfo.database_ids.length; v++) { const databaseId = dbInfo.database_ids[v]; @@ -205,8 +224,11 @@ export const exportMigrations = async ({ project, options, extensionName, + extensionDesc, metaExtensionName, + metaExtensionDesc, database: dbInfo.dbname, + databaseName: dbInfo.databaseName, databaseId, schema_names, author, @@ -221,6 +243,7 @@ interface PreparePackageOptions { author: string; outdir: string; name: string; + description: string; extensions: string[]; } @@ -247,6 +270,7 @@ const preparePackage = async ({ author, outdir, name, + description, extensions }: PreparePackageOptions): Promise => { const curDir = process.cwd(); @@ -258,9 +282,15 @@ const preparePackage = async ({ if (!plan.length) { await project.initModule({ name, - description: name, + description, author, extensions, + answers: { + moduleName: name, + moduleDesc: description, + packageIdentifier: name, + access: 'public' + } }); } else { rmSync(path.resolve(sqitchDir, 'deploy'), { recursive: true, force: true }); From 3a0ba347a092869b718c120c4888a9fe5474a287 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Fri, 26 Dec 2025 22:09:18 +0000 Subject: [PATCH 2/3] fix(pgpm): change default access from 'public' to 'restricted' --- pgpm/core/src/export/export-migrations.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pgpm/core/src/export/export-migrations.ts b/pgpm/core/src/export/export-migrations.ts index e31a20f06..4d4f7a610 100644 --- a/pgpm/core/src/export/export-migrations.ts +++ b/pgpm/core/src/export/export-migrations.ts @@ -289,7 +289,7 @@ const preparePackage = async ({ moduleName: name, moduleDesc: description, packageIdentifier: name, - access: 'public' + access: 'restricted' } }); } else { From ad96963d265a3e4385b65289bbe910c99375c9c3 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Sat, 27 Dec 2025 00:45:15 +0000 Subject: [PATCH 3/3] fix(pgpm): remove packageIdentifier from answers (no longer required) --- pgpm/core/src/export/export-migrations.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/pgpm/core/src/export/export-migrations.ts b/pgpm/core/src/export/export-migrations.ts index 4d4f7a610..29f1e4c00 100644 --- a/pgpm/core/src/export/export-migrations.ts +++ b/pgpm/core/src/export/export-migrations.ts @@ -288,7 +288,6 @@ const preparePackage = async ({ answers: { moduleName: name, moduleDesc: description, - packageIdentifier: name, access: 'restricted' } });