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