@constructive-io/errors 0.3.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/LICENSE +23 -0
- package/README.md +139 -0
- package/classify.d.ts +10 -0
- package/classify.js +20 -0
- package/define.d.ts +16 -0
- package/define.js +11 -0
- package/error.d.ts +32 -0
- package/error.js +47 -0
- package/esm/classify.d.ts +10 -0
- package/esm/classify.js +16 -0
- package/esm/define.d.ts +16 -0
- package/esm/define.js +8 -0
- package/esm/error.d.ts +32 -0
- package/esm/error.js +43 -0
- package/esm/factory.d.ts +35 -0
- package/esm/factory.js +49 -0
- package/esm/format.d.ts +24 -0
- package/esm/format.js +54 -0
- package/esm/generated/registry.generated.d.ts +27 -0
- package/esm/generated/registry.generated.js +601 -0
- package/esm/index.d.ts +9 -0
- package/esm/index.js +9 -0
- package/esm/interpolate.d.ts +6 -0
- package/esm/interpolate.js +11 -0
- package/esm/parse.d.ts +30 -0
- package/esm/parse.js +199 -0
- package/esm/pg.d.ts +14 -0
- package/esm/pg.js +49 -0
- package/esm/registry.d.ts +147 -0
- package/esm/registry.js +468 -0
- package/esm/types.d.ts +81 -0
- package/esm/types.js +10 -0
- package/factory.d.ts +35 -0
- package/factory.js +55 -0
- package/format.d.ts +24 -0
- package/format.js +59 -0
- package/generated/registry.generated.d.ts +27 -0
- package/generated/registry.generated.js +604 -0
- package/index.d.ts +9 -0
- package/index.js +25 -0
- package/interpolate.d.ts +6 -0
- package/interpolate.js +14 -0
- package/package.json +45 -0
- package/parse.d.ts +30 -0
- package/parse.js +203 -0
- package/pg.d.ts +14 -0
- package/pg.js +53 -0
- package/registry.d.ts +147 -0
- package/registry.js +474 -0
- package/types.d.ts +81 -0
- package/types.js +11 -0
package/registry.js
ADDED
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registry = exports.defineError = void 0;
|
|
4
|
+
exports.getDefinition = getDefinition;
|
|
5
|
+
exports.allCodes = allCodes;
|
|
6
|
+
const define_1 = require("./define");
|
|
7
|
+
const registry_generated_1 = require("./generated/registry.generated");
|
|
8
|
+
var define_2 = require("./define");
|
|
9
|
+
Object.defineProperty(exports, "defineError", { enumerable: true, get: function () { return define_2.defineError; } });
|
|
10
|
+
/**
|
|
11
|
+
* The curated Constructive error registry.
|
|
12
|
+
*
|
|
13
|
+
* These entries carry refined, typed context and hand-written copy for the
|
|
14
|
+
* codes that matter most (public auth/limit codes with real dashboard copy,
|
|
15
|
+
* native PostgreSQL constraint codes, and the pgpm CLI codes). They OVERRIDE
|
|
16
|
+
* the generated entries in {@link generatedRegistry} — every constructive-db
|
|
17
|
+
* code is present via generation; these just refine a subset.
|
|
18
|
+
*/
|
|
19
|
+
exports.registry = {
|
|
20
|
+
// ===========================================================================
|
|
21
|
+
// Auth / account (public) — copy sourced from dashboard auth-errors.ts
|
|
22
|
+
// ===========================================================================
|
|
23
|
+
ACCOUNT_EXISTS: (0, define_1.defineError)({
|
|
24
|
+
code: 'ACCOUNT_EXISTS',
|
|
25
|
+
class: 'public',
|
|
26
|
+
http: 409,
|
|
27
|
+
message: 'An account with this email already exists. Please sign in or use a different email.'
|
|
28
|
+
}),
|
|
29
|
+
ACCOUNT_NOT_FOUND: (0, define_1.defineError)({
|
|
30
|
+
code: 'ACCOUNT_NOT_FOUND',
|
|
31
|
+
class: 'public',
|
|
32
|
+
http: 404,
|
|
33
|
+
message: 'No account was found.'
|
|
34
|
+
}),
|
|
35
|
+
NO_ACCOUNT_EXISTS: (0, define_1.defineError)({
|
|
36
|
+
code: 'NO_ACCOUNT_EXISTS',
|
|
37
|
+
class: 'public',
|
|
38
|
+
http: 404,
|
|
39
|
+
message: 'No account exists for this user.'
|
|
40
|
+
}),
|
|
41
|
+
INVALID_CREDENTIALS: (0, define_1.defineError)({
|
|
42
|
+
code: 'INVALID_CREDENTIALS',
|
|
43
|
+
class: 'public',
|
|
44
|
+
http: 401,
|
|
45
|
+
message: 'Invalid email or password.'
|
|
46
|
+
}),
|
|
47
|
+
INCORRECT_PASSWORD: (0, define_1.defineError)({
|
|
48
|
+
code: 'INCORRECT_PASSWORD',
|
|
49
|
+
class: 'public',
|
|
50
|
+
http: 401,
|
|
51
|
+
message: 'The password you entered is incorrect. Please try again.'
|
|
52
|
+
}),
|
|
53
|
+
ACCOUNT_LOCKED_EXCEED_ATTEMPTS: (0, define_1.defineError)({
|
|
54
|
+
code: 'ACCOUNT_LOCKED_EXCEED_ATTEMPTS',
|
|
55
|
+
class: 'public',
|
|
56
|
+
http: 423,
|
|
57
|
+
message: 'Your account has been temporarily locked due to too many failed login attempts. Please try again later or reset your password.'
|
|
58
|
+
}),
|
|
59
|
+
ACCOUNT_DISABLED: (0, define_1.defineError)({
|
|
60
|
+
code: 'ACCOUNT_DISABLED',
|
|
61
|
+
class: 'public',
|
|
62
|
+
http: 403,
|
|
63
|
+
message: 'Your account has been disabled. Please contact support for assistance.'
|
|
64
|
+
}),
|
|
65
|
+
PASSWORD_INSECURE: (0, define_1.defineError)({
|
|
66
|
+
code: 'PASSWORD_INSECURE',
|
|
67
|
+
class: 'public',
|
|
68
|
+
http: 400,
|
|
69
|
+
message: 'This password is not secure enough. Please choose a stronger password.'
|
|
70
|
+
}),
|
|
71
|
+
PASSWORD_LEN: (0, define_1.defineError)({
|
|
72
|
+
code: 'PASSWORD_LEN',
|
|
73
|
+
class: 'public',
|
|
74
|
+
http: 400,
|
|
75
|
+
message: 'Password must be between 8 and 63 characters long.'
|
|
76
|
+
}),
|
|
77
|
+
EMAIL_NOT_VERIFIED: (0, define_1.defineError)({
|
|
78
|
+
code: 'EMAIL_NOT_VERIFIED',
|
|
79
|
+
class: 'public',
|
|
80
|
+
http: 403,
|
|
81
|
+
message: 'Please verify your email address to continue.'
|
|
82
|
+
}),
|
|
83
|
+
SIGN_UP_DISABLED: (0, define_1.defineError)({
|
|
84
|
+
code: 'SIGN_UP_DISABLED',
|
|
85
|
+
class: 'public',
|
|
86
|
+
http: 403,
|
|
87
|
+
message: 'Sign-up is currently disabled.'
|
|
88
|
+
}),
|
|
89
|
+
// ===========================================================================
|
|
90
|
+
// Auth / account (public) — migrated from the server graphile SAFE_ERROR_CODES
|
|
91
|
+
// allowlist so the registry (not a hand-maintained set) is the source of truth
|
|
92
|
+
// for what is user-facing.
|
|
93
|
+
// ===========================================================================
|
|
94
|
+
USER_NOT_AUTHENTICATED: (0, define_1.defineError)({
|
|
95
|
+
code: 'USER_NOT_AUTHENTICATED',
|
|
96
|
+
class: 'public',
|
|
97
|
+
http: 401,
|
|
98
|
+
message: 'You must be signed in to do that.'
|
|
99
|
+
}),
|
|
100
|
+
ACCOUNT_LOCKED: (0, define_1.defineError)({
|
|
101
|
+
code: 'ACCOUNT_LOCKED',
|
|
102
|
+
class: 'public',
|
|
103
|
+
http: 423,
|
|
104
|
+
message: 'Your account is locked. Please try again later or reset your password.'
|
|
105
|
+
}),
|
|
106
|
+
USER_NOT_FOUND: (0, define_1.defineError)({
|
|
107
|
+
code: 'USER_NOT_FOUND',
|
|
108
|
+
class: 'public',
|
|
109
|
+
http: 404,
|
|
110
|
+
message: 'No matching user was found.'
|
|
111
|
+
}),
|
|
112
|
+
NO_PRIMARY_EMAIL: (0, define_1.defineError)({
|
|
113
|
+
code: 'NO_PRIMARY_EMAIL',
|
|
114
|
+
class: 'public',
|
|
115
|
+
http: 400,
|
|
116
|
+
message: 'No primary email address is set for this account.'
|
|
117
|
+
}),
|
|
118
|
+
NO_CREDENTIALS: (0, define_1.defineError)({
|
|
119
|
+
code: 'NO_CREDENTIALS',
|
|
120
|
+
class: 'public',
|
|
121
|
+
http: 400,
|
|
122
|
+
message: 'No credentials were provided.'
|
|
123
|
+
}),
|
|
124
|
+
BAD_SIGNIN: (0, define_1.defineError)({
|
|
125
|
+
code: 'BAD_SIGNIN',
|
|
126
|
+
class: 'public',
|
|
127
|
+
http: 401,
|
|
128
|
+
message: 'Sign in failed. Please check your credentials and try again.'
|
|
129
|
+
}),
|
|
130
|
+
// ===========================================================================
|
|
131
|
+
// Auth method toggles (public) — app-level allow_* settings
|
|
132
|
+
// ===========================================================================
|
|
133
|
+
SSO_SIGN_IN_DISABLED: (0, define_1.defineError)({
|
|
134
|
+
code: 'SSO_SIGN_IN_DISABLED',
|
|
135
|
+
class: 'public',
|
|
136
|
+
http: 403,
|
|
137
|
+
message: 'Single sign-on is not enabled for sign in.'
|
|
138
|
+
}),
|
|
139
|
+
SSO_SIGN_UP_DISABLED: (0, define_1.defineError)({
|
|
140
|
+
code: 'SSO_SIGN_UP_DISABLED',
|
|
141
|
+
class: 'public',
|
|
142
|
+
http: 403,
|
|
143
|
+
message: 'Single sign-on is not enabled for sign up.'
|
|
144
|
+
}),
|
|
145
|
+
SSO_ACCOUNT_NOT_FOUND: (0, define_1.defineError)({
|
|
146
|
+
code: 'SSO_ACCOUNT_NOT_FOUND',
|
|
147
|
+
class: 'public',
|
|
148
|
+
http: 404,
|
|
149
|
+
message: 'No single sign-on account was found.'
|
|
150
|
+
}),
|
|
151
|
+
MAGIC_LINK_SIGN_IN_DISABLED: (0, define_1.defineError)({
|
|
152
|
+
code: 'MAGIC_LINK_SIGN_IN_DISABLED',
|
|
153
|
+
class: 'public',
|
|
154
|
+
http: 403,
|
|
155
|
+
message: 'Magic link sign in is disabled.'
|
|
156
|
+
}),
|
|
157
|
+
MAGIC_LINK_SIGN_UP_DISABLED: (0, define_1.defineError)({
|
|
158
|
+
code: 'MAGIC_LINK_SIGN_UP_DISABLED',
|
|
159
|
+
class: 'public',
|
|
160
|
+
http: 403,
|
|
161
|
+
message: 'Magic link sign up is disabled.'
|
|
162
|
+
}),
|
|
163
|
+
EMAIL_OTP_SIGN_IN_DISABLED: (0, define_1.defineError)({
|
|
164
|
+
code: 'EMAIL_OTP_SIGN_IN_DISABLED',
|
|
165
|
+
class: 'public',
|
|
166
|
+
http: 403,
|
|
167
|
+
message: 'Email one-time-code sign in is disabled.'
|
|
168
|
+
}),
|
|
169
|
+
// ===========================================================================
|
|
170
|
+
// PublicKeySignature / uploads / misc (public) — migrated from the allowlist
|
|
171
|
+
// ===========================================================================
|
|
172
|
+
INVALID_PUBLIC_KEY: (0, define_1.defineError)({
|
|
173
|
+
code: 'INVALID_PUBLIC_KEY',
|
|
174
|
+
class: 'public',
|
|
175
|
+
http: 400,
|
|
176
|
+
message: 'The public key is invalid.'
|
|
177
|
+
}),
|
|
178
|
+
INVALID_MESSAGE: (0, define_1.defineError)({
|
|
179
|
+
code: 'INVALID_MESSAGE',
|
|
180
|
+
class: 'public',
|
|
181
|
+
http: 400,
|
|
182
|
+
message: 'The message is invalid.'
|
|
183
|
+
}),
|
|
184
|
+
INVALID_SIGNATURE: (0, define_1.defineError)({
|
|
185
|
+
code: 'INVALID_SIGNATURE',
|
|
186
|
+
class: 'public',
|
|
187
|
+
http: 401,
|
|
188
|
+
message: 'The signature is invalid.'
|
|
189
|
+
}),
|
|
190
|
+
UPLOAD_MIMETYPE: (0, define_1.defineError)({
|
|
191
|
+
code: 'UPLOAD_MIMETYPE',
|
|
192
|
+
class: 'public',
|
|
193
|
+
http: 415,
|
|
194
|
+
message: 'This file type is not allowed.'
|
|
195
|
+
}),
|
|
196
|
+
SINGLETON_TABLE: (0, define_1.defineError)({
|
|
197
|
+
code: 'SINGLETON_TABLE',
|
|
198
|
+
class: 'public',
|
|
199
|
+
http: 409,
|
|
200
|
+
message: 'Only one record is allowed for this resource.'
|
|
201
|
+
}),
|
|
202
|
+
// ===========================================================================
|
|
203
|
+
// Invites (public)
|
|
204
|
+
// ===========================================================================
|
|
205
|
+
INVITE_NOT_FOUND: (0, define_1.defineError)({
|
|
206
|
+
code: 'INVITE_NOT_FOUND',
|
|
207
|
+
class: 'public',
|
|
208
|
+
http: 404,
|
|
209
|
+
message: 'The invitation code is invalid or has expired. Please check the code or request a new invitation.'
|
|
210
|
+
}),
|
|
211
|
+
INVITE_LIMIT: (0, define_1.defineError)({
|
|
212
|
+
code: 'INVITE_LIMIT',
|
|
213
|
+
class: 'public',
|
|
214
|
+
http: 429,
|
|
215
|
+
message: 'This invitation has reached its usage limit. Please request a new invitation.'
|
|
216
|
+
}),
|
|
217
|
+
INVITE_EMAIL_NOT_FOUND: (0, define_1.defineError)({
|
|
218
|
+
code: 'INVITE_EMAIL_NOT_FOUND',
|
|
219
|
+
class: 'public',
|
|
220
|
+
http: 404,
|
|
221
|
+
message: 'This email is not associated with the invitation. Please use the email address the invitation was sent to.'
|
|
222
|
+
}),
|
|
223
|
+
// ===========================================================================
|
|
224
|
+
// Authorization / step-up (public)
|
|
225
|
+
// ===========================================================================
|
|
226
|
+
UNAUTHENTICATED: (0, define_1.defineError)({
|
|
227
|
+
code: 'UNAUTHENTICATED',
|
|
228
|
+
class: 'public',
|
|
229
|
+
http: 401,
|
|
230
|
+
message: 'You must be signed in to do that.'
|
|
231
|
+
}),
|
|
232
|
+
FORBIDDEN: (0, define_1.defineError)({
|
|
233
|
+
code: 'FORBIDDEN',
|
|
234
|
+
class: 'public',
|
|
235
|
+
http: 403,
|
|
236
|
+
message: 'You do not have permission to do that.'
|
|
237
|
+
}),
|
|
238
|
+
STEP_UP_REQUIRED: (0, define_1.defineError)({
|
|
239
|
+
code: 'STEP_UP_REQUIRED',
|
|
240
|
+
class: 'public',
|
|
241
|
+
http: 403,
|
|
242
|
+
message: 'Additional verification is required to continue.'
|
|
243
|
+
}),
|
|
244
|
+
MFA_REQUIRED: (0, define_1.defineError)({
|
|
245
|
+
code: 'MFA_REQUIRED',
|
|
246
|
+
class: 'public',
|
|
247
|
+
http: 403,
|
|
248
|
+
message: 'Multi-factor authentication is required to continue.'
|
|
249
|
+
}),
|
|
250
|
+
INVALID_TOKEN: (0, define_1.defineError)({
|
|
251
|
+
code: 'INVALID_TOKEN',
|
|
252
|
+
class: 'public',
|
|
253
|
+
http: 401,
|
|
254
|
+
message: 'This link or token is invalid or has expired.'
|
|
255
|
+
}),
|
|
256
|
+
// ===========================================================================
|
|
257
|
+
// Limits (public, dynamic)
|
|
258
|
+
// ===========================================================================
|
|
259
|
+
LIMIT_REACHED: (0, define_1.defineError)({
|
|
260
|
+
code: 'LIMIT_REACHED',
|
|
261
|
+
class: 'public',
|
|
262
|
+
http: 429,
|
|
263
|
+
message: 'You have reached a plan limit for this resource.',
|
|
264
|
+
positional: ['resource', 'limit']
|
|
265
|
+
}),
|
|
266
|
+
RATE_LIMITED: (0, define_1.defineError)({
|
|
267
|
+
code: 'RATE_LIMITED',
|
|
268
|
+
class: 'public',
|
|
269
|
+
http: 429,
|
|
270
|
+
message: 'Too many requests. Please slow down and try again shortly.'
|
|
271
|
+
}),
|
|
272
|
+
// ===========================================================================
|
|
273
|
+
// Client / transport (public) — synthesized client-side by the GraphQL client
|
|
274
|
+
// for network, timeout, and HTTP-level failures (no DB/server origin).
|
|
275
|
+
// ===========================================================================
|
|
276
|
+
NETWORK_ERROR: (0, define_1.defineError)({
|
|
277
|
+
code: 'NETWORK_ERROR',
|
|
278
|
+
class: 'public',
|
|
279
|
+
http: 0,
|
|
280
|
+
message: 'Network error. Please check your connection and try again.'
|
|
281
|
+
}),
|
|
282
|
+
TIMEOUT_ERROR: (0, define_1.defineError)({
|
|
283
|
+
code: 'TIMEOUT_ERROR',
|
|
284
|
+
class: 'public',
|
|
285
|
+
http: 408,
|
|
286
|
+
message: 'The request timed out. Please try again.'
|
|
287
|
+
}),
|
|
288
|
+
BAD_USER_INPUT: (0, define_1.defineError)({
|
|
289
|
+
code: 'BAD_USER_INPUT',
|
|
290
|
+
class: 'public',
|
|
291
|
+
http: 400,
|
|
292
|
+
message: 'The request was invalid. Please check your input and try again.'
|
|
293
|
+
}),
|
|
294
|
+
VALIDATION_FAILED: (0, define_1.defineError)({
|
|
295
|
+
code: 'VALIDATION_FAILED',
|
|
296
|
+
class: 'public',
|
|
297
|
+
http: 400,
|
|
298
|
+
message: 'Validation failed. Please check your input and try again.'
|
|
299
|
+
}),
|
|
300
|
+
UNKNOWN_ERROR: (0, define_1.defineError)({
|
|
301
|
+
code: 'UNKNOWN_ERROR',
|
|
302
|
+
class: 'internal',
|
|
303
|
+
http: 500,
|
|
304
|
+
message: 'An unexpected error occurred.'
|
|
305
|
+
}),
|
|
306
|
+
// ===========================================================================
|
|
307
|
+
// Native PostgreSQL constraint violations (public) — synthetic codes mapped
|
|
308
|
+
// from SQLSTATE by parse().
|
|
309
|
+
// ===========================================================================
|
|
310
|
+
UNIQUE_VIOLATION: (0, define_1.defineError)({
|
|
311
|
+
code: 'UNIQUE_VIOLATION',
|
|
312
|
+
class: 'public',
|
|
313
|
+
http: 409,
|
|
314
|
+
message: 'That value already exists.'
|
|
315
|
+
}),
|
|
316
|
+
FOREIGN_KEY_VIOLATION: (0, define_1.defineError)({
|
|
317
|
+
code: 'FOREIGN_KEY_VIOLATION',
|
|
318
|
+
class: 'public',
|
|
319
|
+
http: 409,
|
|
320
|
+
message: 'A related record is required or still referenced.'
|
|
321
|
+
}),
|
|
322
|
+
NOT_NULL_VIOLATION: (0, define_1.defineError)({
|
|
323
|
+
code: 'NOT_NULL_VIOLATION',
|
|
324
|
+
class: 'public',
|
|
325
|
+
http: 400,
|
|
326
|
+
message: 'A required value is missing.'
|
|
327
|
+
}),
|
|
328
|
+
CHECK_VIOLATION: (0, define_1.defineError)({
|
|
329
|
+
code: 'CHECK_VIOLATION',
|
|
330
|
+
class: 'public',
|
|
331
|
+
http: 400,
|
|
332
|
+
message: 'A value did not satisfy a constraint.'
|
|
333
|
+
}),
|
|
334
|
+
EXCLUSION_VIOLATION: (0, define_1.defineError)({
|
|
335
|
+
code: 'EXCLUSION_VIOLATION',
|
|
336
|
+
class: 'public',
|
|
337
|
+
http: 409,
|
|
338
|
+
message: 'A value conflicts with an existing record.'
|
|
339
|
+
}),
|
|
340
|
+
// ===========================================================================
|
|
341
|
+
// pgpm CLI / engine (mostly internal) — behavior preserved from the former
|
|
342
|
+
// pgpm/types error-factory so existing call sites are unchanged.
|
|
343
|
+
// ===========================================================================
|
|
344
|
+
NOT_FOUND: (0, define_1.defineError)({
|
|
345
|
+
code: 'NOT_FOUND',
|
|
346
|
+
class: 'public',
|
|
347
|
+
http: 404,
|
|
348
|
+
message: 'Not found.'
|
|
349
|
+
}),
|
|
350
|
+
MODULE_NOT_FOUND: (0, define_1.defineError)({
|
|
351
|
+
code: 'MODULE_NOT_FOUND',
|
|
352
|
+
class: 'internal',
|
|
353
|
+
http: 404,
|
|
354
|
+
message: 'Module "{{name}}" not found in modules list.'
|
|
355
|
+
}),
|
|
356
|
+
INTERNAL_FAILURE: (0, define_1.defineError)({
|
|
357
|
+
code: 'INTERNAL_FAILURE',
|
|
358
|
+
class: 'internal',
|
|
359
|
+
http: 500,
|
|
360
|
+
message: 'Something went wrong: {{details}}'
|
|
361
|
+
}),
|
|
362
|
+
CONTEXT_MISSING: (0, define_1.defineError)({
|
|
363
|
+
code: 'CONTEXT_MISSING',
|
|
364
|
+
class: 'internal',
|
|
365
|
+
http: 500,
|
|
366
|
+
message: 'Context is not initialized. Did you run setup()?'
|
|
367
|
+
}),
|
|
368
|
+
NOT_IN_WORKSPACE: (0, define_1.defineError)({
|
|
369
|
+
code: 'NOT_IN_WORKSPACE',
|
|
370
|
+
class: 'internal',
|
|
371
|
+
http: 400,
|
|
372
|
+
message: 'You must be in a PGPM workspace. Initialize with "pgpm init workspace".'
|
|
373
|
+
}),
|
|
374
|
+
NOT_IN_WORKSPACE_MODULE: (0, define_1.defineError)({
|
|
375
|
+
code: 'NOT_IN_WORKSPACE_MODULE',
|
|
376
|
+
class: 'internal',
|
|
377
|
+
http: 400,
|
|
378
|
+
message: 'Error: You must be inside one of the workspace packages.'
|
|
379
|
+
}),
|
|
380
|
+
DEPLOYMENT_FAILED: (0, define_1.defineError)({
|
|
381
|
+
code: 'DEPLOYMENT_FAILED',
|
|
382
|
+
class: 'internal',
|
|
383
|
+
http: 500,
|
|
384
|
+
message: '{{type}} failed for module: {{module}}'
|
|
385
|
+
}),
|
|
386
|
+
UNSUPPORTED_TYPE_HINT: (0, define_1.defineError)({
|
|
387
|
+
code: 'UNSUPPORTED_TYPE_HINT',
|
|
388
|
+
class: 'internal',
|
|
389
|
+
http: 400,
|
|
390
|
+
message: 'Unsupported type hint: {{typeHint}}'
|
|
391
|
+
}),
|
|
392
|
+
BAD_FILE_NAME: (0, define_1.defineError)({
|
|
393
|
+
code: 'BAD_FILE_NAME',
|
|
394
|
+
class: 'internal',
|
|
395
|
+
http: 400,
|
|
396
|
+
message: 'Invalid file name: {{name}}'
|
|
397
|
+
}),
|
|
398
|
+
UNKNOWN_COMMAND: (0, define_1.defineError)({
|
|
399
|
+
code: 'UNKNOWN_COMMAND',
|
|
400
|
+
class: 'internal',
|
|
401
|
+
http: 400,
|
|
402
|
+
message: 'Unknown command: {{cmd}}'
|
|
403
|
+
}),
|
|
404
|
+
CHANGE_NOT_FOUND: (0, define_1.defineError)({
|
|
405
|
+
code: 'CHANGE_NOT_FOUND',
|
|
406
|
+
class: 'internal',
|
|
407
|
+
http: 404,
|
|
408
|
+
message: ({ change, plan }) => `Change '${change}' not found in plan${plan ? ` file: ${plan}` : ''}`
|
|
409
|
+
}),
|
|
410
|
+
TAG_NOT_FOUND: (0, define_1.defineError)({
|
|
411
|
+
code: 'TAG_NOT_FOUND',
|
|
412
|
+
class: 'internal',
|
|
413
|
+
http: 404,
|
|
414
|
+
message: ({ tag, project }) => `Tag '${tag}' not found${project ? ` in project ${project}` : ' in plan'}`
|
|
415
|
+
}),
|
|
416
|
+
PATH_NOT_FOUND: (0, define_1.defineError)({
|
|
417
|
+
code: 'PATH_NOT_FOUND',
|
|
418
|
+
class: 'internal',
|
|
419
|
+
http: 404,
|
|
420
|
+
message: ({ path, type }) => `${type} path not found: ${path}`
|
|
421
|
+
}),
|
|
422
|
+
OPERATION_FAILED: (0, define_1.defineError)({
|
|
423
|
+
code: 'OPERATION_FAILED',
|
|
424
|
+
class: 'internal',
|
|
425
|
+
http: 500,
|
|
426
|
+
message: ({ operation, target, reason }) => `${operation} failed${target ? ` for ${target}` : ''}${reason ? `: ${reason}` : ''}`
|
|
427
|
+
}),
|
|
428
|
+
PLAN_PARSE_ERROR: (0, define_1.defineError)({
|
|
429
|
+
code: 'PLAN_PARSE_ERROR',
|
|
430
|
+
class: 'internal',
|
|
431
|
+
http: 400,
|
|
432
|
+
message: ({ planPath, errors }) => `Failed to parse plan file ${planPath}: ${errors}`
|
|
433
|
+
}),
|
|
434
|
+
CIRCULAR_DEPENDENCY: (0, define_1.defineError)({
|
|
435
|
+
code: 'CIRCULAR_DEPENDENCY',
|
|
436
|
+
class: 'internal',
|
|
437
|
+
http: 400,
|
|
438
|
+
message: ({ module, dependency }) => `Circular reference detected: ${module} → ${dependency}`
|
|
439
|
+
}),
|
|
440
|
+
INVALID_NAME: (0, define_1.defineError)({
|
|
441
|
+
code: 'INVALID_NAME',
|
|
442
|
+
class: 'internal',
|
|
443
|
+
http: 400,
|
|
444
|
+
message: ({ name, type, rules }) => `Invalid ${type} name: ${name}${rules ? `. ${rules}` : ''}`
|
|
445
|
+
}),
|
|
446
|
+
WORKSPACE_OPERATION_ERROR: (0, define_1.defineError)({
|
|
447
|
+
code: 'WORKSPACE_OPERATION_ERROR',
|
|
448
|
+
class: 'internal',
|
|
449
|
+
http: 400,
|
|
450
|
+
message: ({ operation }) => `Cannot perform non-recursive ${operation} on workspace. Use recursive=true or specify a target module.`
|
|
451
|
+
}),
|
|
452
|
+
FILE_NOT_FOUND: (0, define_1.defineError)({
|
|
453
|
+
code: 'FILE_NOT_FOUND',
|
|
454
|
+
class: 'internal',
|
|
455
|
+
http: 404,
|
|
456
|
+
message: ({ filePath, type }) => `${type ? `${type} file` : 'File'} not found: ${filePath}`
|
|
457
|
+
})
|
|
458
|
+
};
|
|
459
|
+
/**
|
|
460
|
+
* All known definitions, keyed by code: every constructive-db code (generated)
|
|
461
|
+
* merged with the curated entries, curated winning on conflict.
|
|
462
|
+
*/
|
|
463
|
+
const allDefinitions = {
|
|
464
|
+
...registry_generated_1.generatedRegistry,
|
|
465
|
+
...exports.registry
|
|
466
|
+
};
|
|
467
|
+
/** Look up a definition by code (from anywhere, not just typed keys). */
|
|
468
|
+
function getDefinition(code) {
|
|
469
|
+
return allDefinitions[code];
|
|
470
|
+
}
|
|
471
|
+
/** Every registered code (curated + generated). */
|
|
472
|
+
function allCodes() {
|
|
473
|
+
return Object.keys(allDefinitions);
|
|
474
|
+
}
|
package/types.d.ts
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core types for the Constructive error system.
|
|
3
|
+
*
|
|
4
|
+
* A Constructive error is identified by a stable, machine-readable `code`
|
|
5
|
+
* (ALL_CAPS). Human-facing copy is kept separate (in i18n catalogs) so the
|
|
6
|
+
* same code can be localized. Every code is classified as `public` (safe to
|
|
7
|
+
* surface to end users) or `internal` (an invariant/developer error that must
|
|
8
|
+
* be masked in production).
|
|
9
|
+
*/
|
|
10
|
+
/** Values that can be interpolated into a message or carried as error context. */
|
|
11
|
+
export type ContextValue = string | number | boolean | null | undefined;
|
|
12
|
+
/** Structured, machine-readable context attached to an error. */
|
|
13
|
+
export type ErrorContext = Record<string, ContextValue>;
|
|
14
|
+
/** A context with no parameters (codes that take no dynamic values). */
|
|
15
|
+
export type EmptyContext = Record<never, never>;
|
|
16
|
+
/**
|
|
17
|
+
* Classification of a code.
|
|
18
|
+
* - `public` — user-facing; safe to send to clients as-is.
|
|
19
|
+
* - `internal` — developer/invariant error; masked in production.
|
|
20
|
+
*/
|
|
21
|
+
export type ErrorClass = 'public' | 'internal';
|
|
22
|
+
/**
|
|
23
|
+
* A single registry entry describing one error code. This is the source of
|
|
24
|
+
* truth; message copy, factories, and classification all derive from it.
|
|
25
|
+
*/
|
|
26
|
+
export interface ErrorDefinition<C extends ErrorContext = EmptyContext> {
|
|
27
|
+
/** Stable machine code, e.g. `ACCOUNT_EXISTS`. */
|
|
28
|
+
code: string;
|
|
29
|
+
/** Public (surface to users) vs internal (mask in prod). */
|
|
30
|
+
class: ErrorClass;
|
|
31
|
+
/** HTTP status hint for transports that want one. */
|
|
32
|
+
http: number;
|
|
33
|
+
/**
|
|
34
|
+
* Default message. Either an i18n template using `{{var}}` placeholders
|
|
35
|
+
* (preferred — localizable) or a function for messages with conditional
|
|
36
|
+
* logic that a flat template cannot express.
|
|
37
|
+
*/
|
|
38
|
+
message: string | ((context: C) => string);
|
|
39
|
+
/** Documented context parameter names (for tooling / codegen). */
|
|
40
|
+
params?: readonly (keyof C & string)[];
|
|
41
|
+
/**
|
|
42
|
+
* For legacy dynamic DB throws of the form `CODE (arg0, arg1)`, maps the
|
|
43
|
+
* positional args to context keys so `parse()` can recover structure.
|
|
44
|
+
*/
|
|
45
|
+
positional?: readonly (keyof C & string)[];
|
|
46
|
+
}
|
|
47
|
+
/** The canonical, normalized result of parsing an error from any source. */
|
|
48
|
+
export interface ParsedError {
|
|
49
|
+
/** Constructive code if one could be determined, else `null`. */
|
|
50
|
+
code: string | null;
|
|
51
|
+
/** Structured context recovered from the error (may be empty). */
|
|
52
|
+
context: ErrorContext;
|
|
53
|
+
/** Classification (`internal` when the code is unknown — fail safe). */
|
|
54
|
+
class: ErrorClass;
|
|
55
|
+
/** `true` when `code` is present in the registry. */
|
|
56
|
+
known: boolean;
|
|
57
|
+
/** Best-effort raw message from the source error. */
|
|
58
|
+
rawMessage: string;
|
|
59
|
+
/** Original PostgreSQL SQLSTATE, when the source was a pg error. */
|
|
60
|
+
sqlState?: string;
|
|
61
|
+
/** The original error, for logging/debugging. */
|
|
62
|
+
originalError: unknown;
|
|
63
|
+
}
|
|
64
|
+
/** Extended PostgreSQL error fields (populated by pg-protocol on errors). */
|
|
65
|
+
export interface PgErrorFields {
|
|
66
|
+
code?: string;
|
|
67
|
+
detail?: string;
|
|
68
|
+
hint?: string;
|
|
69
|
+
where?: string;
|
|
70
|
+
position?: string;
|
|
71
|
+
internalPosition?: string;
|
|
72
|
+
internalQuery?: string;
|
|
73
|
+
schema?: string;
|
|
74
|
+
table?: string;
|
|
75
|
+
column?: string;
|
|
76
|
+
dataType?: string;
|
|
77
|
+
constraint?: string;
|
|
78
|
+
file?: string;
|
|
79
|
+
line?: string;
|
|
80
|
+
routine?: string;
|
|
81
|
+
}
|
package/types.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Core types for the Constructive error system.
|
|
4
|
+
*
|
|
5
|
+
* A Constructive error is identified by a stable, machine-readable `code`
|
|
6
|
+
* (ALL_CAPS). Human-facing copy is kept separate (in i18n catalogs) so the
|
|
7
|
+
* same code can be localized. Every code is classified as `public` (safe to
|
|
8
|
+
* surface to end users) or `internal` (an invariant/developer error that must
|
|
9
|
+
* be masked in production).
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|