Skip to content

Commit

Permalink
- Added Error Handler and Error Listener options
Browse files Browse the repository at this point in the history
- Some utility changes
- Changed the way Service Object is generated
  • Loading branch information
DavidArayan committed Nov 30, 2023
1 parent fc3babb commit 0e46d13
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 17 deletions.
63 changes: 49 additions & 14 deletions sdk-core/src/core/service.ts
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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');
Expand All @@ -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;
}
Expand All @@ -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}`;
}
}
6 changes: 3 additions & 3 deletions sdk-core/src/generator/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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`;

Expand All @@ -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
}
}
Expand Down
7 changes: 7 additions & 0 deletions sdk-core/src/generator/generators/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

0 comments on commit 0e46d13

Please sign in to comment.