@constructive-io/graphql-query 4.5.4 → 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.
package/README.md CHANGED
@@ -28,7 +28,7 @@ This package is the **canonical source** for PostGraphile query generation logic
28
28
  - **Mutation generators** — `buildPostGraphileCreate`, `buildPostGraphileUpdate`, `buildPostGraphileDelete`
29
29
  - **Introspection pipeline** — `inferTablesFromIntrospection` to convert a GraphQL schema into `CleanTable` metadata
30
30
  - **AST builders** — low-level `getAll`, `getMany`, `getOne`, `createOne`, `patchOne`, `deleteOne`
31
- - **Client utilities** — `TypedDocumentString`, `execute`, `DataError` for type-safe execution and error handling
31
+ - **Client utilities** — `TypedDocumentString`, `execute`, and `@constructive-io/errors` re-exports (`ConstructiveError`, `parseGraphQLError`) for type-safe execution and error handling
32
32
  - **Naming helpers** — server-aware inflection functions that respect PostGraphile's schema naming
33
33
 
34
34
  All modules are **browser-safe** (no Node.js APIs). `@constructive-io/graphql-codegen` depends on this package for the core logic and adds Node.js-only features (CLI, file output, watch mode).
@@ -329,20 +329,36 @@ const { data, errors } = await client.execute(query, {
329
329
 
330
330
  ## Error Handling
331
331
 
332
+ Error handling is backed by [`@constructive-io/errors`](../../packages/errors), the
333
+ single source of truth for error codes, their public/internal class, message
334
+ copy (i18n), and cross-source parsing. There is no separate client-side error
335
+ catalog or message string-matching — the client re-exports the canonical
336
+ `ConstructiveError`, `parse`, `format`, and helpers.
337
+
332
338
  ```ts
333
- import { DataError, parseGraphQLError, DataErrorType } from '@constructive-io/graphql-query';
339
+ import {
340
+ ConstructiveError,
341
+ parseGraphQLError,
342
+ format,
343
+ isRetryable,
344
+ } from '@constructive-io/graphql-query';
334
345
 
335
346
  try {
336
347
  const result = await client.execute(createQuery, { input: { user: { name: 'Alice' } } });
337
348
  if (result.errors) {
349
+ // Normalize any error into a ConstructiveError (machine code + context + class).
338
350
  const error = parseGraphQLError(result.errors[0]);
339
- if (error.type === DataErrorType.UNIQUE_VIOLATION) {
340
- console.log('Duplicate entry:', error.constraintName);
351
+ if (error.code === 'UNIQUE_VIOLATION') {
352
+ console.log('Duplicate entry:', error.context.constraint);
341
353
  }
342
354
  }
343
355
  } catch (err) {
344
- if (err instanceof DataError) {
345
- console.log(err.type, err.message);
356
+ if (err instanceof ConstructiveError) {
357
+ // Localized, user-facing copy for public codes; retry hint for transport errors.
358
+ console.log(err.code, format(err.code, err.context));
359
+ if (isRetryable(err)) {
360
+ // network/timeout/rate-limit — safe to retry
361
+ }
346
362
  }
347
363
  }
348
364
  ```
@@ -441,8 +457,8 @@ GraphQL Schema (introspection or _meta)
441
457
  | `TypedDocumentString` | Type-safe GraphQL document wrapper (compatible with codegen client) |
442
458
  | `createGraphQLClient(options)` | Create a typed GraphQL client |
443
459
  | `execute(url, query, variables, options?)` | Execute a GraphQL query |
444
- | `DataError` | Structured error class with PG SQLSTATE classification |
445
- | `parseGraphQLError(error)` | Parse raw GraphQL error into `DataError` |
460
+ | `ConstructiveError` | Canonical error class (`code`, `context`, `class`, `http`) from `@constructive-io/errors` |
461
+ | `parseGraphQLError(error)` | Parse any error (pg / GraphQL / message / SQLSTATE) into a `ConstructiveError` |
446
462
 
447
463
  ### Naming Helpers
448
464
 
@@ -504,6 +520,7 @@ Common issues and solutions for pgpm, PostgreSQL, and testing.
504
520
  ### 🧪 Testing
505
521
 
506
522
  * [pgsql-test](https://github.com/constructive-io/constructive/tree/main/postgres/pgsql-test): **📊 Isolated testing environments** with per-test transaction rollbacks—ideal for integration tests, complex migrations, and RLS simulation.
523
+ * [pglite-test](https://github.com/constructive-io/constructive/tree/main/postgres/pglite-test): **🪶 Drop-in pgsql-test replacement backed by PGlite** — in-process Postgres, no server required, instance-per-suite isolation.
507
524
  * [pgsql-seed](https://github.com/constructive-io/constructive/tree/main/postgres/pgsql-seed): **🌱 PostgreSQL seeding utilities** for CSV, JSON, SQL data loading, and pgpm deployment.
508
525
  * [supabase-test](https://github.com/constructive-io/constructive/tree/main/postgres/supabase-test): **🧪 Supabase-native test harness** preconfigured for the local Supabase stack—per-test rollbacks, JWT/role context helpers, and CI/GitHub Actions ready.
509
526
  * [graphile-test](https://github.com/constructive-io/constructive/tree/main/graphile/graphile-test): **🔐 Authentication mocking** for Graphile-focused test helpers and emulating row-level security contexts.
package/client/error.d.ts CHANGED
@@ -1,83 +1,21 @@
1
1
  /**
2
- * Error handling for GraphQL operations
3
- * Provides consistent error types and parsing for PostGraphile responses
2
+ * Error handling for GraphQL operations.
3
+ *
4
+ * This is a thin client-side adapter over the canonical `@constructive-io/errors`
5
+ * package. The package owns the single source of truth for error codes, their
6
+ * public/internal class, message copy (i18n), and cross-source parsing (pg
7
+ * `DatabaseError`, GraphQL `extensions`, structured `DETAIL`, message tokens,
8
+ * and native SQLSTATE). There is no separate client-side error catalog or
9
+ * message string-matching anymore.
4
10
  */
5
- export declare const DataErrorType: {
6
- readonly NETWORK_ERROR: "NETWORK_ERROR";
7
- readonly TIMEOUT_ERROR: "TIMEOUT_ERROR";
8
- readonly VALIDATION_FAILED: "VALIDATION_FAILED";
9
- readonly REQUIRED_FIELD_MISSING: "REQUIRED_FIELD_MISSING";
10
- readonly INVALID_MUTATION_DATA: "INVALID_MUTATION_DATA";
11
- readonly QUERY_GENERATION_FAILED: "QUERY_GENERATION_FAILED";
12
- readonly QUERY_EXECUTION_FAILED: "QUERY_EXECUTION_FAILED";
13
- readonly UNAUTHORIZED: "UNAUTHORIZED";
14
- readonly FORBIDDEN: "FORBIDDEN";
15
- readonly TABLE_NOT_FOUND: "TABLE_NOT_FOUND";
16
- readonly BAD_REQUEST: "BAD_REQUEST";
17
- readonly NOT_FOUND: "NOT_FOUND";
18
- readonly GRAPHQL_ERROR: "GRAPHQL_ERROR";
19
- readonly UNIQUE_VIOLATION: "UNIQUE_VIOLATION";
20
- readonly FOREIGN_KEY_VIOLATION: "FOREIGN_KEY_VIOLATION";
21
- readonly NOT_NULL_VIOLATION: "NOT_NULL_VIOLATION";
22
- readonly CHECK_VIOLATION: "CHECK_VIOLATION";
23
- readonly EXCLUSION_VIOLATION: "EXCLUSION_VIOLATION";
24
- readonly UNKNOWN_ERROR: "UNKNOWN_ERROR";
25
- };
26
- export type DataErrorType = (typeof DataErrorType)[keyof typeof DataErrorType];
27
- export interface DataErrorOptions {
28
- tableName?: string;
29
- fieldName?: string;
30
- constraint?: string;
31
- originalError?: Error;
32
- code?: string;
33
- context?: Record<string, unknown>;
34
- }
35
- /**
36
- * Standard error class for data layer operations
37
- */
38
- export declare class DataError extends Error {
39
- readonly type: DataErrorType;
40
- readonly code?: string;
41
- readonly originalError?: Error;
42
- readonly context?: Record<string, unknown>;
43
- readonly tableName?: string;
44
- readonly fieldName?: string;
45
- readonly constraint?: string;
46
- constructor(type: DataErrorType, message: string, options?: DataErrorOptions);
47
- getUserMessage(): string;
48
- isRetryable(): boolean;
49
- }
50
- export declare const PG_ERROR_CODES: {
51
- readonly UNIQUE_VIOLATION: "23505";
52
- readonly FOREIGN_KEY_VIOLATION: "23503";
53
- readonly NOT_NULL_VIOLATION: "23502";
54
- readonly CHECK_VIOLATION: "23514";
55
- readonly EXCLUSION_VIOLATION: "23P01";
56
- readonly NUMERIC_VALUE_OUT_OF_RANGE: "22003";
57
- readonly STRING_DATA_RIGHT_TRUNCATION: "22001";
58
- readonly INVALID_TEXT_REPRESENTATION: "22P02";
59
- readonly DATETIME_FIELD_OVERFLOW: "22008";
60
- readonly UNDEFINED_TABLE: "42P01";
61
- readonly UNDEFINED_COLUMN: "42703";
62
- readonly INSUFFICIENT_PRIVILEGE: "42501";
63
- };
64
- export declare const createError: {
65
- network: (originalError?: Error) => DataError;
66
- timeout: (originalError?: Error) => DataError;
67
- unauthorized: (message?: string) => DataError;
68
- forbidden: (message?: string) => DataError;
69
- badRequest: (message: string, code?: string) => DataError;
70
- notFound: (message?: string) => DataError;
71
- graphql: (message: string, code?: string) => DataError;
72
- uniqueViolation: (message: string, fieldName?: string, constraint?: string) => DataError;
73
- foreignKeyViolation: (message: string, fieldName?: string, constraint?: string) => DataError;
74
- notNullViolation: (message: string, fieldName?: string, constraint?: string) => DataError;
75
- unknown: (originalError: Error) => DataError;
76
- };
11
+ import { ConstructiveError } from '@constructive-io/errors';
12
+ export { ConstructiveError, classify, format, isPublicCode, parse, type ErrorClass, type ErrorContext, type ParsedError, toError, } from '@constructive-io/errors';
13
+ /** Shape of a single GraphQL error entry in a response `errors[]` array. */
77
14
  export interface GraphQLError {
78
15
  message: string;
79
16
  extensions?: {
80
17
  code?: string;
18
+ class?: string;
81
19
  } & Record<string, unknown>;
82
20
  locations?: Array<{
83
21
  line: number;
@@ -86,10 +24,28 @@ export interface GraphQLError {
86
24
  path?: Array<string | number>;
87
25
  }
88
26
  /**
89
- * Parse any error into a DataError
27
+ * Parse any error (pg error, GraphQL error/response, `ConstructiveError`, plain
28
+ * `Error`, or string) into a throwable {@link ConstructiveError}.
90
29
  */
91
- export declare function parseGraphQLError(error: unknown): DataError;
30
+ export declare function parseGraphQLError(error: unknown, locale?: string): ConstructiveError;
31
+ /** True when the value is a {@link ConstructiveError}. */
32
+ export declare function isConstructiveError(error: unknown): error is ConstructiveError;
33
+ /** Whether an error is safe to retry (network/timeout/rate-limit). */
34
+ export declare function isRetryable(error: unknown): boolean;
92
35
  /**
93
- * Check if value is a DataError
36
+ * Factory for the transport/HTTP-level errors the client synthesizes itself
37
+ * (before any server/DB response is parsed). All produce a
38
+ * {@link ConstructiveError} from the canonical registry.
94
39
  */
95
- export declare function isDataError(error: unknown): error is DataError;
40
+ export declare const createError: {
41
+ network: (originalError?: Error) => ConstructiveError;
42
+ timeout: () => ConstructiveError;
43
+ unauthorized: (message?: string) => ConstructiveError;
44
+ forbidden: (message?: string) => ConstructiveError;
45
+ notFound: (message?: string) => ConstructiveError;
46
+ badRequest: (message: string) => ConstructiveError;
47
+ graphql: (error: unknown) => ConstructiveError;
48
+ unknown: (originalError: Error) => ConstructiveError;
49
+ };
50
+ /** Whether an error is safe to surface to end users (public class). */
51
+ export declare function isPublicError(error: unknown): boolean;
package/client/error.js CHANGED
@@ -1,277 +1,67 @@
1
1
  "use strict";
2
2
  /**
3
- * Error handling for GraphQL operations
4
- * Provides consistent error types and parsing for PostGraphile responses
3
+ * Error handling for GraphQL operations.
4
+ *
5
+ * This is a thin client-side adapter over the canonical `@constructive-io/errors`
6
+ * package. The package owns the single source of truth for error codes, their
7
+ * public/internal class, message copy (i18n), and cross-source parsing (pg
8
+ * `DatabaseError`, GraphQL `extensions`, structured `DETAIL`, message tokens,
9
+ * and native SQLSTATE). There is no separate client-side error catalog or
10
+ * message string-matching anymore.
5
11
  */
6
12
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.createError = exports.PG_ERROR_CODES = exports.DataError = exports.DataErrorType = void 0;
13
+ exports.createError = exports.toError = exports.parse = exports.isPublicCode = exports.format = exports.classify = exports.ConstructiveError = void 0;
8
14
  exports.parseGraphQLError = parseGraphQLError;
9
- exports.isDataError = isDataError;
10
- // ============================================================================
11
- // Error Types
12
- // ============================================================================
13
- exports.DataErrorType = {
14
- // Network/Connection errors
15
- NETWORK_ERROR: 'NETWORK_ERROR',
16
- TIMEOUT_ERROR: 'TIMEOUT_ERROR',
17
- // Validation errors
18
- VALIDATION_FAILED: 'VALIDATION_FAILED',
19
- REQUIRED_FIELD_MISSING: 'REQUIRED_FIELD_MISSING',
20
- INVALID_MUTATION_DATA: 'INVALID_MUTATION_DATA',
21
- // Query errors
22
- QUERY_GENERATION_FAILED: 'QUERY_GENERATION_FAILED',
23
- QUERY_EXECUTION_FAILED: 'QUERY_EXECUTION_FAILED',
24
- // Permission errors
25
- UNAUTHORIZED: 'UNAUTHORIZED',
26
- FORBIDDEN: 'FORBIDDEN',
27
- // Schema errors
28
- TABLE_NOT_FOUND: 'TABLE_NOT_FOUND',
29
- // Request errors
30
- BAD_REQUEST: 'BAD_REQUEST',
31
- NOT_FOUND: 'NOT_FOUND',
32
- // GraphQL-specific errors
33
- GRAPHQL_ERROR: 'GRAPHQL_ERROR',
34
- // PostgreSQL constraint errors (surfaced via PostGraphile)
35
- UNIQUE_VIOLATION: 'UNIQUE_VIOLATION',
36
- FOREIGN_KEY_VIOLATION: 'FOREIGN_KEY_VIOLATION',
37
- NOT_NULL_VIOLATION: 'NOT_NULL_VIOLATION',
38
- CHECK_VIOLATION: 'CHECK_VIOLATION',
39
- EXCLUSION_VIOLATION: 'EXCLUSION_VIOLATION',
40
- // Generic errors
41
- UNKNOWN_ERROR: 'UNKNOWN_ERROR',
42
- };
15
+ exports.isConstructiveError = isConstructiveError;
16
+ exports.isRetryable = isRetryable;
17
+ exports.isPublicError = isPublicError;
18
+ const errors_1 = require("@constructive-io/errors");
19
+ var errors_2 = require("@constructive-io/errors");
20
+ Object.defineProperty(exports, "ConstructiveError", { enumerable: true, get: function () { return errors_2.ConstructiveError; } });
21
+ Object.defineProperty(exports, "classify", { enumerable: true, get: function () { return errors_2.classify; } });
22
+ Object.defineProperty(exports, "format", { enumerable: true, get: function () { return errors_2.format; } });
23
+ Object.defineProperty(exports, "isPublicCode", { enumerable: true, get: function () { return errors_2.isPublicCode; } });
24
+ Object.defineProperty(exports, "parse", { enumerable: true, get: function () { return errors_2.parse; } });
25
+ Object.defineProperty(exports, "toError", { enumerable: true, get: function () { return errors_2.toError; } });
43
26
  /**
44
- * Standard error class for data layer operations
27
+ * Parse any error (pg error, GraphQL error/response, `ConstructiveError`, plain
28
+ * `Error`, or string) into a throwable {@link ConstructiveError}.
45
29
  */
46
- class DataError extends Error {
47
- type;
48
- code;
49
- originalError;
50
- context;
51
- tableName;
52
- fieldName;
53
- constraint;
54
- constructor(type, message, options = {}) {
55
- super(message);
56
- this.name = 'DataError';
57
- this.type = type;
58
- this.code = options.code;
59
- this.originalError = options.originalError;
60
- this.context = options.context;
61
- this.tableName = options.tableName;
62
- this.fieldName = options.fieldName;
63
- this.constraint = options.constraint;
64
- if (Error.captureStackTrace) {
65
- Error.captureStackTrace(this, DataError);
66
- }
67
- }
68
- getUserMessage() {
69
- switch (this.type) {
70
- case exports.DataErrorType.NETWORK_ERROR:
71
- return 'Network error. Please check your connection and try again.';
72
- case exports.DataErrorType.TIMEOUT_ERROR:
73
- return 'Request timed out. Please try again.';
74
- case exports.DataErrorType.UNAUTHORIZED:
75
- return 'You are not authorized. Please log in and try again.';
76
- case exports.DataErrorType.FORBIDDEN:
77
- return 'You do not have permission to access this resource.';
78
- case exports.DataErrorType.VALIDATION_FAILED:
79
- return 'Validation failed. Please check your input and try again.';
80
- case exports.DataErrorType.REQUIRED_FIELD_MISSING:
81
- return this.fieldName
82
- ? `The field "${this.fieldName}" is required.`
83
- : 'A required field is missing.';
84
- case exports.DataErrorType.UNIQUE_VIOLATION:
85
- return this.fieldName
86
- ? `A record with this ${this.fieldName} already exists.`
87
- : 'A record with this value already exists.';
88
- case exports.DataErrorType.FOREIGN_KEY_VIOLATION:
89
- return 'This record references a record that does not exist.';
90
- case exports.DataErrorType.NOT_NULL_VIOLATION:
91
- return this.fieldName
92
- ? `The field "${this.fieldName}" cannot be empty.`
93
- : 'A required field cannot be empty.';
94
- case exports.DataErrorType.CHECK_VIOLATION:
95
- return this.fieldName
96
- ? `The value for "${this.fieldName}" is not valid.`
97
- : 'The value does not meet the required constraints.';
98
- default:
99
- return this.message || 'An unexpected error occurred.';
100
- }
101
- }
102
- isRetryable() {
103
- return (this.type === exports.DataErrorType.NETWORK_ERROR ||
104
- this.type === exports.DataErrorType.TIMEOUT_ERROR);
105
- }
106
- }
107
- exports.DataError = DataError;
108
- // ============================================================================
109
- // PostgreSQL Error Codes
110
- // ============================================================================
111
- exports.PG_ERROR_CODES = {
112
- UNIQUE_VIOLATION: '23505',
113
- FOREIGN_KEY_VIOLATION: '23503',
114
- NOT_NULL_VIOLATION: '23502',
115
- CHECK_VIOLATION: '23514',
116
- EXCLUSION_VIOLATION: '23P01',
117
- NUMERIC_VALUE_OUT_OF_RANGE: '22003',
118
- STRING_DATA_RIGHT_TRUNCATION: '22001',
119
- INVALID_TEXT_REPRESENTATION: '22P02',
120
- DATETIME_FIELD_OVERFLOW: '22008',
121
- UNDEFINED_TABLE: '42P01',
122
- UNDEFINED_COLUMN: '42703',
123
- INSUFFICIENT_PRIVILEGE: '42501',
124
- };
125
- // ============================================================================
126
- // Error Factory
127
- // ============================================================================
128
- exports.createError = {
129
- network: (originalError) => new DataError(exports.DataErrorType.NETWORK_ERROR, 'Network error occurred', {
130
- originalError,
131
- }),
132
- timeout: (originalError) => new DataError(exports.DataErrorType.TIMEOUT_ERROR, 'Request timed out', {
133
- originalError,
134
- }),
135
- unauthorized: (message = 'Authentication required') => new DataError(exports.DataErrorType.UNAUTHORIZED, message),
136
- forbidden: (message = 'Access forbidden') => new DataError(exports.DataErrorType.FORBIDDEN, message),
137
- badRequest: (message, code) => new DataError(exports.DataErrorType.BAD_REQUEST, message, { code }),
138
- notFound: (message = 'Resource not found') => new DataError(exports.DataErrorType.NOT_FOUND, message),
139
- graphql: (message, code) => new DataError(exports.DataErrorType.GRAPHQL_ERROR, message, { code }),
140
- uniqueViolation: (message, fieldName, constraint) => new DataError(exports.DataErrorType.UNIQUE_VIOLATION, message, {
141
- fieldName,
142
- constraint,
143
- code: '23505',
144
- }),
145
- foreignKeyViolation: (message, fieldName, constraint) => new DataError(exports.DataErrorType.FOREIGN_KEY_VIOLATION, message, {
146
- fieldName,
147
- constraint,
148
- code: '23503',
149
- }),
150
- notNullViolation: (message, fieldName, constraint) => new DataError(exports.DataErrorType.NOT_NULL_VIOLATION, message, {
151
- fieldName,
152
- constraint,
153
- code: '23502',
154
- }),
155
- unknown: (originalError) => new DataError(exports.DataErrorType.UNKNOWN_ERROR, originalError.message, {
156
- originalError,
157
- }),
158
- };
159
- function parseGraphQLErrorCode(code) {
160
- if (!code)
161
- return exports.DataErrorType.UNKNOWN_ERROR;
162
- const normalized = code.toUpperCase();
163
- // GraphQL standard codes
164
- if (normalized === 'UNAUTHENTICATED')
165
- return exports.DataErrorType.UNAUTHORIZED;
166
- if (normalized === 'FORBIDDEN')
167
- return exports.DataErrorType.FORBIDDEN;
168
- if (normalized === 'GRAPHQL_VALIDATION_FAILED')
169
- return exports.DataErrorType.QUERY_GENERATION_FAILED;
170
- // PostgreSQL SQLSTATE codes
171
- if (code === exports.PG_ERROR_CODES.UNIQUE_VIOLATION)
172
- return exports.DataErrorType.UNIQUE_VIOLATION;
173
- if (code === exports.PG_ERROR_CODES.FOREIGN_KEY_VIOLATION)
174
- return exports.DataErrorType.FOREIGN_KEY_VIOLATION;
175
- if (code === exports.PG_ERROR_CODES.NOT_NULL_VIOLATION)
176
- return exports.DataErrorType.NOT_NULL_VIOLATION;
177
- if (code === exports.PG_ERROR_CODES.CHECK_VIOLATION)
178
- return exports.DataErrorType.CHECK_VIOLATION;
179
- if (code === exports.PG_ERROR_CODES.EXCLUSION_VIOLATION)
180
- return exports.DataErrorType.EXCLUSION_VIOLATION;
181
- return exports.DataErrorType.UNKNOWN_ERROR;
30
+ function parseGraphQLError(error, locale) {
31
+ return (0, errors_1.toError)(error, locale);
182
32
  }
183
- function classifyByMessage(message) {
184
- const lower = message.toLowerCase();
185
- if (lower.includes('timeout') || lower.includes('timed out')) {
186
- return exports.DataErrorType.TIMEOUT_ERROR;
187
- }
188
- if (lower.includes('network') ||
189
- lower.includes('fetch') ||
190
- lower.includes('failed to fetch')) {
191
- return exports.DataErrorType.NETWORK_ERROR;
192
- }
193
- if (lower.includes('unauthorized') ||
194
- lower.includes('authentication required')) {
195
- return exports.DataErrorType.UNAUTHORIZED;
196
- }
197
- if (lower.includes('forbidden') || lower.includes('permission')) {
198
- return exports.DataErrorType.FORBIDDEN;
199
- }
200
- if (lower.includes('duplicate key') || lower.includes('already exists')) {
201
- return exports.DataErrorType.UNIQUE_VIOLATION;
202
- }
203
- if (lower.includes('foreign key constraint')) {
204
- return exports.DataErrorType.FOREIGN_KEY_VIOLATION;
205
- }
206
- if (lower.includes('not-null constraint') ||
207
- lower.includes('null value in column')) {
208
- return exports.DataErrorType.NOT_NULL_VIOLATION;
209
- }
210
- return exports.DataErrorType.UNKNOWN_ERROR;
33
+ /** True when the value is a {@link ConstructiveError}. */
34
+ function isConstructiveError(error) {
35
+ return error instanceof errors_1.ConstructiveError;
211
36
  }
212
- function extractFieldFromError(message, constraint, column) {
213
- if (column)
214
- return column;
215
- const columnMatch = message.match(/column\s+"?([a-z_][a-z0-9_]*)"?/i);
216
- if (columnMatch)
217
- return columnMatch[1];
218
- if (constraint) {
219
- const constraintMatch = constraint.match(/_([a-z_][a-z0-9_]*)_(?:key|fkey|check|pkey)$/i);
220
- if (constraintMatch)
221
- return constraintMatch[1];
222
- }
223
- const keyMatch = message.match(/Key\s+\(([a-z_][a-z0-9_]*)\)/i);
224
- if (keyMatch)
225
- return keyMatch[1];
226
- return undefined;
37
+ /** Codes worth automatically retrying (transient transport/rate failures). */
38
+ const RETRYABLE_CODES = new Set([
39
+ 'NETWORK_ERROR',
40
+ 'TIMEOUT_ERROR',
41
+ 'RATE_LIMITED',
42
+ 'TOO_MANY_REQUESTS',
43
+ ]);
44
+ /** Whether an error is safe to retry (network/timeout/rate-limit). */
45
+ function isRetryable(error) {
46
+ const { code } = (0, errors_1.parse)(error);
47
+ return Boolean(code && RETRYABLE_CODES.has(code));
227
48
  }
228
49
  /**
229
- * Parse any error into a DataError
50
+ * Factory for the transport/HTTP-level errors the client synthesizes itself
51
+ * (before any server/DB response is parsed). All produce a
52
+ * {@link ConstructiveError} from the canonical registry.
230
53
  */
231
- function parseGraphQLError(error) {
232
- if (error instanceof DataError) {
233
- return error;
234
- }
235
- // GraphQL error object
236
- if (error &&
237
- typeof error === 'object' &&
238
- 'message' in error &&
239
- typeof error.message === 'string') {
240
- const gqlError = error;
241
- const extCode = gqlError.extensions?.code;
242
- const mappedType = parseGraphQLErrorCode(extCode);
243
- const column = gqlError.extensions?.column;
244
- const constraint = gqlError.extensions?.constraint;
245
- const fieldName = extractFieldFromError(gqlError.message, constraint, column);
246
- if (mappedType !== exports.DataErrorType.UNKNOWN_ERROR) {
247
- return new DataError(mappedType, gqlError.message, {
248
- code: extCode,
249
- fieldName,
250
- constraint,
251
- context: gqlError.extensions,
252
- });
253
- }
254
- // Fallback: classify by message
255
- const fallbackType = classifyByMessage(gqlError.message);
256
- return new DataError(fallbackType, gqlError.message, {
257
- code: extCode,
258
- fieldName,
259
- constraint,
260
- context: gqlError.extensions,
261
- });
262
- }
263
- // Standard Error
264
- if (error instanceof Error) {
265
- const type = classifyByMessage(error.message);
266
- return new DataError(type, error.message, { originalError: error });
267
- }
268
- // Unknown
269
- const message = typeof error === 'string' ? error : 'Unknown error occurred';
270
- return new DataError(exports.DataErrorType.UNKNOWN_ERROR, message);
271
- }
272
- /**
273
- * Check if value is a DataError
274
- */
275
- function isDataError(error) {
276
- return error instanceof DataError;
54
+ exports.createError = {
55
+ network: (originalError) => errors_1.errors.NETWORK_ERROR({}, originalError?.message),
56
+ timeout: () => errors_1.errors.TIMEOUT_ERROR(),
57
+ unauthorized: (message = 'Authentication required') => errors_1.errors.UNAUTHENTICATED({}, message),
58
+ forbidden: (message = 'Access forbidden') => errors_1.errors.FORBIDDEN({}, message),
59
+ notFound: (message = 'Resource not found') => errors_1.errors.NOT_FOUND({}, message),
60
+ badRequest: (message) => errors_1.errors.BAD_USER_INPUT({}, message),
61
+ graphql: (error) => (0, errors_1.toError)(error),
62
+ unknown: (originalError) => (0, errors_1.toError)(originalError),
63
+ };
64
+ /** Whether an error is safe to surface to end users (public class). */
65
+ function isPublicError(error) {
66
+ return (0, errors_1.isPublicCode)((0, errors_1.parse)(error).code);
277
67
  }
package/client/index.d.ts CHANGED
@@ -4,5 +4,5 @@
4
4
  * Re-exports client utilities for GraphQL execution and error handling.
5
5
  */
6
6
  export { TypedDocumentString, type DocumentTypeDecoration, } from './typed-document';
7
- export { DataError, DataErrorType, PG_ERROR_CODES, createError, parseGraphQLError, isDataError, type DataErrorOptions, type GraphQLError, } from './error';
7
+ export { ConstructiveError, classify, createError, format, isConstructiveError, isPublicCode, isPublicError, isRetryable, parse, parseGraphQLError, toError, type ErrorClass, type ErrorContext, type GraphQLError, type ParsedError, } from './error';
8
8
  export { execute, createGraphQLClient, type ExecuteOptions, type GraphQLResponse, type GraphQLClientOptions, type GraphQLClient, } from './execute';
package/client/index.js CHANGED
@@ -5,16 +5,21 @@
5
5
  * Re-exports client utilities for GraphQL execution and error handling.
6
6
  */
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.createGraphQLClient = exports.execute = exports.isDataError = exports.parseGraphQLError = exports.createError = exports.PG_ERROR_CODES = exports.DataErrorType = exports.DataError = exports.TypedDocumentString = void 0;
8
+ exports.createGraphQLClient = exports.execute = exports.toError = exports.parseGraphQLError = exports.parse = exports.isRetryable = exports.isPublicError = exports.isPublicCode = exports.isConstructiveError = exports.format = exports.createError = exports.classify = exports.ConstructiveError = exports.TypedDocumentString = void 0;
9
9
  var typed_document_1 = require("./typed-document");
10
10
  Object.defineProperty(exports, "TypedDocumentString", { enumerable: true, get: function () { return typed_document_1.TypedDocumentString; } });
11
11
  var error_1 = require("./error");
12
- Object.defineProperty(exports, "DataError", { enumerable: true, get: function () { return error_1.DataError; } });
13
- Object.defineProperty(exports, "DataErrorType", { enumerable: true, get: function () { return error_1.DataErrorType; } });
14
- Object.defineProperty(exports, "PG_ERROR_CODES", { enumerable: true, get: function () { return error_1.PG_ERROR_CODES; } });
12
+ Object.defineProperty(exports, "ConstructiveError", { enumerable: true, get: function () { return error_1.ConstructiveError; } });
13
+ Object.defineProperty(exports, "classify", { enumerable: true, get: function () { return error_1.classify; } });
15
14
  Object.defineProperty(exports, "createError", { enumerable: true, get: function () { return error_1.createError; } });
15
+ Object.defineProperty(exports, "format", { enumerable: true, get: function () { return error_1.format; } });
16
+ Object.defineProperty(exports, "isConstructiveError", { enumerable: true, get: function () { return error_1.isConstructiveError; } });
17
+ Object.defineProperty(exports, "isPublicCode", { enumerable: true, get: function () { return error_1.isPublicCode; } });
18
+ Object.defineProperty(exports, "isPublicError", { enumerable: true, get: function () { return error_1.isPublicError; } });
19
+ Object.defineProperty(exports, "isRetryable", { enumerable: true, get: function () { return error_1.isRetryable; } });
20
+ Object.defineProperty(exports, "parse", { enumerable: true, get: function () { return error_1.parse; } });
16
21
  Object.defineProperty(exports, "parseGraphQLError", { enumerable: true, get: function () { return error_1.parseGraphQLError; } });
17
- Object.defineProperty(exports, "isDataError", { enumerable: true, get: function () { return error_1.isDataError; } });
22
+ Object.defineProperty(exports, "toError", { enumerable: true, get: function () { return error_1.toError; } });
18
23
  var execute_1 = require("./execute");
19
24
  Object.defineProperty(exports, "execute", { enumerable: true, get: function () { return execute_1.execute; } });
20
25
  Object.defineProperty(exports, "createGraphQLClient", { enumerable: true, get: function () { return execute_1.createGraphQLClient; } });
@@ -1,271 +1,54 @@
1
1
  /**
2
- * Error handling for GraphQL operations
3
- * Provides consistent error types and parsing for PostGraphile responses
2
+ * Error handling for GraphQL operations.
3
+ *
4
+ * This is a thin client-side adapter over the canonical `@constructive-io/errors`
5
+ * package. The package owns the single source of truth for error codes, their
6
+ * public/internal class, message copy (i18n), and cross-source parsing (pg
7
+ * `DatabaseError`, GraphQL `extensions`, structured `DETAIL`, message tokens,
8
+ * and native SQLSTATE). There is no separate client-side error catalog or
9
+ * message string-matching anymore.
4
10
  */
5
- // ============================================================================
6
- // Error Types
7
- // ============================================================================
8
- export const DataErrorType = {
9
- // Network/Connection errors
10
- NETWORK_ERROR: 'NETWORK_ERROR',
11
- TIMEOUT_ERROR: 'TIMEOUT_ERROR',
12
- // Validation errors
13
- VALIDATION_FAILED: 'VALIDATION_FAILED',
14
- REQUIRED_FIELD_MISSING: 'REQUIRED_FIELD_MISSING',
15
- INVALID_MUTATION_DATA: 'INVALID_MUTATION_DATA',
16
- // Query errors
17
- QUERY_GENERATION_FAILED: 'QUERY_GENERATION_FAILED',
18
- QUERY_EXECUTION_FAILED: 'QUERY_EXECUTION_FAILED',
19
- // Permission errors
20
- UNAUTHORIZED: 'UNAUTHORIZED',
21
- FORBIDDEN: 'FORBIDDEN',
22
- // Schema errors
23
- TABLE_NOT_FOUND: 'TABLE_NOT_FOUND',
24
- // Request errors
25
- BAD_REQUEST: 'BAD_REQUEST',
26
- NOT_FOUND: 'NOT_FOUND',
27
- // GraphQL-specific errors
28
- GRAPHQL_ERROR: 'GRAPHQL_ERROR',
29
- // PostgreSQL constraint errors (surfaced via PostGraphile)
30
- UNIQUE_VIOLATION: 'UNIQUE_VIOLATION',
31
- FOREIGN_KEY_VIOLATION: 'FOREIGN_KEY_VIOLATION',
32
- NOT_NULL_VIOLATION: 'NOT_NULL_VIOLATION',
33
- CHECK_VIOLATION: 'CHECK_VIOLATION',
34
- EXCLUSION_VIOLATION: 'EXCLUSION_VIOLATION',
35
- // Generic errors
36
- UNKNOWN_ERROR: 'UNKNOWN_ERROR',
37
- };
11
+ import { ConstructiveError, errors, isPublicCode, parse, toError, } from '@constructive-io/errors';
12
+ export { ConstructiveError, classify, format, isPublicCode, parse, toError, } from '@constructive-io/errors';
38
13
  /**
39
- * Standard error class for data layer operations
14
+ * Parse any error (pg error, GraphQL error/response, `ConstructiveError`, plain
15
+ * `Error`, or string) into a throwable {@link ConstructiveError}.
40
16
  */
41
- export class DataError extends Error {
42
- type;
43
- code;
44
- originalError;
45
- context;
46
- tableName;
47
- fieldName;
48
- constraint;
49
- constructor(type, message, options = {}) {
50
- super(message);
51
- this.name = 'DataError';
52
- this.type = type;
53
- this.code = options.code;
54
- this.originalError = options.originalError;
55
- this.context = options.context;
56
- this.tableName = options.tableName;
57
- this.fieldName = options.fieldName;
58
- this.constraint = options.constraint;
59
- if (Error.captureStackTrace) {
60
- Error.captureStackTrace(this, DataError);
61
- }
62
- }
63
- getUserMessage() {
64
- switch (this.type) {
65
- case DataErrorType.NETWORK_ERROR:
66
- return 'Network error. Please check your connection and try again.';
67
- case DataErrorType.TIMEOUT_ERROR:
68
- return 'Request timed out. Please try again.';
69
- case DataErrorType.UNAUTHORIZED:
70
- return 'You are not authorized. Please log in and try again.';
71
- case DataErrorType.FORBIDDEN:
72
- return 'You do not have permission to access this resource.';
73
- case DataErrorType.VALIDATION_FAILED:
74
- return 'Validation failed. Please check your input and try again.';
75
- case DataErrorType.REQUIRED_FIELD_MISSING:
76
- return this.fieldName
77
- ? `The field "${this.fieldName}" is required.`
78
- : 'A required field is missing.';
79
- case DataErrorType.UNIQUE_VIOLATION:
80
- return this.fieldName
81
- ? `A record with this ${this.fieldName} already exists.`
82
- : 'A record with this value already exists.';
83
- case DataErrorType.FOREIGN_KEY_VIOLATION:
84
- return 'This record references a record that does not exist.';
85
- case DataErrorType.NOT_NULL_VIOLATION:
86
- return this.fieldName
87
- ? `The field "${this.fieldName}" cannot be empty.`
88
- : 'A required field cannot be empty.';
89
- case DataErrorType.CHECK_VIOLATION:
90
- return this.fieldName
91
- ? `The value for "${this.fieldName}" is not valid.`
92
- : 'The value does not meet the required constraints.';
93
- default:
94
- return this.message || 'An unexpected error occurred.';
95
- }
96
- }
97
- isRetryable() {
98
- return (this.type === DataErrorType.NETWORK_ERROR ||
99
- this.type === DataErrorType.TIMEOUT_ERROR);
100
- }
101
- }
102
- // ============================================================================
103
- // PostgreSQL Error Codes
104
- // ============================================================================
105
- export const PG_ERROR_CODES = {
106
- UNIQUE_VIOLATION: '23505',
107
- FOREIGN_KEY_VIOLATION: '23503',
108
- NOT_NULL_VIOLATION: '23502',
109
- CHECK_VIOLATION: '23514',
110
- EXCLUSION_VIOLATION: '23P01',
111
- NUMERIC_VALUE_OUT_OF_RANGE: '22003',
112
- STRING_DATA_RIGHT_TRUNCATION: '22001',
113
- INVALID_TEXT_REPRESENTATION: '22P02',
114
- DATETIME_FIELD_OVERFLOW: '22008',
115
- UNDEFINED_TABLE: '42P01',
116
- UNDEFINED_COLUMN: '42703',
117
- INSUFFICIENT_PRIVILEGE: '42501',
118
- };
119
- // ============================================================================
120
- // Error Factory
121
- // ============================================================================
122
- export const createError = {
123
- network: (originalError) => new DataError(DataErrorType.NETWORK_ERROR, 'Network error occurred', {
124
- originalError,
125
- }),
126
- timeout: (originalError) => new DataError(DataErrorType.TIMEOUT_ERROR, 'Request timed out', {
127
- originalError,
128
- }),
129
- unauthorized: (message = 'Authentication required') => new DataError(DataErrorType.UNAUTHORIZED, message),
130
- forbidden: (message = 'Access forbidden') => new DataError(DataErrorType.FORBIDDEN, message),
131
- badRequest: (message, code) => new DataError(DataErrorType.BAD_REQUEST, message, { code }),
132
- notFound: (message = 'Resource not found') => new DataError(DataErrorType.NOT_FOUND, message),
133
- graphql: (message, code) => new DataError(DataErrorType.GRAPHQL_ERROR, message, { code }),
134
- uniqueViolation: (message, fieldName, constraint) => new DataError(DataErrorType.UNIQUE_VIOLATION, message, {
135
- fieldName,
136
- constraint,
137
- code: '23505',
138
- }),
139
- foreignKeyViolation: (message, fieldName, constraint) => new DataError(DataErrorType.FOREIGN_KEY_VIOLATION, message, {
140
- fieldName,
141
- constraint,
142
- code: '23503',
143
- }),
144
- notNullViolation: (message, fieldName, constraint) => new DataError(DataErrorType.NOT_NULL_VIOLATION, message, {
145
- fieldName,
146
- constraint,
147
- code: '23502',
148
- }),
149
- unknown: (originalError) => new DataError(DataErrorType.UNKNOWN_ERROR, originalError.message, {
150
- originalError,
151
- }),
152
- };
153
- function parseGraphQLErrorCode(code) {
154
- if (!code)
155
- return DataErrorType.UNKNOWN_ERROR;
156
- const normalized = code.toUpperCase();
157
- // GraphQL standard codes
158
- if (normalized === 'UNAUTHENTICATED')
159
- return DataErrorType.UNAUTHORIZED;
160
- if (normalized === 'FORBIDDEN')
161
- return DataErrorType.FORBIDDEN;
162
- if (normalized === 'GRAPHQL_VALIDATION_FAILED')
163
- return DataErrorType.QUERY_GENERATION_FAILED;
164
- // PostgreSQL SQLSTATE codes
165
- if (code === PG_ERROR_CODES.UNIQUE_VIOLATION)
166
- return DataErrorType.UNIQUE_VIOLATION;
167
- if (code === PG_ERROR_CODES.FOREIGN_KEY_VIOLATION)
168
- return DataErrorType.FOREIGN_KEY_VIOLATION;
169
- if (code === PG_ERROR_CODES.NOT_NULL_VIOLATION)
170
- return DataErrorType.NOT_NULL_VIOLATION;
171
- if (code === PG_ERROR_CODES.CHECK_VIOLATION)
172
- return DataErrorType.CHECK_VIOLATION;
173
- if (code === PG_ERROR_CODES.EXCLUSION_VIOLATION)
174
- return DataErrorType.EXCLUSION_VIOLATION;
175
- return DataErrorType.UNKNOWN_ERROR;
17
+ export function parseGraphQLError(error, locale) {
18
+ return toError(error, locale);
176
19
  }
177
- function classifyByMessage(message) {
178
- const lower = message.toLowerCase();
179
- if (lower.includes('timeout') || lower.includes('timed out')) {
180
- return DataErrorType.TIMEOUT_ERROR;
181
- }
182
- if (lower.includes('network') ||
183
- lower.includes('fetch') ||
184
- lower.includes('failed to fetch')) {
185
- return DataErrorType.NETWORK_ERROR;
186
- }
187
- if (lower.includes('unauthorized') ||
188
- lower.includes('authentication required')) {
189
- return DataErrorType.UNAUTHORIZED;
190
- }
191
- if (lower.includes('forbidden') || lower.includes('permission')) {
192
- return DataErrorType.FORBIDDEN;
193
- }
194
- if (lower.includes('duplicate key') || lower.includes('already exists')) {
195
- return DataErrorType.UNIQUE_VIOLATION;
196
- }
197
- if (lower.includes('foreign key constraint')) {
198
- return DataErrorType.FOREIGN_KEY_VIOLATION;
199
- }
200
- if (lower.includes('not-null constraint') ||
201
- lower.includes('null value in column')) {
202
- return DataErrorType.NOT_NULL_VIOLATION;
203
- }
204
- return DataErrorType.UNKNOWN_ERROR;
20
+ /** True when the value is a {@link ConstructiveError}. */
21
+ export function isConstructiveError(error) {
22
+ return error instanceof ConstructiveError;
205
23
  }
206
- function extractFieldFromError(message, constraint, column) {
207
- if (column)
208
- return column;
209
- const columnMatch = message.match(/column\s+"?([a-z_][a-z0-9_]*)"?/i);
210
- if (columnMatch)
211
- return columnMatch[1];
212
- if (constraint) {
213
- const constraintMatch = constraint.match(/_([a-z_][a-z0-9_]*)_(?:key|fkey|check|pkey)$/i);
214
- if (constraintMatch)
215
- return constraintMatch[1];
216
- }
217
- const keyMatch = message.match(/Key\s+\(([a-z_][a-z0-9_]*)\)/i);
218
- if (keyMatch)
219
- return keyMatch[1];
220
- return undefined;
24
+ /** Codes worth automatically retrying (transient transport/rate failures). */
25
+ const RETRYABLE_CODES = new Set([
26
+ 'NETWORK_ERROR',
27
+ 'TIMEOUT_ERROR',
28
+ 'RATE_LIMITED',
29
+ 'TOO_MANY_REQUESTS',
30
+ ]);
31
+ /** Whether an error is safe to retry (network/timeout/rate-limit). */
32
+ export function isRetryable(error) {
33
+ const { code } = parse(error);
34
+ return Boolean(code && RETRYABLE_CODES.has(code));
221
35
  }
222
36
  /**
223
- * Parse any error into a DataError
37
+ * Factory for the transport/HTTP-level errors the client synthesizes itself
38
+ * (before any server/DB response is parsed). All produce a
39
+ * {@link ConstructiveError} from the canonical registry.
224
40
  */
225
- export function parseGraphQLError(error) {
226
- if (error instanceof DataError) {
227
- return error;
228
- }
229
- // GraphQL error object
230
- if (error &&
231
- typeof error === 'object' &&
232
- 'message' in error &&
233
- typeof error.message === 'string') {
234
- const gqlError = error;
235
- const extCode = gqlError.extensions?.code;
236
- const mappedType = parseGraphQLErrorCode(extCode);
237
- const column = gqlError.extensions?.column;
238
- const constraint = gqlError.extensions?.constraint;
239
- const fieldName = extractFieldFromError(gqlError.message, constraint, column);
240
- if (mappedType !== DataErrorType.UNKNOWN_ERROR) {
241
- return new DataError(mappedType, gqlError.message, {
242
- code: extCode,
243
- fieldName,
244
- constraint,
245
- context: gqlError.extensions,
246
- });
247
- }
248
- // Fallback: classify by message
249
- const fallbackType = classifyByMessage(gqlError.message);
250
- return new DataError(fallbackType, gqlError.message, {
251
- code: extCode,
252
- fieldName,
253
- constraint,
254
- context: gqlError.extensions,
255
- });
256
- }
257
- // Standard Error
258
- if (error instanceof Error) {
259
- const type = classifyByMessage(error.message);
260
- return new DataError(type, error.message, { originalError: error });
261
- }
262
- // Unknown
263
- const message = typeof error === 'string' ? error : 'Unknown error occurred';
264
- return new DataError(DataErrorType.UNKNOWN_ERROR, message);
265
- }
266
- /**
267
- * Check if value is a DataError
268
- */
269
- export function isDataError(error) {
270
- return error instanceof DataError;
41
+ export const createError = {
42
+ network: (originalError) => errors.NETWORK_ERROR({}, originalError?.message),
43
+ timeout: () => errors.TIMEOUT_ERROR(),
44
+ unauthorized: (message = 'Authentication required') => errors.UNAUTHENTICATED({}, message),
45
+ forbidden: (message = 'Access forbidden') => errors.FORBIDDEN({}, message),
46
+ notFound: (message = 'Resource not found') => errors.NOT_FOUND({}, message),
47
+ badRequest: (message) => errors.BAD_USER_INPUT({}, message),
48
+ graphql: (error) => toError(error),
49
+ unknown: (originalError) => toError(originalError),
50
+ };
51
+ /** Whether an error is safe to surface to end users (public class). */
52
+ export function isPublicError(error) {
53
+ return isPublicCode(parse(error).code);
271
54
  }
@@ -4,5 +4,5 @@
4
4
  * Re-exports client utilities for GraphQL execution and error handling.
5
5
  */
6
6
  export { TypedDocumentString, } from './typed-document';
7
- export { DataError, DataErrorType, PG_ERROR_CODES, createError, parseGraphQLError, isDataError, } from './error';
7
+ export { ConstructiveError, classify, createError, format, isConstructiveError, isPublicCode, isPublicError, isRetryable, parse, parseGraphQLError, toError, } from './error';
8
8
  export { execute, createGraphQLClient, } from './execute';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@constructive-io/graphql-query",
3
- "version": "4.5.4",
3
+ "version": "4.7.0",
4
4
  "description": "Constructive GraphQL Query",
5
5
  "author": "Constructive <developers@constructive.io>",
6
6
  "main": "index.js",
@@ -30,14 +30,15 @@
30
30
  },
31
31
  "dependencies": {
32
32
  "@0no-co/graphql.web": "^1.1.2",
33
+ "@constructive-io/errors": "^0.3.0",
33
34
  "@constructive-io/fetch": "^1.1.1",
34
- "@constructive-io/graphql-types": "^3.22.0",
35
+ "@constructive-io/graphql-types": "^3.23.0",
35
36
  "ajv": "^8.20.0",
36
- "gql-ast": "^3.17.0",
37
+ "gql-ast": "^3.18.0",
37
38
  "grafast": "1.0.2",
38
39
  "graphile-build-pg": "5.0.2",
39
40
  "graphile-config": "1.0.1",
40
- "graphile-settings": "^6.5.4",
41
+ "graphile-settings": "^6.6.0",
41
42
  "graphql": "16.13.0",
42
43
  "inflection": "^3.0.0",
43
44
  "inflekt": "^0.7.1",
@@ -54,5 +55,5 @@
54
55
  "devDependencies": {
55
56
  "makage": "^0.3.0"
56
57
  },
57
- "gitHead": "31f7cd3d3cc28cf069056eae5b2a0d4198d154a1"
58
+ "gitHead": "bb3269d48cdf2bc8f361bdd79b4833c921c13ec3"
58
59
  }