Make CodexError extends Error

This commit is contained in:
Arnaud 2024-09-27 17:35:50 +02:00
parent dd116dc571
commit 49f82f49bc
No known key found for this signature in database
GPG Key ID: 69D6CE281FCAE663
13 changed files with 71 additions and 64 deletions

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "@codex-storage/sdk-js", "name": "@codex-storage/sdk-js",
"version": "0.0.5", "version": "0.0.^",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@codex-storage/sdk-js", "name": "@codex-storage/sdk-js",
"version": "0.0.5", "version": "0.0.^",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"valibot": "^0.32.0" "valibot": "^0.32.0"

View File

@ -1,6 +1,6 @@
{ {
"name": "@codex-storage/sdk-js", "name": "@codex-storage/sdk-js",
"version": "0.0.5", "version": "0.0.^",
"description": "Codex SDK to interact with the Codex decentralized storage network.", "description": "Codex SDK to interact with the Codex decentralized storage network.",
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -1,4 +1,5 @@
import { Api } from "../api/config"; import { Api } from "../api/config";
import { CodexError } from "../errors/errors";
import { Fetch } from "../fetch-safe/fetch-safe"; import { Fetch } from "../fetch-safe/fetch-safe";
import type { SafeValue } from "../values/values"; import type { SafeValue } from "../values/values";
import type { import type {
@ -77,10 +78,9 @@ export class CodexData {
if (xhr.status != 200) { if (xhr.status != 200) {
resolve({ resolve({
error: true, error: true,
data: { data: new CodexError(xhr.responseText, {
code: xhr.status, code: xhr.status,
message: xhr.responseText, }),
},
}); });
} else { } else {
resolve({ error: false, data: xhr.response }); resolve({ error: false, data: xhr.response });
@ -90,9 +90,7 @@ export class CodexData {
xhr.onerror = function () { xhr.onerror = function () {
resolve({ resolve({
error: true, error: true,
data: { data: new CodexError("Something went wrong during the file upload."),
message: "Something went wrong during the file upload.",
},
}); });
}; };
}); });

View File

@ -1,6 +1,7 @@
import { afterEach, assert, describe, it, vi } from "vitest"; import { afterEach, assert, describe, it, vi } from "vitest";
import { CodexDebug } from "./debug"; import { CodexDebug } from "./debug";
import type { CodexLogLevel } from "./types"; import type { CodexLogLevel } from "./types";
import { CodexError } from "../errors/errors";
describe("debug", () => { describe("debug", () => {
afterEach(() => { afterEach(() => {
@ -14,8 +15,7 @@ describe("debug", () => {
assert.deepStrictEqual(response, { assert.deepStrictEqual(response, {
error: true, error: true,
data: { data: new CodexError("Cannot validate the input", {
message: "Cannot validate the input",
errors: [ errors: [
{ {
expected: expected:
@ -26,7 +26,7 @@ describe("debug", () => {
received: '"TEST"', received: '"TEST"',
}, },
], ],
}, }),
}); });
}); });

View File

@ -1,5 +1,5 @@
import { Api } from "../api/config"; import { Api } from "../api/config";
import { CodexValibotIssuesMap } from "../errors/errors"; import { CodexError, CodexValibotIssuesMap } from "../errors/errors";
import { Fetch } from "../fetch-safe/fetch-safe"; import { Fetch } from "../fetch-safe/fetch-safe";
import type { SafeValue } from "../values/values"; import type { SafeValue } from "../values/values";
import { CodexLogLevel, type CodexDebugInfo } from "./types"; import { CodexLogLevel, type CodexDebugInfo } from "./types";
@ -21,10 +21,9 @@ export class CodexDebug {
if (!result.success) { if (!result.success) {
return Promise.resolve({ return Promise.resolve({
error: true, error: true,
data: { data: new CodexError("Cannot validate the input", {
message: "Cannot validate the input",
errors: CodexValibotIssuesMap(result.issues), errors: CodexValibotIssuesMap(result.issues),
}, }),
}); });
} }

View File

@ -13,11 +13,27 @@ type ValidationError = {
* `errors`: A {ValidationError} array when it comes from an object validation process * `errors`: A {ValidationError} array when it comes from an object validation process
* `stack`: The error stack when the CodexError results from a error thrown * `stack`: The error stack when the CodexError results from a error thrown
*/ */
export type CodexError = { export class CodexError extends Error {
message: string; code: number | null;
code?: number; errors: ValidationError[] | null;
errors?: ValidationError[]; sourceStack: string | null;
stack?: string;
constructor(
message: string,
{ code, errors, sourceStack }: CodexErrorProps = {}
) {
super(message);
this.code = code || null;
this.errors = errors || null;
this.sourceStack = sourceStack || null;
}
}
type CodexErrorProps = {
code?: number | null;
errors?: ValidationError[] | null;
sourceStack?: string | null;
}; };
export const CodexValibotIssuesMap = (issues: InferIssue<any>[]) => export const CodexValibotIssuesMap = (issues: InferIssue<any>[]) =>

View File

@ -1,5 +1,6 @@
import { afterEach, assert, describe, it, vi } from "vitest"; import { afterEach, assert, describe, it, vi } from "vitest";
import { Fetch } from "../fetch-safe/fetch-safe"; import { Fetch } from "../fetch-safe/fetch-safe";
import { CodexError } from "../async";
describe.only("fetch", () => { describe.only("fetch", () => {
afterEach(() => { afterEach(() => {
@ -18,10 +19,9 @@ describe.only("fetch", () => {
method: "GET", method: "GET",
}); });
const error = { const error = new CodexError("error", {
message: "error",
code: 500, code: 500,
}; });
assert.deepStrictEqual(result, { error: true, data: error }); assert.deepStrictEqual(result, { error: true, data: error });
}); });

View File

@ -1,3 +1,4 @@
import { CodexError } from "../errors/errors";
import { Promises } from "../promise-safe/promise-safe"; import { Promises } from "../promise-safe/promise-safe";
import { type SafeValue } from "../values/values"; import { type SafeValue } from "../values/values";
@ -8,15 +9,14 @@ export const Fetch = {
if (res.error) { if (res.error) {
return { return {
error: true, error: true,
data: { data: new CodexError(res.data.message, {
message: res.data.message,
code: 502, code: 502,
}, }),
}; };
} }
if (!res.data.ok) { if (!res.data.ok) {
const message = await Promises.safe(() => res.data.text()); const message = await Promises.safe(res.data.text);
if (message.error) { if (message.error) {
return message; return message;
@ -24,10 +24,9 @@ export const Fetch = {
return { return {
error: true, error: true,
data: { data: new CodexError(message.data, {
message: message.data,
code: res.data.status, code: res.data.status,
}, }),
}; };
} }

View File

@ -6,6 +6,7 @@ import {
randomInt, randomInt,
randomString, randomString,
} from "../tests/tests.util"; } from "../tests/tests.util";
import { CodexError } from "../errors/errors";
function createStorageRequest() { function createStorageRequest() {
return { return {
@ -23,8 +24,7 @@ function createStorageRequest() {
function missingNumberValidationError(field: string) { function missingNumberValidationError(field: string) {
return { return {
error: true as any, error: true as any,
data: { data: new CodexError("Cannot validate the input", {
message: "Cannot validate the input",
errors: [ errors: [
{ {
path: field, path: field,
@ -33,15 +33,14 @@ function missingNumberValidationError(field: string) {
received: "undefined", received: "undefined",
}, },
], ],
}, }),
}; };
} }
function extraValidationError(field: string, value: unknown) { function extraValidationError(field: string, value: unknown) {
return { return {
error: true as any, error: true as any,
data: { data: new CodexError("Cannot validate the input", {
message: "Cannot validate the input",
errors: [ errors: [
{ {
path: field, path: field,
@ -50,15 +49,14 @@ function extraValidationError(field: string, value: unknown) {
received: `"${value}"`, received: `"${value}"`,
}, },
], ],
}, }),
}; };
} }
function missingStringValidationError(field: string) { function missingStringValidationError(field: string) {
return { return {
error: true as any, error: true as any,
data: { data: new CodexError("Cannot validate the input", {
message: "Cannot validate the input",
errors: [ errors: [
{ {
path: field, path: field,
@ -67,15 +65,14 @@ function missingStringValidationError(field: string) {
received: "undefined", received: "undefined",
}, },
], ],
}, }),
}; };
} }
function mistypeNumberValidationError(field: string, value: string) { function mistypeNumberValidationError(field: string, value: string) {
return { return {
error: true as any, error: true as any,
data: { data: new CodexError("Cannot validate the input", {
message: "Cannot validate the input",
errors: [ errors: [
{ {
path: field, path: field,
@ -84,15 +81,14 @@ function mistypeNumberValidationError(field: string, value: string) {
received: `"${value}"`, received: `"${value}"`,
}, },
], ],
}, }),
}; };
} }
function minNumberValidationError(field: string, min: number) { function minNumberValidationError(field: string, min: number) {
return { return {
error: true as any, error: true as any,
data: { data: new CodexError("Cannot validate the input", {
message: "Cannot validate the input",
errors: [ errors: [
{ {
path: field, path: field,
@ -101,7 +97,7 @@ function minNumberValidationError(field: string, min: number) {
received: "0", received: "0",
}, },
], ],
}, }),
}; };
} }

View File

@ -1,6 +1,6 @@
import * as v from "valibot"; import * as v from "valibot";
import { Api } from "../api/config"; import { Api } from "../api/config";
import { CodexValibotIssuesMap } from "../errors/errors"; import { CodexError, CodexValibotIssuesMap } from "../errors/errors";
import { Fetch } from "../fetch-safe/fetch-safe"; import { Fetch } from "../fetch-safe/fetch-safe";
import type { SafeValue } from "../values/values"; import type { SafeValue } from "../values/values";
import { import {
@ -82,10 +82,9 @@ export class CodexMarketplace {
if (!result.success) { if (!result.success) {
return { return {
error: true, error: true,
data: { data: new CodexError("Cannot validate the input", {
message: "Cannot validate the input",
errors: CodexValibotIssuesMap(result.issues), errors: CodexValibotIssuesMap(result.issues),
}, }),
}; };
} }
@ -116,10 +115,9 @@ export class CodexMarketplace {
if (!result.success) { if (!result.success) {
return { return {
error: true, error: true,
data: { data: new CodexError("Cannot validate the input", {
message: "Cannot validate the input",
errors: CodexValibotIssuesMap(result.issues), errors: CodexValibotIssuesMap(result.issues),
}, }),
}; };
} }
@ -229,10 +227,9 @@ export class CodexMarketplace {
if (!result.success) { if (!result.success) {
return { return {
error: true, error: true,
data: { data: new CodexError("Cannot validate the input", {
message: "Cannot validate the input",
errors: CodexValibotIssuesMap(result.issues), errors: CodexValibotIssuesMap(result.issues),
}, }),
}; };
} }

View File

@ -1,6 +1,6 @@
import { Api } from "../api/config"; import { Api } from "../api/config";
import type { SafeValue } from "../async";
import { Fetch } from "../fetch-safe/fetch-safe"; import { Fetch } from "../fetch-safe/fetch-safe";
import type { SafeValue } from "../values/values";
import type { CodexSpr } from "./types"; import type { CodexSpr } from "./types";
export class CodexNode { export class CodexNode {

View File

@ -1,5 +1,6 @@
import { assert, describe, it } from "vitest"; import { assert, describe, it } from "vitest";
import { Promises } from "./promise-safe"; import { Promises } from "./promise-safe";
import { CodexError } from "../async";
describe("promise safe", () => { describe("promise safe", () => {
it("returns an error when the promise failed", async () => { it("returns an error when the promise failed", async () => {
@ -7,7 +8,10 @@ describe("promise safe", () => {
() => new Promise((_, reject) => reject("error")) () => new Promise((_, reject) => reject("error"))
); );
assert.deepStrictEqual(result, { error: true, data: { message: "error" } }); assert.deepStrictEqual(result, {
error: true,
data: new CodexError("error"),
});
}); });
it("returns the value when the promise succeed", async () => { it("returns the value when the promise succeed", async () => {

View File

@ -1,3 +1,4 @@
import { CodexError } from "../async";
import type { SafeValue } from "../values/values"; import type { SafeValue } from "../values/values";
export const Promises = { export const Promises = {
@ -7,14 +8,11 @@ export const Promises = {
return { error: false, data: result }; return { error: false, data: result };
} catch (e) { } catch (e) {
const opts = e instanceof Error && e.stack ? { stack: e.stack } : {};
return { return {
error: true, error: true,
data: { data: new CodexError(e instanceof Error ? e.message : "" + e, {
message: e instanceof Error ? e.message : "" + e, sourceStack: e instanceof Error ? e.stack || null : null,
...opts, }),
},
}; };
} }
}, },