From 9e89c30562b4dba164a75410b8b458e75fe716b9 Mon Sep 17 00:00:00 2001 From: Arnaud Date: Fri, 28 Mar 2025 09:13:01 +0100 Subject: [PATCH 1/4] 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 = { From 54dca841f10cd9629c85e9fdeecccfbf8c239112 Mon Sep 17 00:00:00 2001 From: Arnaud Date: Fri, 28 Mar 2025 11:30:51 +0100 Subject: [PATCH 2/4] Set props as optional --- src/index.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/index.ts b/src/index.ts index fc8d121..79b3a8f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -28,15 +28,15 @@ export class Codex { private _debug: CodexDebug | null; private readonly auth: FetchAuth = {}; - constructor(url: string, { auth }: CodexProps) { + constructor(url: string, options?: CodexProps) { this.url = url; this._marketplace = null; this._data = null; this._node = null; this._debug = null; - if (auth) { - this.auth = auth; + if (options?.auth) { + this.auth = options?.auth; } } From f6d0852e86937c89d391c9d2f0641b92937f01b5 Mon Sep 17 00:00:00 2001 From: Arnaud Date: Mon, 31 Mar 2025 20:51:54 +0200 Subject: [PATCH 3/4] Update version --- package-lock.json | 4 ++-- package.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1d64653..be1c185 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@codex-storage/sdk-js", - "version": "0.1.0", + "version": "0.1.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@codex-storage/sdk-js", - "version": "0.1.0", + "version": "0.1.1", "license": "MIT", "dependencies": { "undici": "^7.5.0", diff --git a/package.json b/package.json index 72957b2..4082932 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@codex-storage/sdk-js", - "version": "0.1.0", + "version": "0.1.1", "description": "Codex SDK to interact with the Codex decentralized storage network.", "repository": { "type": "git", @@ -87,4 +87,4 @@ "undici": "^7.5.0", "valibot": "^0.32.0" } -} +} \ No newline at end of file From 921bb617ef636789e7c798e23f06676dba53ab49 Mon Sep 17 00:00:00 2001 From: Arnaud Date: Mon, 31 Mar 2025 20:56:13 +0200 Subject: [PATCH 4/4] Update dependencies --- examples/upload-node/package-lock.json | 21 +++- examples/upload-node/package.json | 3 +- package-lock.json | 127 +++++++++++++------------ package.json | 8 +- 4 files changed, 90 insertions(+), 69 deletions(-) diff --git a/examples/upload-node/package-lock.json b/examples/upload-node/package-lock.json index 65237cc..8e31d13 100644 --- a/examples/upload-node/package-lock.json +++ b/examples/upload-node/package-lock.json @@ -9,7 +9,8 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "@codex-storage/sdk-js": "../.." + "@codex-storage/sdk-js": "../..", + "undici": "^7.6.0" }, "devDependencies": { "prettier": "^3.5.3" @@ -20,21 +21,24 @@ }, "../..": { "name": "@codex-storage/sdk-js", - "version": "0.0.23", + "version": "0.1.1", "license": "MIT", "dependencies": { - "undici": "^7.5.0", "valibot": "^0.32.0" }, "devDependencies": { "@tsconfig/strictest": "^2.0.5", + "@types/node": "^22.13.13", "prettier": "^3.5.3", "tsup": "^8.3.6", "typescript": "^5.8.2", - "vitest": "^3.0.9" + "vitest": "^3.1.1" }, "engines": { "node": ">=20.18.1" + }, + "peerDependencies": { + "undici": "^7.6.0" } }, "../dist": { @@ -59,6 +63,15 @@ "funding": { "url": "https://github.com/prettier/prettier?sponsor=1" } + }, + "node_modules/undici": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.6.0.tgz", + "integrity": "sha512-gaFsbThjrDGvAaD670r81RZro/s6H2PVZF640Qn0p5kZK+/rim7/mmyfp2W7VB5vOMaFM8vuFBJUaMlaZTYHlA==", + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } } } } diff --git a/examples/upload-node/package.json b/examples/upload-node/package.json index 0629a13..706cc6c 100644 --- a/examples/upload-node/package.json +++ b/examples/upload-node/package.json @@ -9,7 +9,8 @@ "license": "ISC", "description": "", "dependencies": { - "@codex-storage/sdk-js": "../.." + "@codex-storage/sdk-js": "../..", + "undici": "^7.6.0" }, "devDependencies": { "prettier": "^3.5.3" diff --git a/package-lock.json b/package-lock.json index be1c185..ef3ed35 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,19 +9,21 @@ "version": "0.1.1", "license": "MIT", "dependencies": { - "undici": "^7.5.0", "valibot": "^0.32.0" }, "devDependencies": { "@tsconfig/strictest": "^2.0.5", - "@types/node": "^22.13.13", + "@types/node": "^22.13.14", "prettier": "^3.5.3", "tsup": "^8.3.6", "typescript": "^5.8.2", - "vitest": "^3.0.9" + "vitest": "^3.1.1" }, "engines": { "node": ">=20.18.1" + }, + "peerDependencies": { + "undici": "^7.0.0" } }, "node_modules/@esbuild/aix-ppc64": { @@ -803,9 +805,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "22.13.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.13.tgz", - "integrity": "sha512-ClsL5nMwKaBRwPcCvH8E7+nU4GxHVx1axNvMZTFHMEfNI7oahimt26P5zjVCRrjiIWj6YFXfE1v3dEp94wLcGQ==", + "version": "22.13.14", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.14.tgz", + "integrity": "sha512-Zs/Ollc1SJ8nKUAgc7ivOEdIBM8JAKgrqqUYi2J997JuKO7/tpQC+WCetQ1sypiKCQWHdvdg9wBNpUPEWZae7w==", "dev": true, "license": "MIT", "dependencies": { @@ -813,14 +815,14 @@ } }, "node_modules/@vitest/expect": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.9.tgz", - "integrity": "sha512-5eCqRItYgIML7NNVgJj6TVCmdzE7ZVgJhruW0ziSQV4V7PvLkDL1bBkBdcTs/VuIz0IxPb5da1IDSqc1TR9eig==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.1.1.tgz", + "integrity": "sha512-q/zjrW9lgynctNbwvFtQkGK9+vvHA5UzVi2V8APrp1C6fG6/MuYYkmlx4FubuqLycCeSdHD5aadWfua/Vr0EUA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.0.9", - "@vitest/utils": "3.0.9", + "@vitest/spy": "3.1.1", + "@vitest/utils": "3.1.1", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" }, @@ -829,13 +831,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.9.tgz", - "integrity": "sha512-ryERPIBOnvevAkTq+L1lD+DTFBRcjueL9lOUfXsLfwP92h4e+Heb+PjiqS3/OURWPtywfafK0kj++yDFjWUmrA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.1.1.tgz", + "integrity": "sha512-bmpJJm7Y7i9BBELlLuuM1J1Q6EQ6K5Ye4wcyOpOMXMcePYKSIYlpcrCm4l/O6ja4VJA5G2aMJiuZkZdnxlC3SA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.0.9", + "@vitest/spy": "3.1.1", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, @@ -856,9 +858,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.9.tgz", - "integrity": "sha512-OW9F8t2J3AwFEwENg3yMyKWweF7oRJlMyHOMIhO5F3n0+cgQAJZBjNgrF8dLwFTEXl5jUqBLXd9QyyKv8zEcmA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.1.1.tgz", + "integrity": "sha512-dg0CIzNx+hMMYfNmSqJlLSXEmnNhMswcn3sXO7Tpldr0LiGmg3eXdLLhwkv2ZqgHb/d5xg5F7ezNFRA1fA13yA==", "dev": true, "license": "MIT", "dependencies": { @@ -869,13 +871,13 @@ } }, "node_modules/@vitest/runner": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.9.tgz", - "integrity": "sha512-NX9oUXgF9HPfJSwl8tUZCMP1oGx2+Sf+ru6d05QjzQz4OwWg0psEzwY6VexP2tTHWdOkhKHUIZH+fS6nA7jfOw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.1.1.tgz", + "integrity": "sha512-X/d46qzJuEDO8ueyjtKfxffiXraPRfmYasoC4i5+mlLEJ10UvPb0XH5M9C3gWuxd7BAQhpK42cJgJtq53YnWVA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.0.9", + "@vitest/utils": "3.1.1", "pathe": "^2.0.3" }, "funding": { @@ -883,13 +885,13 @@ } }, "node_modules/@vitest/snapshot": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.9.tgz", - "integrity": "sha512-AiLUiuZ0FuA+/8i19mTYd+re5jqjEc2jZbgJ2up0VY0Ddyyxg/uUtBDpIFAy4uzKaQxOW8gMgBdAJJ2ydhu39A==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.1.1.tgz", + "integrity": "sha512-bByMwaVWe/+1WDf9exFxWWgAixelSdiwo2p33tpqIlM14vW7PRV5ppayVXtfycqze4Qhtwag5sVhX400MLBOOw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.0.9", + "@vitest/pretty-format": "3.1.1", "magic-string": "^0.30.17", "pathe": "^2.0.3" }, @@ -898,9 +900,9 @@ } }, "node_modules/@vitest/spy": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.9.tgz", - "integrity": "sha512-/CcK2UDl0aQ2wtkp3YVWldrpLRNCfVcIOFGlVGKO4R5eajsH393Z1yiXLVQ7vWsj26JOEjeZI0x5sm5P4OGUNQ==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.1.1.tgz", + "integrity": "sha512-+EmrUOOXbKzLkTDwlsc/xrwOlPDXyVk3Z6P6K4oiCndxz7YLpp/0R0UsWVOKT0IXWjjBJuSMk6D27qipaupcvQ==", "dev": true, "license": "MIT", "dependencies": { @@ -911,13 +913,13 @@ } }, "node_modules/@vitest/utils": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.9.tgz", - "integrity": "sha512-ilHM5fHhZ89MCp5aAaM9uhfl1c2JdxVxl3McqsdVyVNN6JffnEen8UMCdRTzOhGXNQGo5GNL9QugHrz727Wnng==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.1.1.tgz", + "integrity": "sha512-1XIjflyaU2k3HMArJ50bwSh3wKWPD6Q47wz/NUSmRV0zNywPc4w79ARjg/i/aNINHwA+mIALhUVqD9/aUvZNgg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.0.9", + "@vitest/pretty-format": "3.1.1", "loupe": "^3.1.3", "tinyrainbow": "^2.0.0" }, @@ -1198,10 +1200,11 @@ } }, "node_modules/expect-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.1.0.tgz", - "integrity": "sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.1.tgz", + "integrity": "sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=12.0.0" } @@ -1737,10 +1740,11 @@ "dev": true }, "node_modules/std-env": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.0.tgz", - "integrity": "sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==", - "dev": true + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.1.tgz", + "integrity": "sha512-vj5lIj3Mwf9D79hBkltk5qmkFI+biIKWS2IBxEyEU3AX1tUf7AoL8nSazCOiiqQsGKIq01SClsKEzweu34uwvA==", + "dev": true, + "license": "MIT" }, "node_modules/string-width": { "version": "5.1.2", @@ -2035,6 +2039,7 @@ "resolved": "https://registry.npmjs.org/undici/-/undici-7.5.0.tgz", "integrity": "sha512-NFQG741e8mJ0fLQk90xKxFdaSM7z4+IQpAgsFI36bCDY9Z2+aXXZjVy2uUksMouWfMI9+w5ejOq5zYYTBCQJDQ==", "license": "MIT", + "peer": true, "engines": { "node": ">=20.18.1" } @@ -2053,9 +2058,9 @@ "license": "MIT" }, "node_modules/vite": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.3.tgz", - "integrity": "sha512-IzwM54g4y9JA/xAeBPNaDXiBF8Jsgl3VBQ2YQ/wOY6fyW3xMdSoltIV3Bo59DErdqdE6RxUfv8W69DvUorE4Eg==", + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.4.tgz", + "integrity": "sha512-veHMSew8CcRzhL5o8ONjy8gkfmFJAd5Ac16oxBUjlwgX3Gq2Wqr+qNC3TjPIpy7TPV/KporLga5GT9HqdrCizw==", "dev": true, "license": "MIT", "dependencies": { @@ -2125,9 +2130,9 @@ } }, "node_modules/vite-node": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.9.tgz", - "integrity": "sha512-w3Gdx7jDcuT9cNn9jExXgOyKmf5UOTb6WMHz8LGAm54eS1Elf5OuBhCxl6zJxGhEeIkgsE1WbHuoL0mj/UXqXg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.1.1.tgz", + "integrity": "sha512-V+IxPAE2FvXpTCHXyNem0M+gWm6J7eRyWPR6vYoG/Gl+IscNOjXzztUhimQgTxaAoUoj40Qqimaa0NLIOOAH4w==", "dev": true, "license": "MIT", "dependencies": { @@ -2148,31 +2153,31 @@ } }, "node_modules/vitest": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.9.tgz", - "integrity": "sha512-BbcFDqNyBlfSpATmTtXOAOj71RNKDDvjBM/uPfnxxVGrG+FSH2RQIwgeEngTaTkuU/h0ScFvf+tRcKfYXzBybQ==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.1.1.tgz", + "integrity": "sha512-kiZc/IYmKICeBAZr9DQ5rT7/6bD9G7uqQEki4fxazi1jdVl2mWGzedtBs5s6llz59yQhVb7FFY2MbHzHCnT79Q==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "3.0.9", - "@vitest/mocker": "3.0.9", - "@vitest/pretty-format": "^3.0.9", - "@vitest/runner": "3.0.9", - "@vitest/snapshot": "3.0.9", - "@vitest/spy": "3.0.9", - "@vitest/utils": "3.0.9", + "@vitest/expect": "3.1.1", + "@vitest/mocker": "3.1.1", + "@vitest/pretty-format": "^3.1.1", + "@vitest/runner": "3.1.1", + "@vitest/snapshot": "3.1.1", + "@vitest/spy": "3.1.1", + "@vitest/utils": "3.1.1", "chai": "^5.2.0", "debug": "^4.4.0", - "expect-type": "^1.1.0", + "expect-type": "^1.2.0", "magic-string": "^0.30.17", "pathe": "^2.0.3", - "std-env": "^3.8.0", + "std-env": "^3.8.1", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinypool": "^1.0.2", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0", - "vite-node": "3.0.9", + "vite-node": "3.1.1", "why-is-node-running": "^2.3.0" }, "bin": { @@ -2188,8 +2193,8 @@ "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.0.9", - "@vitest/ui": "3.0.9", + "@vitest/browser": "3.1.1", + "@vitest/ui": "3.1.1", "happy-dom": "*", "jsdom": "*" }, diff --git a/package.json b/package.json index 4082932..6622f4d 100644 --- a/package.json +++ b/package.json @@ -77,14 +77,16 @@ }, "devDependencies": { "@tsconfig/strictest": "^2.0.5", - "@types/node": "^22.13.13", + "@types/node": "^22.13.14", "prettier": "^3.5.3", "tsup": "^8.3.6", "typescript": "^5.8.2", - "vitest": "^3.0.9" + "vitest": "^3.1.1" }, "dependencies": { - "undici": "^7.5.0", "valibot": "^0.32.0" + }, + "peerDependencies": { + "undici": "^7.0.0" } } \ No newline at end of file