@promptbook/cli 0.112.0-52 → 0.112.0-54

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.
@@ -15,7 +15,7 @@ export declare const BOOK_LANGUAGE_VERSION: string_semantic_version;
15
15
  export declare const PROMPTBOOK_ENGINE_VERSION: string_promptbook_version;
16
16
  /**
17
17
  * Represents the version string of the Promptbook engine.
18
- * It follows semantic versioning (e.g., `0.112.0-51`).
18
+ * It follows semantic versioning (e.g., `0.112.0-53`).
19
19
  *
20
20
  * @generated
21
21
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@promptbook/cli",
3
- "version": "0.112.0-52",
3
+ "version": "0.112.0-54",
4
4
  "description": "Promptbook: Create persistent AI agents that turn your company's scattered knowledge into action",
5
5
  "private": false,
6
6
  "sideEffects": false,
@@ -0,0 +1,58 @@
1
+ import { DatabaseError } from '../../../../src/errors/DatabaseError';
2
+ import type { DatabaseMigrationExecutionLockMode } from './acquireMigrationExecutionLock';
3
+ import type { MigratePrefixProgressStage } from './migratePrefix';
4
+ /**
5
+ * High-level migration stages used to explain where one migration run failed.
6
+ *
7
+ * @private internal utility of runDatabaseMigrations
8
+ */
9
+ export type DatabaseMigrationFailureStage = 'prepare-migration-plan' | 'connect-to-database' | 'acquire-migration-lock' | 'migrate-prefix';
10
+ /**
11
+ * Snapshot of migration-run state captured when an error escapes the runner.
12
+ *
13
+ * @private internal utility of runDatabaseMigrations
14
+ */
15
+ export type DatabaseMigrationFailureContext = {
16
+ /**
17
+ * The broad migration phase that was running when the error occurred.
18
+ */
19
+ stage: DatabaseMigrationFailureStage;
20
+ /**
21
+ * Requested `--only` migration targets before prefix expansion.
22
+ */
23
+ onlyTargets: ReadonlyArray<string> | null;
24
+ /**
25
+ * Resolved prefixes selected for the current run.
26
+ */
27
+ selectedPrefixes: ReadonlyArray<string>;
28
+ /**
29
+ * Number of SQL migration files discovered on disk.
30
+ */
31
+ totalMigrationFiles: number;
32
+ /**
33
+ * Current migration lock mode.
34
+ */
35
+ executionLockMode: DatabaseMigrationExecutionLockMode;
36
+ /**
37
+ * Current prefix being migrated, when already known.
38
+ */
39
+ currentPrefix?: string;
40
+ /**
41
+ * More detailed sub-step inside one prefix migration.
42
+ */
43
+ currentPrefixStage?: MigratePrefixProgressStage;
44
+ /**
45
+ * Current migration filename being applied, when already known.
46
+ */
47
+ currentMigrationFile?: string;
48
+ };
49
+ /**
50
+ * Creates one branded migration failure error enriched with migration context and PostgreSQL details.
51
+ *
52
+ * @param error - Original failure thrown by the migration runner.
53
+ * @param context - Snapshot of migration progress at the time of failure.
54
+ * @returns Branded migration error with copied PostgreSQL fields for downstream logging.
55
+ *
56
+ * @private internal utility of runDatabaseMigrations
57
+ */
58
+ export declare function createDatabaseMigrationFailureError(error: unknown, context: DatabaseMigrationFailureContext): DatabaseError;
@@ -38,6 +38,35 @@ export type MigratePrefixOptions = {
38
38
  * If true, print SQL before execution.
39
39
  */
40
40
  readonly logSqlStatements: boolean;
41
+ /**
42
+ * Optional observer notified about the current prefix migration sub-step.
43
+ */
44
+ readonly onProgress?: (progress: MigratePrefixProgress) => void;
45
+ };
46
+ /**
47
+ * Detailed prefix-migration stages used for richer error reporting.
48
+ *
49
+ * @private function of runDatabaseMigrations
50
+ */
51
+ export type MigratePrefixProgressStage = 'ensure-migrations-table-schema' | 'read-applied-migrations' | 'apply-migration-file' | 'record-applied-migration';
52
+ /**
53
+ * Progress snapshot emitted while one prefix is being migrated.
54
+ *
55
+ * @private function of runDatabaseMigrations
56
+ */
57
+ export type MigratePrefixProgress = {
58
+ /**
59
+ * Prefix currently being migrated.
60
+ */
61
+ readonly prefix: string;
62
+ /**
63
+ * Detailed migration sub-step.
64
+ */
65
+ readonly stage: MigratePrefixProgressStage;
66
+ /**
67
+ * Migration file currently being applied, when relevant.
68
+ */
69
+ readonly migrationFile?: string;
41
70
  };
42
71
  /**
43
72
  * Applies pending migrations for one prefix inside the current transaction.
package/umd/index.umd.js CHANGED
@@ -60,7 +60,7 @@
60
60
  * @generated
61
61
  * @see https://github.com/webgptorg/promptbook
62
62
  */
63
- const PROMPTBOOK_ENGINE_VERSION = '0.112.0-52';
63
+ const PROMPTBOOK_ENGINE_VERSION = '0.112.0-54';
64
64
  /**
65
65
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
66
66
  * Note: [šŸ’ž] Ignore a discrepancy between file name and entity name
@@ -42650,8 +42650,9 @@
42650
42650
  iconName = 'SquareArrowUpRight';
42651
42651
  }
42652
42652
  if (isVoidPseudoAgentReference(reference)) {
42653
- label = VOID_PSEUDO_AGENT_REFERENCE;
42653
+ label = VOID_PSEUDO_AGENT_REFERENCE; // <- {Void} label
42654
42654
  iconName = 'ShieldAlert';
42655
+ return null; // <- Note: Do not show `{Void}` in capabilities, it's only used for internal logic
42655
42656
  }
42656
42657
  return {
42657
42658
  type: 'inheritance',
@@ -46309,6 +46310,255 @@
46309
46310
  }
46310
46311
  }
46311
46312
 
46313
+ /**
46314
+ * Creates one branded migration failure error enriched with migration context and PostgreSQL details.
46315
+ *
46316
+ * @param error - Original failure thrown by the migration runner.
46317
+ * @param context - Snapshot of migration progress at the time of failure.
46318
+ * @returns Branded migration error with copied PostgreSQL fields for downstream logging.
46319
+ *
46320
+ * @private internal utility of runDatabaseMigrations
46321
+ */
46322
+ function createDatabaseMigrationFailureError(error, context) {
46323
+ const postgresLikeError = getPostgresLikeError(error);
46324
+ const message = _spaceTrim.spaceTrim(`
46325
+ Database migration failed while ${describeFailureStage(context.stage)}.
46326
+
46327
+ ${createDatabaseMigrationFailureDetails(context, error, postgresLikeError)}
46328
+ ${createDatabaseMigrationFailureHint(context, postgresLikeError)}
46329
+ `);
46330
+ const migrationError = new DatabaseError(message);
46331
+ if (error instanceof Error) {
46332
+ Object.defineProperty(migrationError, 'cause', {
46333
+ value: error,
46334
+ enumerable: false,
46335
+ configurable: true,
46336
+ writable: true,
46337
+ });
46338
+ }
46339
+ copyPostgresLikeErrorProperties(migrationError, postgresLikeError);
46340
+ return migrationError;
46341
+ }
46342
+ /**
46343
+ * Creates the detailed markdown block appended to the migration failure summary.
46344
+ *
46345
+ * @param context - Snapshot of migration progress.
46346
+ * @param error - Original failure.
46347
+ * @param postgresLikeError - PostgreSQL-flavored view of the original failure.
46348
+ * @returns Markdown details section.
46349
+ *
46350
+ * @private internal utility of runDatabaseMigrations
46351
+ */
46352
+ function createDatabaseMigrationFailureDetails(context, error, postgresLikeError) {
46353
+ const detailLines = [
46354
+ `- **Stage:** ${formatCode(describeFailureStage(context.stage))}`,
46355
+ `- **Execution lock mode:** ${formatCode(context.executionLockMode)}`,
46356
+ context.onlyTargets && context.onlyTargets.length > 0
46357
+ ? `- **Requested targets:** ${formatCodeList(context.onlyTargets)}`
46358
+ : null,
46359
+ context.selectedPrefixes.length > 0
46360
+ ? `- **Selected prefixes:** ${formatCodeList(context.selectedPrefixes.map(formatPrefixForLogs))}`
46361
+ : '- **Selected prefixes:** _not resolved yet_',
46362
+ context.totalMigrationFiles > 0
46363
+ ? `- **Migration files discovered:** ${formatCode(String(context.totalMigrationFiles))}`
46364
+ : null,
46365
+ context.currentPrefix !== undefined
46366
+ ? `- **Current prefix:** ${formatCode(formatPrefixForLogs(context.currentPrefix))}`
46367
+ : null,
46368
+ context.currentPrefixStage !== undefined
46369
+ ? `- **Current prefix step:** ${formatCode(describePrefixStage(context.currentPrefixStage))}`
46370
+ : null,
46371
+ context.currentMigrationFile
46372
+ ? `- **Current migration file:** ${formatCode(context.currentMigrationFile)}`
46373
+ : null,
46374
+ error instanceof Error ? `- **Original error:** ${formatCode(error.message)}` : `- **Original error:** ${formatCode(String(error))}`,
46375
+ (postgresLikeError === null || postgresLikeError === void 0 ? void 0 : postgresLikeError.code) ? `- **PostgreSQL code:** ${formatCode(postgresLikeError.code)}` : null,
46376
+ (postgresLikeError === null || postgresLikeError === void 0 ? void 0 : postgresLikeError.severity) ? `- **PostgreSQL severity:** ${formatCode(postgresLikeError.severity)}` : null,
46377
+ (postgresLikeError === null || postgresLikeError === void 0 ? void 0 : postgresLikeError.detail) ? `- **PostgreSQL detail:** ${formatCode(postgresLikeError.detail)}` : null,
46378
+ (postgresLikeError === null || postgresLikeError === void 0 ? void 0 : postgresLikeError.hint) ? `- **PostgreSQL hint:** ${formatCode(postgresLikeError.hint)}` : null,
46379
+ (postgresLikeError === null || postgresLikeError === void 0 ? void 0 : postgresLikeError.where) ? `- **PostgreSQL where:** ${formatCode(postgresLikeError.where)}` : null,
46380
+ (postgresLikeError === null || postgresLikeError === void 0 ? void 0 : postgresLikeError.schema) ? `- **PostgreSQL schema:** ${formatCode(postgresLikeError.schema)}` : null,
46381
+ (postgresLikeError === null || postgresLikeError === void 0 ? void 0 : postgresLikeError.table) ? `- **PostgreSQL table:** ${formatCode(postgresLikeError.table)}` : null,
46382
+ (postgresLikeError === null || postgresLikeError === void 0 ? void 0 : postgresLikeError.column) ? `- **PostgreSQL column:** ${formatCode(postgresLikeError.column)}` : null,
46383
+ (postgresLikeError === null || postgresLikeError === void 0 ? void 0 : postgresLikeError.constraint) ? `- **PostgreSQL constraint:** ${formatCode(postgresLikeError.constraint)}` : null,
46384
+ (postgresLikeError === null || postgresLikeError === void 0 ? void 0 : postgresLikeError.file) ? `- **PostgreSQL file:** ${formatCode(postgresLikeError.file)}` : null,
46385
+ (postgresLikeError === null || postgresLikeError === void 0 ? void 0 : postgresLikeError.line) ? `- **PostgreSQL line:** ${formatCode(postgresLikeError.line)}` : null,
46386
+ (postgresLikeError === null || postgresLikeError === void 0 ? void 0 : postgresLikeError.routine) ? `- **PostgreSQL routine:** ${formatCode(postgresLikeError.routine)}` : null,
46387
+ ].filter((detailLine) => detailLine !== null);
46388
+ return detailLines.join('\n');
46389
+ }
46390
+ /**
46391
+ * Creates extra actionable guidance for common migration failures.
46392
+ *
46393
+ * @param context - Snapshot of migration progress.
46394
+ * @param postgresLikeError - PostgreSQL-flavored view of the original failure.
46395
+ * @returns Optional markdown hint block.
46396
+ *
46397
+ * @private internal utility of runDatabaseMigrations
46398
+ */
46399
+ function createDatabaseMigrationFailureHint(context, postgresLikeError) {
46400
+ if (isMigrationLockStatementTimeout(context, postgresLikeError)) {
46401
+ return _spaceTrim.spaceTrim(`
46402
+ **Likely cause:** Another process is already running database migrations, so PostgreSQL kept this command blocked inside ${formatCode('pg_advisory_lock(...)')} until ${formatCode('statement_timeout')} canceled the wait.
46403
+
46404
+ **What to check next:**
46405
+ - Wait for the other migration to finish and rerun this command.
46406
+ - Inspect active PostgreSQL sessions holding the advisory migration lock.
46407
+ - Increase ${formatCode('statement_timeout')} for this manual migration session if the wait is expected.
46408
+ `);
46409
+ }
46410
+ return '';
46411
+ }
46412
+ /**
46413
+ * Detects the specific timeout caused by waiting on the shared migration advisory lock.
46414
+ *
46415
+ * @param context - Snapshot of migration progress.
46416
+ * @param postgresLikeError - PostgreSQL-flavored view of the original failure.
46417
+ * @returns `true` when the failure most likely came from timing out inside `pg_advisory_lock`.
46418
+ *
46419
+ * @private internal utility of runDatabaseMigrations
46420
+ */
46421
+ function isMigrationLockStatementTimeout(context, postgresLikeError) {
46422
+ if (context.stage !== 'acquire-migration-lock' || context.executionLockMode !== 'wait' || !postgresLikeError) {
46423
+ return false;
46424
+ }
46425
+ if (postgresLikeError.code === '57014') {
46426
+ return true;
46427
+ }
46428
+ return /statement timeout/i.test(postgresLikeError.message);
46429
+ }
46430
+ /**
46431
+ * Returns a human-readable description for one failure stage.
46432
+ *
46433
+ * @param stage - Raw failure stage.
46434
+ * @returns Human-readable stage description.
46435
+ *
46436
+ * @private internal utility of runDatabaseMigrations
46437
+ */
46438
+ function describeFailureStage(stage) {
46439
+ switch (stage) {
46440
+ case 'prepare-migration-plan':
46441
+ return 'preparing the migration plan';
46442
+ case 'connect-to-database':
46443
+ return 'connecting to the database';
46444
+ case 'acquire-migration-lock':
46445
+ return 'waiting for the migration execution lock';
46446
+ case 'migrate-prefix':
46447
+ return 'migrating one database prefix';
46448
+ }
46449
+ }
46450
+ /**
46451
+ * Returns a human-readable description for one prefix sub-step.
46452
+ *
46453
+ * @param stage - Raw prefix stage.
46454
+ * @returns Human-readable stage description.
46455
+ *
46456
+ * @private internal utility of runDatabaseMigrations
46457
+ */
46458
+ function describePrefixStage(stage) {
46459
+ switch (stage) {
46460
+ case 'ensure-migrations-table-schema':
46461
+ return 'ensuring the migrations table schema';
46462
+ case 'read-applied-migrations':
46463
+ return 'reading already-applied migrations';
46464
+ case 'apply-migration-file':
46465
+ return 'executing a migration file';
46466
+ case 'record-applied-migration':
46467
+ return 'recording an applied migration file';
46468
+ }
46469
+ }
46470
+ /**
46471
+ * Formats one prefix for logs while keeping the default namespace readable.
46472
+ *
46473
+ * @param prefix - Raw table prefix.
46474
+ * @returns Human-readable prefix label.
46475
+ *
46476
+ * @private internal utility of runDatabaseMigrations
46477
+ */
46478
+ function formatPrefixForLogs(prefix) {
46479
+ return prefix === '' ? '<default>' : prefix;
46480
+ }
46481
+ /**
46482
+ * Wraps one string as inline markdown code.
46483
+ *
46484
+ * @param value - Raw string value.
46485
+ * @returns Inline-code representation.
46486
+ *
46487
+ * @private internal utility of runDatabaseMigrations
46488
+ */
46489
+ function formatCode(value) {
46490
+ return `\`${value.replace(/`/g, '\\`')}\``;
46491
+ }
46492
+ /**
46493
+ * Formats a list of strings as inline-code items separated by commas.
46494
+ *
46495
+ * @param values - Values to format.
46496
+ * @returns Inline-code list.
46497
+ *
46498
+ * @private internal utility of runDatabaseMigrations
46499
+ */
46500
+ function formatCodeList(values) {
46501
+ return values.map(formatCode).join(', ');
46502
+ }
46503
+ /**
46504
+ * Narrows unknown failures to the PostgreSQL error shape when possible.
46505
+ *
46506
+ * @param error - Unknown failure value.
46507
+ * @returns PostgreSQL-like error object or `null`.
46508
+ *
46509
+ * @private internal utility of runDatabaseMigrations
46510
+ */
46511
+ function getPostgresLikeError(error) {
46512
+ if (!(error instanceof Error)) {
46513
+ return null;
46514
+ }
46515
+ return error;
46516
+ }
46517
+ /**
46518
+ * Copies useful PostgreSQL error properties onto the branded migration error.
46519
+ *
46520
+ * This keeps downstream logging compatible with the raw `pg` error shape.
46521
+ *
46522
+ * @param target - Branded migration error.
46523
+ * @param postgresLikeError - Original PostgreSQL-style error, when available.
46524
+ *
46525
+ * @private internal utility of runDatabaseMigrations
46526
+ */
46527
+ function copyPostgresLikeErrorProperties(target, postgresLikeError) {
46528
+ if (!postgresLikeError) {
46529
+ return;
46530
+ }
46531
+ const postgresFields = {
46532
+ code: postgresLikeError.code,
46533
+ severity: postgresLikeError.severity,
46534
+ detail: postgresLikeError.detail,
46535
+ hint: postgresLikeError.hint,
46536
+ position: postgresLikeError.position,
46537
+ internalPosition: postgresLikeError.internalPosition,
46538
+ internalQuery: postgresLikeError.internalQuery,
46539
+ where: postgresLikeError.where,
46540
+ schema: postgresLikeError.schema,
46541
+ table: postgresLikeError.table,
46542
+ column: postgresLikeError.column,
46543
+ dataType: postgresLikeError.dataType,
46544
+ constraint: postgresLikeError.constraint,
46545
+ file: postgresLikeError.file,
46546
+ line: postgresLikeError.line,
46547
+ routine: postgresLikeError.routine,
46548
+ };
46549
+ for (const [fieldName, fieldValue] of Object.entries(postgresFields)) {
46550
+ if (fieldValue === undefined) {
46551
+ continue;
46552
+ }
46553
+ Object.defineProperty(target, fieldName, {
46554
+ value: fieldValue,
46555
+ enumerable: true,
46556
+ configurable: true,
46557
+ writable: true,
46558
+ });
46559
+ }
46560
+ }
46561
+
46312
46562
  /**
46313
46563
  * Supported `_Server.environment` values.
46314
46564
  */
@@ -46505,14 +46755,23 @@
46505
46755
  * @private function of runDatabaseMigrations
46506
46756
  */
46507
46757
  async function applyPendingMigrationsForPrefix(options) {
46758
+ var _a, _b, _c, _d;
46508
46759
  const { readFile } = await importRuntimeModule('fs/promises');
46509
46760
  const migrationsTableName = `${options.prefix}Migrations`;
46510
46761
  const migrationsTableIdentifier = quoteIdentifier$1(migrationsTableName);
46762
+ (_a = options.onProgress) === null || _a === void 0 ? void 0 : _a.call(options, {
46763
+ prefix: options.prefix,
46764
+ stage: 'ensure-migrations-table-schema',
46765
+ });
46511
46766
  await ensureMigrationsTableSchema({
46512
46767
  client: options.client,
46513
46768
  migrationsTableIdentifier,
46514
46769
  manualAppliedByDefault: options.manualAppliedByDefault,
46515
46770
  });
46771
+ (_b = options.onProgress) === null || _b === void 0 ? void 0 : _b.call(options, {
46772
+ prefix: options.prefix,
46773
+ stage: 'read-applied-migrations',
46774
+ });
46516
46775
  const { rows } = await options.client.query(`SELECT "filename" FROM ${migrationsTableIdentifier}`);
46517
46776
  const appliedMigrations = new Set(rows.map((row) => row.filename));
46518
46777
  let appliedCount = 0;
@@ -46522,11 +46781,21 @@
46522
46781
  }
46523
46782
  const migrationFilePath = `${options.migrationsDirectory}/${migrationFile}`;
46524
46783
  options.logger.info(` šŸ”¼ Applying ${migrationFilePath.split('\\').join('/')}...`);
46784
+ (_c = options.onProgress) === null || _c === void 0 ? void 0 : _c.call(options, {
46785
+ prefix: options.prefix,
46786
+ stage: 'apply-migration-file',
46787
+ migrationFile,
46788
+ });
46525
46789
  const sql = (await readFile(migrationFilePath, 'utf-8')).replace(/prefix_/g, options.prefix);
46526
46790
  if (options.logSqlStatements) {
46527
46791
  options.logger.info(sql);
46528
46792
  }
46529
46793
  await options.client.query(sql);
46794
+ (_d = options.onProgress) === null || _d === void 0 ? void 0 : _d.call(options, {
46795
+ prefix: options.prefix,
46796
+ stage: 'record-applied-migration',
46797
+ migrationFile,
46798
+ });
46530
46799
  await options.client.query(`INSERT INTO ${migrationsTableIdentifier} ("filename", "appliedBy") VALUES ($1, $2)`, [migrationFile, options.appliedBy]);
46531
46800
  appliedCount++;
46532
46801
  options.logger.info(` āœ… Applied ${migrationFile}`);
@@ -46813,24 +47082,41 @@
46813
47082
  * @returns Aggregated migration summary.
46814
47083
  */
46815
47084
  async function runDatabaseMigrations(options) {
46816
- var _a, _b, _c, _d, _e;
47085
+ var _a, _b, _c, _d, _e, _f, _g;
46817
47086
  const logger = (_a = options.logger) !== null && _a !== void 0 ? _a : console;
46818
- const selectedPrefixes = selectPrefixesForMigration(options.prefixes, (_b = options.registeredServers) !== null && _b !== void 0 ? _b : [], options.onlyTargets);
46819
- const migrationsDirectory = (_c = options.migrationsDirectory) !== null && _c !== void 0 ? _c : (await resolveMigrationsDirectory());
46820
- const migrationFiles = await readMigrationFiles(migrationsDirectory);
46821
- const totalMigrationFiles = migrationFiles.length;
47087
+ const failureContext = {
47088
+ stage: 'prepare-migration-plan',
47089
+ onlyTargets: (_b = options.onlyTargets) !== null && _b !== void 0 ? _b : null,
47090
+ selectedPrefixes: [],
47091
+ totalMigrationFiles: 0,
47092
+ executionLockMode: (_c = options.executionLockMode) !== null && _c !== void 0 ? _c : 'wait',
47093
+ };
46822
47094
  const perPrefix = [];
46823
- logger.info(`šŸ“‚ Found ${totalMigrationFiles} migration files`);
46824
- logger.info(`šŸ“‹ Found ${selectedPrefixes.length} prefixes to migrate: ${selectedPrefixes
46825
- .map((prefix) => prefix || '<default>')
46826
- .join(', ')}`);
46827
- const client = await createPostgresClient(options.connectionString);
47095
+ let client = null;
47096
+ let selectedPrefixes = [];
47097
+ let totalMigrationFiles = 0;
46828
47098
  let hasExecutionLock = false;
46829
47099
  let isSkippedDueToActiveMigrationLock = false;
47100
+ let migrationFailure = null;
47101
+ let migrationsDirectory = '';
47102
+ let migrationFiles = [];
46830
47103
  try {
47104
+ selectedPrefixes = selectPrefixesForMigration(options.prefixes, (_d = options.registeredServers) !== null && _d !== void 0 ? _d : [], options.onlyTargets);
47105
+ failureContext.selectedPrefixes = selectedPrefixes;
47106
+ migrationsDirectory = (_e = options.migrationsDirectory) !== null && _e !== void 0 ? _e : (await resolveMigrationsDirectory());
47107
+ migrationFiles = await readMigrationFiles(migrationsDirectory);
47108
+ totalMigrationFiles = migrationFiles.length;
47109
+ failureContext.totalMigrationFiles = totalMigrationFiles;
47110
+ logger.info(`šŸ“‚ Found ${totalMigrationFiles} migration files`);
47111
+ logger.info(`šŸ“‹ Found ${selectedPrefixes.length} prefixes to migrate: ${selectedPrefixes
47112
+ .map((prefix) => prefix || '<default>')
47113
+ .join(', ')}`);
47114
+ failureContext.stage = 'connect-to-database';
47115
+ client = await createPostgresClient(options.connectionString);
46831
47116
  await client.connect();
46832
47117
  logger.info('šŸ”Œ Connected to database');
46833
- hasExecutionLock = await acquireMigrationExecutionLock(client, logger, (_d = options.executionLockMode) !== null && _d !== void 0 ? _d : 'wait');
47118
+ failureContext.stage = 'acquire-migration-lock';
47119
+ hasExecutionLock = await acquireMigrationExecutionLock(client, logger, (_f = options.executionLockMode) !== null && _f !== void 0 ? _f : 'wait');
46834
47120
  if (!hasExecutionLock) {
46835
47121
  isSkippedDueToActiveMigrationLock = true;
46836
47122
  return {
@@ -46841,6 +47127,10 @@
46841
47127
  };
46842
47128
  }
46843
47129
  for (const prefix of selectedPrefixes) {
47130
+ failureContext.stage = 'migrate-prefix';
47131
+ failureContext.currentPrefix = prefix;
47132
+ failureContext.currentPrefixStage = undefined;
47133
+ failureContext.currentMigrationFile = undefined;
46844
47134
  logger.info(`\nšŸ—ļø Migrating prefix: "${prefix}"`);
46845
47135
  const appliedCount = await migratePrefix({
46846
47136
  prefix,
@@ -46850,23 +47140,45 @@
46850
47140
  logger,
46851
47141
  migrationFiles,
46852
47142
  migrationsDirectory,
46853
- logSqlStatements: (_e = options.logSqlStatements) !== null && _e !== void 0 ? _e : false,
47143
+ logSqlStatements: (_g = options.logSqlStatements) !== null && _g !== void 0 ? _g : false,
47144
+ onProgress: ({ prefix, stage, migrationFile }) => {
47145
+ failureContext.currentPrefix = prefix;
47146
+ failureContext.currentPrefixStage = stage;
47147
+ failureContext.currentMigrationFile = migrationFile;
47148
+ },
46854
47149
  });
46855
47150
  perPrefix.push({ prefix, appliedCount });
46856
47151
  }
47152
+ return {
47153
+ processedPrefixes: selectedPrefixes,
47154
+ totalMigrationFiles,
47155
+ perPrefix,
47156
+ isSkippedDueToActiveMigrationLock,
47157
+ };
47158
+ }
47159
+ catch (error) {
47160
+ migrationFailure = createDatabaseMigrationFailureError(error, failureContext);
46857
47161
  }
46858
47162
  finally {
46859
- if (hasExecutionLock) {
46860
- await releaseMigrationExecutionLock(client, logger);
47163
+ if (client) {
47164
+ if (hasExecutionLock) {
47165
+ await releaseMigrationExecutionLock(client, logger);
47166
+ }
47167
+ try {
47168
+ await client.end();
47169
+ }
47170
+ catch (clientEndError) {
47171
+ if (migrationFailure === null) {
47172
+ migrationFailure = clientEndError;
47173
+ }
47174
+ else {
47175
+ logger.warn('āš ļø Failed to close migration database connection');
47176
+ logger.warn(String(clientEndError));
47177
+ }
47178
+ }
46861
47179
  }
46862
- await client.end();
46863
47180
  }
46864
- return {
46865
- processedPrefixes: selectedPrefixes,
46866
- totalMigrationFiles,
46867
- perPrefix,
46868
- isSkippedDueToActiveMigrationLock,
46869
- };
47181
+ throw migrationFailure;
46870
47182
  }
46871
47183
  /**
46872
47184
  * Resolves PostgreSQL connection string from supported environment variables.