velocious 1.0.577 → 1.0.578
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 +11 -5
- package/build/background-jobs/main.js +2 -2
- package/build/configuration-types.js +1 -0
- package/build/configuration.js +52 -10
- package/build/database/drivers/mysql/structure-sql.js +70 -9
- package/build/database/query/with-count.js +8 -8
- package/build/database/record/record-not-found-error.js +1 -0
- package/build/frontend-model-controller.js +71 -69
- package/build/frontend-models/base.js +10 -1
- package/build/src/background-jobs/main.js +3 -3
- package/build/src/configuration-types.d.ts +5 -0
- package/build/src/configuration-types.d.ts.map +1 -1
- package/build/src/configuration-types.js +2 -1
- package/build/src/configuration.d.ts +13 -1
- package/build/src/configuration.d.ts.map +1 -1
- package/build/src/configuration.js +52 -11
- package/build/src/database/drivers/mysql/structure-sql.d.ts +11 -0
- package/build/src/database/drivers/mysql/structure-sql.d.ts.map +1 -1
- package/build/src/database/drivers/mysql/structure-sql.js +61 -10
- package/build/src/database/query/with-count.js +8 -8
- package/build/src/database/record/record-not-found-error.d.ts +1 -0
- package/build/src/database/record/record-not-found-error.d.ts.map +1 -1
- package/build/src/database/record/record-not-found-error.js +2 -1
- package/build/src/frontend-model-controller.d.ts +10 -10
- package/build/src/frontend-model-controller.d.ts.map +1 -1
- package/build/src/frontend-model-controller.js +73 -67
- package/build/src/frontend-models/base.d.ts.map +1 -1
- package/build/src/frontend-models/base.js +11 -2
- package/build/src/velocious-error.d.ts +10 -0
- package/build/src/velocious-error.d.ts.map +1 -1
- package/build/src/velocious-error.js +8 -2
- package/build/velocious-error.js +7 -1
- package/package.json +2 -2
- package/src/background-jobs/main.js +2 -2
- package/src/configuration-types.js +1 -0
- package/src/configuration.js +52 -10
- package/src/database/drivers/mysql/structure-sql.js +70 -9
- package/src/database/query/with-count.js +8 -8
- package/src/database/record/record-not-found-error.js +1 -0
- package/src/frontend-model-controller.js +71 -69
- package/src/frontend-models/base.js +10 -1
- package/src/velocious-error.js +7 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
|
+
import {randomUUID} from "node:crypto"
|
|
3
4
|
import * as inflection from "inflection"
|
|
4
5
|
import Controller from "./controller.js"
|
|
5
6
|
import FrontendModelBaseResource from "./frontend-model-resource/base-resource.js"
|
|
@@ -14,6 +15,7 @@ import {assignSafeProperty, deserializeFrontendModelTransportValue, isBackendMod
|
|
|
14
15
|
import {requestDetails} from "./error-reporting/request-details.js"
|
|
15
16
|
import RoutesResolver from "./routes/resolver.js"
|
|
16
17
|
import {ValidationError} from "./database/record/index.js"
|
|
18
|
+
import RecordNotFoundError from "./database/record/record-not-found-error.js"
|
|
17
19
|
import { normalizeDateStringForWrite } from "./database/datetime-storage.js"
|
|
18
20
|
import VelociousError from "./velocious-error.js"
|
|
19
21
|
import isDate from "./utils/is-date.js"
|
|
@@ -231,31 +233,18 @@ function frontendModelErrorHasVelociousMetadata(error) {
|
|
|
231
233
|
return isPlainObject(errorRecord.velocious)
|
|
232
234
|
}
|
|
233
235
|
|
|
234
|
-
/**
|
|
235
|
-
* Whether the error has a frontend-model error type marker.
|
|
236
|
-
* @param {unknown} error - Caught error.
|
|
237
|
-
* @returns {boolean} Whether the error has an error type.
|
|
238
|
-
*/
|
|
239
|
-
function frontendModelErrorHasErrorType(error) {
|
|
240
|
-
if (!error || typeof error !== "object") return false
|
|
241
|
-
|
|
242
|
-
// Runtime checks above narrow this caught value to the marker record shape.
|
|
243
|
-
const errorRecord = /** @type {{errorType?: string}} */ (error)
|
|
244
|
-
|
|
245
|
-
return typeof errorRecord.errorType === "string" && errorRecord.errorType.length > 0
|
|
246
|
-
}
|
|
247
|
-
|
|
248
236
|
/**
|
|
249
237
|
* Whether the error is an expected frontend-model user-flow failure.
|
|
250
238
|
* @param {unknown} error - Caught error.
|
|
251
239
|
* @returns {boolean} Whether the error is expected.
|
|
252
240
|
*/
|
|
253
241
|
function frontendModelExpectedError(error) {
|
|
242
|
+
if (error instanceof RecordNotFoundError) return true
|
|
254
243
|
if (error instanceof ValidationError) return true
|
|
255
244
|
if (error instanceof VelociousError && error.safeToExpose) return true
|
|
256
245
|
if (frontendModelErrorHasVelociousMetadata(error)) return true
|
|
257
246
|
|
|
258
|
-
return
|
|
247
|
+
return false
|
|
259
248
|
}
|
|
260
249
|
|
|
261
250
|
/**
|
|
@@ -285,6 +274,10 @@ function frontendModelVelociousMetadataForError(error) {
|
|
|
285
274
|
* @returns {string} - Message safe to return to API clients.
|
|
286
275
|
*/
|
|
287
276
|
function frontendModelClientMessageForError(error) {
|
|
277
|
+
if (error instanceof RecordNotFoundError) {
|
|
278
|
+
return "Record not found."
|
|
279
|
+
}
|
|
280
|
+
|
|
288
281
|
if (error instanceof VelociousError && error.safeToExpose) {
|
|
289
282
|
return error.message
|
|
290
283
|
}
|
|
@@ -323,6 +316,10 @@ function frontendModelDebugPayloadForError({configuration, environment, error})
|
|
|
323
316
|
return {}
|
|
324
317
|
}
|
|
325
318
|
|
|
319
|
+
if (error instanceof RecordNotFoundError) {
|
|
320
|
+
return {}
|
|
321
|
+
}
|
|
322
|
+
|
|
326
323
|
if (frontendModelErrorHasVelociousMetadata(error)) {
|
|
327
324
|
return {}
|
|
328
325
|
}
|
|
@@ -3098,11 +3095,16 @@ export default class FrontendModelController extends Controller {
|
|
|
3098
3095
|
/**
|
|
3099
3096
|
* Runs frontend model error payload.
|
|
3100
3097
|
* @param {string} errorMessage - Error message.
|
|
3098
|
+
* @param {object} [options] - Structured error fields.
|
|
3099
|
+
* @param {import("./configuration-types.js").ClientErrorPayloadReporterPayload} [options.details] - Client-safe details.
|
|
3100
|
+
* @param {"application_error" | "authorization_error" | "internal_error" | "record_not_found" | "validation_error"} [options.errorType] - Stable client-facing error category.
|
|
3101
3101
|
* @returns {Record<string, ?>} - Error payload.
|
|
3102
3102
|
*/
|
|
3103
|
-
frontendModelErrorPayload(errorMessage) {
|
|
3103
|
+
frontendModelErrorPayload(errorMessage, options = {}) {
|
|
3104
3104
|
return {
|
|
3105
|
+
...(options.details ? {details: options.details} : {}),
|
|
3105
3106
|
errorMessage,
|
|
3107
|
+
...(options.errorType ? {errorType: options.errorType} : {}),
|
|
3106
3108
|
status: "error"
|
|
3107
3109
|
}
|
|
3108
3110
|
}
|
|
@@ -3127,6 +3129,7 @@ export default class FrontendModelController extends Controller {
|
|
|
3127
3129
|
*/
|
|
3128
3130
|
frontendModelEndpointErrorContext({action, commandType, error, model, requestId}) {
|
|
3129
3131
|
let resolvedModel = model
|
|
3132
|
+
const expectedError = frontendModelExpectedError(error)
|
|
3130
3133
|
|
|
3131
3134
|
if (!resolvedModel) {
|
|
3132
3135
|
const cachedParams = this._frontendModelParamsOverride || this._frontendModelParams
|
|
@@ -3138,7 +3141,8 @@ export default class FrontendModelController extends Controller {
|
|
|
3138
3141
|
action,
|
|
3139
3142
|
commandType,
|
|
3140
3143
|
controller: this.constructor.name,
|
|
3141
|
-
expectedError:
|
|
3144
|
+
...(expectedError ? {} : {correlationId: randomUUID()}),
|
|
3145
|
+
expectedError,
|
|
3142
3146
|
frontendModelEndpoint: true,
|
|
3143
3147
|
model: resolvedModel,
|
|
3144
3148
|
requestId
|
|
@@ -3154,6 +3158,22 @@ export default class FrontendModelController extends Controller {
|
|
|
3154
3158
|
async frontendModelClientErrorPayloadForError(error, endpointErrorContext) {
|
|
3155
3159
|
const velociousMetadata = frontendModelVelociousMetadataForError(error)
|
|
3156
3160
|
const normalizedError = error instanceof Error ? error : new Error(String(error))
|
|
3161
|
+
/** @type {import("./configuration-types.js").ClientErrorPayloadReporterPayload} */
|
|
3162
|
+
const safeErrorPayload = {}
|
|
3163
|
+
|
|
3164
|
+
if (error instanceof VelociousError && error.safeToExpose) {
|
|
3165
|
+
if (error.errorType) safeErrorPayload.errorType = error.errorType
|
|
3166
|
+
if (error.details) safeErrorPayload.details = error.details
|
|
3167
|
+
} else if (error instanceof RecordNotFoundError) {
|
|
3168
|
+
safeErrorPayload.errorType = "record_not_found"
|
|
3169
|
+
} else if (velociousMetadata) {
|
|
3170
|
+
if (typeof velociousMetadata.errorType === "string") {
|
|
3171
|
+
safeErrorPayload.errorType = velociousMetadata.errorType
|
|
3172
|
+
}
|
|
3173
|
+
if (isPlainObject(velociousMetadata.details)) {
|
|
3174
|
+
safeErrorPayload.details = velociousMetadata.details
|
|
3175
|
+
}
|
|
3176
|
+
}
|
|
3157
3177
|
|
|
3158
3178
|
let validationErrorsPayload = {}
|
|
3159
3179
|
|
|
@@ -3179,7 +3199,14 @@ export default class FrontendModelController extends Controller {
|
|
|
3179
3199
|
}
|
|
3180
3200
|
}
|
|
3181
3201
|
|
|
3202
|
+
const reporterPayload = await this.getConfiguration().clientErrorPayloadForError({
|
|
3203
|
+
context: endpointErrorContext || {controller: this.constructor.name},
|
|
3204
|
+
error: normalizedError,
|
|
3205
|
+
request: this.getRequest()
|
|
3206
|
+
})
|
|
3207
|
+
|
|
3182
3208
|
return {
|
|
3209
|
+
...reporterPayload,
|
|
3183
3210
|
...this.frontendModelErrorPayload(frontendModelClientMessageForError(error)),
|
|
3184
3211
|
...frontendModelDebugPayloadForError({
|
|
3185
3212
|
configuration: this.getConfiguration(),
|
|
@@ -3187,28 +3214,22 @@ export default class FrontendModelController extends Controller {
|
|
|
3187
3214
|
error
|
|
3188
3215
|
}),
|
|
3189
3216
|
...(velociousMetadata ? {velocious: velociousMetadata} : {}),
|
|
3217
|
+
...safeErrorPayload,
|
|
3190
3218
|
...validationErrorsPayload,
|
|
3191
|
-
...(
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
request: this.getRequest()
|
|
3195
|
-
}))
|
|
3219
|
+
...(!endpointErrorContext?.expectedError && endpointErrorContext?.correlationId
|
|
3220
|
+
? {correlationId: endpointErrorContext.correlationId, errorType: "internal_error"}
|
|
3221
|
+
: {})
|
|
3196
3222
|
}
|
|
3197
3223
|
}
|
|
3198
3224
|
|
|
3199
3225
|
/**
|
|
3200
3226
|
* Runs frontend model log endpoint error.
|
|
3201
3227
|
* @param {object} args - Error log args.
|
|
3202
|
-
* @param {string} args.action - Endpoint/action label.
|
|
3203
3228
|
* @param {?} args.error - Caught error.
|
|
3204
|
-
* @param {
|
|
3205
|
-
* @param {string | undefined} [args.model] - Request model name when available.
|
|
3206
|
-
* @param {string | undefined} [args.requestId] - Batch request id when available.
|
|
3229
|
+
* @param {FrontendModelEndpointErrorContext} args.errorContext - Shared client/logging error context.
|
|
3207
3230
|
* @returns {Promise<void>} - Resolves after logging.
|
|
3208
3231
|
*/
|
|
3209
|
-
async frontendModelLogEndpointError({
|
|
3210
|
-
const errorContext = this.frontendModelEndpointErrorContext({action, commandType, error, model, requestId})
|
|
3211
|
-
|
|
3232
|
+
async frontendModelLogEndpointError({error, errorContext}) {
|
|
3212
3233
|
// Expected user-flow errors are surfaced to clients by
|
|
3213
3234
|
// frontendModelClientErrorPayloadForError, but skipped here so monitoring
|
|
3214
3235
|
// stays focused on real backend failures.
|
|
@@ -3219,11 +3240,12 @@ export default class FrontendModelController extends Controller {
|
|
|
3219
3240
|
: String(error)
|
|
3220
3241
|
|
|
3221
3242
|
await this.logger.error(() => ["Frontend model endpoint request failed", {
|
|
3222
|
-
action,
|
|
3223
|
-
commandType,
|
|
3243
|
+
action: errorContext.action,
|
|
3244
|
+
commandType: errorContext.commandType,
|
|
3245
|
+
correlationId: errorContext.correlationId,
|
|
3224
3246
|
error: errorMessage,
|
|
3225
3247
|
model: errorContext.model,
|
|
3226
|
-
requestId
|
|
3248
|
+
requestId: errorContext.requestId
|
|
3227
3249
|
}])
|
|
3228
3250
|
|
|
3229
3251
|
// Surface genuinely unexpected backend failures on the framework-error
|
|
@@ -3231,6 +3253,7 @@ export default class FrontendModelController extends Controller {
|
|
|
3231
3253
|
// controller silently swallowing them behind the generic "Request
|
|
3232
3254
|
// failed." client message.
|
|
3233
3255
|
const errorPayload = {
|
|
3256
|
+
correlationId: errorContext.correlationId,
|
|
3234
3257
|
context: errorContext,
|
|
3235
3258
|
error: error instanceof Error ? error : new Error(String(error)),
|
|
3236
3259
|
request: this.getRequest(),
|
|
@@ -3257,7 +3280,7 @@ export default class FrontendModelController extends Controller {
|
|
|
3257
3280
|
} catch (error) {
|
|
3258
3281
|
const errorContext = this.frontendModelEndpointErrorContext({action, commandType: action, error})
|
|
3259
3282
|
|
|
3260
|
-
await this.frontendModelLogEndpointError({
|
|
3283
|
+
await this.frontendModelLogEndpointError({error, errorContext})
|
|
3261
3284
|
|
|
3262
3285
|
await this.render({
|
|
3263
3286
|
json: /** @type {Record<string, ?>} */ (serializeFrontendModelTransportValue(await this.frontendModelClientErrorPayloadForError(error, errorContext), this.transportSerializationOptions()))
|
|
@@ -3334,7 +3357,7 @@ export default class FrontendModelController extends Controller {
|
|
|
3334
3357
|
)
|
|
3335
3358
|
|
|
3336
3359
|
if (!model) {
|
|
3337
|
-
return this.frontendModelErrorPayload(`${modelClass.name} not found
|
|
3360
|
+
return this.frontendModelErrorPayload(`${modelClass.name} not found.`, {errorType: "record_not_found"})
|
|
3338
3361
|
}
|
|
3339
3362
|
|
|
3340
3363
|
const serializedModel = await resource.serialize(model, "create")
|
|
@@ -3343,7 +3366,7 @@ export default class FrontendModelController extends Controller {
|
|
|
3343
3366
|
}
|
|
3344
3367
|
|
|
3345
3368
|
if ((typeof id !== "string" && typeof id !== "number") || `${id}`.length < 1) {
|
|
3346
|
-
return this.frontendModelErrorPayload("Expected model id.")
|
|
3369
|
+
return this.frontendModelErrorPayload("Expected model id.", {errorType: "validation_error"})
|
|
3347
3370
|
}
|
|
3348
3371
|
|
|
3349
3372
|
if (action === "attach") {
|
|
@@ -3361,7 +3384,7 @@ export default class FrontendModelController extends Controller {
|
|
|
3361
3384
|
const model = await this.frontendModelFindRecord("attach", id)
|
|
3362
3385
|
|
|
3363
3386
|
if (!model) {
|
|
3364
|
-
return this.frontendModelErrorPayload(`${modelClass.name} not found
|
|
3387
|
+
return this.frontendModelErrorPayload(`${modelClass.name} not found.`, {errorType: "record_not_found"})
|
|
3365
3388
|
}
|
|
3366
3389
|
|
|
3367
3390
|
await model.getAttachmentByName(attachmentName).attach(attachmentInput)
|
|
@@ -3377,13 +3400,13 @@ export default class FrontendModelController extends Controller {
|
|
|
3377
3400
|
const model = await this.frontendModelFindRecord("download", id)
|
|
3378
3401
|
|
|
3379
3402
|
if (!model) {
|
|
3380
|
-
return this.frontendModelErrorPayload(`${modelClass.name} not found
|
|
3403
|
+
return this.frontendModelErrorPayload(`${modelClass.name} not found.`, {errorType: "record_not_found"})
|
|
3381
3404
|
}
|
|
3382
3405
|
|
|
3383
3406
|
const downloadedAttachment = await model.getAttachmentByName(attachmentParams.attachmentName).download(attachmentParams.attachmentId)
|
|
3384
3407
|
|
|
3385
3408
|
if (!downloadedAttachment) {
|
|
3386
|
-
return this.frontendModelErrorPayload("Attachment not found.")
|
|
3409
|
+
return this.frontendModelErrorPayload("Attachment not found.", {errorType: "record_not_found"})
|
|
3387
3410
|
}
|
|
3388
3411
|
|
|
3389
3412
|
return {
|
|
@@ -3406,7 +3429,7 @@ export default class FrontendModelController extends Controller {
|
|
|
3406
3429
|
const model = await this.frontendModelFindRecord("url", id)
|
|
3407
3430
|
|
|
3408
3431
|
if (!model) {
|
|
3409
|
-
return this.frontendModelErrorPayload(`${modelClass.name} not found
|
|
3432
|
+
return this.frontendModelErrorPayload(`${modelClass.name} not found.`, {errorType: "record_not_found"})
|
|
3410
3433
|
}
|
|
3411
3434
|
|
|
3412
3435
|
const url = await model.getAttachmentByName(attachmentParams.attachmentName).url(attachmentParams.attachmentId)
|
|
@@ -3428,7 +3451,7 @@ export default class FrontendModelController extends Controller {
|
|
|
3428
3451
|
const model = await this.frontendModelFindRecord("attachmentList", id)
|
|
3429
3452
|
|
|
3430
3453
|
if (!model) {
|
|
3431
|
-
return this.frontendModelErrorPayload(`${modelClass.name} not found
|
|
3454
|
+
return this.frontendModelErrorPayload(`${modelClass.name} not found.`, {errorType: "record_not_found"})
|
|
3432
3455
|
}
|
|
3433
3456
|
|
|
3434
3457
|
const attachments = await model.getAttachmentByName(attachmentParams.attachmentName).listMetadata()
|
|
@@ -3443,7 +3466,7 @@ export default class FrontendModelController extends Controller {
|
|
|
3443
3466
|
const model = await this.frontendModelFindRecord("find", id)
|
|
3444
3467
|
|
|
3445
3468
|
if (!model) {
|
|
3446
|
-
return this.frontendModelErrorPayload(`${modelClass.name} not found
|
|
3469
|
+
return this.frontendModelErrorPayload(`${modelClass.name} not found.`, {errorType: "record_not_found"})
|
|
3447
3470
|
}
|
|
3448
3471
|
|
|
3449
3472
|
await this.frontendModelComputeAbilities([model])
|
|
@@ -3459,7 +3482,7 @@ export default class FrontendModelController extends Controller {
|
|
|
3459
3482
|
const model = await this.frontendModelFindRecord("update", id)
|
|
3460
3483
|
|
|
3461
3484
|
if (!model) {
|
|
3462
|
-
return this.frontendModelErrorPayload(`${modelClass.name} not found
|
|
3485
|
+
return this.frontendModelErrorPayload(`${modelClass.name} not found.`, {errorType: "record_not_found"})
|
|
3463
3486
|
}
|
|
3464
3487
|
|
|
3465
3488
|
const updatedModel = await resource.update(model, mutationAttributes.attributes, {
|
|
@@ -3475,7 +3498,7 @@ export default class FrontendModelController extends Controller {
|
|
|
3475
3498
|
const model = await this.frontendModelFindRecord("destroy", id)
|
|
3476
3499
|
|
|
3477
3500
|
if (!model) {
|
|
3478
|
-
return this.frontendModelErrorPayload(`${modelClass.name} not found
|
|
3501
|
+
return this.frontendModelErrorPayload(`${modelClass.name} not found.`, {errorType: "record_not_found"})
|
|
3479
3502
|
}
|
|
3480
3503
|
|
|
3481
3504
|
await resource.destroy(model)
|
|
@@ -3624,12 +3647,7 @@ export default class FrontendModelController extends Controller {
|
|
|
3624
3647
|
: undefined
|
|
3625
3648
|
})
|
|
3626
3649
|
|
|
3627
|
-
await this.frontendModelLogEndpointError({
|
|
3628
|
-
action: errorContext.action,
|
|
3629
|
-
commandType: errorContext.commandType,
|
|
3630
|
-
error,
|
|
3631
|
-
model: errorContext.model
|
|
3632
|
-
})
|
|
3650
|
+
await this.frontendModelLogEndpointError({error, errorContext})
|
|
3633
3651
|
|
|
3634
3652
|
results.push({
|
|
3635
3653
|
idempotencyKey,
|
|
@@ -3724,12 +3742,7 @@ export default class FrontendModelController extends Controller {
|
|
|
3724
3742
|
model: mutation.model
|
|
3725
3743
|
})
|
|
3726
3744
|
|
|
3727
|
-
await this.frontendModelLogEndpointError({
|
|
3728
|
-
action: errorContext.action,
|
|
3729
|
-
commandType: errorContext.commandType,
|
|
3730
|
-
error,
|
|
3731
|
-
model: errorContext.model
|
|
3732
|
-
})
|
|
3745
|
+
await this.frontendModelLogEndpointError({error, errorContext})
|
|
3733
3746
|
|
|
3734
3747
|
return {
|
|
3735
3748
|
response: await this.frontendModelClientErrorPayloadForError(error, errorContext),
|
|
@@ -3754,12 +3767,7 @@ export default class FrontendModelController extends Controller {
|
|
|
3754
3767
|
model: mutation.model
|
|
3755
3768
|
})
|
|
3756
3769
|
|
|
3757
|
-
await this.frontendModelLogEndpointError({
|
|
3758
|
-
action: errorContext.action,
|
|
3759
|
-
commandType: errorContext.commandType,
|
|
3760
|
-
error,
|
|
3761
|
-
model: errorContext.model
|
|
3762
|
-
})
|
|
3770
|
+
await this.frontendModelLogEndpointError({error, errorContext})
|
|
3763
3771
|
|
|
3764
3772
|
return {
|
|
3765
3773
|
response,
|
|
@@ -4275,13 +4283,7 @@ export default class FrontendModelController extends Controller {
|
|
|
4275
4283
|
requestId
|
|
4276
4284
|
})
|
|
4277
4285
|
|
|
4278
|
-
await this.frontendModelLogEndpointError({
|
|
4279
|
-
action: errorContext.action,
|
|
4280
|
-
commandType: errorContext.commandType,
|
|
4281
|
-
error,
|
|
4282
|
-
model: errorContext.model,
|
|
4283
|
-
requestId: errorContext.requestId
|
|
4284
|
-
})
|
|
4286
|
+
await this.frontendModelLogEndpointError({error, errorContext})
|
|
4285
4287
|
|
|
4286
4288
|
responses.push({
|
|
4287
4289
|
requestId,
|
|
@@ -4506,7 +4508,7 @@ export default class FrontendModelController extends Controller {
|
|
|
4506
4508
|
} catch (error) {
|
|
4507
4509
|
const errorContext = this.frontendModelEndpointErrorContext({action: "frontendCustomCommand", commandType: "custom-command", error})
|
|
4508
4510
|
|
|
4509
|
-
await this.frontendModelLogEndpointError({
|
|
4511
|
+
await this.frontendModelLogEndpointError({error, errorContext})
|
|
4510
4512
|
|
|
4511
4513
|
await this.render({
|
|
4512
4514
|
json: /** @type {Record<string, ?>} */ (serializeFrontendModelTransportValue(await this.frontendModelClientErrorPayloadForError(error, errorContext), this.transportSerializationOptions()))
|
|
@@ -4744,7 +4744,10 @@ export default class FrontendModelBase {
|
|
|
4744
4744
|
? response.errorMessage
|
|
4745
4745
|
: `Request failed for ${this.name}#${commandType}`)
|
|
4746
4746
|
|
|
4747
|
-
const error = /** @type {Error & {velocious?: Record<string, ?>, errorType?: string, validationErrors?: Record<string, ?>, debugErrorClass?: string, debugBacktrace?: string[]}} */ (new Error(errorMessage))
|
|
4747
|
+
const error = /** @type {Error & {correlationId?: string, details?: Record<string, ?>, errorMessage?: string, velocious?: Record<string, ?>, errorType?: string, validationErrors?: Record<string, ?>, debugErrorClass?: string, debugBacktrace?: string[]}} */ (new Error(errorMessage))
|
|
4748
|
+
if (hasErrorMessage) {
|
|
4749
|
+
error.errorMessage = response.errorMessage
|
|
4750
|
+
}
|
|
4748
4751
|
if (response.velocious && typeof response.velocious === "object") {
|
|
4749
4752
|
error.velocious = response.velocious
|
|
4750
4753
|
}
|
|
@@ -4754,6 +4757,12 @@ export default class FrontendModelBase {
|
|
|
4754
4757
|
if (response.validationErrors && typeof response.validationErrors === "object") {
|
|
4755
4758
|
error.validationErrors = response.validationErrors
|
|
4756
4759
|
}
|
|
4760
|
+
if (response.details && typeof response.details === "object") {
|
|
4761
|
+
error.details = response.details
|
|
4762
|
+
}
|
|
4763
|
+
if (typeof response.correlationId === "string") {
|
|
4764
|
+
error.correlationId = response.correlationId
|
|
4765
|
+
}
|
|
4757
4766
|
// Forward server-provided debug detail (included only when the backend
|
|
4758
4767
|
// deems the requester allowed to see it, e.g. an admin) so callers can
|
|
4759
4768
|
// render the real error class and stack trace instead of the generic
|