Skip to content

Commit 68a9b24

Browse files
committed
Adapt ConstraintViolationError/ExclusivityViolationError parsing for new EdgeDB logic
Constraints were standardized with: geldata/gel#6796 So now I parse out all the dynamic parts of the message for all constraint errors. I kept the subclass for now, but it could be replaced with the check ```diff - e instanceof ExclusivityViolationError + e instanceof ConstraintViolationError && e.constraint === 'std::exclusive' ```
1 parent e4e10aa commit 68a9b24

File tree

7 files changed

+69
-65
lines changed

7 files changed

+69
-65
lines changed

src/core/edgedb/edgedb.service.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
/* eslint-disable @typescript-eslint/unified-signatures */
22
import { Injectable, Optional } from '@nestjs/common';
3-
import { $, EdgeDBError, Executor } from 'edgedb';
3+
import { $, ConstraintViolationError, EdgeDBError, Executor } from 'edgedb';
44
import { QueryArgs } from 'edgedb/dist/ifaces';
55
import { retry, RetryOptions } from '~/common/retry';
66
import { jestSkipFileInExceptionSource } from '../exception';
77
import { TypedEdgeQL } from './edgeql';
8-
import { ExclusivityViolationError } from './exclusivity-violation.error';
8+
import { enhanceConstraintError } from './errors';
99
import { InlineQueryRuntimeMap } from './generated-client/inline-queries';
1010
import { ApplyOptions, OptionsContext } from './options.context';
1111
import { Client } from './reexports';
@@ -146,8 +146,8 @@ export class EdgeDB {
146146
);
147147
}
148148

149-
if (ExclusivityViolationError.is(e)) {
150-
throw ExclusivityViolationError.cast(e);
149+
if (e instanceof ConstraintViolationError) {
150+
throw enhanceConstraintError(e);
151151
}
152152
throw e;
153153
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { ConstraintViolationError } from 'edgedb';
2+
import { LiteralUnion } from 'type-fest';
3+
import type { AllResourceDBNames } from '~/core/resources';
4+
import { ExclusivityViolationError } from './exclusivity-violation.error';
5+
6+
declare module 'edgedb' {
7+
interface ConstraintViolationError {
8+
readonly objectFQN: AllResourceDBNames;
9+
readonly property: string;
10+
readonly constraint: LiteralUnion<'std::exclusive' | 'std::regexp', string>;
11+
}
12+
}
13+
14+
export const enhanceConstraintError = (e: ConstraintViolationError) => {
15+
// @ts-expect-error it is a private field
16+
const attrs: Map<number, Uint8Array> = e._attrs;
17+
18+
const detail = new TextDecoder('utf8').decode(attrs.get(2 /* details */));
19+
const matches = detail.match(
20+
/^violated constraint '(?<constraint>.+)' on property '(?<property>.+)' of object type '(?<fqn>.+)'$/,
21+
);
22+
if (!matches) {
23+
throw new Error(`Could not parse constraint violation error`, { cause: e });
24+
}
25+
const { fqn, property, constraint } = matches.groups!;
26+
27+
if (constraint === 'std::exclusive') {
28+
e = ExclusivityViolationError.cast(e);
29+
}
30+
31+
return Object.assign(e, {
32+
objectFQN: fqn,
33+
property: property,
34+
constraint: constraint,
35+
});
36+
};
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { ConstraintViolationError } from 'edgedb';
2+
3+
export class ExclusivityViolationError extends ConstraintViolationError {
4+
static cast(e: ConstraintViolationError) {
5+
// @ts-expect-error it is a private field
6+
const message: string = e._message;
7+
// @ts-expect-error it is a private field
8+
const query: string = e._query;
9+
// @ts-expect-error it is a private field
10+
const attrs: Map<number, Uint8Array> = e._attrs;
11+
12+
const ex = new ExclusivityViolationError(message);
13+
14+
ex.stack = e.stack!.replace(
15+
/^ConstraintViolationError:/,
16+
'ExclusivityViolationError:',
17+
);
18+
// @ts-expect-error it's a private field
19+
ex._query = query;
20+
// @ts-expect-error it's a private field
21+
ex._attrs = attrs;
22+
23+
return ex;
24+
}
25+
}

src/core/edgedb/errors/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './constraint-violation.error';
2+
export * from './exclusivity-violation.error';

src/core/edgedb/exclusivity-violation.error.ts

Lines changed: 0 additions & 59 deletions
This file was deleted.

src/core/edgedb/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export * from './options';
44
export type { OptionsFn } from './options.context';
55
export * from './edgedb.service';
66
export * from './withScope';
7-
export * from './exclusivity-violation.error';
7+
export * from './errors/exclusivity-violation.error';
88
export * from './common.repository';
99
export * from './dto.repository';
1010
export * from './query-util/disable-access-policies.option';

src/core/exception/exception.normalizer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ import {
3030
ServerException,
3131
} from '~/common';
3232
import type { ConfigService } from '~/core';
33+
import { ExclusivityViolationError } from '~/core/edgedb/errors';
3334
import * as Neo from '../database/errors';
34-
import { ExclusivityViolationError } from '../edgedb/exclusivity-violation.error';
3535
import { ResourcesHost } from '../resources/resources.host';
3636
import { isSrcFrame } from './is-src-frame';
3737
import { normalizeFramePath } from './normalize-frame-path';

0 commit comments

Comments
 (0)