@balena/pinejs 16.0.3-build-renovate-major-commander-fdfadc781eb734f1b4326f8bc7c5d1f163092b02-1 → 16.1.0-build-partial-unique-index-constraints-c664148d85c67b645954adc929c778a7ce81115f-2

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.
@@ -242,11 +242,17 @@ const prettifyConstraintError = (
242
242
  request: uriParser.ODataRequest,
243
243
  ) => {
244
244
  if (err instanceof db.ConstraintError) {
245
- let matches: RegExpExecArray | null = null;
245
+ let keyMatches: RegExpExecArray | null = null;
246
+ let violatedConstraintInfo:
247
+ | {
248
+ table: AbstractSQLCompiler.AbstractSqlTable;
249
+ name: string;
250
+ }
251
+ | undefined;
246
252
  if (err instanceof db.UniqueConstraintError) {
247
253
  switch (db.engine) {
248
254
  case 'mysql':
249
- matches =
255
+ keyMatches =
250
256
  /ER_DUP_ENTRY: Duplicate entry '.*?[^\\]' for key '(.*?[^\\])'/.exec(
251
257
  err.message,
252
258
  );
@@ -254,22 +260,46 @@ const prettifyConstraintError = (
254
260
  case 'postgres': {
255
261
  const resourceName = resolveSynonym(request);
256
262
  const abstractSqlModel = getFinalAbstractSqlModel(request);
257
- matches = new RegExp(
258
- '"' + abstractSqlModel.tables[resourceName].name + '_(.*?)_key"',
259
- ).exec(err.message);
263
+ const table = abstractSqlModel.tables[resourceName];
264
+ keyMatches = new RegExp('"' + table.name + '_(.*?)_key"').exec(
265
+ err.message,
266
+ );
267
+ // no need to run the regex if a `_key` error was already matched, or if there are
268
+ // no indexes on the table (since those are the only supported uniqueness errors atm)
269
+ if (keyMatches == null && table.indexes.length > 0) {
270
+ const indexConstraintName =
271
+ /duplicate key value violates unique constraint "(.*)"/.exec(
272
+ err.message,
273
+ )?.[1];
274
+ if (indexConstraintName != null) {
275
+ violatedConstraintInfo = {
276
+ table,
277
+ name: indexConstraintName,
278
+ };
279
+ }
280
+ }
260
281
  break;
261
282
  }
262
283
  }
263
- // We know it's the right error type, so if matches exists just throw a generic error message, since we have failed to get the info for a more specific one.
264
- if (matches == null) {
265
- throw new db.UniqueConstraintError('Unique key constraint violated');
284
+ if (keyMatches != null) {
285
+ const columns = keyMatches[1].split('_');
286
+ throw new db.UniqueConstraintError(
287
+ '"' +
288
+ columns.map(sqlNameToODataName).join('" and "') +
289
+ '" must be unique.',
290
+ );
266
291
  }
267
- const columns = matches[1].split('_');
268
- throw new db.UniqueConstraintError(
269
- '"' +
270
- columns.map(sqlNameToODataName).join('" and "') +
271
- '" must be unique.',
272
- );
292
+ if (violatedConstraintInfo != null) {
293
+ const { table, name: violatedConstraintName } = violatedConstraintInfo;
294
+ const violatedUniqueIndex = table.indexes.find(
295
+ (idx) => idx.name === violatedConstraintName,
296
+ );
297
+ if (violatedUniqueIndex?.description != null) {
298
+ throw new BadRequestError(violatedUniqueIndex.description);
299
+ }
300
+ }
301
+ // We know it's the right error type, so if matches exists just throw a generic error message, since we have failed to get the info for a more specific one.
302
+ throw new db.UniqueConstraintError('Unique key constraint violated');
273
303
  }
274
304
 
275
305
  if (err instanceof db.ExclusionConstraintError) {
@@ -280,7 +310,7 @@ const prettifyConstraintError = (
280
310
  if (err instanceof db.ForeignKeyConstraintError) {
281
311
  switch (db.engine) {
282
312
  case 'mysql':
283
- matches =
313
+ keyMatches =
284
314
  /ER_ROW_IS_REFERENCED_: Cannot delete or update a parent row: a foreign key constraint fails \(".*?"\.(".*?").*/.exec(
285
315
  err.message,
286
316
  );
@@ -289,13 +319,13 @@ const prettifyConstraintError = (
289
319
  const resourceName = resolveSynonym(request);
290
320
  const abstractSqlModel = getFinalAbstractSqlModel(request);
291
321
  const tableName = abstractSqlModel.tables[resourceName].name;
292
- matches = new RegExp(
322
+ keyMatches = new RegExp(
293
323
  '"' +
294
324
  tableName +
295
325
  '" violates foreign key constraint ".*?" on table "(.*?)"',
296
326
  ).exec(err.message);
297
- if (matches == null) {
298
- matches = new RegExp(
327
+ if (keyMatches == null) {
328
+ keyMatches = new RegExp(
299
329
  '"' +
300
330
  tableName +
301
331
  '" violates foreign key constraint "' +
@@ -308,13 +338,13 @@ const prettifyConstraintError = (
308
338
  }
309
339
  // We know it's the right error type, so if no matches exists just throw a generic error message,
310
340
  // since we have failed to get the info for a more specific one.
311
- if (matches == null) {
341
+ if (keyMatches == null) {
312
342
  throw new db.ForeignKeyConstraintError(
313
343
  'Foreign key constraint violated',
314
344
  );
315
345
  }
316
346
  throw new db.ForeignKeyConstraintError(
317
- 'Data is referenced by ' + sqlNameToODataName(matches[1]) + '.',
347
+ 'Data is referenced by ' + sqlNameToODataName(keyMatches[1]) + '.',
318
348
  );
319
349
  }
320
350
 
@@ -325,7 +355,7 @@ const prettifyConstraintError = (
325
355
  if (table.checks) {
326
356
  switch (db.engine) {
327
357
  case 'postgres':
328
- matches = new RegExp(
358
+ keyMatches = new RegExp(
329
359
  'new row for relation "' +
330
360
  table.name +
331
361
  '" violates check constraint "(.*?)"',
@@ -333,8 +363,8 @@ const prettifyConstraintError = (
333
363
  break;
334
364
  }
335
365
  }
336
- if (matches != null) {
337
- const checkName = matches[1];
366
+ if (keyMatches != null) {
367
+ const checkName = keyMatches[1];
338
368
  const check = table.checks!.find((c) => c.name === checkName);
339
369
  if (check?.description != null) {
340
370
  throw new BadRequestError(check.description);