@instamenta/grpc-errors
Version:
grpc status codes builder for javascript and typescript grpc server responses
251 lines (250 loc) • 8.25 kB
JavaScript
import { Metadata } from '@grpc/grpc-js';
//! GRPC DEFAULT ERRORS
const invalidArgumentError = {
name: 'InvalidArgument',
code: 3,
details: '',
metadata: new Metadata(),
message: 'Invalid argument provided.',
};
const deadlineExceededError = {
name: 'DeadlineExceeded',
code: 4,
details: '',
metadata: new Metadata(),
message: 'Deadline for the operation exceeded.',
};
const notFoundError = {
name: 'NotFound',
code: 5,
details: '',
metadata: new Metadata(),
message: 'Resource not found.',
};
const alreadyExistsError = {
name: 'AlreadyExists',
code: 6,
details: '',
metadata: new Metadata(),
message: 'Resource already exists.',
};
const permissionDeniedError = {
name: 'PermissionDenied',
code: 7,
details: '',
metadata: new Metadata(),
message: 'Permission denied for the operation.',
};
const internalError = {
name: 'Internal',
code: 13,
details: 'Server ran into unexpected internal error.',
metadata: new Metadata(),
message: 'Internal server error.',
};
const unavailableError = {
name: 'Unavailable',
code: 14,
details: '',
metadata: new Metadata(),
message: 'Service unavailable.',
};
const dataLossError = {
name: 'DataLoss',
code: 15,
details: '',
metadata: new Metadata(),
message: 'Data loss occurred.',
};
const unauthenticatedError = {
name: 'Unauthenticated',
code: 16,
details: '',
metadata: new Metadata(),
message: 'Request not authenticated.',
};
const failedPreconditionError = {
name: 'FailedPrecondition',
code: 9,
details: '',
metadata: new Metadata(),
message: 'Operation failed precondition check.',
};
const validationError = {
name: 'GrpcValidationError',
code: 3,
details: '',
metadata: new Metadata(),
message: 'gRPC validation error occurred.',
};
const unauthorizedError = {
name: 'GrpcUnauthorized',
code: 16,
details: '',
metadata: new Metadata(),
message: 'gRPC unauthorized access.',
};
const resourceNotFoundError = {
name: 'GrpcResourceNotFound',
code: 5,
details: '',
metadata: new Metadata(),
message: 'gRPC resource not found.',
};
/** Tired of boring old meta whose methods cant be chained? Try this! Simple yet wonderful */
export class Meta {
#metadata = new Metadata();
set(key, value) {
this.#metadata.set(key, value);
return this;
}
get() {
return this.#metadata;
}
static build() {
return new Meta();
}
}
/**
* * Class that provides utility functions for managing gRPC errors. Logging meaningful errors to the console.
*
* ! With unmatched type safety and extendability!
*
* @template T - string literal type representing gRPC error keys.
* @class GrpcErrors
*/
export default class GrpcErrors {
K = {
INVALID_ARGUMENT: 'INVALID_ARGUMENT',
DEADLINE_EXCEEDED: 'DEADLINE_EXCEEDED',
NOT_FOUND: 'NOT_FOUND',
ALREADY_EXISTS: 'ALREADY_EXISTS',
PERMISSION_DENIED: 'PERMISSION_DENIED',
INTERNAL: 'INTERNAL',
UNAVAILABLE: 'UNAVAILABLE',
DATA_LOSS: 'DATA_LOSS',
UNAUTHENTICATED: 'UNAUTHENTICATED',
FAILED_PRECONDITION: 'FAILED_PRECONDITION',
VALIDATION: 'VALIDATION',
UNAUTHORIZED: 'UNAUTHORIZED',
RESOURCE_NOT_FOUND: 'RESOURCE_NOT_FOUND',
};
/**
* A record of gRPC errors, where keys correspond to error codes
* and values contain error details.
*/
ERRORS = {
INVALID_ARGUMENT: invalidArgumentError,
DEADLINE_EXCEEDED: deadlineExceededError,
NOT_FOUND: notFoundError,
ALREADY_EXISTS: alreadyExistsError,
PERMISSION_DENIED: permissionDeniedError,
INTERNAL: internalError,
UNAVAILABLE: unavailableError,
DATA_LOSS: dataLossError,
UNAUTHENTICATED: unauthenticatedError,
FAILED_PRECONDITION: failedPreconditionError,
VALIDATION: validationError,
UNAUTHORIZED: unauthorizedError,
RESOURCE_NOT_FOUND: resourceNotFoundError,
};
/**
* * Creates and returns a new instance of the GrpcErrors class.
*
* @template T - string literal type representing gRPC error keys.
* @returns - new instance of the GrpcErrors class.
*/
static getInstance() {
return new GrpcErrors();
}
/**
* * Extends the ERRORS record with a custom gRPC error object.
*
* @param _key - The key representing the custom gRPC error type.
* @param _error - The custom gRPC error object to add to the ERRORS record.
* @param _metadata - Additional metadata to attach to the custom gRPC error (if available).
* @param _details - Additional details about the custom gRPC error (if available).
*/
EXTEND({ _key, _error, _metadata = null, _details = null, }) {
this.ERRORS[_key] = _error;
}
/**
* * Throws a gRPC error and logs it.
*
* @param _key - The key representing the gRPC error type.
* @param _source - The source of the error (if available).
* @param _metadata - Additional metadata to attach to the gRPC error.
* @param _details - Additional details about the error (if available).
* @returns - The thrown gRPC error response.
*/
T({ _key, _source = null, _metadata = null, _details = null, }) {
const key = String(_key);
console.log(_source ? `[ Emitting GRPC ERROR: [ ${key} ] from "${_source}" ]` : `[ Emitting ERROR: [ ${key} ] ]`);
const _error = this.ERRORS[_key];
if (_metadata)
_error.metadata = _metadata;
if (_details)
_error.details = _details;
return _error;
}
/**
* * Emits a gRPC error on a writable stream and logs it.
*
* @param call - The writable stream on which to emit the gRPC error.
* @param _key - The key representing the gRPC error type.
* @param _source - The source of the error (if available).
* @param _metadata - Additional metadata to attach to the gRPC error.
* @param _details - Additional details about the error (if available).
*/
E({ call, _key, _source = null, _metadata = null, _details = null, }) {
const key = String(_key);
const _error = this.ERRORS[_key];
if (_metadata)
_error.metadata = _metadata;
if (_details)
_error.details = _details;
call.emit('error', _error);
return console.log(_source ? `[ Emitting GRPC ERROR: [ ${key} ] from "${_source}" ]` : `[ Emitting ERROR: [ ${key} ] ]`);
}
/**
* * Calls a callback function with a gRPC error and logs it.
*
* @param callback - The callback function to call with the gRPC error.
* @param _key - The key representing the gRPC error type.
* @param _source - The source of the error (if available).
* @param _metadata - Additional metadata to attach to the gRPC error. (if available).
* @param _details - Additional details about the error (if available).
*/
CB({ callback, _key, _source = null, _metadata = null, _details = null, }) {
const key = String(_key);
const _error = this.ERRORS[_key];
if (_metadata)
_error.metadata = _metadata;
if (_details)
_error.details = _details;
callback(_error);
return console.log(_source ? `[ Emitting GRPC ERROR: [ ${key} ] from "${_source}" ]` : `[ Emitting ERROR: [ ${key} ] ]`);
}
/**
* * Converts a Zod error to a gRPC error response with metadata and details.
*
* @param error - The Zod error to convert.
* @returns - The gRPC error response.
*/
handleZodError(error) {
const _error = this.ERRORS.VALIDATION;
const _metadata = new Metadata();
error?.errors?.forEach((e, i) => {
_metadata.set(`error_${i}`, e.message);
});
_error.metadata = _metadata;
_error.details = error?.errors?.map((e) => e.message).join(', ');
return _error;
}
}
/**
* * Get default Class instance.
*
* @type {GrpcErrors<IGrpcErrorKeys>}
*/
export const w = GrpcErrors.getInstance();