From 9e89c30562b4dba164a75410b8b458e75fe716b9 Mon Sep 17 00:00:00 2001 From: Arnaud Date: Fri, 28 Mar 2025 09:13:01 +0100 Subject: [PATCH] Support basic authentication --- README.md | 22 +++++-- examples/basic-auth/.gitignore | 1 + examples/basic-auth/README.md | 23 +++++++ examples/basic-auth/esbuild.js | 22 +++++++ examples/basic-auth/index.html | 4 ++ examples/basic-auth/index.js | 19 ++++++ .../package-lock.json | 34 +++++++++-- examples/basic-auth/package.json | 18 ++++++ examples/download/README.md | 2 +- examples/download/esbuild.js | 3 + examples/download/package.json | 2 +- examples/upload-browser/README.md | 2 +- src/data/browser-upload.ts | 11 +++- src/data/data.ts | 61 ++++++++++++++----- src/data/node-upload.ts | 10 ++- src/data/types.ts | 10 ++- src/debug/debug.ts | 19 +++++- src/fetch-safe/fetch-safe.test.ts | 2 +- src/fetch-safe/fetch-safe.ts | 15 +++++ src/index.ts | 20 ++++-- src/marketplace/marketplace.ts | 27 +++++++- src/node/node.ts | 20 +++++- src/promise-safe/promise-safe.test.ts | 2 +- src/promise-safe/promise-safe.ts | 2 +- 24 files changed, 303 insertions(+), 48 deletions(-) create mode 100644 examples/basic-auth/.gitignore create mode 100644 examples/basic-auth/README.md create mode 100644 examples/basic-auth/esbuild.js create mode 100644 examples/basic-auth/index.html create mode 100644 examples/basic-auth/index.js rename examples/{download => basic-auth}/package-lock.json (94%) create mode 100644 examples/basic-auth/package.json diff --git a/README.md b/README.md index 314e8c0..6e60f65 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,20 @@ To use a module, you need to use the await syntax. If the module is not loaded y const marketplace = await codex.marketplace(); ``` +### Authentication + +You can use basic authentication when creating a new Codex object: + +```js +const codex = new Codex("http://localhost:3000", { + auth: { + basic: "MY BASIC AUTH SECRET" + } +}); + +You can obtain your secret using the `btoa` method in the browser or `Buffer.from(string).toString('base64')` in Node.js. The secret is stored in memory only. +``` + ### Error handling The SDK provides a type called `SafeValue` for error handling instead of throwing errors. It is inspired by Go's "error as value" concept. @@ -105,7 +119,7 @@ const codex = new Codex("http://localhost:3000"); const marketplace = await codex.marketplace(); // When using the sync api -const marketplace = codex.marketplace +const marketplace = codex.marketplace; ``` #### activeSlots() @@ -253,7 +267,7 @@ const codex = new Codex("http://localhost:3000"); const data = await codex.data(); // When using the sync api -const data = codex.data +const data = codex.data; ``` #### cids @@ -389,7 +403,7 @@ const codex = new Codex("http://localhost:3000"); const data = await codex.debug(); // When using the sync api -const data = codex.debug +const data = codex.debug; ``` #### setLogLevel @@ -427,7 +441,7 @@ const codex = new Codex("http://localhost:3000"); const node = await codex.node(); // When using the sync api -const node = codex.node +const node = codex.node; ``` #### spr diff --git a/examples/basic-auth/.gitignore b/examples/basic-auth/.gitignore new file mode 100644 index 0000000..91097d8 --- /dev/null +++ b/examples/basic-auth/.gitignore @@ -0,0 +1 @@ +index.bundle.js \ No newline at end of file diff --git a/examples/basic-auth/README.md b/examples/basic-auth/README.md new file mode 100644 index 0000000..c999b21 --- /dev/null +++ b/examples/basic-auth/README.md @@ -0,0 +1,23 @@ +# Download example + +Small example to show how to download a file in the browser with Codex. + +## Install dependencies + +```bash +npm install +``` + +## Build the javascript asset + +```bash +CODEX_CID=REPLACE_BY_YOUR_CID npm run build +``` + +The response will be displayed as text, so it is better to test with .txt files. + +Note: You can define `CODEX_NODE_URL`, default value is "http://localhost:8080". + +## Check the results + +Open the index.html and open the web console. diff --git a/examples/basic-auth/esbuild.js b/examples/basic-auth/esbuild.js new file mode 100644 index 0000000..37b09c6 --- /dev/null +++ b/examples/basic-auth/esbuild.js @@ -0,0 +1,22 @@ +const { build } = require("esbuild"); +const define = {}; + +for (const k in process.env) { + define[`process.env.${k}`] = JSON.stringify(process.env[k]); +} + +if (!process.env["CODEX_NODE_URL"]) { + define[`process.env.CODEX_NODE_URL`] = '"http://localhost:8080"'; +} + +const options = { + entryPoints: ["./index.js"], + outfile: "./index.bundle.js", + bundle: true, + define, + logOverride: { + "ignored-bare-import": "silent", + }, +}; + +build(options).catch(() => process.exit(1)); diff --git a/examples/basic-auth/index.html b/examples/basic-auth/index.html new file mode 100644 index 0000000..0a494ed --- /dev/null +++ b/examples/basic-auth/index.html @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/examples/basic-auth/index.js b/examples/basic-auth/index.js new file mode 100644 index 0000000..b3d1117 --- /dev/null +++ b/examples/basic-auth/index.js @@ -0,0 +1,19 @@ +import { Codex } from "@codex-storage/sdk-js"; + +async function main() { + const codex = new Codex(process.env.CODEX_NODE_URL, { + auth: { + basic: btoa("admin:SuperSecret123"), + }, + }); + + const data = codex.data; + + const cid = process.env.CODEX_CID; + + const result = await data.networkDownloadStream(cid); + + console.info(await result.data.text()); +} + +main(); diff --git a/examples/download/package-lock.json b/examples/basic-auth/package-lock.json similarity index 94% rename from examples/download/package-lock.json rename to examples/basic-auth/package-lock.json index a7d1c79..7701ddd 100644 --- a/examples/download/package-lock.json +++ b/examples/basic-auth/package-lock.json @@ -1,24 +1,48 @@ { - "name": "@codex-storage/sdk-js-download-example", + "name": "@codex-storage/sdk-js-basic-auth-example", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "@codex-storage/sdk-js-download-example", + "name": "@codex-storage/sdk-js-basic-auth-example", "version": "1.0.0", "license": "ISC", "dependencies": { - "@codex-storage/sdk-js": ".." + "@codex-storage/sdk-js": "../.." }, "devDependencies": { "esbuild": "^0.25.1", "prettier": "^3.5.3" } }, - "..": {}, + "..": { + "extraneous": true + }, + "../..": { + "name": "@codex-storage/sdk-js", + "version": "0.1.0", + "license": "MIT", + "dependencies": { + "undici": "^7.5.0", + "valibot": "^0.32.0" + }, + "devDependencies": { + "@tsconfig/strictest": "^2.0.5", + "@types/node": "^22.13.13", + "oas-normalize": "^13.1.2", + "openapi-typescript": "^7.6.1", + "prettier": "^3.5.3", + "tsup": "^8.3.6", + "typescript": "^5.8.2", + "vitest": "^3.0.9" + }, + "engines": { + "node": ">=20.18.1" + } + }, "node_modules/@codex-storage/sdk-js": { - "resolved": "..", + "resolved": "../..", "link": true }, "node_modules/@esbuild/aix-ppc64": { diff --git a/examples/basic-auth/package.json b/examples/basic-auth/package.json new file mode 100644 index 0000000..c5b2110 --- /dev/null +++ b/examples/basic-auth/package.json @@ -0,0 +1,18 @@ +{ + "name": "@codex-storage/sdk-js-basic-auth-example", + "version": "1.0.0", + "main": "index.js", + "scripts": { + "build": "node esbuild.js" + }, + "author": "", + "license": "ISC", + "description": "", + "dependencies": { + "@codex-storage/sdk-js": "../.." + }, + "devDependencies": { + "esbuild": "^0.25.1", + "prettier": "^3.5.3" + } +} diff --git a/examples/download/README.md b/examples/download/README.md index 1c13969..c999b21 100644 --- a/examples/download/README.md +++ b/examples/download/README.md @@ -11,7 +11,7 @@ npm install ## Build the javascript asset ```bash -CODEX_CID=REPLACE_BY_YOUR_CIDE npm run build +CODEX_CID=REPLACE_BY_YOUR_CID npm run build ``` The response will be displayed as text, so it is better to test with .txt files. diff --git a/examples/download/esbuild.js b/examples/download/esbuild.js index 93c9831..37b09c6 100644 --- a/examples/download/esbuild.js +++ b/examples/download/esbuild.js @@ -14,6 +14,9 @@ const options = { outfile: "./index.bundle.js", bundle: true, define, + logOverride: { + "ignored-bare-import": "silent", + }, }; build(options).catch(() => process.exit(1)); diff --git a/examples/download/package.json b/examples/download/package.json index 6dcbd6b..1d32f3b 100644 --- a/examples/download/package.json +++ b/examples/download/package.json @@ -9,7 +9,7 @@ "license": "ISC", "description": "", "dependencies": { - "@codex-storage/sdk-js": ".." + "@codex-storage/sdk-js": "../.." }, "devDependencies": { "esbuild": "^0.25.1", diff --git a/examples/upload-browser/README.md b/examples/upload-browser/README.md index 1c13969..c999b21 100644 --- a/examples/upload-browser/README.md +++ b/examples/upload-browser/README.md @@ -11,7 +11,7 @@ npm install ## Build the javascript asset ```bash -CODEX_CID=REPLACE_BY_YOUR_CIDE npm run build +CODEX_CID=REPLACE_BY_YOUR_CID npm run build ``` The response will be displayed as text, so it is better to test with .txt files. diff --git a/src/data/browser-upload.ts b/src/data/browser-upload.ts index 8ddf0c5..9470441 100644 --- a/src/data/browser-upload.ts +++ b/src/data/browser-upload.ts @@ -1,6 +1,6 @@ import { CodexError } from "../errors/errors"; import type { SafeValue } from "../values/values"; -import type { UploadStategy } from "./types"; +import type { UploadStategy, UploadStategyOptions } from "./types"; export class BrowserUploadStategy implements UploadStategy { private readonly file: Document | XMLHttpRequestBodyInit; @@ -22,7 +22,10 @@ export class BrowserUploadStategy implements UploadStategy { this.metadata = metadata; } - download(url: string): Promise> { + upload( + url: string, + { auth }: UploadStategyOptions + ): Promise> { const xhr = new XMLHttpRequest(); this.xhr = xhr; @@ -42,6 +45,10 @@ export class BrowserUploadStategy implements UploadStategy { ); } + if (auth?.basic) { + xhr.setRequestHeader("Authorization", "Basic " + auth.basic); + } + if (this.metadata?.mimetype) { xhr.setRequestHeader("Content-Type", this.metadata.mimetype); } diff --git a/src/data/data.ts b/src/data/data.ts index bc5688a..3aec5b8 100644 --- a/src/data/data.ts +++ b/src/data/data.ts @@ -1,5 +1,9 @@ import { Api } from "../api/config"; -import { Fetch } from "../fetch-safe/fetch-safe"; +import { + Fetch, + FetchAuthBuilder, + type FetchAuth, +} from "../fetch-safe/fetch-safe"; import type { SafeValue } from "../values/values"; import type { CodexDataResponse, @@ -10,11 +14,20 @@ import type { UploadResponse, } from "./types"; +type CodexDataOptions = { + auth?: FetchAuth; +}; + export class CodexData { readonly url: string; + readonly auth: FetchAuth = {}; - constructor(url: string) { + constructor(url: string, options?: CodexDataOptions) { this.url = url; + + if (options?.auth) { + this.auth = options.auth; + } } /** @@ -24,15 +37,16 @@ export class CodexData { cids(): Promise> { const url = this.url + Api.config.prefix + "/data"; - return Fetch.safeJson(url, { method: "GET" }).then( - (data) => { - if (data.error) { - return data; - } - - return { error: false, data: { content: data.data.content } }; + return Fetch.safeJson(url, { + method: "GET", + headers: FetchAuthBuilder.build(this.auth), + }).then((data) => { + if (data.error) { + return data; } - ); + + return { error: false, data: { content: data.data.content } }; + }); } /** @@ -41,7 +55,10 @@ export class CodexData { space() { const url = this.url + Api.config.prefix + "/space"; - return Fetch.safeJson(url, { method: "GET" }); + return Fetch.safeJson(url, { + method: "GET", + headers: FetchAuthBuilder.build(this.auth), + }); } /** @@ -54,7 +71,7 @@ export class CodexData { const url = this.url + Api.config.prefix + "/data"; return { - result: stategy.download(url), + result: stategy.upload(url, { auth: this.auth }), abort: () => { stategy.abort(); }, @@ -68,7 +85,10 @@ export class CodexData { async localDownload(cid: string): Promise> { const url = this.url + Api.config.prefix + "/data/" + cid; - return Fetch.safe(url, { method: "GET" }); + return Fetch.safe(url, { + method: "GET", + headers: FetchAuthBuilder.build(this.auth), + }); } /** @@ -80,7 +100,10 @@ export class CodexData { ): Promise> { const url = this.url + Api.config.prefix + `/data/${cid}/network`; - return Fetch.safeJson(url, { method: "POST" }); + return Fetch.safeJson(url, { + method: "POST", + headers: FetchAuthBuilder.build(this.auth), + }); } /** @@ -90,7 +113,10 @@ export class CodexData { async networkDownloadStream(cid: string): Promise> { const url = this.url + Api.config.prefix + `/data/${cid}/network/stream`; - return Fetch.safe(url, { method: "GET" }); + return Fetch.safe(url, { + method: "GET", + headers: FetchAuthBuilder.build(this.auth), + }); } /** @@ -100,6 +126,9 @@ export class CodexData { async fetchManifest(cid: string) { const url = this.url + Api.config.prefix + `/data/${cid}/network/manifest`; - return Fetch.safeJson(url, { method: "GET" }); + return Fetch.safeJson(url, { + method: "GET", + headers: FetchAuthBuilder.build(this.auth), + }); } } diff --git a/src/data/node-upload.ts b/src/data/node-upload.ts index 507b5e8..7c262e3 100644 --- a/src/data/node-upload.ts +++ b/src/data/node-upload.ts @@ -3,7 +3,8 @@ import { CodexError } from "../errors/errors"; import type { SafeValue } from "../values/values"; import Undici from "undici"; import { type FormData } from "undici"; -import type { UploadStategy } from "./types"; +import type { UploadStategy, UploadStategyOptions } from "./types"; +import { FetchAuthBuilder } from "../fetch-safe/fetch-safe"; export class NodeUploadStategy implements UploadStategy { private readonly body: @@ -26,8 +27,11 @@ export class NodeUploadStategy implements UploadStategy { this.metadata = metadata; } - async download(url: string): Promise> { - const headers: Record = {}; + async upload( + url: string, + { auth }: UploadStategyOptions + ): Promise> { + const headers: Record = FetchAuthBuilder.build(auth); if (this.metadata?.filename) { headers["Content-Disposition"] = diff --git a/src/data/types.ts b/src/data/types.ts index 25d4e67..0c57fa4 100644 --- a/src/data/types.ts +++ b/src/data/types.ts @@ -1,3 +1,4 @@ +import type { FetchAuth } from "../fetch-safe/fetch-safe"; import type { SafeValue } from "../values/values"; export type CodexManifest = { @@ -82,7 +83,14 @@ export type UploadResponse = { export type NetworkDownloadResponse = { cid: string; manifest: CodexManifest }; +export type UploadStategyOptions = { + auth?: FetchAuth; +}; + export interface UploadStategy { - download(url: string): Promise>; + upload( + url: string, + options?: UploadStategyOptions + ): Promise>; abort(): void; } diff --git a/src/debug/debug.ts b/src/debug/debug.ts index fa9cfa6..c51feb2 100644 --- a/src/debug/debug.ts +++ b/src/debug/debug.ts @@ -1,15 +1,28 @@ import { Api } from "../api/config"; import { CodexError, CodexValibotIssuesMap } from "../errors/errors"; -import { Fetch } from "../fetch-safe/fetch-safe"; +import { + Fetch, + FetchAuthBuilder, + type FetchAuth, +} from "../fetch-safe/fetch-safe"; import type { SafeValue } from "../values/values"; import { CodexLogLevel, type CodexDebugInfo } from "./types"; import * as v from "valibot"; +type CodexDebugOptions = { + auth?: FetchAuth; +}; + export class CodexDebug { readonly url: string; + readonly auth: FetchAuth = {}; - constructor(url: string) { + constructor(url: string, options?: CodexDebugOptions) { this.url = url; + + if (options?.auth) { + this.auth = options.auth; + } } /** @@ -35,6 +48,7 @@ export class CodexDebug { const res = await Fetch.safe(url, { method: "POST", + headers: FetchAuthBuilder.build(this.auth), body: "", }); @@ -53,6 +67,7 @@ export class CodexDebug { return Fetch.safeJson(url, { method: "GET", + headers: FetchAuthBuilder.build(this.auth), }); } } diff --git a/src/fetch-safe/fetch-safe.test.ts b/src/fetch-safe/fetch-safe.test.ts index 0464cba..5a6484a 100644 --- a/src/fetch-safe/fetch-safe.test.ts +++ b/src/fetch-safe/fetch-safe.test.ts @@ -1,6 +1,6 @@ import { afterEach, assert, describe, it, vi } from "vitest"; import { Fetch } from "../fetch-safe/fetch-safe"; -import { CodexError } from "../async"; +import { CodexError } from "../errors/errors"; describe.only("fetch", () => { afterEach(() => { diff --git a/src/fetch-safe/fetch-safe.ts b/src/fetch-safe/fetch-safe.ts index 1e2e4b7..3da25e9 100644 --- a/src/fetch-safe/fetch-safe.ts +++ b/src/fetch-safe/fetch-safe.ts @@ -2,6 +2,21 @@ import { CodexError } from "../errors/errors"; import { Promises } from "../promise-safe/promise-safe"; import { type SafeValue } from "../values/values"; +export type FetchAuth = { + basic?: string; +}; + +export const FetchAuthBuilder = { + build(auth: FetchAuth | undefined) { + if (auth?.basic) { + return { + Authorization: "Basic " + auth.basic, + }; + } + return {}; + }, +}; + export const Fetch = { async safe(url: string, init: RequestInit): Promise> { const res = await Promises.safe(() => fetch(url, init)); diff --git a/src/index.ts b/src/index.ts index 56cc17a..fc8d121 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,6 +2,7 @@ import { CodexData } from "./data/data"; import { CodexNode } from "./node/node"; import { CodexMarketplace } from "./marketplace/marketplace"; import { CodexDebug } from "./debug/debug"; +import type { FetchAuth } from "./fetch-safe/fetch-safe"; export * from "./fetch-safe/fetch-safe"; export * from "./marketplace/types"; @@ -15,19 +16,28 @@ export { CodexData } from "./data/data"; export { CodexNode } from "./node/node"; export { CodexMarketplace } from "./marketplace/marketplace"; +type CodexProps = { + auth?: FetchAuth; +}; + export class Codex { readonly url: string; private _marketplace: CodexMarketplace | null; private _data: CodexData | null; private _node: CodexNode | null; private _debug: CodexDebug | null; + private readonly auth: FetchAuth = {}; - constructor(url: string) { + constructor(url: string, { auth }: CodexProps) { this.url = url; this._marketplace = null; this._data = null; this._node = null; this._debug = null; + + if (auth) { + this.auth = auth; + } } get marketplace() { @@ -35,7 +45,7 @@ export class Codex { return this._marketplace; } - this._marketplace = new CodexMarketplace(this.url); + this._marketplace = new CodexMarketplace(this.url, { auth: this.auth }); return this._marketplace; } @@ -45,7 +55,7 @@ export class Codex { return this._data; } - this._data = new CodexData(this.url); + this._data = new CodexData(this.url, { auth: this.auth }); return this._data; } @@ -55,7 +65,7 @@ export class Codex { return this._node; } - this._node = new CodexNode(this.url); + this._node = new CodexNode(this.url, { auth: this.auth }); return this._node; } @@ -65,7 +75,7 @@ export class Codex { return this._debug; } - this._debug = new CodexDebug(this.url); + this._debug = new CodexDebug(this.url, { auth: this.auth }); return this._debug; } diff --git a/src/marketplace/marketplace.ts b/src/marketplace/marketplace.ts index 187a825..9dede63 100644 --- a/src/marketplace/marketplace.ts +++ b/src/marketplace/marketplace.ts @@ -1,7 +1,11 @@ import * as v from "valibot"; import { Api } from "../api/config"; import { CodexError, CodexValibotIssuesMap } from "../errors/errors"; -import { Fetch } from "../fetch-safe/fetch-safe"; +import { + Fetch, + FetchAuthBuilder, + type FetchAuth, +} from "../fetch-safe/fetch-safe"; import type { SafeValue } from "../values/values"; import { type CodexAvailability, @@ -16,11 +20,20 @@ import { CodexUpdateAvailabilityInput, } from "./types"; +type CodexMarketplaceOptions = { + auth?: FetchAuth; +}; + export class CodexMarketplace { readonly url: string; + readonly auth: FetchAuth = {}; - constructor(url: string) { + constructor(url: string, options?: CodexMarketplaceOptions) { this.url = url; + + if (options?.auth) { + this.auth = options.auth; + } } /** @@ -31,6 +44,7 @@ export class CodexMarketplace { return Fetch.safeJson(url, { method: "GET", + headers: FetchAuthBuilder.build(this.auth), }); } @@ -42,6 +56,7 @@ export class CodexMarketplace { return Fetch.safeJson(url, { method: "GET", + headers: FetchAuthBuilder.build(this.auth), }); } @@ -53,6 +68,7 @@ export class CodexMarketplace { const res = await Fetch.safeJson(url, { method: "GET", + headers: FetchAuthBuilder.build(this.auth), }); if (res.error) { @@ -96,6 +112,7 @@ export class CodexMarketplace { return Fetch.safeJson(url, { method: "POST", + headers: FetchAuthBuilder.build(this.auth), body: JSON.stringify({ totalSize: body.totalSize.toString(), duration: body.duration.toString(), @@ -130,6 +147,7 @@ export class CodexMarketplace { const res = await Fetch.safe(url, { method: "PATCH", + headers: FetchAuthBuilder.build(this.auth), body: JSON.stringify({ totalSize: body.totalSize.toString(), duration: body.duration.toString(), @@ -158,6 +176,7 @@ export class CodexMarketplace { return Fetch.safeJson(url, { method: "GET", + headers: FetchAuthBuilder.build(this.auth), }); } @@ -169,6 +188,7 @@ export class CodexMarketplace { return Fetch.safeJson(url, { method: "GET", + headers: FetchAuthBuilder.build(this.auth), }); } @@ -177,6 +197,7 @@ export class CodexMarketplace { const res = await Fetch.safeJson(url, { method: "GET", + headers: FetchAuthBuilder.build(this.auth), }); if (res.error) { @@ -215,6 +236,7 @@ export class CodexMarketplace { return Fetch.safeJson(url, { method: "GET", + headers: FetchAuthBuilder.build(this.auth), }); } @@ -249,6 +271,7 @@ export class CodexMarketplace { const res = await Fetch.safe(url, { method: "POST", + headers: FetchAuthBuilder.build(this.auth), body: JSON.stringify({ duration: duration.toString(), pricePerBytePerSecond: pricePerBytePerSecond.toString(), diff --git a/src/node/node.ts b/src/node/node.ts index c8fab9f..b2ef8a2 100644 --- a/src/node/node.ts +++ b/src/node/node.ts @@ -1,13 +1,26 @@ import { Api } from "../api/config"; -import { Fetch } from "../fetch-safe/fetch-safe"; +import { + Fetch, + FetchAuthBuilder, + type FetchAuth, +} from "../fetch-safe/fetch-safe"; import type { SafeValue } from "../values/values"; import type { CodexSpr } from "./types"; +type CodexNodeOptions = { + auth?: FetchAuth; +}; + export class CodexNode { readonly url: string; + readonly auth: FetchAuth = {}; - constructor(url: string) { + constructor(url: string, options?: CodexNodeOptions) { this.url = url; + + if (options?.auth) { + this.auth = options.auth; + } } /** @@ -26,6 +39,7 @@ export class CodexNode { return Fetch.safe(url, { method: "GET", + headers: FetchAuthBuilder.build(this.auth), }); } @@ -37,6 +51,7 @@ export class CodexNode { return Fetch.safeJson(url, { method: "GET", + headers: FetchAuthBuilder.build(this.auth), }); } @@ -49,6 +64,7 @@ export class CodexNode { return Fetch.safe(url, { method: "GET", + headers: FetchAuthBuilder.build(this.auth), }); } } diff --git a/src/promise-safe/promise-safe.test.ts b/src/promise-safe/promise-safe.test.ts index bccbdc5..4ce2f14 100644 --- a/src/promise-safe/promise-safe.test.ts +++ b/src/promise-safe/promise-safe.test.ts @@ -1,6 +1,6 @@ import { assert, describe, it } from "vitest"; import { Promises } from "./promise-safe"; -import { CodexError } from "../async"; +import { CodexError } from "../errors/errors"; describe("promise safe", () => { it("returns an error when the promise failed", async () => { diff --git a/src/promise-safe/promise-safe.ts b/src/promise-safe/promise-safe.ts index 0a9cb91..4944f18 100644 --- a/src/promise-safe/promise-safe.ts +++ b/src/promise-safe/promise-safe.ts @@ -1,4 +1,4 @@ -import { CodexError } from "../async"; +import { CodexError } from "../errors/errors"; import type { SafeValue } from "../values/values"; export const Promises = {