@pgpmjs/core 4.6.3 → 4.7.0

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.
@@ -1,5 +1,5 @@
1
1
  import { Logger } from '@pgpmjs/logger';
2
- import { errors } from '@pgpmjs/types';
2
+ import { errors, extractPgErrorFields, formatPgError, formatPgErrorFields } from '@pgpmjs/types';
3
3
  import { readFileSync } from 'fs';
4
4
  import { dirname, join } from 'path';
5
5
  import { getPgPool } from 'pg-cache';
@@ -174,6 +174,14 @@ export class PgpmMigrate {
174
174
  errorLines.push(` Dependencies: ${qualifiedDeps && qualifiedDeps.length > 0 ? qualifiedDeps.join(', ') : 'none'}`);
175
175
  errorLines.push(` Error Code: ${error.code || 'N/A'}`);
176
176
  errorLines.push(` Error Message: ${error.message || 'N/A'}`);
177
+ // Add extended PostgreSQL error fields
178
+ const pgFields = extractPgErrorFields(error);
179
+ if (pgFields) {
180
+ const fieldLines = formatPgErrorFields(pgFields);
181
+ if (fieldLines.length > 0) {
182
+ fieldLines.forEach(line => errorLines.push(` ${line}`));
183
+ }
184
+ }
177
185
  // Show SQL script preview for debugging
178
186
  if (cleanDeploySql) {
179
187
  const sqlLines = cleanDeploySql.split('\n');
@@ -212,6 +220,12 @@ export class PgpmMigrate {
212
220
  // Log the consolidated error message
213
221
  log.error(errorLines.join('\n'));
214
222
  failed = change.name;
223
+ // Enhance the thrown error message with PostgreSQL extended fields
224
+ // This ensures callers get the same enhanced error format as PgTestClient
225
+ if (!error.__pgpmEnhanced) {
226
+ error.message = formatPgError(error);
227
+ error.__pgpmEnhanced = true;
228
+ }
215
229
  throw error; // Re-throw to trigger rollback if in transaction
216
230
  }
217
231
  // Stop if this was the target change
@@ -277,6 +291,11 @@ export class PgpmMigrate {
277
291
  });
278
292
  log.error(`Failed to revert ${change.name}:`, error);
279
293
  failed = change.name;
294
+ // Enhance the thrown error message with PostgreSQL extended fields
295
+ if (!error.__pgpmEnhanced) {
296
+ error.message = formatPgError(error);
297
+ error.__pgpmEnhanced = true;
298
+ }
280
299
  throw error; // Re-throw to trigger rollback if in transaction
281
300
  }
282
301
  }
@@ -53,6 +53,17 @@ CREATE PROCEDURE pgpm_migrate.deploy(
53
53
  LANGUAGE plpgsql AS $$
54
54
  DECLARE
55
55
  v_change_id TEXT;
56
+ -- Error diagnostic variables
57
+ v_sqlstate TEXT;
58
+ v_message TEXT;
59
+ v_detail TEXT;
60
+ v_hint TEXT;
61
+ v_context TEXT;
62
+ v_schema_name TEXT;
63
+ v_table_name TEXT;
64
+ v_column_name TEXT;
65
+ v_constraint_name TEXT;
66
+ v_datatype_name TEXT;
56
67
  BEGIN
57
68
  -- Ensure package exists
58
69
  CALL pgpm_migrate.register_package(p_package);
@@ -97,7 +108,30 @@ BEGIN
97
108
  BEGIN
98
109
  EXECUTE p_deploy_sql;
99
110
  EXCEPTION WHEN OTHERS THEN
100
- RAISE;
111
+ -- Capture all error diagnostics to preserve them in the re-raised exception
112
+ GET STACKED DIAGNOSTICS
113
+ v_sqlstate = RETURNED_SQLSTATE,
114
+ v_message = MESSAGE_TEXT,
115
+ v_detail = PG_EXCEPTION_DETAIL,
116
+ v_hint = PG_EXCEPTION_HINT,
117
+ v_context = PG_EXCEPTION_CONTEXT,
118
+ v_schema_name = SCHEMA_NAME,
119
+ v_table_name = TABLE_NAME,
120
+ v_column_name = COLUMN_NAME,
121
+ v_constraint_name = CONSTRAINT_NAME,
122
+ v_datatype_name = PG_DATATYPE_NAME;
123
+
124
+ -- Re-raise with all captured diagnostics preserved
125
+ RAISE EXCEPTION USING
126
+ ERRCODE = v_sqlstate,
127
+ MESSAGE = v_message,
128
+ DETAIL = v_detail,
129
+ HINT = v_hint,
130
+ SCHEMA = v_schema_name,
131
+ TABLE = v_table_name,
132
+ COLUMN = v_column_name,
133
+ CONSTRAINT = v_constraint_name,
134
+ DATATYPE = v_datatype_name;
101
135
  END;
102
136
  END IF;
103
137
 
@@ -124,6 +158,18 @@ CREATE PROCEDURE pgpm_migrate.revert(
124
158
  p_revert_sql TEXT
125
159
  )
126
160
  LANGUAGE plpgsql AS $$
161
+ DECLARE
162
+ -- Error diagnostic variables
163
+ v_sqlstate TEXT;
164
+ v_message TEXT;
165
+ v_detail TEXT;
166
+ v_hint TEXT;
167
+ v_context TEXT;
168
+ v_schema_name TEXT;
169
+ v_table_name TEXT;
170
+ v_column_name TEXT;
171
+ v_constraint_name TEXT;
172
+ v_datatype_name TEXT;
127
173
  BEGIN
128
174
  -- Check if deployed
129
175
  IF NOT pgpm_migrate.is_deployed(p_package, p_change_name) THEN
@@ -165,8 +211,35 @@ BEGIN
165
211
  END;
166
212
  END IF;
167
213
 
168
- -- Execute revert
169
- EXECUTE p_revert_sql;
214
+ -- Execute revert with error diagnostics preservation
215
+ BEGIN
216
+ EXECUTE p_revert_sql;
217
+ EXCEPTION WHEN OTHERS THEN
218
+ -- Capture all error diagnostics to preserve them in the re-raised exception
219
+ GET STACKED DIAGNOSTICS
220
+ v_sqlstate = RETURNED_SQLSTATE,
221
+ v_message = MESSAGE_TEXT,
222
+ v_detail = PG_EXCEPTION_DETAIL,
223
+ v_hint = PG_EXCEPTION_HINT,
224
+ v_context = PG_EXCEPTION_CONTEXT,
225
+ v_schema_name = SCHEMA_NAME,
226
+ v_table_name = TABLE_NAME,
227
+ v_column_name = COLUMN_NAME,
228
+ v_constraint_name = CONSTRAINT_NAME,
229
+ v_datatype_name = PG_DATATYPE_NAME;
230
+
231
+ -- Re-raise with all captured diagnostics preserved
232
+ RAISE EXCEPTION USING
233
+ ERRCODE = v_sqlstate,
234
+ MESSAGE = v_message,
235
+ DETAIL = v_detail,
236
+ HINT = v_hint,
237
+ SCHEMA = v_schema_name,
238
+ TABLE = v_table_name,
239
+ COLUMN = v_column_name,
240
+ CONSTRAINT = v_constraint_name,
241
+ DATATYPE = v_datatype_name;
242
+ END;
170
243
 
171
244
  -- Remove from deployed
172
245
  DELETE FROM pgpm_migrate.changes
@@ -1,4 +1,5 @@
1
1
  import { Logger } from '@pgpmjs/logger';
2
+ import { extractPgErrorFields, formatPgErrorFields } from '@pgpmjs/types';
2
3
  const log = new Logger('migrate:transaction');
3
4
  /**
4
5
  * Execute a function within a transaction context
@@ -51,6 +52,14 @@ export async function withTransaction(pool, options, fn) {
51
52
  errorLines.push(`Transaction rolled back due to error after ${transactionDuration}ms:`);
52
53
  errorLines.push(`Error Code: ${error.code || 'N/A'}`);
53
54
  errorLines.push(`Error Message: ${error.message || 'N/A'}`);
55
+ // Add extended PostgreSQL error fields
56
+ const pgFields = extractPgErrorFields(error);
57
+ if (pgFields) {
58
+ const fieldLines = formatPgErrorFields(pgFields);
59
+ if (fieldLines.length > 0) {
60
+ errorLines.push(...fieldLines);
61
+ }
62
+ }
54
63
  // Log query history for debugging
55
64
  if (queryHistory.length > 0) {
56
65
  errorLines.push('Query history for this transaction:');
@@ -101,10 +110,18 @@ export async function executeQuery(context, query, params) {
101
110
  errorLines.push(`Query failed after ${duration}ms:`);
102
111
  errorLines.push(` Query: ${query.split('\n')[0].trim()}`);
103
112
  if (params && params.length > 0) {
104
- errorLines.push(` Params: ${JSON.stringify(params.slice(0, 3))}${params.length > 3 ? '...' : ''}`);
113
+ errorLines.push(` Params: ${JSON.stringify(params)}`);
105
114
  }
106
115
  errorLines.push(` Error Code: ${error.code || 'N/A'}`);
107
116
  errorLines.push(` Error Message: ${error.message || 'N/A'}`);
117
+ // Add extended PostgreSQL error fields
118
+ const pgFields = extractPgErrorFields(error);
119
+ if (pgFields) {
120
+ const fieldLines = formatPgErrorFields(pgFields);
121
+ if (fieldLines.length > 0) {
122
+ fieldLines.forEach(line => errorLines.push(` ${line}`));
123
+ }
124
+ }
108
125
  // Provide debugging hints for common errors
109
126
  if (error.code === '42P01') {
110
127
  errorLines.push('💡 Hint: Relation (table/view) does not exist. Check if migrations are applied in correct order.');
package/migrate/client.js CHANGED
@@ -177,6 +177,14 @@ class PgpmMigrate {
177
177
  errorLines.push(` Dependencies: ${qualifiedDeps && qualifiedDeps.length > 0 ? qualifiedDeps.join(', ') : 'none'}`);
178
178
  errorLines.push(` Error Code: ${error.code || 'N/A'}`);
179
179
  errorLines.push(` Error Message: ${error.message || 'N/A'}`);
180
+ // Add extended PostgreSQL error fields
181
+ const pgFields = (0, types_1.extractPgErrorFields)(error);
182
+ if (pgFields) {
183
+ const fieldLines = (0, types_1.formatPgErrorFields)(pgFields);
184
+ if (fieldLines.length > 0) {
185
+ fieldLines.forEach(line => errorLines.push(` ${line}`));
186
+ }
187
+ }
180
188
  // Show SQL script preview for debugging
181
189
  if (cleanDeploySql) {
182
190
  const sqlLines = cleanDeploySql.split('\n');
@@ -215,6 +223,12 @@ class PgpmMigrate {
215
223
  // Log the consolidated error message
216
224
  log.error(errorLines.join('\n'));
217
225
  failed = change.name;
226
+ // Enhance the thrown error message with PostgreSQL extended fields
227
+ // This ensures callers get the same enhanced error format as PgTestClient
228
+ if (!error.__pgpmEnhanced) {
229
+ error.message = (0, types_1.formatPgError)(error);
230
+ error.__pgpmEnhanced = true;
231
+ }
218
232
  throw error; // Re-throw to trigger rollback if in transaction
219
233
  }
220
234
  // Stop if this was the target change
@@ -280,6 +294,11 @@ class PgpmMigrate {
280
294
  });
281
295
  log.error(`Failed to revert ${change.name}:`, error);
282
296
  failed = change.name;
297
+ // Enhance the thrown error message with PostgreSQL extended fields
298
+ if (!error.__pgpmEnhanced) {
299
+ error.message = (0, types_1.formatPgError)(error);
300
+ error.__pgpmEnhanced = true;
301
+ }
283
302
  throw error; // Re-throw to trigger rollback if in transaction
284
303
  }
285
304
  }
@@ -53,6 +53,17 @@ CREATE PROCEDURE pgpm_migrate.deploy(
53
53
  LANGUAGE plpgsql AS $$
54
54
  DECLARE
55
55
  v_change_id TEXT;
56
+ -- Error diagnostic variables
57
+ v_sqlstate TEXT;
58
+ v_message TEXT;
59
+ v_detail TEXT;
60
+ v_hint TEXT;
61
+ v_context TEXT;
62
+ v_schema_name TEXT;
63
+ v_table_name TEXT;
64
+ v_column_name TEXT;
65
+ v_constraint_name TEXT;
66
+ v_datatype_name TEXT;
56
67
  BEGIN
57
68
  -- Ensure package exists
58
69
  CALL pgpm_migrate.register_package(p_package);
@@ -97,7 +108,30 @@ BEGIN
97
108
  BEGIN
98
109
  EXECUTE p_deploy_sql;
99
110
  EXCEPTION WHEN OTHERS THEN
100
- RAISE;
111
+ -- Capture all error diagnostics to preserve them in the re-raised exception
112
+ GET STACKED DIAGNOSTICS
113
+ v_sqlstate = RETURNED_SQLSTATE,
114
+ v_message = MESSAGE_TEXT,
115
+ v_detail = PG_EXCEPTION_DETAIL,
116
+ v_hint = PG_EXCEPTION_HINT,
117
+ v_context = PG_EXCEPTION_CONTEXT,
118
+ v_schema_name = SCHEMA_NAME,
119
+ v_table_name = TABLE_NAME,
120
+ v_column_name = COLUMN_NAME,
121
+ v_constraint_name = CONSTRAINT_NAME,
122
+ v_datatype_name = PG_DATATYPE_NAME;
123
+
124
+ -- Re-raise with all captured diagnostics preserved
125
+ RAISE EXCEPTION USING
126
+ ERRCODE = v_sqlstate,
127
+ MESSAGE = v_message,
128
+ DETAIL = v_detail,
129
+ HINT = v_hint,
130
+ SCHEMA = v_schema_name,
131
+ TABLE = v_table_name,
132
+ COLUMN = v_column_name,
133
+ CONSTRAINT = v_constraint_name,
134
+ DATATYPE = v_datatype_name;
101
135
  END;
102
136
  END IF;
103
137
 
@@ -124,6 +158,18 @@ CREATE PROCEDURE pgpm_migrate.revert(
124
158
  p_revert_sql TEXT
125
159
  )
126
160
  LANGUAGE plpgsql AS $$
161
+ DECLARE
162
+ -- Error diagnostic variables
163
+ v_sqlstate TEXT;
164
+ v_message TEXT;
165
+ v_detail TEXT;
166
+ v_hint TEXT;
167
+ v_context TEXT;
168
+ v_schema_name TEXT;
169
+ v_table_name TEXT;
170
+ v_column_name TEXT;
171
+ v_constraint_name TEXT;
172
+ v_datatype_name TEXT;
127
173
  BEGIN
128
174
  -- Check if deployed
129
175
  IF NOT pgpm_migrate.is_deployed(p_package, p_change_name) THEN
@@ -165,8 +211,35 @@ BEGIN
165
211
  END;
166
212
  END IF;
167
213
 
168
- -- Execute revert
169
- EXECUTE p_revert_sql;
214
+ -- Execute revert with error diagnostics preservation
215
+ BEGIN
216
+ EXECUTE p_revert_sql;
217
+ EXCEPTION WHEN OTHERS THEN
218
+ -- Capture all error diagnostics to preserve them in the re-raised exception
219
+ GET STACKED DIAGNOSTICS
220
+ v_sqlstate = RETURNED_SQLSTATE,
221
+ v_message = MESSAGE_TEXT,
222
+ v_detail = PG_EXCEPTION_DETAIL,
223
+ v_hint = PG_EXCEPTION_HINT,
224
+ v_context = PG_EXCEPTION_CONTEXT,
225
+ v_schema_name = SCHEMA_NAME,
226
+ v_table_name = TABLE_NAME,
227
+ v_column_name = COLUMN_NAME,
228
+ v_constraint_name = CONSTRAINT_NAME,
229
+ v_datatype_name = PG_DATATYPE_NAME;
230
+
231
+ -- Re-raise with all captured diagnostics preserved
232
+ RAISE EXCEPTION USING
233
+ ERRCODE = v_sqlstate,
234
+ MESSAGE = v_message,
235
+ DETAIL = v_detail,
236
+ HINT = v_hint,
237
+ SCHEMA = v_schema_name,
238
+ TABLE = v_table_name,
239
+ COLUMN = v_column_name,
240
+ CONSTRAINT = v_constraint_name,
241
+ DATATYPE = v_datatype_name;
242
+ END;
170
243
 
171
244
  -- Remove from deployed
172
245
  DELETE FROM pgpm_migrate.changes
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.withTransaction = withTransaction;
4
4
  exports.executeQuery = executeQuery;
5
5
  const logger_1 = require("@pgpmjs/logger");
6
+ const types_1 = require("@pgpmjs/types");
6
7
  const log = new logger_1.Logger('migrate:transaction');
7
8
  /**
8
9
  * Execute a function within a transaction context
@@ -55,6 +56,14 @@ async function withTransaction(pool, options, fn) {
55
56
  errorLines.push(`Transaction rolled back due to error after ${transactionDuration}ms:`);
56
57
  errorLines.push(`Error Code: ${error.code || 'N/A'}`);
57
58
  errorLines.push(`Error Message: ${error.message || 'N/A'}`);
59
+ // Add extended PostgreSQL error fields
60
+ const pgFields = (0, types_1.extractPgErrorFields)(error);
61
+ if (pgFields) {
62
+ const fieldLines = (0, types_1.formatPgErrorFields)(pgFields);
63
+ if (fieldLines.length > 0) {
64
+ errorLines.push(...fieldLines);
65
+ }
66
+ }
58
67
  // Log query history for debugging
59
68
  if (queryHistory.length > 0) {
60
69
  errorLines.push('Query history for this transaction:');
@@ -105,10 +114,18 @@ async function executeQuery(context, query, params) {
105
114
  errorLines.push(`Query failed after ${duration}ms:`);
106
115
  errorLines.push(` Query: ${query.split('\n')[0].trim()}`);
107
116
  if (params && params.length > 0) {
108
- errorLines.push(` Params: ${JSON.stringify(params.slice(0, 3))}${params.length > 3 ? '...' : ''}`);
117
+ errorLines.push(` Params: ${JSON.stringify(params)}`);
109
118
  }
110
119
  errorLines.push(` Error Code: ${error.code || 'N/A'}`);
111
120
  errorLines.push(` Error Message: ${error.message || 'N/A'}`);
121
+ // Add extended PostgreSQL error fields
122
+ const pgFields = (0, types_1.extractPgErrorFields)(error);
123
+ if (pgFields) {
124
+ const fieldLines = (0, types_1.formatPgErrorFields)(pgFields);
125
+ if (fieldLines.length > 0) {
126
+ fieldLines.forEach(line => errorLines.push(` ${line}`));
127
+ }
128
+ }
112
129
  // Provide debugging hints for common errors
113
130
  if (error.code === '42P01') {
114
131
  errorLines.push('💡 Hint: Relation (table/view) does not exist. Check if migrations are applied in correct order.');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pgpmjs/core",
3
- "version": "4.6.3",
3
+ "version": "4.7.0",
4
4
  "author": "Constructive <developers@constructive.io>",
5
5
  "description": "PGPM Package and Migration Tools",
6
6
  "main": "index.js",
@@ -45,24 +45,24 @@
45
45
  "@types/pg": "^8.16.0",
46
46
  "copyfiles": "^2.4.1",
47
47
  "inquirerer": "^4.2.0",
48
- "makage": "^0.1.9"
48
+ "makage": "^0.1.10"
49
49
  },
50
50
  "dependencies": {
51
- "@pgpmjs/env": "^2.9.1",
52
- "@pgpmjs/logger": "^1.3.6",
53
- "@pgpmjs/server-utils": "^2.8.13",
54
- "@pgpmjs/types": "^2.13.0",
55
- "csv-to-pg": "^3.3.1",
51
+ "@pgpmjs/env": "^2.9.2",
52
+ "@pgpmjs/logger": "^1.3.7",
53
+ "@pgpmjs/server-utils": "^2.8.14",
54
+ "@pgpmjs/types": "^2.14.0",
55
+ "csv-to-pg": "^3.3.2",
56
56
  "genomic": "^5.2.0",
57
57
  "glob": "^13.0.0",
58
58
  "komoji": "^0.7.14",
59
59
  "parse-package-name": "^1.0.0",
60
60
  "pg": "^8.16.3",
61
- "pg-cache": "^1.6.13",
62
- "pg-env": "^1.2.4",
61
+ "pg-cache": "^1.6.14",
62
+ "pg-env": "^1.2.5",
63
63
  "pgsql-deparser": "^17.17.0",
64
64
  "pgsql-parser": "^17.9.9",
65
65
  "yanse": "^0.1.11"
66
66
  },
67
- "gitHead": "e53cd1f303d796268d94b47e95cde30916e39c1f"
67
+ "gitHead": "f2f9c9851beff3214790dfca371e4ca7f6c1373f"
68
68
  }