From 0e46d13d65a786b7ad2ae0222fb9cf9fa6887f7a Mon Sep 17 00:00:00 2001 From: David Arayan Date: Thu, 30 Nov 2023 14:09:45 +1100 Subject: [PATCH] - Added Error Handler and Error Listener options - Some utility changes - Changed the way Service Object is generated --- sdk-core/src/core/service.ts | 63 ++++++++++++++++++----- sdk-core/src/generator/generator.ts | 6 +-- sdk-core/src/generator/generators/util.ts | 7 +++ 3 files changed, 59 insertions(+), 17 deletions(-) diff --git a/sdk-core/src/core/service.ts b/sdk-core/src/core/service.ts index 2b77565..557c2d4 100644 --- a/sdk-core/src/core/service.ts +++ b/sdk-core/src/core/service.ts @@ -1,4 +1,8 @@ +import { Util } from "../generator/generators/util"; + export type ServiceAuthType = 'cookie' | 'token'; +export type ServiceErrorHandler = 'silent' | 'console.error' | 'console.warn' | 'throw'; +export type ServiceErrorListener = (err: Error) => void; export interface ServiceAuth { // the authentication type to use for backend @@ -7,7 +11,9 @@ export interface ServiceAuth { // (optional) the authentication token to use, this will be ignored if // authentication type is 'cookie' readonly token?: string | null; +} +export interface ServiceOptions { // (optional) ask server to return gzipped content, this will reduce // download time for requests and might speed things up at expense of // additional processing on the client-side @@ -17,14 +23,26 @@ export interface ServiceAuth { // (optuonal) for non-secure NodeJS environments to enable/disable tls // this defaults to 'false' readonly tls?: boolean | null; + + // (optional) for error handling when api throws errors like 404, 401 etc + // defaults to `console.error` which will print the error via console.error() + readonly errorHandler?: ServiceErrorHandler | null; + + // (optional) catch-all error listener for any errors that occur in the api + // this is useful for global reporting or analytics reporting etc.. + // this will be called first before errors are thrown to higher code + readonly errorListener?: ServiceErrorListener | null; + + // (optional) provide an API version to use, this defaults to 'v3' + readonly version?: string | null; } export interface ServiceConfig { // the full backend url readonly url: string; - // (optional) provide an API version to use, this defaults to 'v3' - readonly version?: string; + // (optional) additional configuration options for the backend + readonly options?: ServiceOptions | null; // (optional) the authentication to use for backend, this // will default to 'cookie' based auth if not supplied @@ -45,40 +63,54 @@ export interface ServiceStaticContainer { */ export interface LockedServiceConfig { readonly url: string; - readonly version: string; + readonly options: { + readonly version: string; + readonly tls: boolean; + readonly gzip: boolean; + readonly errorHandler: ServiceErrorHandler; + readonly errorListener: ServiceErrorListener; + }; readonly auth: { readonly type: ServiceAuthType; readonly token: string | null; - readonly tls: boolean; - readonly gzip: boolean; - } + }; } +/** + * Allows configuration of a connection service to an api-core based backend service + */ export abstract class Service { private readonly _config: LockedServiceConfig; public constructor(config: ServiceConfig) { // makes a deep copy of the provided config so references do not get mixed up // plus creates proper defaults - this._config = { + this._config = Object.freeze({ url: config.url, - version: config.version ? config.version : 'v3', + options: { + version: (config.options && config.options.version) ? config.options.version : 'v3', + tls: (config.options && config.options.tls) ? true : false, + gzip: (config.options && config.options.gzip) ? true : false, + errorHandler: (config.options && config.options.errorHandler) ? config.options.errorHandler : 'console.error', + errorListener: (config.options && config.options.errorListener && Util.isFunction(config.options.errorListener)) ? config.options.errorListener : (_: Error) => { /* silent handler */ } + }, auth: { type: (config.auth && config.auth.type) ? config.auth.type : 'cookie', - token: (config.auth && config.auth.token) ? config.auth.token : null, - tls: (config.auth && config.auth.tls) ? true : false, - gzip: (config.auth && config.auth.gzip) ? true : false + token: (config.auth && config.auth.token) ? config.auth.token : null } - } + }); } /** * Configure a new default service */ - public static config(config: ServiceConfig): Service { + public static config(_config: ServiceConfig): Service { throw new Error('Service.config is not implemented correctly, contact admin'); } + /** + * Returns the default service object + */ public static get default(): Service { if (!this.container.service) { throw new Error('Service.default is not configured, use Service.config() to set a new default'); @@ -91,6 +123,9 @@ export abstract class Service { throw new Error('Service.container is not implemented correctly, contact admin'); } + /** + * Returns the currently locked, read-only Service Configuration + */ public get config(): LockedServiceConfig { return this._config; } @@ -99,6 +134,6 @@ export abstract class Service { * This returns the base url and versioning combined */ public get url(): string { - return `${this.config.url}/${this.config.version}`; + return `${this.config.url}/${this.config.options.version}`; } } \ No newline at end of file diff --git a/sdk-core/src/generator/generator.ts b/sdk-core/src/generator/generator.ts index ba814a2..95ccaf4 100644 --- a/sdk-core/src/generator/generator.ts +++ b/sdk-core/src/generator/generator.ts @@ -80,7 +80,7 @@ export class Generator { } public static generateServiceFile(data: GeneratorData): GeneratedSchema { - const className: string = `${Util.capitaliseClassName(data.package.name)}Service`; + const className: string = `Connection`; let output: string = `import { Service, ServiceConfig, ServiceStaticContainer } from '@plattar/sdk-core';\n\n`; @@ -96,8 +96,8 @@ export class Generator { output += '}\n'; return { - name: `${data.package.name}-service`, - fname: `${data.package.name}-service.ts`, + name: `connection-service`, + fname: `connection-service.ts`, data: output } } diff --git a/sdk-core/src/generator/generators/util.ts b/sdk-core/src/generator/generators/util.ts index b054d1a..ebe85db 100644 --- a/sdk-core/src/generator/generators/util.ts +++ b/sdk-core/src/generator/generators/util.ts @@ -42,4 +42,11 @@ export class Util { return results; } + + /** + * Checks if the provided object is a function + */ + public static isFunction(obj: any): boolean { + return !!(obj && obj.constructor && obj.call && obj.apply); + } } \ No newline at end of file