@rainbow-o23/n1 0.1.1

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.
Files changed (40) hide show
  1. package/.babelrc +11 -0
  2. package/.eslintrc +23 -0
  3. package/README.md +233 -0
  4. package/index.cjs +760 -0
  5. package/index.d.ts +3 -0
  6. package/index.js +732 -0
  7. package/lib/pipeline/envs.d.ts +1 -0
  8. package/lib/pipeline/index.d.ts +6 -0
  9. package/lib/pipeline/pipeline-execution.d.ts +38 -0
  10. package/lib/pipeline/pipeline-step.d.ts +41 -0
  11. package/lib/pipeline/pipeline.d.ts +47 -0
  12. package/lib/pipeline/step-helpers-utils.d.ts +41 -0
  13. package/lib/pipeline/step-helpers.d.ts +31 -0
  14. package/lib/repo/index.d.ts +1 -0
  15. package/lib/repo/pipeline-repository.d.ts +11 -0
  16. package/lib/utils/config.d.ts +16 -0
  17. package/lib/utils/error.d.ts +21 -0
  18. package/lib/utils/index.d.ts +4 -0
  19. package/lib/utils/logger.d.ts +50 -0
  20. package/lib/utils/types.d.ts +7 -0
  21. package/package.json +41 -0
  22. package/rollup.config.base.js +30 -0
  23. package/rollup.config.ci.js +3 -0
  24. package/rollup.config.js +3 -0
  25. package/src/index.ts +4 -0
  26. package/src/lib/pipeline/envs.ts +20 -0
  27. package/src/lib/pipeline/index.ts +7 -0
  28. package/src/lib/pipeline/pipeline-execution.ts +137 -0
  29. package/src/lib/pipeline/pipeline-step.ts +79 -0
  30. package/src/lib/pipeline/pipeline.ts +148 -0
  31. package/src/lib/pipeline/step-helpers-utils.ts +143 -0
  32. package/src/lib/pipeline/step-helpers.ts +77 -0
  33. package/src/lib/repo/index.ts +1 -0
  34. package/src/lib/repo/pipeline-repository.ts +53 -0
  35. package/src/lib/utils/config.ts +110 -0
  36. package/src/lib/utils/error.ts +41 -0
  37. package/src/lib/utils/index.ts +6 -0
  38. package/src/lib/utils/logger.ts +292 -0
  39. package/src/lib/utils/types.ts +11 -0
  40. package/tsconfig.json +36 -0
@@ -0,0 +1,148 @@
1
+ import {nanoid} from 'nanoid';
2
+ import {Config, Logger} from '../utils';
3
+ import {AbstractPipelineExecution, PipelineExecutionOptions} from './pipeline-execution';
4
+ import {
5
+ DefaultPipelineStepBuilder,
6
+ PipelineStep,
7
+ PipelineStepBuilder,
8
+ PipelineStepData,
9
+ PipelineStepOptions,
10
+ PipelineStepType
11
+ } from './pipeline-step';
12
+
13
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
+ export type PipelineRequestPayload = any;
15
+
16
+ export interface PipelineRequest<C = PipelineRequestPayload> {
17
+ payload: C;
18
+ traceId?: string;
19
+ }
20
+
21
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
22
+ export type PipelineResponsePayload = any;
23
+
24
+ export interface PipelineResponse<C = PipelineResponsePayload> {
25
+ payload: C;
26
+ }
27
+
28
+ export type PipelineCode = string;
29
+
30
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
31
+ export interface Pipeline<In = any, Out = any> {
32
+ /**
33
+ * code should be unique globally
34
+ */
35
+ getCode(): PipelineCode;
36
+
37
+ /**
38
+ * perform pipeline
39
+ */
40
+ perform(request: PipelineRequest<In>): Promise<PipelineResponse<Out>>;
41
+ }
42
+
43
+ export interface PipelineOptions extends PipelineExecutionOptions {
44
+ config?: Config;
45
+ logger?: Logger;
46
+ }
47
+
48
+ // eslint-disable-next-line @typescript-eslint/ban-types
49
+ export interface PipelineType<P = Pipeline> extends Function {
50
+ new(options?: PipelineOptions): P;
51
+ }
52
+
53
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
54
+ export abstract class AbstractPipeline<In = any, Out = any> extends AbstractPipelineExecution implements Pipeline<In, Out> {
55
+ // noinspection TypeScriptAbstractClassConstructorCanBeMadeProtected
56
+ public constructor(options?: PipelineOptions) {
57
+ super(options);
58
+ }
59
+
60
+ public abstract getCode(): PipelineCode;
61
+
62
+ /**
63
+ * get type of steps
64
+ */
65
+ protected abstract getStepBuilders(): Array<PipelineStepBuilder>;
66
+
67
+ protected buildStepOptions(): Pick<PipelineStepOptions, 'config' | 'logger'> {
68
+ return {config: this._config, logger: this._logger};
69
+ }
70
+
71
+ /**
72
+ * create all steps
73
+ */
74
+ public async createSteps(): Promise<Array<PipelineStep>> {
75
+ const options = this.buildStepOptions();
76
+ return await Promise.all(this.getStepBuilders().map(async builder => await builder.create(options)));
77
+ }
78
+
79
+ public convertRequestToPipelineData<I, FirstStepIn>(request: PipelineRequest<I>): PipelineStepData<FirstStepIn> {
80
+ return {content: request.payload as unknown as FirstStepIn};
81
+ }
82
+
83
+ public convertPipelineDataToResponse<LastStepOut, O>(result: PipelineStepData<LastStepOut>): PipelineResponse<O> {
84
+ return {payload: result.content as unknown as O};
85
+ }
86
+
87
+ protected createTraceId(request: PipelineRequest<In>): string {
88
+ const {traceId} = request;
89
+ if (traceId == null || traceId.trim().length === 0) {
90
+ return nanoid(16);
91
+ } else {
92
+ return traceId;
93
+ }
94
+ }
95
+
96
+ /**
97
+ * perform pipeline.
98
+ * - first step use request as input,
99
+ * - other steps use the result of previous step,
100
+ * - use last step's result as response.
101
+ */
102
+ public async perform(request: PipelineRequest<In>): Promise<PipelineResponse<Out>> {
103
+ const traceId = this.createTraceId(request);
104
+ const response = await this.measurePerformance(traceId, 'PIPELINE')
105
+ .execute(async () => {
106
+ this.traceRequest(traceId, request);
107
+ const steps = await this.createSteps();
108
+ const data = await steps.reduce(async (promise, step) => {
109
+ const request = await promise;
110
+ return await this.measurePerformance(traceId, 'STEP')
111
+ .execute(async () => {
112
+ this.traceStepIn(traceId, step, request);
113
+ const response = await step.perform({
114
+ ...request, $context: {...request.$context, traceId}
115
+ });
116
+ this.traceStepOut(traceId, step, response);
117
+ // if no response returned, keep using request for next
118
+ return this.returnOrContinueOrClear(request, response);
119
+ });
120
+ }, Promise.resolve(this.convertRequestToPipelineData(request)));
121
+ return this.traceResponse(traceId, this.convertPipelineDataToResponse(data));
122
+ });
123
+ return response as PipelineResponse<Out>;
124
+ }
125
+ }
126
+
127
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
128
+ export abstract class AbstractStaticPipeline<In = any, Out = any> extends AbstractPipeline<In, Out> {
129
+ protected abstract getStepTypes(): Array<PipelineStepType>;
130
+
131
+ protected getStepBuilders(): Array<PipelineStepBuilder> {
132
+ return this.getStepTypes().map(type => new DefaultPipelineStepBuilder(type));
133
+ }
134
+ }
135
+
136
+ export interface PipelineBuilder {
137
+ create(options?: PipelineOptions): Promise<Pipeline>;
138
+ }
139
+
140
+ // noinspection JSUnusedGlobalSymbols
141
+ export class DefaultPipelineBuilder implements PipelineBuilder {
142
+ public constructor(protected readonly pipeline: PipelineType) {
143
+ }
144
+
145
+ public async create(options?: PipelineOptions): Promise<Pipeline> {
146
+ return new this.pipeline(options);
147
+ }
148
+ }
@@ -0,0 +1,143 @@
1
+ import {customAlphabet, nanoid} from 'nanoid';
2
+ import {CatchableError, ERR_TRIM_NON_STRING, ExposedUncatchableError, UncatchableError} from '../utils';
3
+ import {PipelineStepHelpers} from './index';
4
+
5
+ export interface PipelineStepErrorOptions {
6
+ // exactly same as http status
7
+ status: number;
8
+ code: string;
9
+ reason: string;
10
+ }
11
+
12
+ export interface PipelineStepFileOptions {
13
+ name?: string;
14
+ type?: string;
15
+ content: string | Buffer;
16
+ }
17
+
18
+ export const PIPELINE_STEP_FILE_SYMBOL = Symbol();
19
+ export const PIPELINE_STEP_RETURN_NULL = Symbol();
20
+
21
+ export interface PipelineStepFile {
22
+ $file: typeof PIPELINE_STEP_FILE_SYMBOL;
23
+ name?: string;
24
+ type?: string;
25
+ content: Buffer;
26
+ }
27
+
28
+ export class StepHelpersUtils {
29
+ private static asciiNanoId = customAlphabet('1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_', 32);
30
+ private static OBJECT_PROTOTYPE = Object.prototype;
31
+
32
+ private constructor() {
33
+ // avoid extend
34
+ }
35
+
36
+ // nano id
37
+ public static $nano(size?: number): string {
38
+ return nanoid(size);
39
+ }
40
+
41
+ public static $ascii(size?: number): string {
42
+ return StepHelpersUtils.asciiNanoId(size);
43
+ }
44
+
45
+ // error
46
+ public static createCatchableError = (options: Omit<PipelineStepErrorOptions, 'status'>): never => {
47
+ throw new CatchableError(options.code, options.reason);
48
+ };
49
+ public static createExposedUncatchableError = (options: PipelineStepErrorOptions): never => {
50
+ throw new ExposedUncatchableError(options.status, options.code, options.reason);
51
+ };
52
+ public static createUncatchableError = (options: Omit<PipelineStepErrorOptions, 'status'>): never => {
53
+ throw new UncatchableError(options.code, options.reason);
54
+ };
55
+ public static readonly $errors: PipelineStepHelpers['$errors'] = {
56
+ catchable: StepHelpersUtils.createCatchableError,
57
+ exposed: StepHelpersUtils.createExposedUncatchableError,
58
+ uncatchable: StepHelpersUtils.createUncatchableError
59
+ };
60
+
61
+ // file
62
+ public static createFile(options: PipelineStepFileOptions): PipelineStepFile {
63
+ return {
64
+ $file: PIPELINE_STEP_FILE_SYMBOL,
65
+ name: options.name, type: options.type,
66
+ content: typeof options.content === 'string' ? Buffer.from(options.content) : options.content
67
+ };
68
+ }
69
+
70
+ // semaphore
71
+ public static $clearContextData(): typeof PIPELINE_STEP_RETURN_NULL {
72
+ return PIPELINE_STEP_RETURN_NULL;
73
+ }
74
+
75
+ // utils
76
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
77
+ public static isPrototype(value: any): boolean {
78
+ const Ctor = value && value.constructor;
79
+ const proto = (typeof Ctor === 'function' && Ctor.prototype) || StepHelpersUtils.OBJECT_PROTOTYPE;
80
+
81
+ return value === proto;
82
+ }
83
+
84
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
85
+ public static isLength(value: any): boolean {
86
+ return typeof value === 'number' && value > -1 && value % 1 === 0 && value <= Number.MAX_SAFE_INTEGER;
87
+ }
88
+
89
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
90
+ public static isArrayLike(value: any): boolean {
91
+ return value != null && typeof value !== 'function' && StepHelpersUtils.isLength(value.length);
92
+ }
93
+
94
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
95
+ public static isEmpty(value: any): boolean {
96
+ if (value == null) {
97
+ return true;
98
+ }
99
+ if (StepHelpersUtils.isArrayLike(value) && (Array.isArray(value) || typeof value === 'string')) {
100
+ return value.length === 0;
101
+ } else if (value instanceof Map) {
102
+ return value.size === 0;
103
+ } else if (value instanceof Set) {
104
+ return value.size === 0;
105
+ } else if (StepHelpersUtils.isPrototype(value)) {
106
+ return Object.keys(value).length === 0;
107
+ }
108
+
109
+ return false;
110
+ }
111
+
112
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
113
+ public static isNotEmpty(value: any): boolean {
114
+ return !StepHelpersUtils.isEmpty(value);
115
+ }
116
+
117
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
118
+ public static isBlank(value: any): boolean {
119
+ if (value == null) {
120
+ return true;
121
+ }
122
+ if (typeof value !== 'string') {
123
+ return false;
124
+ }
125
+ return value.trim().length === 0;
126
+ }
127
+
128
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
129
+ public static isNotBlank(value: any): boolean {
130
+ return !StepHelpersUtils.isBlank(value);
131
+ }
132
+
133
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
134
+ public static trim(value: any): string {
135
+ if (value == null) {
136
+ return '';
137
+ }
138
+ if (typeof value === 'string') {
139
+ return value.trim();
140
+ }
141
+ throw new UncatchableError(ERR_TRIM_NON_STRING, `Cannot apply trim to non-string object[type=${typeof value}, value=${value}].`);
142
+ }
143
+ }
@@ -0,0 +1,77 @@
1
+ import dayjs from 'dayjs';
2
+ import {Config, DateTime, Logger} from '../utils';
3
+ import {
4
+ PIPELINE_STEP_RETURN_NULL,
5
+ PipelineStepErrorOptions,
6
+ PipelineStepFile,
7
+ PipelineStepFileOptions,
8
+ StepHelpersUtils
9
+ } from './step-helpers-utils';
10
+
11
+ export class PipelineStepDateHelper {
12
+ private readonly _dateTimeFormat: string;
13
+
14
+ public constructor(config: Config) {
15
+ this._dateTimeFormat = config.getString('format.datetime', 'YYYY-MM-DD HH:mm:ss');
16
+ }
17
+
18
+ public getDateTimeFormat(): string {
19
+ return this._dateTimeFormat;
20
+ }
21
+
22
+ public now(): DateTime {
23
+ return dayjs().format(this.getDateTimeFormat());
24
+ }
25
+
26
+ public get dayjs(): typeof dayjs {
27
+ return dayjs;
28
+ }
29
+ }
30
+
31
+ export interface PipelineStepHelpers {
32
+ $config?: Config;
33
+ $logger?: Logger;
34
+ $date: PipelineStepDateHelper;
35
+ $nano: (size?: number) => string;
36
+ $ascii: (size?: number) => string;
37
+ /** create an exposed uncatchable error*/
38
+ $error: (options: PipelineStepErrorOptions) => never;
39
+ $errors: {
40
+ catchable: (options: Omit<PipelineStepErrorOptions, 'status'>) => never;
41
+ exposed: (options: PipelineStepErrorOptions) => never;
42
+ uncatchable: (options: Omit<PipelineStepErrorOptions, 'status'>) => never;
43
+ };
44
+ /** create a file */
45
+ $file: (options: PipelineStepFileOptions) => PipelineStepFile;
46
+ $clearContextData: () => typeof PIPELINE_STEP_RETURN_NULL;
47
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
48
+ isEmpty: (value: any) => boolean;
49
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
50
+ isNotEmpty: (value: any) => boolean;
51
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
52
+ isBlank: (value: any) => boolean;
53
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
54
+ isNotBlank: (value: any) => boolean;
55
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
56
+ trim: (value: any) => string;
57
+ }
58
+
59
+ export const createStepHelpers = (config: Config, logger: Logger): PipelineStepHelpers => {
60
+ return {
61
+ $config: config, $logger: logger,
62
+ // date
63
+ $date: new PipelineStepDateHelper(config),
64
+ // nano
65
+ $nano: StepHelpersUtils.$nano, $ascii: StepHelpersUtils.$ascii,
66
+ // errors
67
+ $error: StepHelpersUtils.createExposedUncatchableError, $errors: StepHelpersUtils.$errors,
68
+ // file
69
+ $file: StepHelpersUtils.createFile,
70
+ // semaphore
71
+ $clearContextData: StepHelpersUtils.$clearContextData,
72
+ // utilities
73
+ isEmpty: StepHelpersUtils.isEmpty, isNotEmpty: StepHelpersUtils.isNotEmpty,
74
+ isBlank: StepHelpersUtils.isBlank, isNotBlank: StepHelpersUtils.isNotBlank,
75
+ trim: StepHelpersUtils.trim
76
+ };
77
+ };
@@ -0,0 +1 @@
1
+ export * from './pipeline-repository';
@@ -0,0 +1,53 @@
1
+ import {
2
+ Pipeline,
3
+ PipelineBuilder,
4
+ PipelineCode,
5
+ PipelineOptions,
6
+ PipelineStepBuilder,
7
+ PipelineStepCode
8
+ } from '../pipeline';
9
+ import {Undefinable} from '../utils';
10
+
11
+ export class PipelineRepository {
12
+ private static readonly PIPELINE_BUILDERS: Record<PipelineCode, PipelineBuilder> = {};
13
+ private static readonly STEP_BUILDERS: Record<PipelineStepCode, PipelineStepBuilder> = {};
14
+
15
+ private constructor() {
16
+ // avoid extend
17
+ }
18
+
19
+ public static async findPipeline(code: PipelineCode, options: PipelineOptions): Promise<Undefinable<Pipeline>> {
20
+ const builder = this.PIPELINE_BUILDERS[code];
21
+ if (builder == null) {
22
+ return (void 0);
23
+ } else {
24
+ return await builder.create(options);
25
+ }
26
+ }
27
+
28
+ public static putPipeline(builders: Record<PipelineCode, PipelineBuilder>): Record<PipelineCode, PipelineBuilder> {
29
+ return Object.keys(builders).reduce((duplicated, code) => {
30
+ const existing = PipelineRepository.PIPELINE_BUILDERS[code];
31
+ PipelineRepository.PIPELINE_BUILDERS[code] = builders[code];
32
+ if (existing != null) {
33
+ duplicated[code] = existing;
34
+ }
35
+ return duplicated;
36
+ }, {} as Record<PipelineCode, PipelineBuilder>);
37
+ }
38
+
39
+ public static async findStep(code: PipelineStepCode): Promise<Undefinable<PipelineStepBuilder>> {
40
+ return PipelineRepository.STEP_BUILDERS[code];
41
+ }
42
+
43
+ public static putStep(builders: Record<PipelineStepCode, PipelineStepBuilder>): Record<PipelineStepCode, PipelineStepBuilder> {
44
+ return Object.keys(builders).reduce((duplicated, code) => {
45
+ const existing = PipelineRepository.STEP_BUILDERS[code];
46
+ PipelineRepository.STEP_BUILDERS[code] = builders[code];
47
+ if (existing != null) {
48
+ duplicated[code] = existing;
49
+ }
50
+ return duplicated;
51
+ }, {} as Record<PipelineStepCode, PipelineStepBuilder>);
52
+ }
53
+ }
@@ -0,0 +1,110 @@
1
+ import {createLogger, Logger} from './logger';
2
+ import {Undefinable} from './types';
3
+
4
+ const MISSED = Symbol();
5
+
6
+ export class Config {
7
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
8
+ private valueCache: Record<string, any> = {};
9
+
10
+ public constructor(private _logger: Logger) {
11
+ }
12
+
13
+ public getLogger(): Logger {
14
+ return this._logger;
15
+ }
16
+
17
+ public setLogger(value: Logger) {
18
+ this._logger = value;
19
+ }
20
+
21
+ protected generateKey(name: string) {
22
+ const key = name
23
+ .split('.')
24
+ .filter(s => s.trim().length !== 0)
25
+ .map(s => s.toUpperCase())
26
+ .join('_');
27
+ return `CFG_${key}`;
28
+ }
29
+
30
+ protected getFromCache<T>(name: string, read: () => Undefinable<T>, defaultValue?: T): Undefinable<T> {
31
+ const cached = this.valueCache[name];
32
+ if (cached === MISSED) {
33
+ return defaultValue ?? (void 0);
34
+ } else if (cached != null) {
35
+ return cached;
36
+ } else {
37
+ const value = read();
38
+ this.valueCache[name] = value ?? MISSED;
39
+ return value ?? defaultValue ?? (void 0);
40
+ }
41
+ }
42
+
43
+ public getString(name: string, defaultValue?: string): Undefinable<string> {
44
+ return this.getFromCache(name, () => {
45
+ // noinspection JSUnresolvedReference
46
+ const value = process.env[this.generateKey(name)];
47
+ if (value == null || value.trim().length === 0) {
48
+ return (void 0);
49
+ } else {
50
+ return value.trim();
51
+ }
52
+ }, defaultValue);
53
+ }
54
+
55
+ public getBoolean(name: string, defaultValue?: boolean): Undefinable<boolean> {
56
+ return this.getFromCache(name, () => {
57
+ // noinspection JSUnresolvedReference
58
+ const value = process.env[this.generateKey(name)];
59
+ if (value == null || value.trim().length === 0) {
60
+ return (void 0);
61
+ } else if (['TRUE', 'YES', 'ON', '1'].includes(value.trim().toUpperCase())) {
62
+ return true;
63
+ } else if (['FALSE', 'NO', 'OFF', '0'].includes(value.trim().toUpperCase())) {
64
+ return false;
65
+ } else {
66
+ this._logger.warn(`Cannot parse given configuration item value[${value}] to boolean, ignored.`, Config.name);
67
+ return (void 0);
68
+ }
69
+ }, defaultValue);
70
+ }
71
+
72
+ public getNumber(name: string, defaultValue?: number): Undefinable<number> {
73
+ return this.getFromCache(name, () => {
74
+ // noinspection JSUnresolvedReference
75
+ const value = process.env[this.generateKey(name)];
76
+ if (value == null || value.trim().length === 0) {
77
+ return (void 0);
78
+ }
79
+ const v = Number(value);
80
+ if (isNaN(v)) {
81
+ this._logger.error(`Cannot parse given configuration item value[${value}] to number, ignored.`, Config.name);
82
+ return (void 0);
83
+ } else {
84
+ return v;
85
+ }
86
+ }, defaultValue);
87
+ }
88
+
89
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
90
+ public getJson(name: string, defaultValue?: any): Undefinable<any> {
91
+ return this.getFromCache(name, () => {
92
+ // noinspection JSUnresolvedReference
93
+ const value = process.env[this.generateKey(name)];
94
+ if (value == null || value.trim().length === 0) {
95
+ return (void 0);
96
+ } else {
97
+ try {
98
+ return JSON.parse(value);
99
+ } catch {
100
+ this._logger.warn(`Cannot parse given configuration item value[${value}] to boolean, ignored.`, Config.name);
101
+ return (void 0);
102
+ }
103
+ }
104
+ }, defaultValue);
105
+ }
106
+ }
107
+
108
+ export const createConfig = (logger?: Logger) => {
109
+ return new Config(logger ?? createLogger());
110
+ };
@@ -0,0 +1,41 @@
1
+ /** should be O00-00000 - O99-99999 */
2
+ export type O23ReservedErrorCode = `O${number}-${number}`;
3
+ /** prefix should be any uppercase but O00 - O99, number should be 00000 - 99999 */
4
+ export type O23ExternalErrorCode = `O${Uppercase<string>}-${number}`;
5
+ export type O23ErrorCode = O23ReservedErrorCode | O23ExternalErrorCode;
6
+ export const ERR_PIPELINE_NOT_FOUND: O23ReservedErrorCode = 'O01-00001';
7
+ export const ERR_TRIM_NON_STRING: O23ReservedErrorCode = 'O01-00002';
8
+ export const ERR_UNKNOWN: O23ReservedErrorCode = 'O01-99999';
9
+
10
+ export class CatchableError extends Error {
11
+ public constructor(private readonly _code: string, message: string) {
12
+ super(message);
13
+ }
14
+
15
+ public getCode(): string {
16
+ return this._code;
17
+ }
18
+ }
19
+
20
+ export class UncatchableError extends Error {
21
+ public constructor(private readonly _code: string, message: string) {
22
+ super(message);
23
+ }
24
+
25
+ public getCode(): string {
26
+ return this._code;
27
+ }
28
+ }
29
+
30
+ export class ExposedUncatchableError extends UncatchableError {
31
+ private readonly _status: number;
32
+
33
+ public constructor(status: number, code: string, message: string) {
34
+ super(code, message);
35
+ this._status = status;
36
+ }
37
+
38
+ public getStatus(): number {
39
+ return this._status;
40
+ }
41
+ }
@@ -0,0 +1,6 @@
1
+ export * from './types';
2
+
3
+ export * from './error';
4
+
5
+ export * from './logger';
6
+ export * from './config';