@lowerdeck/error 1.0.0
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.
- package/.turbo/turbo-build.log +12 -0
- package/.turbo/turbo-test.log +21 -0
- package/README.md +66 -0
- package/dist/defaultErrors.d.ts +26 -0
- package/dist/defaultErrors.d.ts.map +1 -0
- package/dist/defaultErrors.test.d.ts +2 -0
- package/dist/defaultErrors.test.d.ts.map +1 -0
- package/dist/error.d.ts +34 -0
- package/dist/error.d.ts.map +1 -0
- package/dist/error.test.d.ts +2 -0
- package/dist/error.test.d.ts.map +1 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.modern.js +2 -0
- package/dist/index.modern.js.map +1 -0
- package/dist/index.module.js +2 -0
- package/dist/index.module.js.map +1 -0
- package/dist/index.umd.js +2 -0
- package/dist/index.umd.js.map +1 -0
- package/package.json +34 -0
- package/src/defaultErrors.test.ts +10 -0
- package/src/defaultErrors.ts +118 -0
- package/src/error.test.ts +74 -0
- package/src/error.ts +71 -0
- package/src/index.ts +2 -0
- package/tsconfig.json +11 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
|
|
2
|
+
[0m[2m[35m$[0m [2m[1mmicrobundle[0m
|
|
3
|
+
No name was provided for external module '@lowerdeck/case' in output.globals – guessing '_case'
|
|
4
|
+
[34mBuild "@lowerdeck/error" to dist:[39m
|
|
5
|
+
[32m2.02 kB[39m: [37mindex.cjs[39m.gz
|
|
6
|
+
[32m1.73 kB[39m: [37mindex.cjs[39m.br
|
|
7
|
+
[32m1332 B[39m: [37mindex.modern.js[39m.gz
|
|
8
|
+
[32m1080 B[39m: [37mindex.modern.js[39m.br
|
|
9
|
+
[32m2.03 kB[39m: [37mindex.module.js[39m.gz
|
|
10
|
+
[32m1.73 kB[39m: [37mindex.module.js[39m.br
|
|
11
|
+
[32m2.1 kB[39m: [37mindex.umd.js[39m.gz
|
|
12
|
+
[32m1.79 kB[39m: [37mindex.umd.js[39m.br
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
|
|
2
|
+
[0m[2m[35m$[0m [2m[1mvitest run --passWithNoTests[0m
|
|
3
|
+
[?25l
|
|
4
|
+
[1m[46m RUN [49m[22m [36mv3.2.4 [39m[90m/Users/tobias/code/metorial/metorial-enterprise/oss/src/packages/shared/error[39m
|
|
5
|
+
|
|
6
|
+
[?2026h
|
|
7
|
+
[1m[33m ❯ [39m[22msrc/defaultErrors.test.ts[2m [queued][22m
|
|
8
|
+
|
|
9
|
+
[2m Test Files [22m[1m[32m0 passed[39m[22m[90m (2)[39m
|
|
10
|
+
[2m Tests [22m[1m[32m0 passed[39m[22m[90m (0)[39m
|
|
11
|
+
[2m Start at [22m10:23:43
|
|
12
|
+
[2m Duration [22m101ms
|
|
13
|
+
[?2026l[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K [32m✓[39m src/error.test.ts [2m([22m[2m6 tests[22m[2m)[22m[32m 2[2mms[22m[39m
|
|
14
|
+
[32m✓[39m src/defaultErrors.test.ts [2m([22m[2m1 test[22m[2m)[22m[32m 1[2mms[22m[39m
|
|
15
|
+
|
|
16
|
+
[2m Test Files [22m [1m[32m2 passed[39m[22m[90m (2)[39m
|
|
17
|
+
[2m Tests [22m [1m[32m7 passed[39m[22m[90m (7)[39m
|
|
18
|
+
[2m Start at [22m 10:23:43
|
|
19
|
+
[2m Duration [22m 242ms[2m (transform 57ms, setup 0ms, collect 75ms, tests 4ms, environment 0ms, prepare 83ms)[22m
|
|
20
|
+
|
|
21
|
+
[?25h
|
package/README.md
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# `@lowerdeck/error`
|
|
2
|
+
|
|
3
|
+
Type-safe error handling with structured error objects. Create consistent error responses with status codes, error codes, messages, hints, and descriptions.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @lowerdeck/error
|
|
9
|
+
yarn add @lowerdeck/error
|
|
10
|
+
bun add @lowerdeck/error
|
|
11
|
+
pnpm add @lowerdeck/error
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
import { createError, ServiceError, isServiceError } from '@lowerdeck/error';
|
|
18
|
+
|
|
19
|
+
// Define error types
|
|
20
|
+
const Errors = {
|
|
21
|
+
UserNotFound: new ServiceError(createError({
|
|
22
|
+
statusCode: 404,
|
|
23
|
+
errorCode: 'USER_NOT_FOUND',
|
|
24
|
+
message: 'User not found',
|
|
25
|
+
hint: 'The requested user does not exist',
|
|
26
|
+
description: 'Check the user ID and try again'
|
|
27
|
+
})),
|
|
28
|
+
|
|
29
|
+
Unauthorized: new ServiceError(createError({
|
|
30
|
+
statusCode: 401,
|
|
31
|
+
errorCode: 'UNAUTHORIZED',
|
|
32
|
+
message: 'Unauthorized',
|
|
33
|
+
hint: 'You must be logged in to access this resource'
|
|
34
|
+
}))
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// Throw errors
|
|
38
|
+
function getUser(id: string) {
|
|
39
|
+
const user = findUser(id);
|
|
40
|
+
if (!user) {
|
|
41
|
+
throw Errors.UserNotFound();
|
|
42
|
+
}
|
|
43
|
+
return user;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Handle errors
|
|
47
|
+
try {
|
|
48
|
+
const user = getUser('123');
|
|
49
|
+
} catch (error) {
|
|
50
|
+
if (isServiceError(error)) {
|
|
51
|
+
console.log(error.statusCode); // 404
|
|
52
|
+
console.log(error.data.errorCode); // 'USER_NOT_FOUND'
|
|
53
|
+
|
|
54
|
+
// Convert to HTTP response
|
|
55
|
+
return error.toResponse();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## License
|
|
61
|
+
|
|
62
|
+
This project is licensed under the Apache License 2.0.
|
|
63
|
+
|
|
64
|
+
<div align="center">
|
|
65
|
+
<sub>Built with ❤️ by <a href="https://metorial.com">Metorial</a></sub>
|
|
66
|
+
</div>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ValidationError } from '@lowerdeck/validation';
|
|
2
|
+
import { ErrorData, createError } from './error';
|
|
3
|
+
export declare let validationError: (d: {
|
|
4
|
+
errors: ValidationError[];
|
|
5
|
+
entity: string;
|
|
6
|
+
} & Partial<ErrorData<"invalid_data", 400>>) => import("./error").ErrorRecord<"invalid_data", 400>;
|
|
7
|
+
export declare let internalServerError: import("./error").ErrorRecord<"internal_server_error", 500>;
|
|
8
|
+
export declare let badRequestError: import("./error").ErrorRecord<"bad_request", 400>;
|
|
9
|
+
export declare function notFoundError(p1: {
|
|
10
|
+
entity: string;
|
|
11
|
+
id?: string;
|
|
12
|
+
} & Partial<ErrorData<'not_found', 404>>): ReturnType<typeof createError>;
|
|
13
|
+
export declare function notFoundError(p1: string, p2?: string | null): ReturnType<typeof createError>;
|
|
14
|
+
export declare let unauthorizedError: import("./error").ErrorRecord<"unauthorized", 401>;
|
|
15
|
+
export declare let forbiddenError: import("./error").ErrorRecord<"forbidden", 403>;
|
|
16
|
+
export declare let invalidVersion: import("./error").ErrorRecord<"invalid_version", 400>;
|
|
17
|
+
export declare let conflictError: import("./error").ErrorRecord<"conflict", 409>;
|
|
18
|
+
export declare let goneError: import("./error").ErrorRecord<"gone", 410>;
|
|
19
|
+
export declare let paymentRequiredError: import("./error").ErrorRecord<"payment_required", 402>;
|
|
20
|
+
export declare let preconditionFailedError: import("./error").ErrorRecord<"precondition_failed", 412>;
|
|
21
|
+
export declare let notAcceptableError: import("./error").ErrorRecord<"not_acceptable", 406>;
|
|
22
|
+
export declare let notImplementedError: import("./error").ErrorRecord<"not_implemented", 501>;
|
|
23
|
+
export declare let tooManyRequestsError: import("./error").ErrorRecord<"too_many_requests", 429>;
|
|
24
|
+
export declare let timeoutError: import("./error").ErrorRecord<"timeout", 504>;
|
|
25
|
+
export declare let methodNotAllowedError: import("./error").ErrorRecord<"method_not_allowed", 405>;
|
|
26
|
+
//# sourceMappingURL=defaultErrors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaultErrors.d.ts","sourceRoot":"","sources":["../src/defaultErrors.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEjD,eAAO,IAAI,eAAe,GACxB,GAAG;IAAE,MAAM,EAAE,eAAe,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,SAAS,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC,uDAQxF,CAAC;AAEL,eAAO,IAAI,mBAAmB,6DAI5B,CAAC;AAEH,eAAO,IAAI,eAAe,mDAIxB,CAAC;AAEH,wBAAgB,aAAa,CAAC,EAAE,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,SAAS,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAC1I,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAiB9F,eAAO,IAAI,iBAAiB,oDAK1B,CAAC;AAEH,eAAO,IAAI,cAAc,iDAIvB,CAAC;AAEH,eAAO,IAAI,cAAc,uDAIvB,CAAC;AAEH,eAAO,IAAI,aAAa,gDAItB,CAAC;AAEH,eAAO,IAAI,SAAS,4CAIlB,CAAC;AAEH,eAAO,IAAI,oBAAoB,wDAI7B,CAAC;AAEH,eAAO,IAAI,uBAAuB,2DAIhC,CAAC;AAEH,eAAO,IAAI,kBAAkB,sDAI3B,CAAC;AAEH,eAAO,IAAI,mBAAmB,uDAI5B,CAAC;AAEH,eAAO,IAAI,oBAAoB,yDAK7B,CAAC;AAEH,eAAO,IAAI,YAAY,+CAIrB,CAAC;AAEH,eAAO,IAAI,qBAAqB,0DAI9B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaultErrors.test.d.ts","sourceRoot":"","sources":["../src/defaultErrors.test.ts"],"names":[],"mappings":""}
|
package/dist/error.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export interface ErrorData<Code extends string, Status extends number> {
|
|
2
|
+
status: Status;
|
|
3
|
+
code: Code;
|
|
4
|
+
message: string;
|
|
5
|
+
hint?: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
reason?: string;
|
|
8
|
+
[key: string]: any;
|
|
9
|
+
}
|
|
10
|
+
export type ErrorRecord<Code extends string, Status extends number> = {
|
|
11
|
+
__typename: 'error';
|
|
12
|
+
data: ErrorData<Code, Status>;
|
|
13
|
+
toResponse: () => ErrorData<Code, Status> & {
|
|
14
|
+
__typename: 'error';
|
|
15
|
+
ok: false;
|
|
16
|
+
};
|
|
17
|
+
} & ((extension?: Partial<ErrorData<Code, Status>>) => ErrorRecord<Code, Status>);
|
|
18
|
+
export declare let createError: <Code extends string, Status extends number>(data: ErrorData<Code, Status>) => ErrorRecord<Code, Status>;
|
|
19
|
+
export declare class ServiceError<InnerError extends ErrorRecord<any, any>> extends Error {
|
|
20
|
+
private readonly error;
|
|
21
|
+
__typename: "ServiceError";
|
|
22
|
+
private _parent;
|
|
23
|
+
get parent(): Error | null;
|
|
24
|
+
constructor(error: InnerError);
|
|
25
|
+
setParent(parent: Error): this;
|
|
26
|
+
get data(): ErrorData<any, any>;
|
|
27
|
+
toResponse(): ErrorData<any, any> & {
|
|
28
|
+
__typename: "error";
|
|
29
|
+
ok: false;
|
|
30
|
+
};
|
|
31
|
+
static fromResponse(raw: ErrorData<any, any>): ServiceError<ErrorRecord<any, any>>;
|
|
32
|
+
}
|
|
33
|
+
export declare let isServiceError: (e: any) => e is ServiceError<any>;
|
|
34
|
+
//# sourceMappingURL=error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS,CAAC,IAAI,SAAS,MAAM,EAAE,MAAM,SAAS,MAAM;IACnE,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,IAAI,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,MAAM,WAAW,CAAC,IAAI,SAAS,MAAM,EAAE,MAAM,SAAS,MAAM,IAAI;IACpE,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC9B,UAAU,EAAE,MAAM,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG;QAAE,UAAU,EAAE,OAAO,CAAC;QAAC,EAAE,EAAE,KAAK,CAAA;KAAE,CAAC;CAChF,GAAG,CAAC,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,KAAK,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;AAElF,eAAO,IAAI,WAAW,GAAI,IAAI,SAAS,MAAM,EAAE,MAAM,SAAS,MAAM,EAClE,MAAM,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,KAC5B,WAAW,CAAC,IAAI,EAAE,MAAM,CAa1B,CAAC;AAEF,qBAAa,YAAY,CAAC,UAAU,SAAS,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,CAAE,SAAQ,KAAK;IASnE,OAAO,CAAC,QAAQ,CAAC,KAAK;IARlC,UAAU,EAAG,cAAc,CAAU;IAErC,OAAO,CAAC,OAAO,CAAsB;IAErC,IAAW,MAAM,iBAEhB;gBAE4B,KAAK,EAAE,UAAU;IAI9C,SAAS,CAAC,MAAM,EAAE,KAAK;IAKvB,IAAI,IAAI,wBAEP;IAED,UAAU;oBA1CgD,OAAO;YAAM,KAAK;;IA8C5E,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC;CAO7C;AAED,eAAO,IAAI,cAAc,GAAI,GAAG,GAAG,KAAG,CAAC,IAAI,YAAY,CAAC,GAAG,CAE1D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error.test.d.ts","sourceRoot":"","sources":["../src/error.test.ts"],"names":[],"mappings":""}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var e=require("@lowerdeck/case");function t(){return t=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var o in r)({}).hasOwnProperty.call(r,o)&&(e[o]=r[o])}return e},t.apply(null,arguments)}function r(e){return r=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)},r(e)}function o(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(e){}return(o=function(){return!!e})()}function n(e,t){return n=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},n(e,t)}function s(e){var t=function(e){if("object"!=typeof e||!e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var r=t.call(e,"string");if("object"!=typeof r)return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"==typeof t?t:t+""}function i(e){var t="function"==typeof Map?new Map:void 0;return i=function(e){if(null===e||!function(e){try{return-1!==Function.toString.call(e).indexOf("[native code]")}catch(t){return"function"==typeof e}}(e))return e;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,s)}function s(){return function(e,t,r){if(o())return Reflect.construct.apply(null,arguments);var s=[null];s.push.apply(s,t);var i=new(e.bind.apply(e,s));return r&&n(i,r.prototype),i}(e,arguments,r(this).constructor)}return s.prototype=Object.create(e.prototype,{constructor:{value:s,enumerable:!1,writable:!0,configurable:!0}}),n(s,e)},i(e)}var a=function(e){return Object.assign(function(r){return void 0===r&&(r={}),a(t({},e,r))},{__typename:"error",data:e,toResponse:function(){return t({__typename:"error",ok:!1},e)}})},u=/*#__PURE__*/function(e){function t(t){var r;return(r=e.call(this,t.data.message)||this).error=void 0,r.__typename="ServiceError",r._parent=null,r.error=t,r}var r,o;o=e,(r=t).prototype=Object.create(o.prototype),r.prototype.constructor=r,n(r,o);var i,u,c=t.prototype;return c.setParent=function(e){return this._parent=e,this},c.toResponse=function(){return this.error.toResponse()},t.fromResponse=function(e){var r=e;return delete r.ok,delete r.__typename,new t(a(r))},i=t,(u=[{key:"parent",get:function(){return this._parent}},{key:"data",get:function(){return this.error.data}}])&&function(e,t){for(var r=0;r<t.length;r++){var o=t[r];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,s(o.key),o)}}(i.prototype,u),Object.defineProperty(i,"prototype",{writable:!1}),i}(/*#__PURE__*/i(Error)),c=a({status:500,code:"internal_server_error",message:"An internal server error occurred."}),d=a({status:400,code:"bad_request",message:"The request is invalid."}),p=a({status:401,code:"unauthorized",message:"You are not authorized to access this resource.",hint:"Make sure you are logged in and have the correct permissions to access this resource."}),l=a({status:403,code:"forbidden",message:"You do not have permission to access this resource."}),f=a({status:400,code:"invalid_version",message:"The endpoint does not support the requested version."}),y=a({status:409,code:"conflict",message:"A similar resource already exists."}),m=a({status:410,code:"gone",message:"The requested resource is no longer available."}),h=a({status:402,code:"payment_required",message:"Payment is required to access this resource."}),v=a({status:412,code:"precondition_failed",message:"The precondition of the request failed."}),g=a({status:406,code:"not_acceptable",message:"The requested resource is not acceptable."}),b=a({status:501,code:"not_implemented",message:"The requested resource is not implemented."}),_=a({status:429,code:"too_many_requests",message:"You have made too many requests in a short period of time.",hint:"Please wait a moment and try again."}),E=a({status:504,code:"timeout",message:"The request timed out."}),x=a({status:405,code:"method_not_allowed",message:"The requested method is not allowed for this resource."});exports.ServiceError=u,exports.badRequestError=d,exports.conflictError=y,exports.createError=a,exports.forbiddenError=l,exports.goneError=m,exports.internalServerError=c,exports.invalidVersion=f,exports.isServiceError=function(e){return"ServiceError"===(null==e?void 0:e.__typename)||"ErrorRecord"===(null==e?void 0:e.__typename)},exports.methodNotAllowedError=x,exports.notAcceptableError=g,exports.notFoundError=function(r,o){var n="string"==typeof r?r:r.entity,s="string"==typeof r?o:r.id;return a(t({status:404,code:"not_found",message:"The requested "+e.Cases.toKebabCase(n)+" could not be found.",hint:"Make sure the resource you are trying to access exists, that you have access to it and that it has not been deleted.",entity:n,id:null!=s?s:void 0},"string"==typeof r?{}:r))},exports.notImplementedError=b,exports.paymentRequiredError=h,exports.preconditionFailedError=v,exports.timeoutError=E,exports.tooManyRequestsError=_,exports.unauthorizedError=p,exports.validationError=function(e){return a(t({status:400,code:"invalid_data",message:"The provided data is invalid.",hint:"Make sure the data you are sending follows the specification outlined in the documentation."},e))};
|
|
2
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/error.ts","../src/defaultErrors.ts"],"sourcesContent":["export interface ErrorData<Code extends string, Status extends number> {\n status: Status;\n code: Code;\n message: string;\n hint?: string;\n description?: string;\n reason?: string;\n [key: string]: any;\n}\n\nexport type ErrorRecord<Code extends string, Status extends number> = {\n __typename: 'error';\n data: ErrorData<Code, Status>;\n toResponse: () => ErrorData<Code, Status> & { __typename: 'error'; ok: false };\n} & ((extension?: Partial<ErrorData<Code, Status>>) => ErrorRecord<Code, Status>);\n\nexport let createError = <Code extends string, Status extends number>(\n data: ErrorData<Code, Status>\n): ErrorRecord<Code, Status> => {\n return Object.assign(\n (extension: Partial<ErrorData<Code, Status>> = {}): ErrorRecord<Code, Status> =>\n createError({\n ...data,\n ...extension\n }),\n {\n __typename: 'error' as const,\n data,\n toResponse: () => ({ __typename: 'error' as const, ok: false as const, ...data })\n }\n );\n};\n\nexport class ServiceError<InnerError extends ErrorRecord<any, any>> extends Error {\n __typename = 'ServiceError' as const;\n\n private _parent: Error | null = null;\n\n public get parent() {\n return this._parent;\n }\n\n constructor(private readonly error: InnerError) {\n super(error.data.message);\n }\n\n setParent(parent: Error) {\n this._parent = parent;\n return this;\n }\n\n get data() {\n return this.error.data;\n }\n\n toResponse() {\n return this.error.toResponse();\n }\n\n static fromResponse(raw: ErrorData<any, any>) {\n let data = raw;\n delete data.ok;\n delete data.__typename;\n\n return new ServiceError(createError(data));\n }\n}\n\nexport let isServiceError = (e: any): e is ServiceError<any> => {\n return e?.__typename === 'ServiceError' || e?.__typename === 'ErrorRecord';\n};\n","import { Cases } from '@lowerdeck/case';\nimport { ValidationError } from '@lowerdeck/validation';\nimport { ErrorData, createError } from './error';\n\nexport let validationError = (\n d: { errors: ValidationError[]; entity: string } & Partial<ErrorData<'invalid_data', 400>>\n) =>\n createError({\n status: 400,\n code: 'invalid_data',\n message: 'The provided data is invalid.',\n hint: 'Make sure the data you are sending follows the specification outlined in the documentation.',\n ...d\n });\n\nexport let internalServerError = createError({\n status: 500,\n code: 'internal_server_error',\n message: 'An internal server error occurred.'\n});\n\nexport let badRequestError = createError({\n status: 400,\n code: 'bad_request',\n message: 'The request is invalid.'\n});\n\nexport function notFoundError(p1: { entity: string; id?: string } & Partial<ErrorData<'not_found', 404>>): ReturnType<typeof createError>;\nexport function notFoundError(p1: string, p2?: string | null): ReturnType<typeof createError>;\nexport function notFoundError(p1: any, p2?: any): ReturnType<typeof createError> {\n let entity = typeof p1 == 'string' ? p1 : p1.entity;\n let id = typeof p1 == 'string' ? p2 : p1.id;\n\n return createError({\n status: 404,\n code: 'not_found',\n message: `The requested ${Cases.toKebabCase(entity)} could not be found.`,\n hint: 'Make sure the resource you are trying to access exists, that you have access to it and that it has not been deleted.',\n entity,\n id: id ?? undefined,\n\n ...(typeof p1 == 'string' ? {} : p1)\n });\n}\n\nexport let unauthorizedError = createError({\n status: 401,\n code: 'unauthorized',\n message: 'You are not authorized to access this resource.',\n hint: 'Make sure you are logged in and have the correct permissions to access this resource.'\n});\n\nexport let forbiddenError = createError({\n status: 403,\n code: 'forbidden',\n message: 'You do not have permission to access this resource.'\n});\n\nexport let invalidVersion = createError({\n status: 400,\n code: 'invalid_version',\n message: 'The endpoint does not support the requested version.'\n});\n\nexport let conflictError = createError({\n status: 409,\n code: 'conflict',\n message: 'A similar resource already exists.'\n});\n\nexport let goneError = createError({\n status: 410,\n code: 'gone',\n message: 'The requested resource is no longer available.'\n});\n\nexport let paymentRequiredError = createError({\n status: 402,\n code: 'payment_required',\n message: 'Payment is required to access this resource.'\n});\n\nexport let preconditionFailedError = createError({\n status: 412,\n code: 'precondition_failed',\n message: 'The precondition of the request failed.'\n});\n\nexport let notAcceptableError = createError({\n status: 406,\n code: 'not_acceptable',\n message: 'The requested resource is not acceptable.'\n});\n\nexport let notImplementedError = createError({\n status: 501,\n code: 'not_implemented',\n message: 'The requested resource is not implemented.'\n});\n\nexport let tooManyRequestsError = createError({\n status: 429,\n code: 'too_many_requests',\n message: 'You have made too many requests in a short period of time.',\n hint: 'Please wait a moment and try again.'\n});\n\nexport let timeoutError = createError({\n status: 504,\n code: 'timeout',\n message: 'The request timed out.'\n});\n\nexport let methodNotAllowedError = createError({\n status: 405,\n code: 'method_not_allowed',\n message: 'The requested method is not allowed for this resource.'\n});\n"],"names":["createError","data","Object","assign","extension","_extends","__typename","toResponse","ok","ServiceError","_Error","error","_this","call","message","_parent","_proto","prototype","_createClass","setParent","parent","this","fromResponse","raw","key","get","_wrapNativeSuper","Error","internalServerError","status","code","badRequestError","unauthorizedError","hint","forbiddenError","invalidVersion","conflictError","goneError","paymentRequiredError","preconditionFailedError","notAcceptableError","notImplementedError","tooManyRequestsError","timeoutError","methodNotAllowedError","e","p1","p2","entity","id","Cases","toKebabCase","undefined","d"],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{Cases as e}from"@lowerdeck/case";function t(){return t=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var s=arguments[t];for(var r in s)({}).hasOwnProperty.call(s,r)&&(e[r]=s[r])}return e},t.apply(null,arguments)}let s=e=>Object.assign((r={})=>s(t({},e,r)),{__typename:"error",data:e,toResponse:()=>t({__typename:"error",ok:!1},e)});class r extends Error{get parent(){return this._parent}constructor(e){super(e.data.message),this.error=void 0,this.__typename="ServiceError",this._parent=null,this.error=e}setParent(e){return this._parent=e,this}get data(){return this.error.data}toResponse(){return this.error.toResponse()}static fromResponse(e){let t=e;return delete t.ok,delete t.__typename,new r(s(t))}}let o=e=>"ServiceError"===(null==e?void 0:e.__typename)||"ErrorRecord"===(null==e?void 0:e.__typename),a=e=>s(t({status:400,code:"invalid_data",message:"The provided data is invalid.",hint:"Make sure the data you are sending follows the specification outlined in the documentation."},e)),n=s({status:500,code:"internal_server_error",message:"An internal server error occurred."}),i=s({status:400,code:"bad_request",message:"The request is invalid."});function d(r,o){let a="string"==typeof r?r:r.entity,n="string"==typeof r?o:r.id;return s(t({status:404,code:"not_found",message:`The requested ${e.toKebabCase(a)} could not be found.`,hint:"Make sure the resource you are trying to access exists, that you have access to it and that it has not been deleted.",entity:a,id:null!=n?n:void 0},"string"==typeof r?{}:r))}let u=s({status:401,code:"unauthorized",message:"You are not authorized to access this resource.",hint:"Make sure you are logged in and have the correct permissions to access this resource."}),c=s({status:403,code:"forbidden",message:"You do not have permission to access this resource."}),l=s({status:400,code:"invalid_version",message:"The endpoint does not support the requested version."}),h=s({status:409,code:"conflict",message:"A similar resource already exists."}),m=s({status:410,code:"gone",message:"The requested resource is no longer available."}),p=s({status:402,code:"payment_required",message:"Payment is required to access this resource."}),g=s({status:412,code:"precondition_failed",message:"The precondition of the request failed."}),_=s({status:406,code:"not_acceptable",message:"The requested resource is not acceptable."}),y=s({status:501,code:"not_implemented",message:"The requested resource is not implemented."}),v=s({status:429,code:"too_many_requests",message:"You have made too many requests in a short period of time.",hint:"Please wait a moment and try again."}),f=s({status:504,code:"timeout",message:"The request timed out."}),q=s({status:405,code:"method_not_allowed",message:"The requested method is not allowed for this resource."});export{r as ServiceError,i as badRequestError,h as conflictError,s as createError,c as forbiddenError,m as goneError,n as internalServerError,l as invalidVersion,o as isServiceError,q as methodNotAllowedError,_ as notAcceptableError,d as notFoundError,y as notImplementedError,p as paymentRequiredError,g as preconditionFailedError,f as timeoutError,v as tooManyRequestsError,u as unauthorizedError,a as validationError};
|
|
2
|
+
//# sourceMappingURL=index.modern.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.modern.js","sources":["../src/error.ts","../src/defaultErrors.ts"],"sourcesContent":["export interface ErrorData<Code extends string, Status extends number> {\n status: Status;\n code: Code;\n message: string;\n hint?: string;\n description?: string;\n reason?: string;\n [key: string]: any;\n}\n\nexport type ErrorRecord<Code extends string, Status extends number> = {\n __typename: 'error';\n data: ErrorData<Code, Status>;\n toResponse: () => ErrorData<Code, Status> & { __typename: 'error'; ok: false };\n} & ((extension?: Partial<ErrorData<Code, Status>>) => ErrorRecord<Code, Status>);\n\nexport let createError = <Code extends string, Status extends number>(\n data: ErrorData<Code, Status>\n): ErrorRecord<Code, Status> => {\n return Object.assign(\n (extension: Partial<ErrorData<Code, Status>> = {}): ErrorRecord<Code, Status> =>\n createError({\n ...data,\n ...extension\n }),\n {\n __typename: 'error' as const,\n data,\n toResponse: () => ({ __typename: 'error' as const, ok: false as const, ...data })\n }\n );\n};\n\nexport class ServiceError<InnerError extends ErrorRecord<any, any>> extends Error {\n __typename = 'ServiceError' as const;\n\n private _parent: Error | null = null;\n\n public get parent() {\n return this._parent;\n }\n\n constructor(private readonly error: InnerError) {\n super(error.data.message);\n }\n\n setParent(parent: Error) {\n this._parent = parent;\n return this;\n }\n\n get data() {\n return this.error.data;\n }\n\n toResponse() {\n return this.error.toResponse();\n }\n\n static fromResponse(raw: ErrorData<any, any>) {\n let data = raw;\n delete data.ok;\n delete data.__typename;\n\n return new ServiceError(createError(data));\n }\n}\n\nexport let isServiceError = (e: any): e is ServiceError<any> => {\n return e?.__typename === 'ServiceError' || e?.__typename === 'ErrorRecord';\n};\n","import { Cases } from '@lowerdeck/case';\nimport { ValidationError } from '@lowerdeck/validation';\nimport { ErrorData, createError } from './error';\n\nexport let validationError = (\n d: { errors: ValidationError[]; entity: string } & Partial<ErrorData<'invalid_data', 400>>\n) =>\n createError({\n status: 400,\n code: 'invalid_data',\n message: 'The provided data is invalid.',\n hint: 'Make sure the data you are sending follows the specification outlined in the documentation.',\n ...d\n });\n\nexport let internalServerError = createError({\n status: 500,\n code: 'internal_server_error',\n message: 'An internal server error occurred.'\n});\n\nexport let badRequestError = createError({\n status: 400,\n code: 'bad_request',\n message: 'The request is invalid.'\n});\n\nexport function notFoundError(p1: { entity: string; id?: string } & Partial<ErrorData<'not_found', 404>>): ReturnType<typeof createError>;\nexport function notFoundError(p1: string, p2?: string | null): ReturnType<typeof createError>;\nexport function notFoundError(p1: any, p2?: any): ReturnType<typeof createError> {\n let entity = typeof p1 == 'string' ? p1 : p1.entity;\n let id = typeof p1 == 'string' ? p2 : p1.id;\n\n return createError({\n status: 404,\n code: 'not_found',\n message: `The requested ${Cases.toKebabCase(entity)} could not be found.`,\n hint: 'Make sure the resource you are trying to access exists, that you have access to it and that it has not been deleted.',\n entity,\n id: id ?? undefined,\n\n ...(typeof p1 == 'string' ? {} : p1)\n });\n}\n\nexport let unauthorizedError = createError({\n status: 401,\n code: 'unauthorized',\n message: 'You are not authorized to access this resource.',\n hint: 'Make sure you are logged in and have the correct permissions to access this resource.'\n});\n\nexport let forbiddenError = createError({\n status: 403,\n code: 'forbidden',\n message: 'You do not have permission to access this resource.'\n});\n\nexport let invalidVersion = createError({\n status: 400,\n code: 'invalid_version',\n message: 'The endpoint does not support the requested version.'\n});\n\nexport let conflictError = createError({\n status: 409,\n code: 'conflict',\n message: 'A similar resource already exists.'\n});\n\nexport let goneError = createError({\n status: 410,\n code: 'gone',\n message: 'The requested resource is no longer available.'\n});\n\nexport let paymentRequiredError = createError({\n status: 402,\n code: 'payment_required',\n message: 'Payment is required to access this resource.'\n});\n\nexport let preconditionFailedError = createError({\n status: 412,\n code: 'precondition_failed',\n message: 'The precondition of the request failed.'\n});\n\nexport let notAcceptableError = createError({\n status: 406,\n code: 'not_acceptable',\n message: 'The requested resource is not acceptable.'\n});\n\nexport let notImplementedError = createError({\n status: 501,\n code: 'not_implemented',\n message: 'The requested resource is not implemented.'\n});\n\nexport let tooManyRequestsError = createError({\n status: 429,\n code: 'too_many_requests',\n message: 'You have made too many requests in a short period of time.',\n hint: 'Please wait a moment and try again.'\n});\n\nexport let timeoutError = createError({\n status: 504,\n code: 'timeout',\n message: 'The request timed out.'\n});\n\nexport let methodNotAllowedError = createError({\n status: 405,\n code: 'method_not_allowed',\n message: 'The requested method is not allowed for this resource.'\n});\n"],"names":["createError","data","Object","assign","extension","_extends","__typename","toResponse","ok","ServiceError","Error","parent","this","_parent","constructor","error","super","message","setParent","fromResponse","raw","isServiceError","e","validationError","d","status","code","hint","internalServerError","badRequestError","notFoundError","p1","p2","entity","id","Cases","toKebabCase","undefined","unauthorizedError","forbiddenError","invalidVersion","conflictError","goneError","paymentRequiredError","preconditionFailedError","notAcceptableError","notImplementedError","tooManyRequestsError","timeoutError","methodNotAllowedError"],"mappings":"gQAgBW,IAAAA,EACTC,GAEOC,OAAOC,OACZ,CAACC,EAA8C,CAAA,IAC7CJ,EAAWK,EACNJ,CAAAA,EAAAA,EACAG,IAEP,CACEE,WAAY,QACZL,OACAM,WAAYA,IAAAF,EAAA,CAASC,WAAY,QAAkBE,IAAI,GAAmBP,WAKnEQ,UAA+DC,MAK1E,UAAWC,GACT,OAAWC,KAACC,OACd,CAEAC,WAAAA,CAA6BC,GAC3BC,MAAMD,EAAMd,KAAKgB,SAASL,KADCG,WAR7BT,EAAAA,KAAAA,WAAa,eAELO,KAAAA,QAAwB,KAMHD,KAAKG,MAALA,CAE7B,CAEAG,SAAAA,CAAUP,GAER,OADAC,KAAKC,QAAUF,EAEjBC,IAAA,CAEA,QAAIX,GACF,OAAOW,KAAKG,MAAMd,IACpB,CAEAM,UAAAA,GACE,OAAOK,KAAKG,MAAMR,YACpB,CAEA,mBAAOY,CAAaC,GAClB,IAAInB,EAAOmB,EAIX,cAHOnB,EAAKO,UACLP,EAAKK,WAEL,IAAIG,EAAaT,EAAYC,GACtC,EAGS,IAAAoB,EAAkBC,GACF,kBAAjB,MAADA,OAAC,EAADA,EAAGhB,aAAmD,iBAAjB,MAADgB,OAAC,EAADA,EAAGhB,YCjErCiB,EACTC,GAEAxB,EAAWK,GACToB,OAAQ,IACRC,KAAM,eACNT,QAAS,gCACTU,KAAM,+FACHH,IAGII,EAAsB5B,EAAY,CAC3CyB,OAAQ,IACRC,KAAM,wBACNT,QAAS,uCAGAY,EAAkB7B,EAAY,CACvCyB,OAAQ,IACRC,KAAM,cACNT,QAAS,4BAKK,SAAAa,EAAcC,EAASC,GACrC,IAAIC,EAAsB,iBAANF,EAAiBA,EAAKA,EAAGE,OACzCC,EAAkB,iBAANH,EAAiBC,EAAKD,EAAGG,GAEzC,OAAOlC,EAAWK,EAAA,CAChBoB,OAAQ,IACRC,KAAM,YACNT,QAAS,iBAAiBkB,EAAMC,YAAYH,yBAC5CN,KAAM,uHACNM,SACAC,SAAIA,EAAAA,OAAMG,GAEO,iBAANN,EAAiB,CAAE,EAAGA,GAErC,CAEW,IAAAO,EAAoBtC,EAAY,CACzCyB,OAAQ,IACRC,KAAM,eACNT,QAAS,kDACTU,KAAM,0FAGGY,EAAiBvC,EAAY,CACtCyB,OAAQ,IACRC,KAAM,YACNT,QAAS,wDAGAuB,EAAiBxC,EAAY,CACtCyB,OAAQ,IACRC,KAAM,kBACNT,QAAS,yDAGAwB,EAAgBzC,EAAY,CACrCyB,OAAQ,IACRC,KAAM,WACNT,QAAS,uCAGAyB,EAAY1C,EAAY,CACjCyB,OAAQ,IACRC,KAAM,OACNT,QAAS,mDAGA0B,EAAuB3C,EAAY,CAC5CyB,OAAQ,IACRC,KAAM,mBACNT,QAAS,iDAGA2B,EAA0B5C,EAAY,CAC/CyB,OAAQ,IACRC,KAAM,sBACNT,QAAS,4CAGA4B,EAAqB7C,EAAY,CAC1CyB,OAAQ,IACRC,KAAM,iBACNT,QAAS,8CAGA6B,EAAsB9C,EAAY,CAC3CyB,OAAQ,IACRC,KAAM,kBACNT,QAAS,+CAGA8B,EAAuB/C,EAAY,CAC5CyB,OAAQ,IACRC,KAAM,oBACNT,QAAS,6DACTU,KAAM,wCAGGqB,EAAehD,EAAY,CACpCyB,OAAQ,IACRC,KAAM,UACNT,QAAS,2BAGAgC,EAAwBjD,EAAY,CAC7CyB,OAAQ,IACRC,KAAM,qBACNT,QAAS"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{Cases as e}from"@lowerdeck/case";function t(){return t=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var o in r)({}).hasOwnProperty.call(r,o)&&(e[o]=r[o])}return e},t.apply(null,arguments)}function r(e){return r=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)},r(e)}function o(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(e){}return(o=function(){return!!e})()}function n(e,t){return n=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},n(e,t)}function s(e){var t=function(e){if("object"!=typeof e||!e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var r=t.call(e,"string");if("object"!=typeof r)return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"==typeof t?t:t+""}function a(e){var t="function"==typeof Map?new Map:void 0;return a=function(e){if(null===e||!function(e){try{return-1!==Function.toString.call(e).indexOf("[native code]")}catch(t){return"function"==typeof e}}(e))return e;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,s)}function s(){return function(e,t,r){if(o())return Reflect.construct.apply(null,arguments);var s=[null];s.push.apply(s,t);var a=new(e.bind.apply(e,s));return r&&n(a,r.prototype),a}(e,arguments,r(this).constructor)}return s.prototype=Object.create(e.prototype,{constructor:{value:s,enumerable:!1,writable:!0,configurable:!0}}),n(s,e)},a(e)}var i=function(e){return Object.assign(function(r){return void 0===r&&(r={}),i(t({},e,r))},{__typename:"error",data:e,toResponse:function(){return t({__typename:"error",ok:!1},e)}})},u=/*#__PURE__*/function(e){function t(t){var r;return(r=e.call(this,t.data.message)||this).error=void 0,r.__typename="ServiceError",r._parent=null,r.error=t,r}var r,o;o=e,(r=t).prototype=Object.create(o.prototype),r.prototype.constructor=r,n(r,o);var a,u,c=t.prototype;return c.setParent=function(e){return this._parent=e,this},c.toResponse=function(){return this.error.toResponse()},t.fromResponse=function(e){var r=e;return delete r.ok,delete r.__typename,new t(i(r))},a=t,(u=[{key:"parent",get:function(){return this._parent}},{key:"data",get:function(){return this.error.data}}])&&function(e,t){for(var r=0;r<t.length;r++){var o=t[r];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,s(o.key),o)}}(a.prototype,u),Object.defineProperty(a,"prototype",{writable:!1}),a}(/*#__PURE__*/a(Error)),c=function(e){return"ServiceError"===(null==e?void 0:e.__typename)||"ErrorRecord"===(null==e?void 0:e.__typename)},d=function(e){return i(t({status:400,code:"invalid_data",message:"The provided data is invalid.",hint:"Make sure the data you are sending follows the specification outlined in the documentation."},e))},p=i({status:500,code:"internal_server_error",message:"An internal server error occurred."}),l=i({status:400,code:"bad_request",message:"The request is invalid."});function f(r,o){var n="string"==typeof r?r:r.entity,s="string"==typeof r?o:r.id;return i(t({status:404,code:"not_found",message:"The requested "+e.toKebabCase(n)+" could not be found.",hint:"Make sure the resource you are trying to access exists, that you have access to it and that it has not been deleted.",entity:n,id:null!=s?s:void 0},"string"==typeof r?{}:r))}var y=i({status:401,code:"unauthorized",message:"You are not authorized to access this resource.",hint:"Make sure you are logged in and have the correct permissions to access this resource."}),h=i({status:403,code:"forbidden",message:"You do not have permission to access this resource."}),m=i({status:400,code:"invalid_version",message:"The endpoint does not support the requested version."}),v=i({status:409,code:"conflict",message:"A similar resource already exists."}),g=i({status:410,code:"gone",message:"The requested resource is no longer available."}),b=i({status:402,code:"payment_required",message:"Payment is required to access this resource."}),_=i({status:412,code:"precondition_failed",message:"The precondition of the request failed."}),O=i({status:406,code:"not_acceptable",message:"The requested resource is not acceptable."}),w=i({status:501,code:"not_implemented",message:"The requested resource is not implemented."}),j=i({status:429,code:"too_many_requests",message:"You have made too many requests in a short period of time.",hint:"Please wait a moment and try again."}),q=i({status:504,code:"timeout",message:"The request timed out."}),P=i({status:405,code:"method_not_allowed",message:"The requested method is not allowed for this resource."});export{u as ServiceError,l as badRequestError,v as conflictError,i as createError,h as forbiddenError,g as goneError,p as internalServerError,m as invalidVersion,c as isServiceError,P as methodNotAllowedError,O as notAcceptableError,f as notFoundError,w as notImplementedError,b as paymentRequiredError,_ as preconditionFailedError,q as timeoutError,j as tooManyRequestsError,y as unauthorizedError,d as validationError};
|
|
2
|
+
//# sourceMappingURL=index.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.module.js","sources":["../src/error.ts","../src/defaultErrors.ts"],"sourcesContent":["export interface ErrorData<Code extends string, Status extends number> {\n status: Status;\n code: Code;\n message: string;\n hint?: string;\n description?: string;\n reason?: string;\n [key: string]: any;\n}\n\nexport type ErrorRecord<Code extends string, Status extends number> = {\n __typename: 'error';\n data: ErrorData<Code, Status>;\n toResponse: () => ErrorData<Code, Status> & { __typename: 'error'; ok: false };\n} & ((extension?: Partial<ErrorData<Code, Status>>) => ErrorRecord<Code, Status>);\n\nexport let createError = <Code extends string, Status extends number>(\n data: ErrorData<Code, Status>\n): ErrorRecord<Code, Status> => {\n return Object.assign(\n (extension: Partial<ErrorData<Code, Status>> = {}): ErrorRecord<Code, Status> =>\n createError({\n ...data,\n ...extension\n }),\n {\n __typename: 'error' as const,\n data,\n toResponse: () => ({ __typename: 'error' as const, ok: false as const, ...data })\n }\n );\n};\n\nexport class ServiceError<InnerError extends ErrorRecord<any, any>> extends Error {\n __typename = 'ServiceError' as const;\n\n private _parent: Error | null = null;\n\n public get parent() {\n return this._parent;\n }\n\n constructor(private readonly error: InnerError) {\n super(error.data.message);\n }\n\n setParent(parent: Error) {\n this._parent = parent;\n return this;\n }\n\n get data() {\n return this.error.data;\n }\n\n toResponse() {\n return this.error.toResponse();\n }\n\n static fromResponse(raw: ErrorData<any, any>) {\n let data = raw;\n delete data.ok;\n delete data.__typename;\n\n return new ServiceError(createError(data));\n }\n}\n\nexport let isServiceError = (e: any): e is ServiceError<any> => {\n return e?.__typename === 'ServiceError' || e?.__typename === 'ErrorRecord';\n};\n","import { Cases } from '@lowerdeck/case';\nimport { ValidationError } from '@lowerdeck/validation';\nimport { ErrorData, createError } from './error';\n\nexport let validationError = (\n d: { errors: ValidationError[]; entity: string } & Partial<ErrorData<'invalid_data', 400>>\n) =>\n createError({\n status: 400,\n code: 'invalid_data',\n message: 'The provided data is invalid.',\n hint: 'Make sure the data you are sending follows the specification outlined in the documentation.',\n ...d\n });\n\nexport let internalServerError = createError({\n status: 500,\n code: 'internal_server_error',\n message: 'An internal server error occurred.'\n});\n\nexport let badRequestError = createError({\n status: 400,\n code: 'bad_request',\n message: 'The request is invalid.'\n});\n\nexport function notFoundError(p1: { entity: string; id?: string } & Partial<ErrorData<'not_found', 404>>): ReturnType<typeof createError>;\nexport function notFoundError(p1: string, p2?: string | null): ReturnType<typeof createError>;\nexport function notFoundError(p1: any, p2?: any): ReturnType<typeof createError> {\n let entity = typeof p1 == 'string' ? p1 : p1.entity;\n let id = typeof p1 == 'string' ? p2 : p1.id;\n\n return createError({\n status: 404,\n code: 'not_found',\n message: `The requested ${Cases.toKebabCase(entity)} could not be found.`,\n hint: 'Make sure the resource you are trying to access exists, that you have access to it and that it has not been deleted.',\n entity,\n id: id ?? undefined,\n\n ...(typeof p1 == 'string' ? {} : p1)\n });\n}\n\nexport let unauthorizedError = createError({\n status: 401,\n code: 'unauthorized',\n message: 'You are not authorized to access this resource.',\n hint: 'Make sure you are logged in and have the correct permissions to access this resource.'\n});\n\nexport let forbiddenError = createError({\n status: 403,\n code: 'forbidden',\n message: 'You do not have permission to access this resource.'\n});\n\nexport let invalidVersion = createError({\n status: 400,\n code: 'invalid_version',\n message: 'The endpoint does not support the requested version.'\n});\n\nexport let conflictError = createError({\n status: 409,\n code: 'conflict',\n message: 'A similar resource already exists.'\n});\n\nexport let goneError = createError({\n status: 410,\n code: 'gone',\n message: 'The requested resource is no longer available.'\n});\n\nexport let paymentRequiredError = createError({\n status: 402,\n code: 'payment_required',\n message: 'Payment is required to access this resource.'\n});\n\nexport let preconditionFailedError = createError({\n status: 412,\n code: 'precondition_failed',\n message: 'The precondition of the request failed.'\n});\n\nexport let notAcceptableError = createError({\n status: 406,\n code: 'not_acceptable',\n message: 'The requested resource is not acceptable.'\n});\n\nexport let notImplementedError = createError({\n status: 501,\n code: 'not_implemented',\n message: 'The requested resource is not implemented.'\n});\n\nexport let tooManyRequestsError = createError({\n status: 429,\n code: 'too_many_requests',\n message: 'You have made too many requests in a short period of time.',\n hint: 'Please wait a moment and try again.'\n});\n\nexport let timeoutError = createError({\n status: 504,\n code: 'timeout',\n message: 'The request timed out.'\n});\n\nexport let methodNotAllowedError = createError({\n status: 405,\n code: 'method_not_allowed',\n message: 'The requested method is not allowed for this resource.'\n});\n"],"names":["createError","data","Object","assign","extension","_extends","__typename","toResponse","ok","ServiceError","_Error","error","_this","call","message","_parent","_proto","prototype","_createClass","setParent","parent","this","fromResponse","raw","key","get","_wrapNativeSuper","Error","isServiceError","e","validationError","d","status","code","hint","internalServerError","badRequestError","notFoundError","p1","p2","entity","id","Cases","toKebabCase","undefined","unauthorizedError","forbiddenError","invalidVersion","conflictError","goneError","paymentRequiredError","preconditionFailedError","notAcceptableError","notImplementedError","tooManyRequestsError","timeoutError","methodNotAllowedError"],"mappings":"unDAgBW,IAAAA,EAAc,SACvBC,GAEA,OAAOC,OAAOC,OACZ,SAACC,GACC,YADDA,IAAAA,IAAAA,EAA8C,CAAA,GAC7CJ,EAAWK,EAAA,CAAA,EACNJ,EACAG,GACH,EACJ,CACEE,WAAY,QACZL,KAAAA,EACAM,WAAY,WAAFF,OAAAA,EAAWC,CAAAA,WAAY,QAAkBE,IAAI,GAAmBP,EAAI,GAGpF,EAEaQ,eAAuDC,SAAAA,GASlE,SAAAD,EAA6BE,GAAiB,IAAAC,EAAA,OAC5CA,EAAAF,EAAAG,KAAMF,KAAAA,EAAMV,KAAKa,UAASF,MADCD,aAAAC,EAR7BN,WAAa,eAAuBM,EAE5BG,QAAwB,KAMHH,EAAKD,MAALA,EAAiBC,CAE9C,WAACF,KAAAD,iFAAAO,EAAAP,EAAAQ,UAqBAC,OArBAF,EAEDG,UAAA,SAAUC,GAER,OADAC,KAAKN,QAAUK,EACRC,IACT,EAACL,EAMDT,WAAA,WACE,OAAWc,KAACV,MAAMJ,YACpB,EAACE,EAEMa,aAAP,SAAoBC,GAClB,IAAItB,EAAOsB,EAIX,cAHOtB,EAAKO,UACLP,EAAKK,WAEL,IAAIG,EAAaT,EAAYC,GACtC,IAACQ,OAAAe,IAAA,SAAAC,IA3BD,WACE,OAAWJ,KAACN,OACd,GAACS,CAAAA,IAAAC,OAAAA,IAWD,WACE,OAAOJ,KAAKV,MAAMV,IACpB,iPAACyB,CApBiEhB,cAoBjEgB,EApByEC,QAmCjEC,EAAiB,SAACC,GAC3B,MAAyB,kBAAlBA,MAAAA,OAAAA,EAAAA,EAAGvB,aAAmD,uBAAlBuB,SAAAA,EAAGvB,WAChD,EClEWwB,EAAkB,SAC3BC,UAEA/B,EAAWK,EACT2B,CAAAA,OAAQ,IACRC,KAAM,eACNnB,QAAS,gCACToB,KAAM,+FACHH,GACH,EAEOI,EAAsBnC,EAAY,CAC3CgC,OAAQ,IACRC,KAAM,wBACNnB,QAAS,uCAGAsB,EAAkBpC,EAAY,CACvCgC,OAAQ,IACRC,KAAM,cACNnB,QAAS,qCAKKuB,EAAcC,EAASC,GACrC,IAAIC,EAAsB,iBAANF,EAAiBA,EAAKA,EAAGE,OACzCC,EAAkB,iBAANH,EAAiBC,EAAKD,EAAGG,GAEzC,OAAOzC,EAAWK,EAChB2B,CAAAA,OAAQ,IACRC,KAAM,YACNnB,QAAO,iBAAmB4B,EAAMC,YAAYH,GAAO,uBACnDN,KAAM,uHACNM,OAAAA,EACAC,GAAM,MAAFA,EAAAA,OAAMG,GAEO,iBAANN,EAAiB,CAAA,EAAKA,GAErC,CAEW,IAAAO,EAAoB7C,EAAY,CACzCgC,OAAQ,IACRC,KAAM,eACNnB,QAAS,kDACToB,KAAM,0FAGGY,EAAiB9C,EAAY,CACtCgC,OAAQ,IACRC,KAAM,YACNnB,QAAS,wDAGAiC,EAAiB/C,EAAY,CACtCgC,OAAQ,IACRC,KAAM,kBACNnB,QAAS,yDAGAkC,EAAgBhD,EAAY,CACrCgC,OAAQ,IACRC,KAAM,WACNnB,QAAS,uCAGAmC,EAAYjD,EAAY,CACjCgC,OAAQ,IACRC,KAAM,OACNnB,QAAS,mDAGAoC,EAAuBlD,EAAY,CAC5CgC,OAAQ,IACRC,KAAM,mBACNnB,QAAS,iDAGAqC,EAA0BnD,EAAY,CAC/CgC,OAAQ,IACRC,KAAM,sBACNnB,QAAS,4CAGAsC,EAAqBpD,EAAY,CAC1CgC,OAAQ,IACRC,KAAM,iBACNnB,QAAS,8CAGAuC,EAAsBrD,EAAY,CAC3CgC,OAAQ,IACRC,KAAM,kBACNnB,QAAS,+CAGAwC,EAAuBtD,EAAY,CAC5CgC,OAAQ,IACRC,KAAM,oBACNnB,QAAS,6DACToB,KAAM,wCAGGqB,EAAevD,EAAY,CACpCgC,OAAQ,IACRC,KAAM,UACNnB,QAAS,2BAGA0C,EAAwBxD,EAAY,CAC7CgC,OAAQ,IACRC,KAAM,qBACNnB,QAAS"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@lowerdeck/case")):"function"==typeof define&&define.amd?define(["exports","@lowerdeck/case"],t):t((e||self).error={},e._case)}(this,function(e,t){function r(){return r=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var o in r)({}).hasOwnProperty.call(r,o)&&(e[o]=r[o])}return e},r.apply(null,arguments)}function o(e){return o=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)},o(e)}function n(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(e){}return(n=function(){return!!e})()}function s(e,t){return s=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},s(e,t)}function i(e){var t=function(e){if("object"!=typeof e||!e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var r=t.call(e,"string");if("object"!=typeof r)return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"==typeof t?t:t+""}function a(e){var t="function"==typeof Map?new Map:void 0;return a=function(e){if(null===e||!function(e){try{return-1!==Function.toString.call(e).indexOf("[native code]")}catch(t){return"function"==typeof e}}(e))return e;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,r)}function r(){return function(e,t,r){if(n())return Reflect.construct.apply(null,arguments);var o=[null];o.push.apply(o,t);var i=new(e.bind.apply(e,o));return r&&s(i,r.prototype),i}(e,arguments,o(this).constructor)}return r.prototype=Object.create(e.prototype,{constructor:{value:r,enumerable:!1,writable:!0,configurable:!0}}),s(r,e)},a(e)}var u=function(e){return Object.assign(function(t){return void 0===t&&(t={}),u(r({},e,t))},{__typename:"error",data:e,toResponse:function(){return r({__typename:"error",ok:!1},e)}})},c=/*#__PURE__*/function(e){function t(t){var r;return(r=e.call(this,t.data.message)||this).error=void 0,r.__typename="ServiceError",r._parent=null,r.error=t,r}var r,o;o=e,(r=t).prototype=Object.create(o.prototype),r.prototype.constructor=r,s(r,o);var n,a,c=t.prototype;return c.setParent=function(e){return this._parent=e,this},c.toResponse=function(){return this.error.toResponse()},t.fromResponse=function(e){var r=e;return delete r.ok,delete r.__typename,new t(u(r))},n=t,(a=[{key:"parent",get:function(){return this._parent}},{key:"data",get:function(){return this.error.data}}])&&function(e,t){for(var r=0;r<t.length;r++){var o=t[r];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,i(o.key),o)}}(n.prototype,a),Object.defineProperty(n,"prototype",{writable:!1}),n}(/*#__PURE__*/a(Error)),d=u({status:500,code:"internal_server_error",message:"An internal server error occurred."}),l=u({status:400,code:"bad_request",message:"The request is invalid."}),p=u({status:401,code:"unauthorized",message:"You are not authorized to access this resource.",hint:"Make sure you are logged in and have the correct permissions to access this resource."}),f=u({status:403,code:"forbidden",message:"You do not have permission to access this resource."}),y=u({status:400,code:"invalid_version",message:"The endpoint does not support the requested version."}),h=u({status:409,code:"conflict",message:"A similar resource already exists."}),m=u({status:410,code:"gone",message:"The requested resource is no longer available."}),v=u({status:402,code:"payment_required",message:"Payment is required to access this resource."}),g=u({status:412,code:"precondition_failed",message:"The precondition of the request failed."}),b=u({status:406,code:"not_acceptable",message:"The requested resource is not acceptable."}),_=u({status:501,code:"not_implemented",message:"The requested resource is not implemented."}),E=u({status:429,code:"too_many_requests",message:"You have made too many requests in a short period of time.",hint:"Please wait a moment and try again."}),O=u({status:504,code:"timeout",message:"The request timed out."}),q=u({status:405,code:"method_not_allowed",message:"The requested method is not allowed for this resource."});e.ServiceError=c,e.badRequestError=l,e.conflictError=h,e.createError=u,e.forbiddenError=f,e.goneError=m,e.internalServerError=d,e.invalidVersion=y,e.isServiceError=function(e){return"ServiceError"===(null==e?void 0:e.__typename)||"ErrorRecord"===(null==e?void 0:e.__typename)},e.methodNotAllowedError=q,e.notAcceptableError=b,e.notFoundError=function(e,o){var n="string"==typeof e?e:e.entity,s="string"==typeof e?o:e.id;return u(r({status:404,code:"not_found",message:"The requested "+t.Cases.toKebabCase(n)+" could not be found.",hint:"Make sure the resource you are trying to access exists, that you have access to it and that it has not been deleted.",entity:n,id:null!=s?s:void 0},"string"==typeof e?{}:e))},e.notImplementedError=_,e.paymentRequiredError=v,e.preconditionFailedError=g,e.timeoutError=O,e.tooManyRequestsError=E,e.unauthorizedError=p,e.validationError=function(e){return u(r({status:400,code:"invalid_data",message:"The provided data is invalid.",hint:"Make sure the data you are sending follows the specification outlined in the documentation."},e))}});
|
|
2
|
+
//# sourceMappingURL=index.umd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.umd.js","sources":["../src/error.ts","../src/defaultErrors.ts"],"sourcesContent":["export interface ErrorData<Code extends string, Status extends number> {\n status: Status;\n code: Code;\n message: string;\n hint?: string;\n description?: string;\n reason?: string;\n [key: string]: any;\n}\n\nexport type ErrorRecord<Code extends string, Status extends number> = {\n __typename: 'error';\n data: ErrorData<Code, Status>;\n toResponse: () => ErrorData<Code, Status> & { __typename: 'error'; ok: false };\n} & ((extension?: Partial<ErrorData<Code, Status>>) => ErrorRecord<Code, Status>);\n\nexport let createError = <Code extends string, Status extends number>(\n data: ErrorData<Code, Status>\n): ErrorRecord<Code, Status> => {\n return Object.assign(\n (extension: Partial<ErrorData<Code, Status>> = {}): ErrorRecord<Code, Status> =>\n createError({\n ...data,\n ...extension\n }),\n {\n __typename: 'error' as const,\n data,\n toResponse: () => ({ __typename: 'error' as const, ok: false as const, ...data })\n }\n );\n};\n\nexport class ServiceError<InnerError extends ErrorRecord<any, any>> extends Error {\n __typename = 'ServiceError' as const;\n\n private _parent: Error | null = null;\n\n public get parent() {\n return this._parent;\n }\n\n constructor(private readonly error: InnerError) {\n super(error.data.message);\n }\n\n setParent(parent: Error) {\n this._parent = parent;\n return this;\n }\n\n get data() {\n return this.error.data;\n }\n\n toResponse() {\n return this.error.toResponse();\n }\n\n static fromResponse(raw: ErrorData<any, any>) {\n let data = raw;\n delete data.ok;\n delete data.__typename;\n\n return new ServiceError(createError(data));\n }\n}\n\nexport let isServiceError = (e: any): e is ServiceError<any> => {\n return e?.__typename === 'ServiceError' || e?.__typename === 'ErrorRecord';\n};\n","import { Cases } from '@lowerdeck/case';\nimport { ValidationError } from '@lowerdeck/validation';\nimport { ErrorData, createError } from './error';\n\nexport let validationError = (\n d: { errors: ValidationError[]; entity: string } & Partial<ErrorData<'invalid_data', 400>>\n) =>\n createError({\n status: 400,\n code: 'invalid_data',\n message: 'The provided data is invalid.',\n hint: 'Make sure the data you are sending follows the specification outlined in the documentation.',\n ...d\n });\n\nexport let internalServerError = createError({\n status: 500,\n code: 'internal_server_error',\n message: 'An internal server error occurred.'\n});\n\nexport let badRequestError = createError({\n status: 400,\n code: 'bad_request',\n message: 'The request is invalid.'\n});\n\nexport function notFoundError(p1: { entity: string; id?: string } & Partial<ErrorData<'not_found', 404>>): ReturnType<typeof createError>;\nexport function notFoundError(p1: string, p2?: string | null): ReturnType<typeof createError>;\nexport function notFoundError(p1: any, p2?: any): ReturnType<typeof createError> {\n let entity = typeof p1 == 'string' ? p1 : p1.entity;\n let id = typeof p1 == 'string' ? p2 : p1.id;\n\n return createError({\n status: 404,\n code: 'not_found',\n message: `The requested ${Cases.toKebabCase(entity)} could not be found.`,\n hint: 'Make sure the resource you are trying to access exists, that you have access to it and that it has not been deleted.',\n entity,\n id: id ?? undefined,\n\n ...(typeof p1 == 'string' ? {} : p1)\n });\n}\n\nexport let unauthorizedError = createError({\n status: 401,\n code: 'unauthorized',\n message: 'You are not authorized to access this resource.',\n hint: 'Make sure you are logged in and have the correct permissions to access this resource.'\n});\n\nexport let forbiddenError = createError({\n status: 403,\n code: 'forbidden',\n message: 'You do not have permission to access this resource.'\n});\n\nexport let invalidVersion = createError({\n status: 400,\n code: 'invalid_version',\n message: 'The endpoint does not support the requested version.'\n});\n\nexport let conflictError = createError({\n status: 409,\n code: 'conflict',\n message: 'A similar resource already exists.'\n});\n\nexport let goneError = createError({\n status: 410,\n code: 'gone',\n message: 'The requested resource is no longer available.'\n});\n\nexport let paymentRequiredError = createError({\n status: 402,\n code: 'payment_required',\n message: 'Payment is required to access this resource.'\n});\n\nexport let preconditionFailedError = createError({\n status: 412,\n code: 'precondition_failed',\n message: 'The precondition of the request failed.'\n});\n\nexport let notAcceptableError = createError({\n status: 406,\n code: 'not_acceptable',\n message: 'The requested resource is not acceptable.'\n});\n\nexport let notImplementedError = createError({\n status: 501,\n code: 'not_implemented',\n message: 'The requested resource is not implemented.'\n});\n\nexport let tooManyRequestsError = createError({\n status: 429,\n code: 'too_many_requests',\n message: 'You have made too many requests in a short period of time.',\n hint: 'Please wait a moment and try again.'\n});\n\nexport let timeoutError = createError({\n status: 504,\n code: 'timeout',\n message: 'The request timed out.'\n});\n\nexport let methodNotAllowedError = createError({\n status: 405,\n code: 'method_not_allowed',\n message: 'The requested method is not allowed for this resource.'\n});\n"],"names":["createError","data","Object","assign","extension","_extends","__typename","toResponse","ok","ServiceError","_Error","error","_this","call","message","_parent","_proto","prototype","_createClass","setParent","parent","this","fromResponse","raw","key","get","_wrapNativeSuper","Error","internalServerError","status","code","badRequestError","unauthorizedError","hint","forbiddenError","invalidVersion","conflictError","goneError","paymentRequiredError","preconditionFailedError","notAcceptableError","notImplementedError","tooManyRequestsError","timeoutError","methodNotAllowedError","e","p1","p2","entity","id","Cases","toKebabCase","undefined","d"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lowerdeck/error",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"author": "Tobias Herber",
|
|
8
|
+
"license": "Apache 2",
|
|
9
|
+
"type": "module",
|
|
10
|
+
"source": "src/index.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
"require": "./dist/index.cjs",
|
|
13
|
+
"default": "./dist/index.modern.js"
|
|
14
|
+
},
|
|
15
|
+
"main": "./dist/index.cjs",
|
|
16
|
+
"module": "./dist/index.module.js",
|
|
17
|
+
"types": "dist/index.d.ts",
|
|
18
|
+
"unpkg": "./dist/index.umd.js",
|
|
19
|
+
"scripts": {
|
|
20
|
+
"test": "vitest run --passWithNoTests",
|
|
21
|
+
"lint": "prettier src/**/*.ts --check",
|
|
22
|
+
"build": "microbundle"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@lowerdeck/case": "^1.0.0",
|
|
26
|
+
"@lowerdeck/validation": "^1.0.0"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"microbundle": "^0.15.1",
|
|
30
|
+
"@lowerdeck/tsconfig": "^1.0.0",
|
|
31
|
+
"typescript": "5.8.2",
|
|
32
|
+
"vitest": "^3.1.2"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
import { validationError } from './defaultErrors';
|
|
3
|
+
|
|
4
|
+
describe('validationError', () => {
|
|
5
|
+
test("should return an error object with status 400 and code 'invalid_data'", () => {
|
|
6
|
+
let error = validationError({ errors: [], entity: 'params' });
|
|
7
|
+
expect(error.data.status).toBe(400);
|
|
8
|
+
expect(error.data.code).toBe('invalid_data');
|
|
9
|
+
});
|
|
10
|
+
});
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { Cases } from '@lowerdeck/case';
|
|
2
|
+
import { ValidationError } from '@lowerdeck/validation';
|
|
3
|
+
import { ErrorData, createError } from './error';
|
|
4
|
+
|
|
5
|
+
export let validationError = (
|
|
6
|
+
d: { errors: ValidationError[]; entity: string } & Partial<ErrorData<'invalid_data', 400>>
|
|
7
|
+
) =>
|
|
8
|
+
createError({
|
|
9
|
+
status: 400,
|
|
10
|
+
code: 'invalid_data',
|
|
11
|
+
message: 'The provided data is invalid.',
|
|
12
|
+
hint: 'Make sure the data you are sending follows the specification outlined in the documentation.',
|
|
13
|
+
...d
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export let internalServerError = createError({
|
|
17
|
+
status: 500,
|
|
18
|
+
code: 'internal_server_error',
|
|
19
|
+
message: 'An internal server error occurred.'
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
export let badRequestError = createError({
|
|
23
|
+
status: 400,
|
|
24
|
+
code: 'bad_request',
|
|
25
|
+
message: 'The request is invalid.'
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
export function notFoundError(p1: { entity: string; id?: string } & Partial<ErrorData<'not_found', 404>>): ReturnType<typeof createError>;
|
|
29
|
+
export function notFoundError(p1: string, p2?: string | null): ReturnType<typeof createError>;
|
|
30
|
+
export function notFoundError(p1: any, p2?: any): ReturnType<typeof createError> {
|
|
31
|
+
let entity = typeof p1 == 'string' ? p1 : p1.entity;
|
|
32
|
+
let id = typeof p1 == 'string' ? p2 : p1.id;
|
|
33
|
+
|
|
34
|
+
return createError({
|
|
35
|
+
status: 404,
|
|
36
|
+
code: 'not_found',
|
|
37
|
+
message: `The requested ${Cases.toKebabCase(entity)} could not be found.`,
|
|
38
|
+
hint: 'Make sure the resource you are trying to access exists, that you have access to it and that it has not been deleted.',
|
|
39
|
+
entity,
|
|
40
|
+
id: id ?? undefined,
|
|
41
|
+
|
|
42
|
+
...(typeof p1 == 'string' ? {} : p1)
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export let unauthorizedError = createError({
|
|
47
|
+
status: 401,
|
|
48
|
+
code: 'unauthorized',
|
|
49
|
+
message: 'You are not authorized to access this resource.',
|
|
50
|
+
hint: 'Make sure you are logged in and have the correct permissions to access this resource.'
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
export let forbiddenError = createError({
|
|
54
|
+
status: 403,
|
|
55
|
+
code: 'forbidden',
|
|
56
|
+
message: 'You do not have permission to access this resource.'
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
export let invalidVersion = createError({
|
|
60
|
+
status: 400,
|
|
61
|
+
code: 'invalid_version',
|
|
62
|
+
message: 'The endpoint does not support the requested version.'
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
export let conflictError = createError({
|
|
66
|
+
status: 409,
|
|
67
|
+
code: 'conflict',
|
|
68
|
+
message: 'A similar resource already exists.'
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
export let goneError = createError({
|
|
72
|
+
status: 410,
|
|
73
|
+
code: 'gone',
|
|
74
|
+
message: 'The requested resource is no longer available.'
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
export let paymentRequiredError = createError({
|
|
78
|
+
status: 402,
|
|
79
|
+
code: 'payment_required',
|
|
80
|
+
message: 'Payment is required to access this resource.'
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
export let preconditionFailedError = createError({
|
|
84
|
+
status: 412,
|
|
85
|
+
code: 'precondition_failed',
|
|
86
|
+
message: 'The precondition of the request failed.'
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
export let notAcceptableError = createError({
|
|
90
|
+
status: 406,
|
|
91
|
+
code: 'not_acceptable',
|
|
92
|
+
message: 'The requested resource is not acceptable.'
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
export let notImplementedError = createError({
|
|
96
|
+
status: 501,
|
|
97
|
+
code: 'not_implemented',
|
|
98
|
+
message: 'The requested resource is not implemented.'
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
export let tooManyRequestsError = createError({
|
|
102
|
+
status: 429,
|
|
103
|
+
code: 'too_many_requests',
|
|
104
|
+
message: 'You have made too many requests in a short period of time.',
|
|
105
|
+
hint: 'Please wait a moment and try again.'
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
export let timeoutError = createError({
|
|
109
|
+
status: 504,
|
|
110
|
+
code: 'timeout',
|
|
111
|
+
message: 'The request timed out.'
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
export let methodNotAllowedError = createError({
|
|
115
|
+
status: 405,
|
|
116
|
+
code: 'method_not_allowed',
|
|
117
|
+
message: 'The requested method is not allowed for this resource.'
|
|
118
|
+
});
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
import { ServiceError, createError } from './error';
|
|
3
|
+
|
|
4
|
+
describe('createError', () => {
|
|
5
|
+
test('should create an error record with the provided data', () => {
|
|
6
|
+
let data = {
|
|
7
|
+
code: '404',
|
|
8
|
+
message: 'Not Found',
|
|
9
|
+
status: 404
|
|
10
|
+
};
|
|
11
|
+
let errorRecord = createError(data);
|
|
12
|
+
expect(errorRecord.data).toEqual(data);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test('should create an error record with a response function', () => {
|
|
16
|
+
let data = {
|
|
17
|
+
code: '404',
|
|
18
|
+
message: 'Not Found',
|
|
19
|
+
status: 404
|
|
20
|
+
};
|
|
21
|
+
let errorRecord = createError(data);
|
|
22
|
+
let response = errorRecord.toResponse();
|
|
23
|
+
expect(response).toEqual({ ...data, __typename: 'error', ok: false });
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test('should create an error record with a response function that can be extended', () => {
|
|
27
|
+
let data = {
|
|
28
|
+
code: '404',
|
|
29
|
+
message: 'Not Found',
|
|
30
|
+
status: 404
|
|
31
|
+
};
|
|
32
|
+
let errorRecord = createError(data);
|
|
33
|
+
let response = errorRecord({ hint: 'This is a hint' }).toResponse();
|
|
34
|
+
expect(response).toEqual({
|
|
35
|
+
...data,
|
|
36
|
+
__typename: 'error',
|
|
37
|
+
ok: false,
|
|
38
|
+
hint: 'This is a hint'
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
describe('ServiceError', () => {
|
|
44
|
+
test('should create an ServiceError with the provided error', () => {
|
|
45
|
+
let errorRecord = createError({
|
|
46
|
+
code: '404',
|
|
47
|
+
message: 'Not Found',
|
|
48
|
+
status: 404
|
|
49
|
+
});
|
|
50
|
+
let apiError = new ServiceError(errorRecord);
|
|
51
|
+
expect(apiError.data).toEqual(errorRecord.data);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('should create an ServiceError with the provided error message', () => {
|
|
55
|
+
let errorRecord = createError({
|
|
56
|
+
code: '404',
|
|
57
|
+
message: 'Not Found',
|
|
58
|
+
status: 404
|
|
59
|
+
});
|
|
60
|
+
let apiError = new ServiceError(errorRecord);
|
|
61
|
+
expect(apiError.message).toEqual(errorRecord.data.message);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test('should return the error response', () => {
|
|
65
|
+
let errorRecord = createError({
|
|
66
|
+
code: '404',
|
|
67
|
+
message: 'Not Found',
|
|
68
|
+
status: 404
|
|
69
|
+
});
|
|
70
|
+
let apiError = new ServiceError(errorRecord);
|
|
71
|
+
let response = apiError.toResponse();
|
|
72
|
+
expect(response).toEqual({ ...errorRecord.data, __typename: 'error', ok: false });
|
|
73
|
+
});
|
|
74
|
+
});
|
package/src/error.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
export interface ErrorData<Code extends string, Status extends number> {
|
|
2
|
+
status: Status;
|
|
3
|
+
code: Code;
|
|
4
|
+
message: string;
|
|
5
|
+
hint?: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
reason?: string;
|
|
8
|
+
[key: string]: any;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type ErrorRecord<Code extends string, Status extends number> = {
|
|
12
|
+
__typename: 'error';
|
|
13
|
+
data: ErrorData<Code, Status>;
|
|
14
|
+
toResponse: () => ErrorData<Code, Status> & { __typename: 'error'; ok: false };
|
|
15
|
+
} & ((extension?: Partial<ErrorData<Code, Status>>) => ErrorRecord<Code, Status>);
|
|
16
|
+
|
|
17
|
+
export let createError = <Code extends string, Status extends number>(
|
|
18
|
+
data: ErrorData<Code, Status>
|
|
19
|
+
): ErrorRecord<Code, Status> => {
|
|
20
|
+
return Object.assign(
|
|
21
|
+
(extension: Partial<ErrorData<Code, Status>> = {}): ErrorRecord<Code, Status> =>
|
|
22
|
+
createError({
|
|
23
|
+
...data,
|
|
24
|
+
...extension
|
|
25
|
+
}),
|
|
26
|
+
{
|
|
27
|
+
__typename: 'error' as const,
|
|
28
|
+
data,
|
|
29
|
+
toResponse: () => ({ __typename: 'error' as const, ok: false as const, ...data })
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export class ServiceError<InnerError extends ErrorRecord<any, any>> extends Error {
|
|
35
|
+
__typename = 'ServiceError' as const;
|
|
36
|
+
|
|
37
|
+
private _parent: Error | null = null;
|
|
38
|
+
|
|
39
|
+
public get parent() {
|
|
40
|
+
return this._parent;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
constructor(private readonly error: InnerError) {
|
|
44
|
+
super(error.data.message);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
setParent(parent: Error) {
|
|
48
|
+
this._parent = parent;
|
|
49
|
+
return this;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
get data() {
|
|
53
|
+
return this.error.data;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
toResponse() {
|
|
57
|
+
return this.error.toResponse();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
static fromResponse(raw: ErrorData<any, any>) {
|
|
61
|
+
let data = raw;
|
|
62
|
+
delete data.ok;
|
|
63
|
+
delete data.__typename;
|
|
64
|
+
|
|
65
|
+
return new ServiceError(createError(data));
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export let isServiceError = (e: any): e is ServiceError<any> => {
|
|
70
|
+
return e?.__typename === 'ServiceError' || e?.__typename === 'ErrorRecord';
|
|
71
|
+
};
|
package/src/index.ts
ADDED
package/tsconfig.json
ADDED