@tryghost/errors 1.2.27 → 1.3.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.
@@ -0,0 +1,96 @@
1
+ import {v1 as uuidv1} from 'uuid';
2
+ import {wrapStack} from './wrap-stack';
3
+
4
+ export interface GhostErrorOptions {
5
+ message?: string;
6
+ statusCode?: number;
7
+ level?: string;
8
+ id?: string;
9
+ context?: string;
10
+ help?: string;
11
+ errorType?: string;
12
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
+ errorDetails?: any;
14
+ code?: string;
15
+ property?: string;
16
+ redirect?: string;
17
+ hideStack?: boolean;
18
+ err?: Error | string;
19
+ }
20
+
21
+ export class GhostError extends Error {
22
+ statusCode: number;
23
+ errorType: string;
24
+ level: string;
25
+ id: string;
26
+ context?: string;
27
+ help?: string;
28
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
29
+ errorDetails: any;
30
+ code: string | null;
31
+ property: string | null;
32
+ redirect: string | null;
33
+ hideStack: boolean;
34
+
35
+ constructor(options: GhostErrorOptions = {}) {
36
+ super();
37
+
38
+ /**
39
+ * defaults
40
+ */
41
+ this.statusCode = 500;
42
+ this.errorType = 'InternalServerError';
43
+ this.level = 'normal';
44
+ this.message = 'The server has encountered an error.';
45
+ this.id = uuidv1();
46
+
47
+ /**
48
+ * custom overrides
49
+ */
50
+ this.id = options.id || this.id;
51
+ this.statusCode = options.statusCode || this.statusCode;
52
+ this.level = options.level || this.level;
53
+ this.context = options.context;
54
+ this.help = options.help;
55
+ this.errorType = this.name = options.errorType || this.errorType;
56
+ this.errorDetails = options.errorDetails;
57
+ this.code = options.code || null;
58
+ this.property = options.property || null;
59
+ this.redirect = options.redirect || null;
60
+
61
+ this.message = options.message || this.message;
62
+ this.hideStack = options.hideStack || false;
63
+
64
+ // NOTE: Error to inherit from, override!
65
+ // Nested objects are getting copied over in one piece (can be changed, but not needed right now)
66
+ if (options.err) {
67
+ // CASE: Support err as string (it happens that third party libs return a string instead of an error instance)
68
+ if (typeof options.err === 'string') {
69
+ /* eslint-disable no-restricted-syntax */
70
+ options.err = new Error(options.err);
71
+ /* eslint-enable no-restricted-syntax */
72
+ }
73
+
74
+ Object.getOwnPropertyNames(options.err).forEach((property) => {
75
+ if (['errorType', 'name', 'statusCode', 'message', 'level'].indexOf(property) !== -1) {
76
+ return;
77
+ }
78
+
79
+ // CASE: `code` should put options as priority over err
80
+ if (property === 'code') {
81
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
82
+ this[property] = this[property] || (options.err as any)[property];
83
+ return;
84
+ }
85
+
86
+ if (property === 'stack' && !this.hideStack) {
87
+ this[property] = wrapStack(this, options.err as Error);
88
+ return;
89
+ }
90
+
91
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
92
+ (this as any)[property] = (options.err as any)[property] || (this as any)[property];
93
+ });
94
+ }
95
+ }
96
+ }
package/src/errors.ts ADDED
@@ -0,0 +1,312 @@
1
+ import {GhostError, GhostErrorOptions} from './GhostError';
2
+
3
+ const mergeOptions = (options: GhostErrorOptions, defaults: GhostErrorOptions) => {
4
+ const result = {...defaults};
5
+
6
+ // Ignore undefined options - for example passing statusCode: undefined should not override the default
7
+ (Object.keys(options) as (keyof GhostErrorOptions)[]).forEach((key) => {
8
+ if (options[key] !== undefined) {
9
+ result[key] = options[key];
10
+ }
11
+ });
12
+
13
+ return result;
14
+ };
15
+
16
+ export class InternalServerError extends GhostError {
17
+ constructor(options: GhostErrorOptions = {}) {
18
+ super(mergeOptions(options, {
19
+ statusCode: 500,
20
+ level: 'critical',
21
+ errorType: 'InternalServerError',
22
+ message: 'The server has encountered an error.'
23
+ }));
24
+ }
25
+ }
26
+
27
+ export class IncorrectUsageError extends GhostError {
28
+ constructor(options: GhostErrorOptions = {}) {
29
+ super(mergeOptions(options, {
30
+ statusCode: 400,
31
+ level: 'critical',
32
+ errorType: 'IncorrectUsageError',
33
+ message: 'We detected a misuse. Please read the stack trace.'
34
+ }));
35
+ }
36
+ }
37
+
38
+ export class NotFoundError extends GhostError {
39
+ constructor(options: GhostErrorOptions = {}) {
40
+ super(mergeOptions(options, {
41
+ statusCode: 404,
42
+ errorType: 'NotFoundError',
43
+ message: 'Resource could not be found.',
44
+ hideStack: true
45
+ }));
46
+ }
47
+ }
48
+
49
+ export class BadRequestError extends GhostError {
50
+ constructor(options: GhostErrorOptions = {}) {
51
+ super(mergeOptions(options, {
52
+ statusCode: 400,
53
+ errorType: 'BadRequestError',
54
+ message: 'The request could not be understood.'
55
+ }));
56
+ }
57
+ }
58
+
59
+ export class UnauthorizedError extends GhostError {
60
+ constructor(options: GhostErrorOptions = {}) {
61
+ super(mergeOptions(options, {
62
+ statusCode: 401,
63
+ errorType: 'UnauthorizedError',
64
+ message: 'You are not authorised to make this request.'
65
+ }));
66
+ }
67
+ }
68
+
69
+ export class NoPermissionError extends GhostError {
70
+ constructor(options: GhostErrorOptions = {}) {
71
+ super(mergeOptions(options, {
72
+ statusCode: 403,
73
+ errorType: 'NoPermissionError',
74
+ message: 'You do not have permission to perform this request.'
75
+ }));
76
+ }
77
+ }
78
+
79
+ export class ValidationError extends GhostError {
80
+ constructor(options: GhostErrorOptions = {}) {
81
+ super(mergeOptions(options, {
82
+ statusCode: 422,
83
+ errorType: 'ValidationError',
84
+ message: 'The request failed validation.'
85
+ }));
86
+ }
87
+ }
88
+
89
+ export class UnsupportedMediaTypeError extends GhostError {
90
+ constructor(options: GhostErrorOptions = {}) {
91
+ super(mergeOptions(options, {
92
+ statusCode: 415,
93
+ errorType: 'UnsupportedMediaTypeError',
94
+ message: 'The media in the request is not supported by the server.'
95
+ }));
96
+ }
97
+ }
98
+
99
+ export class TooManyRequestsError extends GhostError {
100
+ constructor(options: GhostErrorOptions = {}) {
101
+ super(mergeOptions(options, {
102
+ statusCode: 429,
103
+ errorType: 'TooManyRequestsError',
104
+ message: 'Server has received too many similar requests in a short space of time.'
105
+ }));
106
+ }
107
+ }
108
+
109
+ export class MaintenanceError extends GhostError {
110
+ constructor(options: GhostErrorOptions = {}) {
111
+ super(mergeOptions(options, {
112
+ statusCode: 503,
113
+ errorType: 'MaintenanceError',
114
+ message: 'The server is temporarily down for maintenance.'
115
+ }));
116
+ }
117
+ }
118
+
119
+ export class MethodNotAllowedError extends GhostError {
120
+ constructor(options: GhostErrorOptions = {}) {
121
+ super(mergeOptions(options, {
122
+ statusCode: 405,
123
+ errorType: 'MethodNotAllowedError',
124
+ message: 'Method not allowed for resource.'
125
+ }));
126
+ }
127
+ }
128
+
129
+ export class RequestNotAcceptableError extends GhostError {
130
+ constructor(options: GhostErrorOptions = {}) {
131
+ super(mergeOptions(options, {
132
+ statusCode: 406,
133
+ errorType: 'RequestNotAcceptableError',
134
+ message: 'Request not acceptable for provided Accept-Version header.',
135
+ hideStack: true
136
+ }));
137
+ }
138
+ }
139
+
140
+ export class RangeNotSatisfiableError extends GhostError {
141
+ constructor(options: GhostErrorOptions = {}) {
142
+ super(mergeOptions(options, {
143
+ statusCode: 416,
144
+ errorType: 'RangeNotSatisfiableError',
145
+ message: 'Range not satisfiable for provided Range header.',
146
+ hideStack: true
147
+ }));
148
+ }
149
+ }
150
+
151
+ export class RequestEntityTooLargeError extends GhostError {
152
+ constructor(options: GhostErrorOptions = {}) {
153
+ super(mergeOptions(options, {
154
+ statusCode: 413,
155
+ errorType: 'RequestEntityTooLargeError',
156
+ message: 'Request was too big for the server to handle.'
157
+ }));
158
+ }
159
+ }
160
+
161
+ export class TokenRevocationError extends GhostError {
162
+ constructor(options: GhostErrorOptions = {}) {
163
+ super(mergeOptions(options, {
164
+ statusCode: 503,
165
+ errorType: 'TokenRevocationError',
166
+ message: 'Token is no longer available.'
167
+ }));
168
+ }
169
+ }
170
+
171
+ export class VersionMismatchError extends GhostError {
172
+ constructor(options: GhostErrorOptions = {}) {
173
+ super(mergeOptions(options, {
174
+ statusCode: 400,
175
+ errorType: 'VersionMismatchError',
176
+ message: 'Requested version does not match server version.'
177
+ }));
178
+ }
179
+ }
180
+
181
+ export class DataExportError extends GhostError {
182
+ constructor(options: GhostErrorOptions = {}) {
183
+ super(mergeOptions(options, {
184
+ statusCode: 500,
185
+ errorType: 'DataExportError',
186
+ message: 'The server encountered an error whilst exporting data.'
187
+ }));
188
+ }
189
+ }
190
+
191
+ export class DataImportError extends GhostError {
192
+ constructor(options: GhostErrorOptions = {}) {
193
+ super(mergeOptions(options, {
194
+ statusCode: 500,
195
+ errorType: 'DataImportError',
196
+ message: 'The server encountered an error whilst importing data.'
197
+ }));
198
+ }
199
+ }
200
+
201
+ export class EmailError extends GhostError {
202
+ constructor(options: GhostErrorOptions = {}) {
203
+ super(mergeOptions(options, {
204
+ statusCode: 500,
205
+ errorType: 'EmailError',
206
+ message: 'The server encountered an error whilst sending email.'
207
+ }));
208
+ }
209
+ }
210
+
211
+ export class ThemeValidationError extends GhostError {
212
+ constructor(options: GhostErrorOptions = {}) {
213
+ super(mergeOptions(options, {
214
+ statusCode: 422,
215
+ errorType: 'ThemeValidationError',
216
+ message: 'The theme has a validation error.',
217
+ errorDetails: {}
218
+ }));
219
+ }
220
+ }
221
+
222
+ export class DisabledFeatureError extends GhostError {
223
+ constructor(options: GhostErrorOptions = {}) {
224
+ super(mergeOptions(options, {
225
+ statusCode: 409,
226
+ errorType: 'DisabledFeatureError',
227
+ message: 'Unable to complete the request, this feature is disabled.'
228
+ }));
229
+ }
230
+ }
231
+
232
+ export class UpdateCollisionError extends GhostError {
233
+ constructor(options: GhostErrorOptions = {}) {
234
+ super(mergeOptions(options, {
235
+ statusCode: 409,
236
+ errorType: 'UpdateCollisionError',
237
+ message: 'Unable to complete the request, there was a conflict.'
238
+ }));
239
+ }
240
+ }
241
+
242
+ export class HostLimitError extends GhostError {
243
+ constructor(options: GhostErrorOptions = {}) {
244
+ super(mergeOptions(options, {
245
+ errorType: 'HostLimitError',
246
+ hideStack: true,
247
+ statusCode: 403,
248
+ message: 'Unable to complete the request, this resource is limited.'
249
+ }));
250
+ }
251
+ }
252
+
253
+ export class HelperWarning extends GhostError {
254
+ constructor(options: GhostErrorOptions = {}) {
255
+ super(mergeOptions(options, {
256
+ errorType: 'HelperWarning',
257
+ hideStack: true,
258
+ statusCode: 400,
259
+ message: 'A theme helper has done something unexpected.'
260
+ }));
261
+ }
262
+ }
263
+
264
+ export class PasswordResetRequiredError extends GhostError {
265
+ constructor(options: GhostErrorOptions = {}) {
266
+ super(mergeOptions(options, {
267
+ errorType: 'PasswordResetRequiredError',
268
+ statusCode: 401,
269
+ message: 'For security, you need to create a new password. An email has been sent to you with instructions!'
270
+ }));
271
+ }
272
+ }
273
+
274
+ export class UnhandledJobError extends GhostError {
275
+ constructor(options: GhostErrorOptions = {}) {
276
+ super(mergeOptions(options, {
277
+ errorType: 'UnhandledJobError',
278
+ message: 'Processed job threw an unhandled error',
279
+ level: 'critical'
280
+ }));
281
+ }
282
+ }
283
+
284
+ export class NoContentError extends GhostError {
285
+ constructor(options: GhostErrorOptions = {}) {
286
+ super(mergeOptions(options, {
287
+ errorType: 'NoContentError',
288
+ statusCode: 204,
289
+ hideStack: true
290
+ }));
291
+ }
292
+ }
293
+
294
+ export class ConflictError extends GhostError {
295
+ constructor(options: GhostErrorOptions = {}) {
296
+ super(mergeOptions(options, {
297
+ errorType: 'ConflictError',
298
+ statusCode: 409,
299
+ message: 'The server has encountered an conflict.'
300
+ }));
301
+ }
302
+ }
303
+
304
+ export class MigrationError extends GhostError {
305
+ constructor(options: GhostErrorOptions = {}) {
306
+ super(mergeOptions(options, {
307
+ errorType: 'MigrationError',
308
+ message: 'An error has occurred applying a database migration.',
309
+ level: 'critical'
310
+ }));
311
+ }
312
+ }
package/src/index.ts ADDED
@@ -0,0 +1,14 @@
1
+ import {GhostError} from './GhostError';
2
+ import * as ghostErrors from './errors';
3
+ import {deserialize, isGhostError, prepareStackForUser, serialize} from './utils';
4
+
5
+ export * from './errors';
6
+ export type {GhostError};
7
+ export default ghostErrors;
8
+
9
+ export const utils = {
10
+ serialize,
11
+ deserialize,
12
+ isGhostError,
13
+ prepareStackForUser
14
+ };
package/src/utils.ts ADDED
@@ -0,0 +1,238 @@
1
+ import deepCopy from '@stdlib/utils-copy';
2
+ import {GhostError} from './GhostError';
3
+ import * as errors from './errors';
4
+
5
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
+ type AnyObject = Record<string, any>
7
+
8
+ const errorsWithBase: Record<string, typeof GhostError> = {...errors, GhostError};
9
+
10
+ const _private = {
11
+ serialize(err: GhostError) {
12
+ try {
13
+ return {
14
+ id: err.id,
15
+ status: err.statusCode,
16
+ code: err.code || err.errorType,
17
+ title: err.name,
18
+ detail: err.message,
19
+ meta: {
20
+ context: err.context,
21
+ help: err.help,
22
+ errorDetails: err.errorDetails,
23
+ level: err.level,
24
+ errorType: err.errorType
25
+ }
26
+ };
27
+ } catch (error) {
28
+ return {
29
+ detail: 'Something went wrong.'
30
+ };
31
+ }
32
+ },
33
+
34
+ deserialize(obj: AnyObject) {
35
+ return {
36
+ id: obj.id,
37
+ message: obj.detail || obj.error_description || obj.message,
38
+ statusCode: obj.status,
39
+ code: obj.code || obj.error,
40
+ level: obj.meta && obj.meta.level,
41
+ help: obj.meta && obj.meta.help,
42
+ context: obj.meta && obj.meta.context
43
+ };
44
+ },
45
+
46
+ /**
47
+ * @description Serialize error instance into oauth format.
48
+ *
49
+ * @see https://tools.ietf.org/html/rfc6749#page-45
50
+ *
51
+ * To not loose any error data when sending errors between internal services, we use the suggested OAuth properties and add ours as well.
52
+ */
53
+ OAuthSerialize(err: GhostError) {
54
+ const matchTable = {
55
+ [errors.NoPermissionError.name]: 'access_denied',
56
+ [errors.MaintenanceError.name]: 'temporarily_unavailable',
57
+ [errors.BadRequestError.name]: 'invalid_request',
58
+ [errors.ValidationError.name]: 'invalid_request',
59
+ default: 'server_error'
60
+ };
61
+
62
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
63
+ const {detail, code, ...properties} = _private.serialize(err);
64
+
65
+ return {
66
+ error: err.code || matchTable[err.name] || 'server_error',
67
+ error_description: err.message,
68
+ ...properties
69
+ };
70
+ },
71
+
72
+ /**
73
+ * @description Deserialize oauth error format into GhostError instance.
74
+ * @constructor
75
+ */
76
+ OAuthDeserialize(errorFormat: AnyObject): GhostError {
77
+ try {
78
+ return new errorsWithBase[errorFormat.title || errorFormat.name || errors.InternalServerError.name](_private.deserialize(errorFormat));
79
+ } catch (err) {
80
+ // CASE: you receive an OAuth formatted error, but the error prototype is unknown
81
+ return new errors.InternalServerError({
82
+ errorType: errorFormat.title || errorFormat.name,
83
+ ..._private.deserialize(errorFormat)
84
+ });
85
+ }
86
+ },
87
+
88
+ /**
89
+ * @description Serialize GhostError instance into jsonapi.org format.
90
+ * @param err
91
+ * @return {Object}
92
+ */
93
+ JSONAPISerialize(err: GhostError): AnyObject {
94
+ const errorFormat: AnyObject = {
95
+ errors: [_private.serialize(err)]
96
+ };
97
+
98
+ errorFormat.errors[0].source = {};
99
+
100
+ if (err.property) {
101
+ errorFormat.errors[0].source.pointer = '/data/attributes/' + err.property;
102
+ }
103
+
104
+ return errorFormat;
105
+ },
106
+
107
+ /**
108
+ * @description Deserialize JSON api format into GhostError instance.
109
+ */
110
+ JSONAPIDeserialize(errorFormat: AnyObject): GhostError {
111
+ errorFormat = errorFormat.errors && errorFormat.errors[0] || {};
112
+
113
+ let internalError;
114
+
115
+ try {
116
+ internalError = new errorsWithBase[errorFormat.title || errorFormat.name || errors.InternalServerError.name](_private.deserialize(errorFormat));
117
+ } catch (err) {
118
+ // CASE: you receive a JSON format error, but the error prototype is unknown
119
+ internalError = new errors.InternalServerError({
120
+ errorType: errorFormat.title || errorFormat.name,
121
+ ..._private.deserialize(errorFormat)
122
+ });
123
+ }
124
+
125
+ if (errorFormat.source && errorFormat.source.pointer) {
126
+ internalError.property = errorFormat.source.pointer.split('/')[3];
127
+ }
128
+
129
+ return internalError;
130
+ }
131
+ };
132
+
133
+ /**
134
+ * @description Serialize GhostError instance to error JSON format
135
+ *
136
+ * jsonapi.org error format:
137
+ *
138
+ * source: {
139
+ * parameter: URL query parameter (no support yet)
140
+ * pointer: HTTP body attribute
141
+ * }
142
+ *
143
+ * @see http://jsonapi.org/format/#errors
144
+ */
145
+ export function serialize(err: GhostError, options?: {format: 'jsonapi' | 'oauth'}) {
146
+ options = options || {format: 'jsonapi'};
147
+
148
+ let errorFormat: AnyObject = {};
149
+
150
+ try {
151
+ if (options.format === 'jsonapi') {
152
+ errorFormat = _private.JSONAPISerialize(err);
153
+ } else {
154
+ errorFormat = _private.OAuthSerialize(err);
155
+ }
156
+ } catch (error) {
157
+ errorFormat.message = 'Something went wrong.';
158
+ }
159
+
160
+ // no need to sanitize the undefined values, on response send JSON.stringify get's called
161
+ return errorFormat;
162
+ };
163
+
164
+ /**
165
+ * @description Deserialize from error JSON format to GhostError instance
166
+ */
167
+ export function deserialize(errorFormat: AnyObject): AnyObject {
168
+ let internalError = {};
169
+
170
+ if (errorFormat.errors) {
171
+ internalError = _private.JSONAPIDeserialize(errorFormat);
172
+ } else {
173
+ internalError = _private.OAuthDeserialize(errorFormat);
174
+ }
175
+
176
+ return internalError;
177
+ };
178
+
179
+ /**
180
+ * @description Replace the stack with a user-facing one
181
+ * @returns Clone of the original error with a user-facing stack
182
+ */
183
+ export function prepareStackForUser(error: GhostError): GhostError
184
+ export function prepareStackForUser(error: Error): Error
185
+ export function prepareStackForUser(error: Error): Error {
186
+ const stackbits = error.stack?.split(/\n/) || [];
187
+
188
+ // We build this up backwards, so we always insert at position 1
189
+
190
+ const hideStack = 'hideStack' in error && error.hideStack;
191
+
192
+ if (process.env.NODE_ENV === 'production' || hideStack) {
193
+ stackbits.splice(1, stackbits.length - 1);
194
+ } else {
195
+ // Clearly mark the strack trace
196
+ stackbits.splice(1, 0, `Stack Trace:`);
197
+ }
198
+
199
+ // Add in our custom context and help methods
200
+ if ('help' in error && error.help) {
201
+ stackbits.splice(1, 0, `${error.help}`);
202
+ }
203
+
204
+ if ('context' in error && error.context) {
205
+ stackbits.splice(1, 0, `${error.context}`);
206
+ }
207
+
208
+ // @NOTE: would be a good idea to swap out the cloning implementation with native
209
+ // `structuredClone` one once we use Node v17 or higher. Before making an
210
+ // upgrade make sure structuredClone does a full copy of all properties
211
+ // present on a custom error (see issue: https://github.com/ungap/structured-clone/issues/12)
212
+ const errorClone = deepCopy(error);
213
+ errorClone.stack = stackbits.join('\n');
214
+ return errorClone;
215
+ };
216
+
217
+ /**
218
+ * @description Check whether an error instance is a GhostError.
219
+ */
220
+ export function isGhostError(err: Error) {
221
+ const errorName = GhostError.name;
222
+ const legacyErrorName = 'IgnitionError';
223
+
224
+ const recursiveIsGhostError = function recursiveIsGhostError(obj: AnyObject): boolean {
225
+ // no super constructor available anymore
226
+ if (!obj || !obj.name) {
227
+ return false;
228
+ }
229
+
230
+ if (obj.name === errorName || obj.name === legacyErrorName) {
231
+ return true;
232
+ }
233
+
234
+ return recursiveIsGhostError(Object.getPrototypeOf(obj));
235
+ };
236
+
237
+ return recursiveIsGhostError(err.constructor);
238
+ };
@@ -0,0 +1,5 @@
1
+ export function wrapStack(err: Error, internalErr: Error) {
2
+ const extraLine = (err.stack?.split(/\n/g) || [])[1];
3
+ const [firstLine, ...rest] = internalErr.stack?.split(/\n/g) || [];
4
+ return [firstLine, extraLine, ...rest].join('\n');
5
+ };
@@ -0,0 +1,30 @@
1
+ export interface GhostErrorOptions {
2
+ message?: string;
3
+ statusCode?: number;
4
+ level?: string;
5
+ id?: string;
6
+ context?: string;
7
+ help?: string;
8
+ errorType?: string;
9
+ errorDetails?: any;
10
+ code?: string;
11
+ property?: string;
12
+ redirect?: string;
13
+ hideStack?: boolean;
14
+ err?: Error | string;
15
+ }
16
+ export declare class GhostError extends Error {
17
+ statusCode: number;
18
+ errorType: string;
19
+ level: string;
20
+ id: string;
21
+ context?: string;
22
+ help?: string;
23
+ errorDetails: any;
24
+ code: string | null;
25
+ property: string | null;
26
+ redirect: string | null;
27
+ hideStack: boolean;
28
+ constructor(options?: GhostErrorOptions);
29
+ }
30
+ //# sourceMappingURL=GhostError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GhostError.d.ts","sourceRoot":"","sources":["../src/GhostError.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,iBAAiB;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,YAAY,CAAC,EAAE,GAAG,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,GAAG,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;CACxB;AAED,qBAAa,UAAW,SAAQ,KAAK;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,YAAY,EAAE,GAAG,CAAC;IAClB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;gBAEP,OAAO,GAAE,iBAAsB;CA6D9C"}