Skip to content

therror/therror-unica

Repository files navigation

therror-unica

Unica Errors and toolbelt for creating them

npm version Build Status Coverage Status Typescript definitions

It's written in ES6, for node >= 4

These Errors are based in Therror.ServerError, hide implementation details and confidential information for the 5XX automatically, and use default HTTP Error messages when no specific one is provided.

Installation

 npm install --save therror therror-unica

Usage

const Therror = require('therror');
const UnicaError = require('therror-unica');

let arg = 'id';
let err = new UnicaError.InvalidArgument(`Missing argument ${arg}`);
err.unicaCode; // INVALID_ARGUMENT
err.toPayload();
/*
{
  "code": "INVALID_ARGUMENT",
  "message": "Missing argument id"
}
*/

Unica Errors Correspondece table

statusCode unicaCode UnicaError class
400 INVALID_ARGUMENT UnicaError.InvalidArgument
400 FAILED_PRECONDITION UnicaError.FailedPrecondition
400 OUT_OF_RANGE UnicaError.OutOfRange
401 UNAUTHENTICATED UnicaError.Unauthenticated
403 PERMISSION_DENIED UnicaError.PermissionDenied
404 NOT_FOUND UnicaError.NotFound
409 ABORTED UnicaError.Aborted
409 ALREADY_EXISTS UnicaError.AlreadyExists
429 TOO_MANY_REQUESTS UnicaError.TooManyRequests
500 DATA_LOSS UnicaError.DataLoss
500 INTERNAL UnicaError.Internal
501 NOT_IMPLEMENTED UnicaError.NotImplemented
503 UNAVAILABLE UnicaError.Unavailable
504 TIMEOUT UnicaError.Timeout

Create your own API Specific Errors

// Create your own Unica Errors based on Therror.ServerErrors using the UnicaError Mixin
class PaymentRequired extends UnicaError('PAYMENTS.NOT_ENOUGH_BALANCE', Therror.ServerError.PaymentRequired) {}
// or specify the statusCode instead of the class
class PaymentRequired extends UnicaError('PAYMENTS.NOT_ENOUGH_BALANCE', Therror.ServerError[402]) {}
// or go wild with the mixin party
class PaymentRequired extends UnicaError('PAYMENTS.NOT_ENOUGH_BALANCE', Therror.ServerError({
  statusCode: 402,
  level: 'info',
})) {}

let err = new PaymentRequired();
err.toPayload();
/*
{
  "code": "PAYMENTS.NOT_ENOUGH_BALANCE",
  "message": "Payment Required"
}
*/

Tips

Create your custom error classes

class InvalidHeader extends UnicaError.InvalidArgument {}
let err = new InvalidHeader('The header "X-Fwd-To" is invalid');
err.toPayload();
/*
{
  "code": "INVALID_ARGUMENT",
  "message": "The header "X-Fwd-To" is not valid"
}
*/

Create errors with a static kwnon message

class InvalidHeader extends Therror.WithMessage('The header "${header}" is not valid', UnicaError.InvalidArgument) {}

let err =  new InvalidHeader({header: 'X-Fwd-To'});
err.toPayload();
/*
{
  "code": "INVALID_ARGUMENT",
  "message": "The header "X-Fwd-To" is not valid"
}
*/

Add Causes to your errors

If your API service depends on other services, you should not blindly propagate errors from those services to your clients. When translating errors, adjust the party responsible for the error. For example, a server that receives an INVALID_ARGUMENT error from another service should propagate an INTERNAL to its own caller.

try {
  throw Error('Boom!');
} catch(err) {
  throw new UnicaError.Internal(err, `Service Call failed`);
}

Don't forget to log our errors

Remember, hide implementation details and confidential information in the payload, but log it for forensics. Hiding is automatic for 5XX errors

// Set your favourite logger (defaults to console)
Therror.Loggable.logger = require('logops');  // but logops is a logger designed to log error causes and properties 

let interestingData = { ... };
let err = new UnicaError.Internal(cause, 'Database error', { interestingData });
err.log();
// will log the cause, the stacktrace, the original provided message and `interestingData`
err.toPayload();
/*
{
  "code": "INTERNAL",
  "message": "Internal Server Error"
}
*/

Peer Projects

LICENSE

Copyright 2017 Telefónica I+D

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.