mirror of
https://github.com/logos-storage/logos-storage-js.git
synced 2026-01-02 13:33:07 +00:00
Support basic authentication
This commit is contained in:
parent
746f96279b
commit
9e89c30562
22
README.md
22
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
|
||||
|
||||
1
examples/basic-auth/.gitignore
vendored
Normal file
1
examples/basic-auth/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
index.bundle.js
|
||||
23
examples/basic-auth/README.md
Normal file
23
examples/basic-auth/README.md
Normal file
@ -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.
|
||||
22
examples/basic-auth/esbuild.js
Normal file
22
examples/basic-auth/esbuild.js
Normal file
@ -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));
|
||||
4
examples/basic-auth/index.html
Normal file
4
examples/basic-auth/index.html
Normal file
@ -0,0 +1,4 @@
|
||||
<html>
|
||||
<script src="./index.bundle.js">
|
||||
</script>
|
||||
</html>
|
||||
19
examples/basic-auth/index.js
Normal file
19
examples/basic-auth/index.js
Normal file
@ -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();
|
||||
@ -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": {
|
||||
18
examples/basic-auth/package.json
Normal file
18
examples/basic-auth/package.json
Normal file
@ -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"
|
||||
}
|
||||
}
|
||||
@ -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.
|
||||
|
||||
@ -14,6 +14,9 @@ const options = {
|
||||
outfile: "./index.bundle.js",
|
||||
bundle: true,
|
||||
define,
|
||||
logOverride: {
|
||||
"ignored-bare-import": "silent",
|
||||
},
|
||||
};
|
||||
|
||||
build(options).catch(() => process.exit(1));
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
"license": "ISC",
|
||||
"description": "",
|
||||
"dependencies": {
|
||||
"@codex-storage/sdk-js": ".."
|
||||
"@codex-storage/sdk-js": "../.."
|
||||
},
|
||||
"devDependencies": {
|
||||
"esbuild": "^0.25.1",
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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<SafeValue<string>> {
|
||||
upload(
|
||||
url: string,
|
||||
{ auth }: UploadStategyOptions
|
||||
): Promise<SafeValue<string>> {
|
||||
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);
|
||||
}
|
||||
|
||||
@ -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<SafeValue<CodexDataResponse>> {
|
||||
const url = this.url + Api.config.prefix + "/data";
|
||||
|
||||
return Fetch.safeJson<CodexDataResponse>(url, { method: "GET" }).then(
|
||||
(data) => {
|
||||
if (data.error) {
|
||||
return data;
|
||||
}
|
||||
|
||||
return { error: false, data: { content: data.data.content } };
|
||||
return Fetch.safeJson<CodexDataResponse>(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<CodexNodeSpace>(url, { method: "GET" });
|
||||
return Fetch.safeJson<CodexNodeSpace>(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<SafeValue<Response>> {
|
||||
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<SafeValue<NetworkDownloadResponse>> {
|
||||
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<SafeValue<Response>> {
|
||||
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<CodexManifest>(url, { method: "GET" });
|
||||
return Fetch.safeJson<CodexManifest>(url, {
|
||||
method: "GET",
|
||||
headers: FetchAuthBuilder.build(this.auth),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<SafeValue<string>> {
|
||||
const headers: Record<string, string> = {};
|
||||
async upload(
|
||||
url: string,
|
||||
{ auth }: UploadStategyOptions
|
||||
): Promise<SafeValue<string>> {
|
||||
const headers: Record<string, string> = FetchAuthBuilder.build(auth);
|
||||
|
||||
if (this.metadata?.filename) {
|
||||
headers["Content-Disposition"] =
|
||||
|
||||
@ -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<SafeValue<string>>;
|
||||
upload(
|
||||
url: string,
|
||||
options?: UploadStategyOptions
|
||||
): Promise<SafeValue<string>>;
|
||||
abort(): void;
|
||||
}
|
||||
|
||||
@ -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<CodexDebugInfo>(url, {
|
||||
method: "GET",
|
||||
headers: FetchAuthBuilder.build(this.auth),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -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(() => {
|
||||
|
||||
@ -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<SafeValue<Response>> {
|
||||
const res = await Promises.safe(() => fetch(url, init));
|
||||
|
||||
20
src/index.ts
20
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;
|
||||
}
|
||||
|
||||
@ -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<CodexSlot[]>(url, {
|
||||
method: "GET",
|
||||
headers: FetchAuthBuilder.build(this.auth),
|
||||
});
|
||||
}
|
||||
|
||||
@ -42,6 +56,7 @@ export class CodexMarketplace {
|
||||
|
||||
return Fetch.safeJson<CodexSlot>(url, {
|
||||
method: "GET",
|
||||
headers: FetchAuthBuilder.build(this.auth),
|
||||
});
|
||||
}
|
||||
|
||||
@ -53,6 +68,7 @@ export class CodexMarketplace {
|
||||
|
||||
const res = await Fetch.safeJson<CodexAvailabilityDto[]>(url, {
|
||||
method: "GET",
|
||||
headers: FetchAuthBuilder.build(this.auth),
|
||||
});
|
||||
|
||||
if (res.error) {
|
||||
@ -96,6 +112,7 @@ export class CodexMarketplace {
|
||||
|
||||
return Fetch.safeJson<CodexAvailabilityCreateResponse>(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<CodexReservation[]>(url, {
|
||||
method: "GET",
|
||||
headers: FetchAuthBuilder.build(this.auth),
|
||||
});
|
||||
}
|
||||
|
||||
@ -169,6 +188,7 @@ export class CodexMarketplace {
|
||||
|
||||
return Fetch.safeJson<string[]>(url, {
|
||||
method: "GET",
|
||||
headers: FetchAuthBuilder.build(this.auth),
|
||||
});
|
||||
}
|
||||
|
||||
@ -177,6 +197,7 @@ export class CodexMarketplace {
|
||||
|
||||
const res = await Fetch.safeJson<string[]>(url, {
|
||||
method: "GET",
|
||||
headers: FetchAuthBuilder.build(this.auth),
|
||||
});
|
||||
|
||||
if (res.error) {
|
||||
@ -215,6 +236,7 @@ export class CodexMarketplace {
|
||||
|
||||
return Fetch.safeJson<CodexPurchase>(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(),
|
||||
|
||||
@ -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),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 () => {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { CodexError } from "../async";
|
||||
import { CodexError } from "../errors/errors";
|
||||
import type { SafeValue } from "../values/values";
|
||||
|
||||
export const Promises = {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user