diff --git a/.gitignore b/.gitignore index c58c7db..6f64587 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules dist -*.tgz \ No newline at end of file +*.tgz +index.bundle.js \ No newline at end of file diff --git a/README.md b/README.md index 6e60f65..7f17ae5 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,14 @@ The SDK is currently under early development and the API can change at any time. - Version 0.1.0 introduces [upload strategy](#upload) to support browser and Node JS. +## Types generation + +The types are generated from the openapi.yaml using the commande: + +```bash +npx openapi-typescript ./openapi.yaml -o src/openapi.ts --default-non-nullable false +``` + ## How to use ### Sync api @@ -126,7 +134,7 @@ const marketplace = codex.marketplace; Returns active slots. -- returns Promise<[CodexSlot](./src/marketplace/types.ts#L85)[]> +- returns Promise<[CodexSlot](./src/marketplace/types.ts#L7)[]> Example: @@ -139,7 +147,7 @@ const slots = await marketplace.activeSlots(); Returns active slot with id {slotId} for the host. - slotId (string, required) -- returns Promise<[CodexSlot](./src/marketplace/types.ts#L85)[]> +- returns Promise<[CodexSlotAgent](./src/marketplace/types.ts#L12)[]> Example: @@ -152,7 +160,7 @@ const slot = await marketplace.activeSlot(slotId); Returns storage that is for sale. -- returns Promise<[CodexAvailability](./src/marketplace/types.ts#L99)> +- returns Promise<[CodexAvailability](./src/marketplace/types.ts#L20)> Example: @@ -164,8 +172,8 @@ const availabilities = await marketplace.availabilities(); Offers storage for sale. -- input ([CodexCreateAvailabilityInput](./src/marketplace/types.ts#L175), required) -- returns Promise<[CodexAvailabilityCreateResponse](./src/marketplace/types.ts#L186)[]> +- input ([CodexCreateAvailabilityInput](./src/marketplace/types.ts#L45), required) +- returns Promise<[CodexAvailability](./src/marketplace/types.ts#L20)[]> Example: @@ -182,7 +190,7 @@ const response = await marketplace.createAvailability({ Updates availability. -- input ([CodexUpdateAvailabilityInput](./src/marketplace/types.ts#L186), required) +- input ([CodexAvailabilityPatchInput](./src/marketplace/types.ts#L66), required) - returns Promise<""> Example: @@ -202,7 +210,7 @@ const response = await marketplace.updateAvailability({ Return list of reservations for ongoing Storage Requests that the node hosts. - availabilityId (string, required) -- returns Promise<[CodexReservation](./src/marketplace/types.ts#L198)[]> +- returns Promise<[CodexReservation](./src/marketplace/types.ts#L83)[]> Example: @@ -214,7 +222,7 @@ const reservations = await marketplace.reservations("Ox..."); Creates a new Request for storage -- input ([CodexCreateStorageRequestInput](./src/marketplace/types.ts#L230), required) +- input ([CodexCreateStorageRequestInput](./src/marketplace/types.ts#L120), required) - returns Promise Example: @@ -248,7 +256,7 @@ const ids = await marketplace.purchaseIds(); Returns purchase details - purchaseId (string, required) -- returns Promise<[CodexPurchase](./src/marketplace/types.ts#L214)[]> +- returns Promise<[CodexPurchase](./src/marketplace/types.ts#L103)[]> Example: @@ -274,7 +282,7 @@ const data = codex.data; Returns the manifest stored locally in node. -- returns Promise<[CodexDataResponse](./src/data/types.ts#L54)[]> +- returns Promise<[CodexDataItem](./src/data/types.ts#L8)[]> Example: @@ -286,7 +294,7 @@ const cids = await data.cids(); Returns a summary of the storage space allocation of the node -- returns Promise<[CodexNodeSpace](./src/data/types.ts#L56)[]> +- returns Promise<[CodexNodeSpace](./src/data/types.ts#L15)[]> Example: @@ -301,7 +309,7 @@ Upload a file in a streaming manner #### Browser - stategy [BrowserUploadStategy](./src/data/browser-upload.ts#L5) -- returns [UploadResponse](./src/data/types.ts#L80) +- returns [UploadResponse](./src/data/types.ts#L17) Example: @@ -330,8 +338,8 @@ console.info("CID is", res.data); #### Node -- stategy [NodeUploadStategy](./src/data/node-download.ts#L8) -- returns [UploadResponse](./src/data/types.ts#L80) +- stategy [NodeUploadStategy](./src/data/node-upload.ts#L9) +- returns [UploadResponse](./src/data/types.ts#L17) Example: @@ -354,7 +362,7 @@ console.info("CID is", res.data); Download only the dataset manifest from the network to the local node if it's not available locally. - cid (string, required) -- returns [CodexManifest](./src/data/types.ts#L3) +- returns [CodexManifest](./src/data/types.ts#L30) Example: @@ -410,7 +418,7 @@ const data = codex.debug; Set log level at run time. -- level ([CodexLogLevel](./src/debug/types.ts#L3), required) +- level ([CodexLogLevel](./src/debug/types.ts#L7), required) - returns Promise<""> Example: @@ -423,7 +431,7 @@ await debug.setLogLevel("DEBUG"); Gets node information -- returns Promise<[CodexDebugInfo](./src/debug/types.ts#L15)> +- returns Promise<[CodexDebugInfo](./src/debug/types.ts#L23)> Example: @@ -448,10 +456,44 @@ const node = codex.node; Get Node's SPR -- returns Promise<[CodexSpr](./src/node/types.ts#L1)> +- returns Promise<[CodexSpr](./src/node/types.ts#L11)> Example: ```js const spr = await node.spr(); ``` + +By default, the response will be a json. You can use `text` option to get the string: + +#### peeriD + +Get Node's peer id + +- returns Promise<[CodexPeerId](./src/node/types.ts#L25)> + +Example: + +```js +const peerId = await node.peerId(); +``` + +By default, the response will be a json. You can use `text` option to get the string: + +```js +const peerId = await node.peerId("text"); +``` + +#### connect + +Connect to a peer + +- returns Promise + +Example: + +```js +const peerId = "..." +const addrs = [...] +const spr = await node.connect(peerId, addrs); +``` diff --git a/examples/upload-node/package-lock.json b/examples/upload-node/package-lock.json index 8e31d13..e3433cb 100644 --- a/examples/upload-node/package-lock.json +++ b/examples/upload-node/package-lock.json @@ -10,7 +10,7 @@ "license": "ISC", "dependencies": { "@codex-storage/sdk-js": "../..", - "undici": "^7.6.0" + "undici": "^7.7.0" }, "devDependencies": { "prettier": "^3.5.3" @@ -24,11 +24,14 @@ "version": "0.1.1", "license": "MIT", "dependencies": { - "valibot": "^0.32.0" + "undici": "^7.7.0", + "valibot": "^1.0.0" }, "devDependencies": { "@tsconfig/strictest": "^2.0.5", - "@types/node": "^22.13.13", + "@types/node": "^22.13.17", + "oas-normalize": "^13.1.2", + "openapi-typescript": "^7.6.1", "prettier": "^3.5.3", "tsup": "^8.3.6", "typescript": "^5.8.2", @@ -65,13 +68,13 @@ } }, "node_modules/undici": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.6.0.tgz", - "integrity": "sha512-gaFsbThjrDGvAaD670r81RZro/s6H2PVZF640Qn0p5kZK+/rim7/mmyfp2W7VB5vOMaFM8vuFBJUaMlaZTYHlA==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.7.0.tgz", + "integrity": "sha512-tZ6+5NBq4KH35rr46XJ2JPFKxfcBlYNaqLF/wyWIO9RMHqqU/gx/CLB1Y2qMcgB8lWw/bKHa7qzspqCN7mUHvA==", "license": "MIT", "engines": { "node": ">=20.18.1" } } } -} +} \ No newline at end of file diff --git a/examples/upload-node/package.json b/examples/upload-node/package.json index 706cc6c..2741a4d 100644 --- a/examples/upload-node/package.json +++ b/examples/upload-node/package.json @@ -2,17 +2,15 @@ "name": "@codex-storage/sdk-js-update-node-example", "version": "1.0.0", "main": "index.js", - "scripts": { - "build": "node esbuild.js" - }, + "scripts": {}, "author": "", "license": "ISC", "description": "", "dependencies": { "@codex-storage/sdk-js": "../..", - "undici": "^7.6.0" + "undici": "^7.7.0" }, "devDependencies": { "prettier": "^3.5.3" } -} +} \ No newline at end of file diff --git a/openapi.yaml b/openapi.yaml new file mode 100644 index 0000000..148601c --- /dev/null +++ b/openapi.yaml @@ -0,0 +1,1012 @@ +openapi: 3.0.3 + +info: + version: 0.0.1 + title: Codex API + description: "List of endpoints and interfaces available to Codex API users" + +security: + - {} + +components: + schemas: + MultiAddress: + type: string + description: Address of node as specified by the multi-address specification https://multiformats.io/multiaddr/ + example: /ip4/127.0.0.1/tcp/8080 + + PeerId: + type: string + description: Peer Identity reference as specified at https://docs.libp2p.io/concepts/fundamentals/peers/ + example: QmYyQSo1c1Ym7orWxLYvCrM2EmxFTANf8wXmmE7DWjhx5N + + Id: + type: string + description: 32bits identifier encoded in hex-decimal string. + minLength: 66 + maxLength: 66 + example: 0x... + + Cid: + type: string + description: Content Identifier as specified at https://github.com/multiformats/cid + example: QmYyQSo1c1Ym7orWxLYvCrM2EmxFTANf8wXmmE7DWjhx5N + + SlotId: + type: string + description: Keccak hash of the abi encoded tuple (RequestId, slot index) + example: 268a781e0db3f7cf36b18e5f4fdb7f586ec9edd08e5500b17c0e518a769f114a + + LogLevel: + type: string + description: "One of the log levels: TRACE, DEBUG, INFO, NOTICE, WARN, ERROR or FATAL" + example: DEBUG + + EthereumAddress: + type: string + description: Address of Ethereum address + + PricePerBytePerSecond: + type: string + description: The amount of tokens paid per byte per second per slot to hosts the client is willing to pay + + Duration: + type: integer + format: int64 + description: The duration of the request in seconds + + ProofProbability: + type: string + description: How often storage proofs are required as decimal string + + Expiry: + type: integer + format: int64 + description: A timestamp as seconds since unix epoch at which this request expires if the Request does not find requested amount of nodes to host the data. + + SPR: + type: string + description: Signed Peer Record (libp2p) + + SPRRead: + type: object + required: + - spr + properties: + spr: + $ref: "#/components/schemas/SPR" + + PeerIdRead: + type: object + properties: + id: + $ref: "#/components/schemas/PeerId" + + Content: + type: object + required: + - cid + description: Parameters specifying the content + properties: + cid: + $ref: "#/components/schemas/Cid" + + Node: + type: object + required: + - nodeId + - peerId + - record + - address + - seen + properties: + nodeId: + type: string + peerId: + type: string + record: + type: string + address: + type: string + seen: + type: boolean + + CodexVersion: + type: object + properties: + version: + type: string + example: v0.1.7 + revision: + type: string + example: 0c647d8 + + PeersTable: + type: object + required: + - localNode + - nodes + properties: + localNode: + $ref: "#/components/schemas/Node" + nodes: + type: array + items: + $ref: "#/components/schemas/Node" + + DebugInfo: + type: object + required: + - id + - addrs + - repo + - spr + - announceAddresses + - table + - codex + properties: + id: + $ref: "#/components/schemas/PeerId" + addrs: + type: array + items: + $ref: "#/components/schemas/MultiAddress" + repo: + type: string + description: Path of the data repository where all nodes data are stored + spr: + $ref: "#/components/schemas/SPR" + announceAddresses: + type: array + items: + $ref: "#/components/schemas/MultiAddress" + table: + $ref: "#/components/schemas/PeersTable" + codex: + $ref: "#/components/schemas/CodexVersion" + + SalesAvailability: + type: object + required: + - totalSize + - duration + - minPricePerBytePerSecond + - totalCollateral + properties: + totalSize: + type: integer + format: int64 + description: Total size of availability's storage in bytes + duration: + $ref: "#/components/schemas/Duration" + minPricePerBytePerSecond: + type: string + description: Minimal price per byte per second paid (in amount of tokens) for the hosted request's slot for the request's duration as decimal string + totalCollateral: + type: string + description: Total collateral (in amount of tokens) that can be used for matching requests + enabled: + type: boolean + description: Enable the ability to receive sales on this availability. + default: true + until: + type: integer + description: Specifies the latest timestamp, after which the availability will no longer host any slots. If set to 0, there will be no restrictions. + default: 0 + + SalesAvailabilityREAD: + required: + - id + - totalRemainingCollateral + allOf: + - $ref: "#/components/schemas/SalesAvailability" + - type: object + properties: + id: + $ref: "#/components/schemas/Id" + readonly: true + freeSize: + type: integer + format: int64 + description: Unused size of availability's storage in bytes as decimal string + readOnly: true + totalRemainingCollateral: + type: string + description: Total collateral effective (in amount of tokens) that can be used for matching requests + readOnly: true + + Slot: + type: object + required: + - id + - request + - slotIndex + properties: + id: + $ref: "#/components/schemas/SlotId" + request: + $ref: "#/components/schemas/StorageRequest" + slotIndex: + type: integer + format: int64 + description: Slot Index number + + SlotAgent: + type: object + required: + - state + - requestId + - slotIndex + properties: + slotIndex: + type: integer + format: int64 + description: Slot Index number + requestId: + $ref: "#/components/schemas/Id" + request: + $ref: "#/components/schemas/StorageRequest" + reservation: + $ref: "#/components/schemas/Reservation" + state: + type: string + description: Description of the slot's + enum: + - SaleCancelled + - SaleDownloading + - SaleErrored + - SaleFailed + - SaleFilled + - SaleFilling + - SaleFinished + - SaleIgnored + - SaleInitialProving + - SalePayout + - SalePreparing + - SaleProving + - SaleUnknown + + Reservation: + type: object + required: + - id + - availabilityId + - size + - requestId + - slotIndex + - validUntil + properties: + id: + $ref: "#/components/schemas/Id" + availabilityId: + $ref: "#/components/schemas/Id" + size: + type: integer + format: int64 + description: Size of the slot in bytes + requestId: + $ref: "#/components/schemas/Id" + slotIndex: + type: integer + format: int64 + description: Slot Index number + validUntil: + type: integer + description: Timestamp after which the reservation will no longer be valid. + + StorageRequestCreation: + type: object + required: + - pricePerBytePerSecond + - duration + - proofProbability + - collateralPerByte + - expiry + properties: + duration: + $ref: "#/components/schemas/Duration" + pricePerBytePerSecond: + $ref: "#/components/schemas/PricePerBytePerSecond" + proofProbability: + $ref: "#/components/schemas/ProofProbability" + nodes: + description: Minimal number of nodes the content should be stored on + type: integer + default: 3 + minimum: 3 + tolerance: + description: Additional number of nodes on top of the `nodes` property that can be lost before pronouncing the content lost + type: integer + default: 1 + minimum: 1 + collateralPerByte: + type: string + description: Number as decimal string that represents how much collateral per byte is asked from hosts that wants to fill a slots + expiry: + type: integer + format: int64 + description: Number that represents expiry threshold in seconds from when the Request is submitted. When the threshold is reached and the Request does not find requested amount of nodes to host the data, the Request is voided. The number of seconds can not be higher then the Request's duration itself. + StorageAsk: + type: object + required: + - slots + - slotSize + - duration + - proofProbability + - pricePerBytePerSecond + - collateralPerByte + - maxSlotLoss + properties: + slots: + description: Number of slots (eq. hosts) that the Request want to have the content spread over + type: integer + format: int64 + slotSize: + type: integer + format: int64 + description: Amount of storage per slot in bytes + duration: + $ref: "#/components/schemas/Duration" + proofProbability: + $ref: "#/components/schemas/ProofProbability" + pricePerBytePerSecond: + $ref: "#/components/schemas/PricePerBytePerSecond" + maxSlotLoss: + type: integer + format: int64 + description: Max slots that can be lost without data considered to be lost + + StorageRequest: + type: object + required: + - id + - client + - ask + - content + - expiry + - nonce + properties: + id: + type: string + description: Request ID + client: + $ref: "#/components/schemas/EthereumAddress" + ask: + $ref: "#/components/schemas/StorageAsk" + content: + $ref: "#/components/schemas/Content" + expiry: + $ref: "#/components/schemas/Expiry" + nonce: + type: string + description: Random data + + Purchase: + type: object + required: + - state + - requestId + properties: + state: + type: string + description: Description of the Request's state + enum: + - cancelled + - error + - failed + - finished + - pending + - started + - submitted + - unknown + error: + type: string + nullable: true + description: If Request failed, then here is presented the error message + request: + $ref: "#/components/schemas/StorageRequest" + requestId: + $ref: "#/components/schemas/Id" + + DataList: + type: object + required: + - content + properties: + content: + type: array + items: + $ref: "#/components/schemas/DataItem" + + DataItem: + type: object + required: + - cid + - manifest + properties: + cid: + $ref: "#/components/schemas/Cid" + manifest: + $ref: "#/components/schemas/ManifestItem" + + ManifestItem: + type: object + required: + - treeCid + - datasetSize + - blockSize + - protected + properties: + treeCid: + $ref: "#/components/schemas/Cid" + description: "Unique data identifier" + datasetSize: + type: integer + format: int64 + description: "Length of original content in bytes" + blockSize: + type: integer + description: "Size of blocks" + protected: + type: boolean + description: "Indicates if content is protected by erasure-coding" + filename: + type: string + nullable: true + description: "The original name of the uploaded content (optional)" + example: codex.png + mimetype: + type: string + nullable: true + description: "The original mimetype of the uploaded content (optional)" + example: image/png + + Space: + type: object + required: + - totalBlocks + - quotaMaxBytes + - quotaUsedBytes + - quotaReservedBytes + properties: + totalBlocks: + description: "Number of blocks stored by the node" + type: integer + format: int64 + quotaMaxBytes: + type: integer + format: int64 + description: "Maximum storage space (in bytes) available for the node in Codex's local repository." + quotaUsedBytes: + type: integer + format: int64 + description: "Amount of storage space (in bytes) currently used for storing files in Codex's local repository." + quotaReservedBytes: + type: integer + format: int64 + description: "Amount of storage reserved (in bytes) in the Codex's local repository for future use when storage requests will be picked up and hosted by the node using node's availabilities. This does not include the storage currently in use." + +servers: + - url: "http://localhost:8080/api/codex/v1" + +tags: + - name: Marketplace + description: Marketplace information and operations + - name: Data + description: Data operations + - name: Node + description: Node management + - name: Debug + description: Debugging configuration + +paths: + "/connect/{peerId}": + get: + summary: "Connect to a peer" + description: | + If `addrs` param is supplied, it will be used to dial the peer, otherwise the `peerId` is used + to invoke peer discovery, if it succeeds the returned addresses will be used to dial. + tags: [Node] + operationId: connectPeer + parameters: + - in: path + name: peerId + required: true + schema: + $ref: "#/components/schemas/PeerId" + description: Peer that should be dialed. + - in: query + name: addrs + schema: + type: array + nullable: true + items: + $ref: "#/components/schemas/MultiAddress" + description: | + If supplied, it will be used to dial the peer. + The address has to target the listening address of the peer, + which is specified with the `--listen-addrs` CLI flag. + + responses: + "200": + description: Successfully connected to peer + "400": + description: Peer either not found or was not possible to dial + + "/data": + get: + summary: "Lists manifest CIDs stored locally in node." + tags: [Data] + operationId: listData + responses: + "200": + description: Retrieved list of content CIDs + content: + application/json: + schema: + $ref: "#/components/schemas/DataList" + + "400": + description: Invalid CID is specified + "404": + description: Content specified by the CID is not found + "422": + description: The content type is not a valid content type or the filename is not valid + "500": + description: Well it was bad-bad + post: + summary: "Upload a file in a streaming manner. Once finished, the file is stored in the node and can be retrieved by any node in the network using the returned CID." + tags: [Data] + operationId: upload + parameters: + - name: content-type + in: header + required: false + description: The content type of the file. Must be valid. + schema: + type: string + example: "image/png" + - name: content-disposition + in: header + required: false + description: The content disposition used to send the filename. + schema: + type: string + example: 'attachment; filename="codex.png"' + requestBody: + content: + application/octet-stream: + schema: + type: string + format: binary + responses: + "200": + description: CID of uploaded file + content: + text/plain: + schema: + type: string + "500": + description: Well it was bad-bad and the upload did not work out + + "/data/{cid}": + get: + summary: "Download a file from the local node in a streaming manner. If the file is not available locally, a 404 is returned." + tags: [Data] + operationId: downloadLocal + parameters: + - in: path + name: cid + required: true + schema: + $ref: "#/components/schemas/Cid" + description: File to be downloaded. + + responses: + "200": + description: Retrieved content specified by CID + content: + application/octet-stream: + schema: + type: string + format: binary + "400": + description: Invalid CID is specified + "404": + description: Content specified by the CID is unavailable locally + "500": + description: Well it was bad-bad + + "/data/{cid}/network": + post: + summary: "Download a file from the network to the local node if it's not available locally. Note: Download is performed async. Call can return before download is completed." + tags: [Data] + operationId: downloadNetwork + parameters: + - in: path + name: cid + required: true + schema: + $ref: "#/components/schemas/Cid" + description: "File to be downloaded." + responses: + "200": + description: Manifest information for download that has been started. + content: + application/json: + schema: + $ref: "#/components/schemas/DataItem" + "400": + description: Invalid CID is specified + "404": + description: Failed to download dataset manifest + "500": + description: Well it was bad-bad + + "/data/{cid}/network/stream": + get: + summary: "Download a file from the network in a streaming manner. If the file is not available locally, it will be retrieved from other nodes in the network if able." + tags: [Data] + operationId: downloadNetworkStream + parameters: + - in: path + name: cid + required: true + schema: + $ref: "#/components/schemas/Cid" + description: "File to be downloaded." + responses: + "200": + description: Retrieved content specified by CID + content: + application/octet-stream: + schema: + type: string + format: binary + "400": + description: Invalid CID is specified + "404": + description: Content specified by the CID is not found + "500": + description: Well it was bad-bad + + "/data/{cid}/network/manifest": + get: + summary: "Download only the dataset manifest from the network to the local node if it's not available locally." + tags: [Data] + operationId: downloadNetworkManifest + parameters: + - in: path + name: cid + required: true + schema: + $ref: "#/components/schemas/Cid" + description: "File for which the manifest is to be downloaded." + responses: + "200": + description: Manifest information. + content: + application/json: + schema: + $ref: "#/components/schemas/DataItem" + "400": + description: Invalid CID is specified + "404": + description: Failed to download dataset manifest + "500": + description: Well it was bad-bad + + "/space": + get: + summary: "Gets a summary of the storage space allocation of the node." + tags: [Data] + operationId: space + responses: + "200": + description: "Summary of storage allocation" + content: + application/json: + schema: + $ref: "#/components/schemas/Space" + + "500": + description: "It's not working as planned" + + "/sales/slots": + get: + summary: "Returns active slots" + tags: [Marketplace] + operationId: getActiveSlots + responses: + "200": + description: Retrieved active slots + content: + application/json: + schema: + type: array + items: + $ref: "#/components/schemas/Slot" + + "503": + description: Persistence is not enabled + + "/sales/slots/{slotId}": + get: + summary: "Returns active slot with id {slotId} for the host" + tags: [Marketplace] + operationId: getActiveSlotById + parameters: + - in: path + name: slotId + required: true + schema: + $ref: "#/components/schemas/Cid" + description: File to be downloaded. + responses: + "200": + description: Retrieved active slot + content: + application/json: + schema: + $ref: "#/components/schemas/SlotAgent" + + "400": + description: Invalid or missing SlotId + + "404": + description: Host is not in an active sale for the slot + + "503": + description: Persistence is not enabled + + "/sales/availability": + get: + summary: "Returns storage that is for sale" + tags: [Marketplace] + operationId: getAvailabilities + responses: + "200": + description: Retrieved storage availabilities of the node + content: + application/json: + schema: + type: array + items: + $ref: "#/components/schemas/SalesAvailabilityREAD" + "500": + description: Error getting unused availabilities + "503": + description: Persistence is not enabled + + post: + summary: "Offers storage for sale" + operationId: offerStorage + tags: [Marketplace] + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/SalesAvailability" + responses: + "201": + description: Created storage availability + content: + application/json: + schema: + $ref: "#/components/schemas/SalesAvailabilityREAD" + "400": + description: Invalid data input + "422": + description: Not enough node's storage quota available or the provided parameters did not pass validation + "500": + description: Error reserving availability + "503": + description: Persistence is not enabled + "/sales/availability/{id}": + patch: + summary: "Updates availability" + description: | + The new parameters will be only considered for new requests. + Existing Requests linked to this Availability will continue as is. + operationId: updateOfferedStorage + tags: [Marketplace] + parameters: + - in: path + name: id + required: true + schema: + type: string + description: ID of Availability + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/SalesAvailability" + responses: + "204": + description: Availability successfully updated + "400": + description: Invalid data input + "404": + description: Availability not found + "422": + description: The provided parameters did not pass validation + "500": + description: Error reserving availability + "503": + description: Persistence is not enabled + + "/sales/availability/{id}/reservations": + get: + summary: "Get availability's reservations" + description: Return's list of Reservations for ongoing Storage Requests that the node hosts. + operationId: getReservations + tags: [Marketplace] + parameters: + - in: path + name: id + required: true + schema: + type: string + description: ID of Availability + responses: + "200": + description: Retrieved storage availabilities of the node + content: + application/json: + schema: + type: array + items: + $ref: "#/components/schemas/Reservation" + "400": + description: Invalid Availability ID + "404": + description: Availability not found + "500": + description: Error getting reservations + "503": + description: Persistence is not enabled + + "/storage/request/{cid}": + post: + summary: "Creates a new Request for storage" + tags: [Marketplace] + operationId: createStorageRequest + parameters: + - in: path + name: cid + required: true + schema: + $ref: "#/components/schemas/Cid" + description: CID of the uploaded data that should be stored + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/StorageRequestCreation" + responses: + "200": + description: Returns the Request ID as decimal string + content: + text/plain: + schema: + type: string + "400": + description: Invalid or missing Request ID + "422": + description: The storage request parameters are not valid + "404": + description: Request ID not found + "503": + description: Persistence is not enabled + + "/storage/purchases": + get: + summary: "Returns list of purchase IDs" + tags: [Marketplace] + operationId: getPurchases + responses: + "200": + description: Gets all purchase IDs stored in node + content: + application/json: + schema: + type: array + items: + type: string + "503": + description: Persistence is not enabled + + "/storage/purchases/{id}": + get: + summary: "Returns purchase details" + tags: [Marketplace] + operationId: getPurchase + parameters: + - in: path + name: id + required: true + schema: + type: string + description: Hexadecimal ID of a Purchase + responses: + "200": + description: Purchase details + content: + application/json: + schema: + $ref: "#/components/schemas/Purchase" + "400": + description: Invalid or missing Purchase ID + "404": + description: Purchase not found + "503": + description: Persistence is not enabled + + "/spr": + get: + summary: "Get Node's SPR" + operationId: getSPR + tags: [Node] + responses: + "200": + description: Node's SPR + content: + text/plain: + schema: + $ref: "#/components/schemas/SPR" + application/json: + schema: + $ref: "#/components/schemas/SPRRead" + "503": + description: Node SPR not ready, try again later + + "/peerid": + get: + summary: "Get Node's PeerID" + operationId: getPeerId + tags: [Node] + responses: + "200": + description: Node's Peer ID + content: + text/plain: + schema: + $ref: "#/components/schemas/PeerId" + application/json: + schema: + $ref: "#/components/schemas/PeerIdRead" + + "/debug/chronicles/loglevel": + post: + summary: "Set log level at run time" + tags: [Debug] + operationId: setDebugLogLevel + + parameters: + - in: query + name: level + required: true + schema: + $ref: "#/components/schemas/LogLevel" + + responses: + "200": + description: Successfully log level set + "400": + description: Invalid or missing log level + "500": + description: Well it was bad-bad + + "/debug/info": + get: + summary: "Gets node information" + operationId: getDebugInfo + tags: [Debug] + responses: + "200": + description: Node's information + content: + application/json: + schema: + $ref: "#/components/schemas/DebugInfo" diff --git a/package-lock.json b/package-lock.json index ef3ed35..eba2921 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,11 +9,13 @@ "version": "0.1.1", "license": "MIT", "dependencies": { - "valibot": "^0.32.0" + "valibot": "^1.0.0" }, "devDependencies": { "@tsconfig/strictest": "^2.0.5", - "@types/node": "^22.13.14", + "@types/node": "^22.13.17", + "oas-normalize": "^13.1.2", + "openapi-typescript": "^7.6.1", "prettier": "^3.5.3", "tsup": "^8.3.6", "typescript": "^5.8.2", @@ -23,7 +25,63 @@ "node": ">=20.18.1" }, "peerDependencies": { - "undici": "^7.0.0" + "undici": "^7.7.0" + } + }, + "node_modules/@apidevtools/json-schema-ref-parser": { + "version": "11.9.3", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.9.3.tgz", + "integrity": "sha512-60vepv88RwcJtSHrD6MjIL6Ta3SOYbgfnkHb+ppAVK+o9mXprRtulx7VlRl3lN3bbvysAfCS7WMVfhUYemB0IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jsdevtools/ono": "^7.1.3", + "@types/json-schema": "^7.0.15", + "js-yaml": "^4.1.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/philsturgeon" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz", + "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@esbuild/aix-ppc64": { @@ -451,6 +509,23 @@ "node": ">=18" } }, + "node_modules/@exodus/schemasafe": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@exodus/schemasafe/-/schemasafe-1.3.0.tgz", + "integrity": "sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@humanwhocodes/momoa": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@humanwhocodes/momoa/-/momoa-2.0.4.tgz", + "integrity": "sha512-RE815I4arJFtt+FVeU1Tgp9/Xvecacji8w/V6XtXsWWH/wz/eNkNbhb+ny/+PlVZjV0rxQpRSQKNKE3lcktHEA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.10.0" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -516,6 +591,13 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@jsdevtools/ono": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", + "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", + "dev": true, + "license": "MIT" + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -526,6 +608,142 @@ "node": ">=14" } }, + "node_modules/@readme/better-ajv-errors": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@readme/better-ajv-errors/-/better-ajv-errors-2.3.2.tgz", + "integrity": "sha512-T4GGnRAlY3C339NhoUpgJJFsMYko9vIgFAlhgV+/vEGFw66qEY4a4TRJIAZBcX/qT1pq5DvXSme+SQODHOoBrw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@babel/code-frame": "^7.22.5", + "@babel/runtime": "^7.22.5", + "@humanwhocodes/momoa": "^2.0.3", + "jsonpointer": "^5.0.0", + "leven": "^3.1.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "ajv": "4.11.8 - 8" + } + }, + "node_modules/@readme/http-status-codes": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@readme/http-status-codes/-/http-status-codes-7.2.0.tgz", + "integrity": "sha512-/dBh9qw3QhJYqlGwt2I+KUP/lQ6nytdCx3aq+GpMUhibLHF3O7fwoowNcTwlbnwtyJ+TJYTIIrp3oVUlRNx3fA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@readme/openapi-parser": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@readme/openapi-parser/-/openapi-parser-3.0.1.tgz", + "integrity": "sha512-U0Hn3bJRs8ZWn6cylNxLsieJjr5liibzn9JDuWNVvBILK5geEtJDS7S2vMbNViufGGLu08q1dvsbbYIZCSkBzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@apidevtools/json-schema-ref-parser": "^11.9.2", + "@readme/better-ajv-errors": "^2.3.2", + "@readme/openapi-schemas": "^3.1.0", + "@types/json-schema": "^7.0.15", + "ajv": "^8.12.0", + "ajv-draft-04": "^1.0.0" + }, + "engines": { + "node": ">=20" + }, + "peerDependencies": { + "openapi-types": ">=7" + } + }, + "node_modules/@readme/openapi-schemas": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@readme/openapi-schemas/-/openapi-schemas-3.1.0.tgz", + "integrity": "sha512-9FC/6ho8uFa8fV50+FPy/ngWN53jaUu4GRXlAjcxIRrzhltJnpKkBG2Tp0IDraFJeWrOpk84RJ9EMEEYzaI1Bw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@readme/postman-to-openapi": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@readme/postman-to-openapi/-/postman-to-openapi-4.1.0.tgz", + "integrity": "sha512-VvV2Hzjskz01m8doSn7Ypt6cSZzgjnypVqXy1ipThbyYD6SGiM74VSePXykOODj/43Y2m6zeYedPk/ZLts/HvQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@readme/http-status-codes": "^7.2.0", + "js-yaml": "^4.1.0", + "jsonc-parser": "3.2.0", + "lodash.camelcase": "^4.3.0", + "marked": "^4.3.0", + "mustache": "^4.2.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@redocly/ajv": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/@redocly/ajv/-/ajv-8.11.2.tgz", + "integrity": "sha512-io1JpnwtIcvojV7QKDUSIuMN/ikdOUd1ReEnUnMKGfDVridQZ31J0MmIuqwuRjWDZfmvr+Q0MqCcfHM2gTivOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js-replace": "^1.0.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@redocly/config": { + "version": "0.22.1", + "resolved": "https://registry.npmjs.org/@redocly/config/-/config-0.22.1.tgz", + "integrity": "sha512-1CqQfiG456v9ZgYBG9xRQHnpXjt8WoSnDwdkX6gxktuK69v2037hTAR1eh0DGIqpZ1p4k82cGH8yTNwt7/pI9g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@redocly/openapi-core": { + "version": "1.34.0", + "resolved": "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-1.34.0.tgz", + "integrity": "sha512-Ji00EiLQRXq0pJIz5pAjGF9MfQvQVsQehc6uIis6sqat8tG/zh25Zi64w6HVGEDgJEzUeq/CuUlD0emu3Hdaqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@redocly/ajv": "^8.11.2", + "@redocly/config": "^0.22.0", + "colorette": "^1.2.0", + "https-proxy-agent": "^7.0.5", + "js-levenshtein": "^1.1.6", + "js-yaml": "^4.1.0", + "minimatch": "^5.0.1", + "pluralize": "^8.0.0", + "yaml-ast-parser": "0.0.43" + }, + "engines": { + "node": ">=18.17.0", + "npm": ">=9.5.0" + } + }, + "node_modules/@redocly/openapi-core/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.34.8", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.8.tgz", @@ -804,10 +1022,17 @@ "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "dev": true }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { - "version": "22.13.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.14.tgz", - "integrity": "sha512-Zs/Ollc1SJ8nKUAgc7ivOEdIBM8JAKgrqqUYi2J997JuKO7/tpQC+WCetQ1sypiKCQWHdvdg9wBNpUPEWZae7w==", + "version": "22.13.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.17.tgz", + "integrity": "sha512-nAJuQXoyPj04uLgu+obZcSmsfOenUg6DxPKogeUy6yNCFwWaj5sBF8/G/pNo8EtBJjAfSVgfIlugR/BCOleO+g==", "dev": true, "license": "MIT", "dependencies": { @@ -927,6 +1152,58 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/agent-base": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-draft-04": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", + "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": "^8.5.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/ansi-regex": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", @@ -957,6 +1234,13 @@ "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", "dev": true }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, "node_modules/assertion-error": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", @@ -1007,6 +1291,13 @@ "node": ">=8" } }, + "node_modules/call-me-maybe": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", + "dev": true, + "license": "MIT" + }, "node_modules/chai": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz", @@ -1024,6 +1315,13 @@ "node": ">=12" } }, + "node_modules/change-case": { + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/change-case/-/change-case-5.4.4.tgz", + "integrity": "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==", + "dev": true, + "license": "MIT" + }, "node_modules/check-error": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", @@ -1050,6 +1348,100 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1068,6 +1460,13 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/colorette": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", + "dev": true, + "license": "MIT" + }, "node_modules/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", @@ -1148,6 +1547,13 @@ "dev": true, "license": "MIT" }, + "node_modules/es6-promise": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", + "integrity": "sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==", + "dev": true, + "license": "MIT" + }, "node_modules/esbuild": { "version": "0.25.0", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz", @@ -1189,6 +1595,16 @@ "@esbuild/win32-x64": "0.25.0" } }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/estree-walker": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", @@ -1209,6 +1625,37 @@ "node": ">=12.0.0" } }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", + "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/fdir": { "version": "6.4.3", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.3.tgz", @@ -1254,6 +1701,16 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/glob": { "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", @@ -1274,6 +1731,40 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/http2-client": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/http2-client/-/http2-client-1.3.5.tgz", + "integrity": "sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA==", + "dev": true, + "license": "MIT" + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/index-to-position": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.0.0.tgz", + "integrity": "sha512-sCO7uaLVhRJ25vz1o8s9IFM3nVS4DkuQnyjMwiQPKvQuBYBDmb8H7zx8ki7nVh4HJQOdVWebyvLE0qt+clruxA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -1313,6 +1804,70 @@ "node": ">=10" } }, + "node_modules/js-levenshtein": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", + "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/lilconfig": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", @@ -1341,6 +1896,13 @@ "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", @@ -1370,6 +1932,19 @@ "@jridgewell/sourcemap-codec": "^1.5.0" } }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "dev": true, + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -1400,6 +1975,16 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, + "node_modules/mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "dev": true, + "license": "MIT", + "bin": { + "mustache": "bin/mustache" + } + }, "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -1430,6 +2015,197 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch-h2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/node-fetch-h2/-/node-fetch-h2-2.3.0.tgz", + "integrity": "sha512-ofRW94Ab0T4AOh5Fk8t0h8OBWrmjb0SSB20xh1H8YnPV9EJ+f5AMoYSUQ2zgJ4Iq2HAK0I2l5/Nequ8YzFS3Hg==", + "dev": true, + "license": "MIT", + "dependencies": { + "http2-client": "^1.2.5" + }, + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/node-readfiles": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/node-readfiles/-/node-readfiles-0.2.0.tgz", + "integrity": "sha512-SU00ZarexNlE4Rjdm83vglt5Y9yiQ+XI1XpflWlb7q7UTN1JUItm69xMeiQCTxtTfnzt+83T8Cx+vI2ED++VDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es6-promise": "^3.2.1" + } + }, + "node_modules/oas-kit-common": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/oas-kit-common/-/oas-kit-common-1.0.8.tgz", + "integrity": "sha512-pJTS2+T0oGIwgjGpw7sIRU8RQMcUoKCDWFLdBqKB2BNmGpbBMH2sdqAaOXUg8OzonZHU0L7vfJu1mJFEiYDWOQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "fast-safe-stringify": "^2.0.7" + } + }, + "node_modules/oas-linter": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/oas-linter/-/oas-linter-3.2.2.tgz", + "integrity": "sha512-KEGjPDVoU5K6swgo9hJVA/qYGlwfbFx+Kg2QB/kd7rzV5N8N5Mg6PlsoCMohVnQmo+pzJap/F610qTodKzecGQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@exodus/schemasafe": "^1.0.0-rc.2", + "should": "^13.2.1", + "yaml": "^1.10.0" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/oas-linter/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/oas-normalize": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/oas-normalize/-/oas-normalize-13.1.2.tgz", + "integrity": "sha512-FXi+1I2MwPZWn4ERMpjJghMBu0qhgDHt0F2HINJyqksIpHJyIO5KMD+8/pUnF3H8iH36ZbszEi35YSllScajUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@readme/openapi-parser": "^3.0.1", + "@readme/postman-to-openapi": "^4.1.0", + "js-yaml": "^4.1.0", + "openapi-types": "^12.1.3", + "swagger2openapi": "^7.0.8" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/oas-resolver": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/oas-resolver/-/oas-resolver-2.5.6.tgz", + "integrity": "sha512-Yx5PWQNZomfEhPPOphFbZKi9W93CocQj18NlD2Pa4GWZzdZpSJvYwoiuurRI7m3SpcChrnO08hkuQDL3FGsVFQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "node-fetch-h2": "^2.3.0", + "oas-kit-common": "^1.0.8", + "reftools": "^1.1.9", + "yaml": "^1.10.0", + "yargs": "^17.0.1" + }, + "bin": { + "resolve": "resolve.js" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/oas-resolver/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/oas-schema-walker": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/oas-schema-walker/-/oas-schema-walker-1.1.5.tgz", + "integrity": "sha512-2yucenq1a9YPmeNExoUa9Qwrt9RFkjqaMAA1X+U7sbb0AqBeTIdMHky9SQQ6iN94bO5NW0W4TRYXerG+BdAvAQ==", + "dev": true, + "license": "BSD-3-Clause", + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/oas-validator": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/oas-validator/-/oas-validator-5.0.8.tgz", + "integrity": "sha512-cu20/HE5N5HKqVygs3dt94eYJfBi0TsZvPVXDhbXQHiEityDN+RROTleefoKRKKJ9dFAF2JBkDHgvWj0sjKGmw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "call-me-maybe": "^1.0.1", + "oas-kit-common": "^1.0.8", + "oas-linter": "^3.2.2", + "oas-resolver": "^2.5.6", + "oas-schema-walker": "^1.1.5", + "reftools": "^1.1.9", + "should": "^13.2.1", + "yaml": "^1.10.0" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/oas-validator/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -1439,12 +2215,58 @@ "node": ">=0.10.0" } }, + "node_modules/openapi-types": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", + "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/openapi-typescript": { + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/openapi-typescript/-/openapi-typescript-7.6.1.tgz", + "integrity": "sha512-F7RXEeo/heF3O9lOXo2bNjCOtfp7u+D6W3a3VNEH2xE6v+fxLtn5nq0uvUcA1F5aT+CMhNeC5Uqtg5tlXFX/ag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@redocly/openapi-core": "^1.28.0", + "ansi-colors": "^4.1.3", + "change-case": "^5.4.4", + "parse-json": "^8.1.0", + "supports-color": "^9.4.0", + "yargs-parser": "^21.1.1" + }, + "bin": { + "openapi-typescript": "bin/cli.js" + }, + "peerDependencies": { + "typescript": "^5.x" + } + }, "node_modules/package-json-from-dist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "dev": true }, + "node_modules/parse-json": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.2.0.tgz", + "integrity": "sha512-eONBZy4hm2AgxjNFd8a4nyDJnzUAH0g34xSQAwWEVGCjdZ4ZL7dKZBfq267GWP/JaS9zW62Xs2FeAdDvpHHJGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "index-to-position": "^1.0.0", + "type-fest": "^4.37.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -1515,6 +2337,16 @@ "node": ">= 6" } }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/postcss": { "version": "8.5.3", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", @@ -1625,6 +2457,43 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/reftools": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/reftools/-/reftools-1.1.9.tgz", + "integrity": "sha512-OVede/NQE13xBQ+ob5CKd5KyeJYU2YInb1bmV4nRoOfquZPkAkxuOXicSe1PvqIuZZ4kD13sPKBbR7UFDmli6w==", + "dev": true, + "license": "BSD-3-Clause", + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true, + "license": "MIT" + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", @@ -1694,6 +2563,66 @@ "node": ">=8" } }, + "node_modules/should": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", + "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "should-equal": "^2.0.0", + "should-format": "^3.0.3", + "should-type": "^1.4.0", + "should-type-adaptors": "^1.0.1", + "should-util": "^1.0.0" + } + }, + "node_modules/should-equal": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz", + "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "should-type": "^1.4.0" + } + }, + "node_modules/should-format": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", + "integrity": "sha512-hZ58adtulAk0gKtua7QxevgUaXTTXxIi8t41L3zo9AHvjXO1/7sdLECuHeIN2SRtYXpNkmhoUP2pdeWgricQ+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "should-type": "^1.3.0", + "should-type-adaptors": "^1.0.1" + } + }, + "node_modules/should-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", + "integrity": "sha512-MdAsTu3n25yDbIe1NeN69G4n6mUnJGtSJHygX3+oN0ZbO3DTiATnf7XnYJdGT42JCXurTb1JI0qOBR65shvhPQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/should-type-adaptors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz", + "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "should-type": "^1.3.0", + "should-util": "^1.0.0" + } + }, + "node_modules/should-util": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz", + "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==", + "dev": true, + "license": "MIT" + }, "node_modules/siginfo": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", @@ -1864,6 +2793,57 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/supports-color": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz", + "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/swagger2openapi": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/swagger2openapi/-/swagger2openapi-7.0.8.tgz", + "integrity": "sha512-upi/0ZGkYgEcLeGieoz8gT74oWHA0E7JivX7aN9mAf+Tc7BQoRBvnIGHoPDw+f9TXTW4s6kGYCZJtauP6OYp7g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "call-me-maybe": "^1.0.1", + "node-fetch": "^2.6.1", + "node-fetch-h2": "^2.3.0", + "node-readfiles": "^0.2.0", + "oas-kit-common": "^1.0.8", + "oas-resolver": "^2.5.6", + "oas-schema-walker": "^1.1.5", + "oas-validator": "^5.0.8", + "reftools": "^1.1.9", + "yaml": "^1.10.0", + "yargs": "^17.0.1" + }, + "bin": { + "boast": "boast.js", + "oas-validate": "oas-validate.js", + "swagger2openapi": "swagger2openapi.js" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/swagger2openapi/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, "node_modules/thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", @@ -2020,11 +3000,24 @@ } } }, + "node_modules/type-fest": { + "version": "4.38.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.38.0.tgz", + "integrity": "sha512-2dBz5D5ycHIoliLYLi0Q2V7KRaDlH0uWIvmk7TYlAg5slqwiPv1ezJdZm1QEM0xgk29oYWMCbIG7E6gHpvChlg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typescript": { "version": "5.8.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", - "dev": true, + "devOptional": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -2035,9 +3028,9 @@ } }, "node_modules/undici": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.5.0.tgz", - "integrity": "sha512-NFQG741e8mJ0fLQk90xKxFdaSM7z4+IQpAgsFI36bCDY9Z2+aXXZjVy2uUksMouWfMI9+w5ejOq5zYYTBCQJDQ==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.7.0.tgz", + "integrity": "sha512-tZ6+5NBq4KH35rr46XJ2JPFKxfcBlYNaqLF/wyWIO9RMHqqU/gx/CLB1Y2qMcgB8lWw/bKHa7qzspqCN7mUHvA==", "license": "MIT", "peer": true, "engines": { @@ -2051,12 +3044,27 @@ "dev": true, "license": "MIT" }, - "node_modules/valibot": { - "version": "0.32.0", - "resolved": "https://registry.npmjs.org/valibot/-/valibot-0.32.0.tgz", - "integrity": "sha512-FXBnJl4bNOmeg7lQv+jfvo/wADsRBN8e9C3r+O77Re3dEnDma8opp7p4hcIbF7XJJ30h/5SVohdjer17/sHOsQ==", + "node_modules/uri-js-replace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uri-js-replace/-/uri-js-replace-1.0.1.tgz", + "integrity": "sha512-W+C9NWNLFOoBI2QWDp4UT9pv65r2w5Cx+3sTYFvtMdDBxkKt1syCqsUdSFAChbEe1uK5TfS04wt/nGwmaeIQ0g==", + "dev": true, "license": "MIT" }, + "node_modules/valibot": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/valibot/-/valibot-1.0.0.tgz", + "integrity": "sha512-1Hc0ihzWxBar6NGeZv7fPLY0QuxFMyxwYR2sF1Blu7Wq7EnremwY2W02tit2ij2VJT8HcSkHAQqmFfl77f73Yw==", + "license": "MIT", + "peerDependencies": { + "typescript": ">=5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/vite": { "version": "6.2.4", "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.4.tgz", @@ -2360,6 +3368,112 @@ "engines": { "node": ">=8" } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yaml": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz", + "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==", + "dev": true, + "license": "ISC", + "optional": true, + "peer": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/yaml-ast-parser": { + "version": "0.0.43", + "resolved": "https://registry.npmjs.org/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz", + "integrity": "sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } } } } diff --git a/package.json b/package.json index 6622f4d..582d7b8 100644 --- a/package.json +++ b/package.json @@ -77,16 +77,18 @@ }, "devDependencies": { "@tsconfig/strictest": "^2.0.5", - "@types/node": "^22.13.14", + "@types/node": "^22.13.17", + "oas-normalize": "^13.1.2", + "openapi-typescript": "^7.6.1", "prettier": "^3.5.3", "tsup": "^8.3.6", "typescript": "^5.8.2", "vitest": "^3.1.1" }, "dependencies": { - "valibot": "^0.32.0" + "valibot": "^1.0.0" }, "peerDependencies": { - "undici": "^7.0.0" + "undici": "^7.7.0" } } \ No newline at end of file diff --git a/src/data/data.ts b/src/data/data.ts index 3aec5b8..d709432 100644 --- a/src/data/data.ts +++ b/src/data/data.ts @@ -7,11 +7,14 @@ import { import type { SafeValue } from "../values/values"; import type { CodexDataResponse, - CodexManifest, - CodexNodeSpace, UploadStategy, - NetworkDownloadResponse, UploadResponse, + CodexSpaceResponse, + CodexNodeSpace, + CodexDataNetworkResponse, + CodexNetworkDownload, + CodexManifest, + CodexDataItems, } from "./types"; type CodexDataOptions = { @@ -34,7 +37,7 @@ export class CodexData { * Lists manifest CIDs stored locally in node. * TODO: remove the faker data part when the api is ready */ - cids(): Promise> { + cids(): Promise> { const url = this.url + Api.config.prefix + "/data"; return Fetch.safeJson(url, { @@ -52,10 +55,10 @@ export class CodexData { /** * Gets a summary of the storage space allocation of the node. */ - space() { + space(): Promise> { const url = this.url + Api.config.prefix + "/space"; - return Fetch.safeJson(url, { + return Fetch.safeJson(url, { method: "GET", headers: FetchAuthBuilder.build(this.auth), }); @@ -95,12 +98,10 @@ export class CodexData { * Download a file from the network to the local node if it's not available locally. * Note: Download is performed async. Call can return before download is completed. */ - async networkDownload( - cid: string - ): Promise> { + async networkDownload(cid: string): Promise> { const url = this.url + Api.config.prefix + `/data/${cid}/network`; - return Fetch.safeJson(url, { + return Fetch.safeJson(url, { method: "POST", headers: FetchAuthBuilder.build(this.auth), }); @@ -123,7 +124,7 @@ export class CodexData { * Download only the dataset manifest from the network to the local node * if it's not available locally. */ - async fetchManifest(cid: string) { + async fetchManifest(cid: string): Promise> { const url = this.url + Api.config.prefix + `/data/${cid}/network/manifest`; return Fetch.safeJson(url, { diff --git a/src/data/types.ts b/src/data/types.ts index 0c57fa4..8e105a0 100644 --- a/src/data/types.ts +++ b/src/data/types.ts @@ -1,87 +1,33 @@ +import type { components, paths } from "../openapi"; import type { FetchAuth } from "../fetch-safe/fetch-safe"; import type { SafeValue } from "../values/values"; -export type CodexManifest = { - /** - * "Root hash of the content" - */ - // rootHash: string; +export type CodexDataResponse = + paths["/data"]["get"]["responses"][200]["content"]["application/json"]; - /** - * Length of original content in bytes - */ - // originalBytes: number; +export type CodexDataItem = components["schemas"]["DataItem"]; - /** - * Total size of all blocks - */ - datasetSize: number; +export type CodexDataItems = CodexDataResponse; - /** - * "Size of blocks" - */ - blockSize: number; +export type CodexSpaceResponse = + paths["/space"]["get"]["responses"][200]["content"]["application/json"]; - /** - * Indicates if content is protected by erasure-coding - */ - protected: boolean; - - /** - * Root of the merkle tree - */ - treeCid: string; - - /** - * Name of the name - */ - filename: string | null; - - /** - * Mimetype - */ - mimetype: string | null; -}; - -export type CodexDataContent = { - /** - * Content Identifier as specified at https://github.com/multiformats/cid - */ - cid: string; - - manifest: CodexManifest; -}; - -export type CodexDataResponse = { content: CodexDataContent[] }; - -export type CodexNodeSpace = { - /** - * Number of blocks stored by the node - */ - totalBlocks: number; - - /** - * Maximum storage space used by the node - */ - quotaMaxBytes: number; - - /** - * Amount of storage space currently in use - */ - quotaUsedBytes: number; - - /** - * Amount of storage space reserved - */ - quotaReservedBytes: number; -}; +export type CodexNodeSpace = CodexSpaceResponse; export type UploadResponse = { result: Promise>; abort: () => void; }; -export type NetworkDownloadResponse = { cid: string; manifest: CodexManifest }; +export type CodexDataNetworkResponse = + paths["/data/{cid}/network"]["post"]["responses"][200]["content"]["application/json"]; + +export type CodexNetworkDownload = components["schemas"]["DataItem"]; + +export type CodexFetchManifestResponse = + paths["/data/{cid}/network/manifest"]["get"]["responses"][200]["content"]["application/json"]; + +export type CodexManifest = CodexFetchManifestResponse; export type UploadStategyOptions = { auth?: FetchAuth; diff --git a/src/debug/debug.ts b/src/debug/debug.ts index c51feb2..f476ba3 100644 --- a/src/debug/debug.ts +++ b/src/debug/debug.ts @@ -6,7 +6,12 @@ import { type FetchAuth, } from "../fetch-safe/fetch-safe"; import type { SafeValue } from "../values/values"; -import { CodexLogLevel, type CodexDebugInfo } from "./types"; +import { + CodexLogLevelInput, + type CodexDebugInfo, + type CodexInfoResponse, + type CodexLogLevel, +} from "./types"; import * as v from "valibot"; type CodexDebugOptions = { @@ -28,8 +33,8 @@ export class CodexDebug { /** * Set log level at run time */ - async setLogLevel(level: CodexLogLevel): Promise> { - const result = v.safeParse(CodexLogLevel, level); + async setLogLevel(level: CodexLogLevel): Promise> { + const result = v.safeParse(CodexLogLevelInput, level); if (!result.success) { return Promise.resolve({ @@ -46,26 +51,20 @@ export class CodexDebug { "/debug/chronicles/loglevel?level=" + level; - const res = await Fetch.safe(url, { + return Fetch.safeText(url, { method: "POST", headers: FetchAuthBuilder.build(this.auth), body: "", }); - - if (res.error) { - return res; - } - - return { error: false, data: "" }; } /** * Gets node information */ - info() { + info(): Promise> { const url = this.url + Api.config.prefix + `/debug/info`; - return Fetch.safeJson(url, { + return Fetch.safeJson(url, { method: "GET", headers: FetchAuthBuilder.build(this.auth), }); diff --git a/src/debug/types.ts b/src/debug/types.ts index dc63cb2..7d62dca 100644 --- a/src/debug/types.ts +++ b/src/debug/types.ts @@ -1,6 +1,13 @@ import * as v from "valibot"; +import type { paths } from "../openapi"; -export const CodexLogLevel = v.picklist([ +export type CodexLogLevelResponse = + paths["/debug/chronicles/loglevel"]["post"]["responses"][200]["content"]; + +export type CodexLogLevel = + paths["/debug/chronicles/loglevel"]["post"]["parameters"]["query"]["level"]; + +export const CodexLogLevelInput = v.picklist([ "TRACE", "DEBUG", "INFO", @@ -10,49 +17,7 @@ export const CodexLogLevel = v.picklist([ "FATAL", ]); -export type CodexLogLevel = v.InferOutput; +export type CodexInfoResponse = + paths["/debug/info"]["get"]["responses"][200]["content"]["application/json"]; -export type CodexDebugInfo = { - /** - * Peer Identity reference as specified at https://docs.libp2p.io/concepts/fundamentals/peers/ - */ - id: string; - - /** - * Address of node as specified by the multi-address specification https://multiformats.io/multiaddr/ - */ - addrs: string[]; - - announceAddresses: string[] - - /** - * Path of the data repository where all nodes data are stored - */ - repo: string; - - // Signed Peer Record (libp2p) - spr: string; - - table: { - localNode: { - nodeId: string - peerId: string - record: string - address: string - seen: boolean - } - - nodes: { - nodeId: string - peerId: string - record: string - address: string - seen: boolean - }[] - } - - codex: { - version: string - revision: string - } -}; +export type CodexDebugInfo = CodexInfoResponse; diff --git a/src/fetch-safe/fetch-safe.ts b/src/fetch-safe/fetch-safe.ts index 3da25e9..0f98871 100644 --- a/src/fetch-safe/fetch-safe.ts +++ b/src/fetch-safe/fetch-safe.ts @@ -60,4 +60,14 @@ export const Fetch = { return Promises.safe(() => res.data.json()); }, + + async safeText(url: string, init: RequestInit): Promise> { + const res = await this.safe(url, init); + + if (res.error) { + return res; + } + + return Promises.safe(() => res.data.text()); + }, }; diff --git a/src/marketplace/marketplace.test.ts b/src/marketplace/marketplace.test.ts index 1f6b4fa..bf7c7b8 100644 --- a/src/marketplace/marketplace.test.ts +++ b/src/marketplace/marketplace.test.ts @@ -104,10 +104,12 @@ function minNumberValidationError(field: string, min: number) { function createAvailability() { return { id: randomEthereumAddress(), - totalSize: randomInt(0, 9).toString(), - duration: randomInt(0, 9).toString(), - minPrice: randomInt(0, 9).toString(), - maxCollateral: randomInt(0, 9).toString(), + totalSize: randomInt(0, 9), + duration: randomInt(0, 9), + minPrice: randomInt(0, 9), + minPricePerBytePerSecond: randomInt(0, 9), + totalCollateral: randomInt(0, 900), + totalRemainingCollateral: randomInt(0, 900), }; } @@ -210,7 +212,7 @@ describe("marketplace", () => { }); it("returns a response when the request succeed", async () => { - const data = { ...createAvailability(), freeSize: "1000" }; + const data = { ...createAvailability(), freeSize: 1000 }; const spy = vi.spyOn(Fetch, "safeJson"); spy.mockImplementationOnce(() => Promise.resolve({ error: false, data })); @@ -228,16 +230,16 @@ describe("marketplace", () => { }); it("returns a response when the create availability succeed", async () => { - const data = { ...createAvailability(), freeSize: "1000" }; + const data = { ...createAvailability(), freeSize: 1000 }; const spy = vi.spyOn(Fetch, "safeJson"); spy.mockImplementationOnce(() => Promise.resolve({ error: false, data })); const response = await marketplace.createAvailability({ - totalCollateral: 1, - totalSize: 3000, - minPricePerBytePerSecond: 100, - duration: 100, + totalCollateral: data.totalCollateral, + totalSize: data.totalSize, + minPricePerBytePerSecond: data.minPricePerBytePerSecond, + duration: data.duration, }); assert.ok(!response.error); diff --git a/src/marketplace/marketplace.ts b/src/marketplace/marketplace.ts index 9dede63..04cd737 100644 --- a/src/marketplace/marketplace.ts +++ b/src/marketplace/marketplace.ts @@ -8,16 +8,27 @@ import { } from "../fetch-safe/fetch-safe"; import type { SafeValue } from "../values/values"; import { + type CodexAvailabilityResponse, type CodexAvailability, + type CodexSlot, + type CodexSlotAgent, + type CodexSlotResponse, + type CodexSlotAgentResponse, + type CodexAvailabilityWithoutTypes, type CodexAvailabilityCreateResponse, - type CodexAvailabilityDto, + type CodexAvailabilityCreateBody, + CodexAvailabilityPatchInput, + type CodexReservationsResponse, + type CodexPurchaseIdsResponse, + type CodexPurchaseResponse, + type CodexPurchase, + type CodexStorageRequestCreateBody, + type CodexReservation, + type CodexPurchaseWithoutTypes, +} from "./types"; +import { CodexCreateAvailabilityInput, CodexCreateStorageRequestInput, - type CodexPurchase, - type CodexReservation, - type CodexSlot, - type CodexStorageRequest, - CodexUpdateAvailabilityInput, } from "./types"; type CodexMarketplaceOptions = { @@ -42,7 +53,7 @@ export class CodexMarketplace { async activeSlots(): Promise> { const url = this.url + Api.config.prefix + "/sales/slots"; - return Fetch.safeJson(url, { + return Fetch.safeJson(url, { method: "GET", headers: FetchAuthBuilder.build(this.auth), }); @@ -51,22 +62,40 @@ export class CodexMarketplace { /** * Returns active slot with id {slotId} for the host */ - async activeSlot(slotId: string): Promise> { + async activeSlot(slotId: string): Promise> { const url = this.url + Api.config.prefix + "/sales/slots/" + slotId; - return Fetch.safeJson(url, { + return Fetch.safeJson(url, { method: "GET", headers: FetchAuthBuilder.build(this.auth), }); } + private transformAvailability({ + freeSize, + ...a + }: CodexAvailabilityWithoutTypes) { + const availability: CodexAvailability = { + ...a, + minPricePerBytePerSecond: parseInt(a.minPricePerBytePerSecond, 10), + totalCollateral: parseInt(a.totalCollateral, 10), + totalRemainingCollateral: parseInt(a.totalRemainingCollateral, 10), + }; + + if (freeSize) { + availability.freeSize = freeSize; + } + + return availability; + } + /** * Returns storage that is for sale */ async availabilities(): Promise> { const url = this.url + Api.config.prefix + "/sales/availability"; - const res = await Fetch.safeJson(url, { + const res = await Fetch.safeJson(url, { method: "GET", headers: FetchAuthBuilder.build(this.auth), }); @@ -77,15 +106,7 @@ export class CodexMarketplace { return { error: false, - data: res.data.map((a) => ({ - id: a.id, - totalSize: parseInt(a.totalSize, 10), - freeSize: parseInt(a.freeSize, 10), - duration: parseInt(a.duration, 10), - minPricePerBytePerSecond: parseInt(a.minPricePerBytePerSecond, 10), - totalCollateral: parseInt(a.totalCollateral, 10), - totalRemainingCollateral: parseInt(a.totalRemainingCollateral, 10), - })), + data: res.data.map(this.transformAvailability), }; } @@ -94,7 +115,7 @@ export class CodexMarketplace { */ async createAvailability( input: CodexCreateAvailabilityInput - ): Promise> { + ): Promise> { const result = v.safeParse(CodexCreateAvailabilityInput, input); if (!result.success) { @@ -108,17 +129,32 @@ export class CodexMarketplace { const url = this.url + Api.config.prefix + "/sales/availability"; - const body = result.output; + const body: CodexAvailabilityCreateBody = { + totalSize: result.output.totalSize, + duration: result.output.duration, + minPricePerBytePerSecond: + result.output.minPricePerBytePerSecond.toString(), + totalCollateral: result.output.totalCollateral.toString(), + }; + + if (result.output.enabled) { + body.enabled = result.output.enabled; + } + + if (result.output.until) { + body.until = result.output.until; + } return Fetch.safeJson(url, { method: "POST", headers: FetchAuthBuilder.build(this.auth), - body: JSON.stringify({ - totalSize: body.totalSize.toString(), - duration: body.duration.toString(), - minPricePerBytePerSecond: body.minPricePerBytePerSecond.toString(), - totalCollateral: body.totalCollateral.toString(), - }), + body: JSON.stringify(body), + }).then((result) => { + if (result.error) { + return result; + } + + return { error: false, data: this.transformAvailability(result.data) }; }); } @@ -127,9 +163,9 @@ export class CodexMarketplace { * Existing Requests linked to this Availability will continue as is. */ async updateAvailability( - input: CodexUpdateAvailabilityInput + input: CodexAvailabilityPatchInput ): Promise> { - const result = v.safeParse(CodexUpdateAvailabilityInput, input); + const result = v.safeParse(CodexAvailabilityPatchInput, input); if (!result.success) { return { @@ -143,17 +179,26 @@ export class CodexMarketplace { const url = this.url + Api.config.prefix + "/sales/availability/" + result.output.id; - const body = result.output; + const body: CodexAvailabilityCreateBody = { + totalSize: result.output.totalSize, + duration: result.output.duration, + minPricePerBytePerSecond: + result.output.minPricePerBytePerSecond.toString(), + totalCollateral: result.output.totalCollateral.toString(), + }; + + if (result.output.enabled) { + body.enabled = result.output.enabled; + } + + if (result.output.until) { + body.until = result.output.until; + } const res = await Fetch.safe(url, { method: "PATCH", headers: FetchAuthBuilder.build(this.auth), - body: JSON.stringify({ - totalSize: body.totalSize.toString(), - duration: body.duration.toString(), - minPricePerBytePerSecond: body.minPricePerBytePerSecond.toString(), - totalCollateral: body.totalCollateral.toString(), - }), + body: JSON.stringify(body), }); if (res.error) { @@ -174,7 +219,7 @@ export class CodexMarketplace { Api.config.prefix + `/sales/availability/${availabilityId}/reservations`; - return Fetch.safeJson(url, { + return Fetch.safeJson(url, { method: "GET", headers: FetchAuthBuilder.build(this.auth), }); @@ -183,22 +228,47 @@ export class CodexMarketplace { /** * Returns list of purchase IDs */ - async purchaseIds(): Promise> { + async purchaseIds(): Promise> { const url = this.url + Api.config.prefix + `/storage/purchases`; - return Fetch.safeJson(url, { + return Fetch.safeJson(url, { method: "GET", headers: FetchAuthBuilder.build(this.auth), }); } - async purchases(): Promise> { - const url = this.url + Api.config.prefix + `/storage/purchases`; + private transformPurchase(p: CodexPurchaseWithoutTypes): CodexPurchase { + const purchase: CodexPurchase = { + requestId: p.requestId, + state: p.state, + }; - const res = await Fetch.safeJson(url, { - method: "GET", - headers: FetchAuthBuilder.build(this.auth), - }); + if (p.error) { + purchase.error = p.error; + } + + if (!p.request) { + return purchase; + } + + return { + ...purchase, + request: { + ...p.request, + ask: { + ...p.request.ask, + proofProbability: parseInt(p.request.ask.proofProbability, 10), + pricePerBytePerSecond: parseInt( + p.request.ask.pricePerBytePerSecond, + 10 + ), + }, + }, + }; + } + + async purchases(): Promise> { + const res = await this.purchaseIds(); if (res.error) { return res; @@ -220,7 +290,6 @@ export class CodexMarketplace { state: "error", error: p.data.message, requestId: "", - request: {} as CodexStorageRequest, } satisfies CodexPurchase) : p.data ), @@ -234,9 +303,15 @@ export class CodexMarketplace { const url = this.url + Api.config.prefix + `/storage/purchases/` + purchaseId; - return Fetch.safeJson(url, { - method: "GET", + return Fetch.safeJson(url, { headers: FetchAuthBuilder.build(this.auth), + method: "GET", + }).then((res) => { + if (res.error) { + return res; + } + + return { error: false, data: this.transformPurchase(res.data) }; }); } @@ -269,24 +344,18 @@ export class CodexMarketplace { } = result.output; const url = this.url + Api.config.prefix + "/storage/request/" + cid; - const res = await Fetch.safe(url, { + return Fetch.safeText(url, { method: "POST", headers: FetchAuthBuilder.build(this.auth), body: JSON.stringify({ - duration: duration.toString(), + duration, pricePerBytePerSecond: pricePerBytePerSecond.toString(), proofProbability: proofProbability.toString(), nodes, collateralPerByte: collateralPerByte.toString(), - expiry: expiry.toString(), + expiry, tolerance, - }), + } satisfies CodexStorageRequestCreateBody), }); - - if (res.error) { - return res; - } - - return { error: false, data: await res.data.text() }; } } diff --git a/src/marketplace/types.ts b/src/marketplace/types.ts index e5e2e78..35fa4e1 100644 --- a/src/marketplace/types.ts +++ b/src/marketplace/types.ts @@ -1,232 +1,122 @@ +import type { components, paths } from "../openapi"; import * as v from "valibot"; -export type CodexStorageRequest = { - id: string; +export type CodexSlotResponse = + paths["/sales/slots"]["get"]["responses"][200]["content"]["application/json"]; - /** - * Address of Ethereum address - */ - client: string; +export type CodexSlot = CodexSlotResponse; - ask: { - /** - * Number of slots that the tequest want to have the content spread over. - */ - slots: number; +export type CodexSlotAgentResponse = + paths["/sales/slots/{slotId}"]["get"]["responses"][200]["content"]["application/json"]; - /** - * Amount of storage per slot (in bytes) as decimal string. - */ - slotSize: string; +export type CodexSlotAgent = CodexSlotAgentResponse; - /** - * The duration of the storage request in seconds. - */ - duration: string; +export type CodexAvailabilityResponse = + paths["/sales/availability"]["get"]["responses"][200]["content"]["application/json"]; - /** - * How often storage proofs are required as decimal string (in periods). - */ - proofProbability: string; +export type CodexAvailabilityWithoutTypes = + components["schemas"]["SalesAvailabilityREAD"]; - /** - * The amount of tokens paid per byte per second per slot to hosts the client is willing to pay - */ - pricePerBytePerSecond: string; - - /** - * Max slots that can be lost without data considered to be lost. - */ - maxSlotLoss: number; - }; - - content: { - /** - * Unique Content ID - */ - cid: string; - - /** - * Erasure code parameters - */ - // erasure: { - /** - * Total number of chunks generated by the erasure code process. - */ - // totalChunks: number; - // }; - - /** - * Parameters for Proof of Retrievability - */ - // por: { - // u: string; - // publicKey: string; - // name: string; - // }; - }; - - /* Number as decimal string that represents expiry threshold in seconds from when the Request is submitted. - * When the threshold is reached and the Request does not find requested amount of nodes to host the data, the Request is voided. - * The number of seconds can not be higher then the Request's duration itself. - */ - expiry: string; - - /** - * Random data - */ - nonce: string; -}; - -/** - * A storage slot is a portion of a storage contract that needs to be fulfilled - * by a host. To initiate a contract, all the slots must be filled. - */ -export type CodexSlot = { - id: string; - - request: CodexStorageRequest; - - /** - * The slot index as hexadecimal string - */ - slotIndex: "string"; -}; - -/** - * Storage availability for sell. - */ -export type CodexAvailability = { - id: string; - - /** - * Size of available storage in bytes - */ +export type CodexAvailability = Omit< + CodexAvailabilityWithoutTypes, + | "freeSize" + | "totalSize" + | "minPricePerBytePerSecond" + | "duration" + | "totalCollateral" + | "totalRemainingCollateral" +> & { + freeSize?: number; totalSize: number; - - /** - * Unused size of availability's storage in bytes as decimal string - */ - freeSize: number; - - /** - * Maximum time the storage should be sold for (in seconds) - */ duration: number; - - /** - * Minimal price per byte per second paid (in amount of tokens) for the - * hosted request's slot for the request's duration as decimal string - */ minPricePerBytePerSecond: number; - - /** - * Total collateral (in amount of tokens) that can be used for matching requests - */ totalCollateral: number; - totalRemainingCollateral: number; }; -/** - * Storage availability received from the api. - */ -export type CodexAvailabilityDto = { - id: string; +export type CodexAvailabilityCreateResponse = + paths["/sales/availability"]["post"]["responses"][201]["content"]["application/json"]; - /** - * Size of available storage in bytes - */ - totalSize: string; - - /** - * Unused size of availability's storage in bytes as decimal string - */ - freeSize: string; - - /** - * Maximum time the storage should be sold for (in seconds) - */ - duration: string; - - /** - * Minimal price per byte per second paid (in amount of tokens) for the - * hosted request's slot for the request's duration as decimal string - */ - minPricePerBytePerSecond: string; - - /** - * Total collateral (in amount of tokens) that can be used for matching requests - */ - totalCollateral: string; - - totalRemainingCollateral: string; -}; - -export type CodexAvailabilityCreateResponse = CodexAvailability & { - id: string; - - /** - * Unused size of availability's storage in bytes as decimal string - */ - freeSize: string; -}; +export type CodexAvailabilityCreateBody = Exclude< + paths["/sales/availability"]["post"]["requestBody"], + undefined +>["content"]["application/json"]; export const CodexCreateAvailabilityInput = v.strictObject({ totalSize: v.pipe(v.number(), v.minValue(1)), duration: v.pipe(v.number(), v.minValue(1)), minPricePerBytePerSecond: v.number(), totalCollateral: v.number(), + enabled: v.optional(v.boolean()), + until: v.optional(v.number()), }); +export type CodexAvailabilityPatchResponse = + paths["/sales/availability/{id}"]["patch"]["responses"][204]["content"]; + +export type CodexAvailabilityPatchBody = Exclude< + paths["/sales/availability"]["post"]["requestBody"], + undefined +>["content"]["application/json"]; + export type CodexCreateAvailabilityInput = v.InferOutput< typeof CodexCreateAvailabilityInput >; -export const CodexUpdateAvailabilityInput = v.strictObject({ +export const CodexAvailabilityPatchInput = v.strictObject({ id: v.string(), totalSize: v.pipe(v.number(), v.minValue(1)), duration: v.pipe(v.number(), v.minValue(1)), minPricePerBytePerSecond: v.number(), totalCollateral: v.number(), + enabled: v.optional(v.boolean()), + until: v.optional(v.number()), }); -export type CodexUpdateAvailabilityInput = v.InferOutput< - typeof CodexUpdateAvailabilityInput +export type CodexAvailabilityPatchInput = v.InferOutput< + typeof CodexAvailabilityPatchInput >; -export type CodexReservation = { - id: string; - availabilityId: string; - requestId: string; +export type CodexReservationsResponse = + paths["/sales/availability/{id}/reservations"]["get"]["responses"][200]["content"]["application/json"]; - /** - * Size in bytes - */ - size: string; +export type CodexReservation = components["schemas"]["Reservation"]; - /** - * Slot Index as hexadecimal string - */ - slotIndex: string; +export type CodexPurchaseIdsResponse = + paths["/storage/purchases"]["get"]["responses"][200]["content"]["application/json"]; + +export type CodexPurchaseResponse = + paths["/storage/purchases/{id}"]["get"]["responses"][200]["content"]["application/json"]; + +export type CodexStorageAsk = Omit< + components["schemas"]["StorageAsk"], + "slotSize" | "duration" | "proofProbability" | "pricePerBytePerSecond" +> & { + slotSize: number; + duration: number; + proofProbability: number; + pricePerBytePerSecond: number; }; -export type CodexPurchase = { - /** - * Description of the request's state - */ - state: string; +export type CodexPurchaseWithoutTypes = components["schemas"]["Purchase"]; - /** - * If request failed, then here is presented the error message - */ - error: string; - - request: CodexStorageRequest; - - requestId: string; +export type CodexPurchase = Omit< + components["schemas"]["Purchase"], + "request" +> & { + request?: Omit & { + ask: CodexStorageAsk; + }; }; +export type CodexStorageRequestResponse = + paths["/storage/request/{cid}"]["post"]["responses"][200]["content"]["text/plain"]; + +export type CodexStorageRequestCreateBody = Exclude< + paths["/storage/request/{cid}"]["post"]["requestBody"], + undefined +>["content"]["application/json"]; + export const CodexCreateStorageRequestInput = v.strictObject({ cid: v.string(), duration: v.pipe(v.number(), v.minValue(1)), diff --git a/src/node/node.ts b/src/node/node.ts index b2ef8a2..c304166 100644 --- a/src/node/node.ts +++ b/src/node/node.ts @@ -5,7 +5,14 @@ import { type FetchAuth, } from "../fetch-safe/fetch-safe"; import type { SafeValue } from "../values/values"; -import type { CodexSpr } from "./types"; +import type { + CodexPeerId, + CodexPeerIdContentType, + CodexPeerIdJsonResponse, + CodexSpr, + CodexSprContentType, + CodexSprJsonResponse, +} from "./types"; type CodexNodeOptions = { auth?: FetchAuth; @@ -25,9 +32,8 @@ export class CodexNode { /** * Connect to a peer - * TODO check result */ - connect(peerId: string, addrs: string[] = []) { + connect(peerId: string, addrs: string[] = []): Promise> { const params = new URLSearchParams(); for (const addr of addrs) { @@ -37,7 +43,7 @@ export class CodexNode { const url = this.url + Api.config.prefix + `/connect/${peerId}?` + params.toString(); - return Fetch.safe(url, { + return Fetch.safeText(url, { method: "GET", headers: FetchAuthBuilder.build(this.auth), }); @@ -46,25 +52,54 @@ export class CodexNode { /** * Get Node's SPR */ - async spr(): Promise> { + async spr( + type: CodexSprContentType = "json" + ): Promise>> { const url = this.url + Api.config.prefix + "/spr"; - return Fetch.safeJson(url, { + if (type === "json") { + return Fetch.safeJson(url, { + method: "GET", + headers: { + ...FetchAuthBuilder.build(this.auth), + "Content-Type": "application/json", + }, + }); + } + + return Fetch.safeText(url, { method: "GET", - headers: FetchAuthBuilder.build(this.auth), + headers: { + ...FetchAuthBuilder.build(this.auth), + "Content-Type": "text/plain", + }, }); } /** * Get Node's PeerID - * TODO check result */ - peerId() { + peerId( + type: CodexPeerIdContentType = "json" + ): Promise>> { const url = this.url + Api.config.prefix + "/node/peerid"; - return Fetch.safe(url, { + if (type === "json") { + return Fetch.safeJson(url, { + method: "GET", + headers: { + ...FetchAuthBuilder.build(this.auth), + "Content-Type": "application/json", + }, + }); + } + + return Fetch.safeText(url, { method: "GET", - headers: FetchAuthBuilder.build(this.auth), + headers: { + ...FetchAuthBuilder.build(this.auth), + "Content-Type": "text/plain", + }, }); } } diff --git a/src/node/types.ts b/src/node/types.ts index 169e999..a62e860 100644 --- a/src/node/types.ts +++ b/src/node/types.ts @@ -1,3 +1,29 @@ -export type CodexSpr = { - spr: string; -}; +import type { paths } from "../openapi"; + +export type CodexSprTextResponse = + paths["/spr"]["get"]["responses"][200]["content"]["text/plain"]; + +export type CodexSprJsonResponse = + paths["/spr"]["get"]["responses"][200]["content"]["application/json"]; + +export type CodexSprContentType = "json" | "text"; + +export type CodexSpr = T extends "json" + ? CodexSprJsonResponse + : T extends "text" + ? CodexSprTextResponse + : never; + +export type CodexPeerIdTextResponse = + paths["/peerid"]["get"]["responses"][200]["content"]["text/plain"]; + +export type CodexPeerIdJsonResponse = + paths["/peerid"]["get"]["responses"][200]["content"]["application/json"]; + +export type CodexPeerIdContentType = "json" | "text"; + +export type CodexPeerId = T extends "json" + ? CodexPeerIdJsonResponse + : T extends "text" + ? CodexPeerIdTextResponse + : never; diff --git a/src/openapi.ts b/src/openapi.ts new file mode 100644 index 0000000..8117dfb --- /dev/null +++ b/src/openapi.ts @@ -0,0 +1,1449 @@ +/** + * This file was auto-generated by openapi-typescript. + * Do not make direct changes to the file. + */ + +export interface paths { + "/connect/{peerId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Connect to a peer + * @description If `addrs` param is supplied, it will be used to dial the peer, otherwise the `peerId` is used + * to invoke peer discovery, if it succeeds the returned addresses will be used to dial. + * + */ + get: operations["connectPeer"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/data": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Lists manifest CIDs stored locally in node. */ + get: operations["listData"]; + put?: never; + /** Upload a file in a streaming manner. Once finished, the file is stored in the node and can be retrieved by any node in the network using the returned CID. */ + post: operations["upload"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/data/{cid}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Download a file from the local node in a streaming manner. If the file is not available locally, a 404 is returned. */ + get: operations["downloadLocal"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/data/{cid}/network": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** Download a file from the network to the local node if it's not available locally. Note: Download is performed async. Call can return before download is completed. */ + post: operations["downloadNetwork"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/data/{cid}/network/stream": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Download a file from the network in a streaming manner. If the file is not available locally, it will be retrieved from other nodes in the network if able. */ + get: operations["downloadNetworkStream"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/data/{cid}/network/manifest": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Download only the dataset manifest from the network to the local node if it's not available locally. */ + get: operations["downloadNetworkManifest"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/space": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Gets a summary of the storage space allocation of the node. */ + get: operations["space"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/sales/slots": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Returns active slots */ + get: operations["getActiveSlots"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/sales/slots/{slotId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Returns active slot with id {slotId} for the host */ + get: operations["getActiveSlotById"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/sales/availability": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Returns storage that is for sale */ + get: operations["getAvailabilities"]; + put?: never; + /** Offers storage for sale */ + post: operations["offerStorage"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/sales/availability/{id}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + /** + * Updates availability + * @description The new parameters will be only considered for new requests. + * Existing Requests linked to this Availability will continue as is. + * + */ + patch: operations["updateOfferedStorage"]; + trace?: never; + }; + "/sales/availability/{id}/reservations": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get availability's reservations + * @description Return's list of Reservations for ongoing Storage Requests that the node hosts. + */ + get: operations["getReservations"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/storage/request/{cid}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** Creates a new Request for storage */ + post: operations["createStorageRequest"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/storage/purchases": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Returns list of purchase IDs */ + get: operations["getPurchases"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/storage/purchases/{id}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Returns purchase details */ + get: operations["getPurchase"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/spr": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Get Node's SPR */ + get: operations["getSPR"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/peerid": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Get Node's PeerID */ + get: operations["getPeerId"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/debug/chronicles/loglevel": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** Set log level at run time */ + post: operations["setDebugLogLevel"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/debug/info": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Gets node information */ + get: operations["getDebugInfo"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; +} +export type webhooks = Record; +export interface components { + schemas: { + /** + * @description Address of node as specified by the multi-address specification https://multiformats.io/multiaddr/ + * @example /ip4/127.0.0.1/tcp/8080 + */ + MultiAddress: string; + /** + * @description Peer Identity reference as specified at https://docs.libp2p.io/concepts/fundamentals/peers/ + * @example QmYyQSo1c1Ym7orWxLYvCrM2EmxFTANf8wXmmE7DWjhx5N + */ + PeerId: string; + /** + * @description 32bits identifier encoded in hex-decimal string. + * @example 0x... + */ + Id: string; + /** + * @description Content Identifier as specified at https://github.com/multiformats/cid + * @example QmYyQSo1c1Ym7orWxLYvCrM2EmxFTANf8wXmmE7DWjhx5N + */ + Cid: string; + /** + * @description Keccak hash of the abi encoded tuple (RequestId, slot index) + * @example 268a781e0db3f7cf36b18e5f4fdb7f586ec9edd08e5500b17c0e518a769f114a + */ + SlotId: string; + /** + * @description One of the log levels: TRACE, DEBUG, INFO, NOTICE, WARN, ERROR or FATAL + * @example DEBUG + */ + LogLevel: string; + /** @description Address of Ethereum address */ + EthereumAddress: string; + /** @description The amount of tokens paid per byte per second per slot to hosts the client is willing to pay */ + PricePerBytePerSecond: string; + /** + * Format: int64 + * @description The duration of the request in seconds + */ + Duration: number; + /** @description How often storage proofs are required as decimal string */ + ProofProbability: string; + /** + * Format: int64 + * @description A timestamp as seconds since unix epoch at which this request expires if the Request does not find requested amount of nodes to host the data. + */ + Expiry: number; + /** @description Signed Peer Record (libp2p) */ + SPR: string; + SPRRead: { + spr: components["schemas"]["SPR"]; + }; + PeerIdRead: { + id?: components["schemas"]["PeerId"]; + }; + /** @description Parameters specifying the content */ + Content: { + cid: components["schemas"]["Cid"]; + }; + Node: { + nodeId: string; + peerId: string; + record: string; + address: string; + seen: boolean; + }; + CodexVersion: { + /** @example v0.1.7 */ + version?: string; + /** @example 0c647d8 */ + revision?: string; + }; + PeersTable: { + localNode: components["schemas"]["Node"]; + nodes: components["schemas"]["Node"][]; + }; + DebugInfo: { + id: components["schemas"]["PeerId"]; + addrs: components["schemas"]["MultiAddress"][]; + /** @description Path of the data repository where all nodes data are stored */ + repo: string; + spr: components["schemas"]["SPR"]; + announceAddresses: components["schemas"]["MultiAddress"][]; + table: components["schemas"]["PeersTable"]; + codex: components["schemas"]["CodexVersion"]; + }; + SalesAvailability: { + /** + * Format: int64 + * @description Total size of availability's storage in bytes + */ + totalSize: number; + duration: components["schemas"]["Duration"]; + /** @description Minimal price per byte per second paid (in amount of tokens) for the hosted request's slot for the request's duration as decimal string */ + minPricePerBytePerSecond: string; + /** @description Total collateral (in amount of tokens) that can be used for matching requests */ + totalCollateral: string; + /** + * @description Enable the ability to receive sales on this availability. + * @default true + */ + enabled?: boolean; + /** + * @description Specifies the latest timestamp, after which the availability will no longer host any slots. If set to 0, there will be no restrictions. + * @default 0 + */ + until?: number; + }; + SalesAvailabilityREAD: components["schemas"]["SalesAvailability"] & { + id: components["schemas"]["Id"]; + /** + * Format: int64 + * @description Unused size of availability's storage in bytes as decimal string + */ + readonly freeSize?: number; + /** @description Total collateral effective (in amount of tokens) that can be used for matching requests */ + readonly totalRemainingCollateral: string; + }; + Slot: { + id: components["schemas"]["SlotId"]; + request: components["schemas"]["StorageRequest"]; + /** + * Format: int64 + * @description Slot Index number + */ + slotIndex: number; + }; + SlotAgent: { + /** + * Format: int64 + * @description Slot Index number + */ + slotIndex: number; + requestId: components["schemas"]["Id"]; + request?: components["schemas"]["StorageRequest"]; + reservation?: components["schemas"]["Reservation"]; + /** + * @description Description of the slot's + * @enum {string} + */ + state: "SaleCancelled" | "SaleDownloading" | "SaleErrored" | "SaleFailed" | "SaleFilled" | "SaleFilling" | "SaleFinished" | "SaleIgnored" | "SaleInitialProving" | "SalePayout" | "SalePreparing" | "SaleProving" | "SaleUnknown"; + }; + Reservation: { + id: components["schemas"]["Id"]; + availabilityId: components["schemas"]["Id"]; + /** + * Format: int64 + * @description Size of the slot in bytes + */ + size: number; + requestId: components["schemas"]["Id"]; + /** + * Format: int64 + * @description Slot Index number + */ + slotIndex: number; + /** @description Timestamp after which the reservation will no longer be valid. */ + validUntil: number; + }; + StorageRequestCreation: { + duration: components["schemas"]["Duration"]; + pricePerBytePerSecond: components["schemas"]["PricePerBytePerSecond"]; + proofProbability: components["schemas"]["ProofProbability"]; + /** + * @description Minimal number of nodes the content should be stored on + * @default 3 + */ + nodes?: number; + /** + * @description Additional number of nodes on top of the `nodes` property that can be lost before pronouncing the content lost + * @default 1 + */ + tolerance?: number; + /** @description Number as decimal string that represents how much collateral per byte is asked from hosts that wants to fill a slots */ + collateralPerByte: string; + /** + * Format: int64 + * @description Number that represents expiry threshold in seconds from when the Request is submitted. When the threshold is reached and the Request does not find requested amount of nodes to host the data, the Request is voided. The number of seconds can not be higher then the Request's duration itself. + */ + expiry: number; + }; + StorageAsk: { + /** + * Format: int64 + * @description Number of slots (eq. hosts) that the Request want to have the content spread over + */ + slots: number; + /** + * Format: int64 + * @description Amount of storage per slot in bytes + */ + slotSize: number; + duration: components["schemas"]["Duration"]; + proofProbability: components["schemas"]["ProofProbability"]; + pricePerBytePerSecond: components["schemas"]["PricePerBytePerSecond"]; + /** + * Format: int64 + * @description Max slots that can be lost without data considered to be lost + */ + maxSlotLoss: number; + }; + StorageRequest: { + /** @description Request ID */ + id: string; + client: components["schemas"]["EthereumAddress"]; + ask: components["schemas"]["StorageAsk"]; + content: components["schemas"]["Content"]; + expiry: components["schemas"]["Expiry"]; + /** @description Random data */ + nonce: string; + }; + Purchase: { + /** + * @description Description of the Request's state + * @enum {string} + */ + state: "cancelled" | "error" | "failed" | "finished" | "pending" | "started" | "submitted" | "unknown"; + /** @description If Request failed, then here is presented the error message */ + error?: string | null; + request?: components["schemas"]["StorageRequest"]; + requestId: components["schemas"]["Id"]; + }; + DataList: { + content: components["schemas"]["DataItem"][]; + }; + DataItem: { + cid: components["schemas"]["Cid"]; + manifest: components["schemas"]["ManifestItem"]; + }; + ManifestItem: { + /** @description Unique data identifier */ + treeCid: components["schemas"]["Cid"]; + /** + * Format: int64 + * @description Length of original content in bytes + */ + datasetSize: number; + /** @description Size of blocks */ + blockSize: number; + /** @description Indicates if content is protected by erasure-coding */ + protected: boolean; + /** + * @description The original name of the uploaded content (optional) + * @example codex.png + */ + filename?: string | null; + /** + * @description The original mimetype of the uploaded content (optional) + * @example image/png + */ + mimetype?: string | null; + }; + Space: { + /** + * Format: int64 + * @description Number of blocks stored by the node + */ + totalBlocks: number; + /** + * Format: int64 + * @description Maximum storage space (in bytes) available for the node in Codex's local repository. + */ + quotaMaxBytes: number; + /** + * Format: int64 + * @description Amount of storage space (in bytes) currently used for storing files in Codex's local repository. + */ + quotaUsedBytes: number; + /** + * Format: int64 + * @description Amount of storage reserved (in bytes) in the Codex's local repository for future use when storage requests will be picked up and hosted by the node using node's availabilities. This does not include the storage currently in use. + */ + quotaReservedBytes: number; + }; + }; + responses: never; + parameters: never; + requestBodies: never; + headers: never; + pathItems: never; +} +export type $defs = Record; +export interface operations { + connectPeer: { + parameters: { + query?: { + /** @description If supplied, it will be used to dial the peer. + * The address has to target the listening address of the peer, + * which is specified with the `--listen-addrs` CLI flag. + * */ + addrs?: components["schemas"]["MultiAddress"][] | null; + }; + header?: never; + path: { + /** @description Peer that should be dialed. */ + peerId: components["schemas"]["PeerId"]; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successfully connected to peer */ + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Peer either not found or was not possible to dial */ + 400: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + listData: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Retrieved list of content CIDs */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DataList"]; + }; + }; + /** @description Invalid CID is specified */ + 400: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Content specified by the CID is not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description The content type is not a valid content type or the filename is not valid */ + 422: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Well it was bad-bad */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + upload: { + parameters: { + query?: never; + header?: { + /** @description The content type of the file. Must be valid. */ + "content-type"?: string; + /** @description The content disposition used to send the filename. */ + "content-disposition"?: string; + }; + path?: never; + cookie?: never; + }; + requestBody?: { + content: { + "application/octet-stream": string; + }; + }; + responses: { + /** @description CID of uploaded file */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": string; + }; + }; + /** @description Well it was bad-bad and the upload did not work out */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + downloadLocal: { + parameters: { + query?: never; + header?: never; + path: { + /** @description File to be downloaded. */ + cid: components["schemas"]["Cid"]; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Retrieved content specified by CID */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/octet-stream": string; + }; + }; + /** @description Invalid CID is specified */ + 400: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Content specified by the CID is unavailable locally */ + 404: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Well it was bad-bad */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + downloadNetwork: { + parameters: { + query?: never; + header?: never; + path: { + /** @description File to be downloaded. */ + cid: components["schemas"]["Cid"]; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Manifest information for download that has been started. */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DataItem"]; + }; + }; + /** @description Invalid CID is specified */ + 400: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to download dataset manifest */ + 404: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Well it was bad-bad */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + downloadNetworkStream: { + parameters: { + query?: never; + header?: never; + path: { + /** @description File to be downloaded. */ + cid: components["schemas"]["Cid"]; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Retrieved content specified by CID */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/octet-stream": string; + }; + }; + /** @description Invalid CID is specified */ + 400: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Content specified by the CID is not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Well it was bad-bad */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + downloadNetworkManifest: { + parameters: { + query?: never; + header?: never; + path: { + /** @description File for which the manifest is to be downloaded. */ + cid: components["schemas"]["Cid"]; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Manifest information. */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DataItem"]; + }; + }; + /** @description Invalid CID is specified */ + 400: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to download dataset manifest */ + 404: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Well it was bad-bad */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + space: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Summary of storage allocation */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Space"]; + }; + }; + /** @description It's not working as planned */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + getActiveSlots: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Retrieved active slots */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Slot"][]; + }; + }; + /** @description Persistence is not enabled */ + 503: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + getActiveSlotById: { + parameters: { + query?: never; + header?: never; + path: { + /** @description File to be downloaded. */ + slotId: components["schemas"]["Cid"]; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Retrieved active slot */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["SlotAgent"]; + }; + }; + /** @description Invalid or missing SlotId */ + 400: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Host is not in an active sale for the slot */ + 404: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Persistence is not enabled */ + 503: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + getAvailabilities: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Retrieved storage availabilities of the node */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["SalesAvailabilityREAD"][]; + }; + }; + /** @description Error getting unused availabilities */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Persistence is not enabled */ + 503: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + offerStorage: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: { + content: { + "application/json": components["schemas"]["SalesAvailability"]; + }; + }; + responses: { + /** @description Created storage availability */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["SalesAvailabilityREAD"]; + }; + }; + /** @description Invalid data input */ + 400: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Not enough node's storage quota available or the provided parameters did not pass validation */ + 422: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Error reserving availability */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Persistence is not enabled */ + 503: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + updateOfferedStorage: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of Availability */ + id: string; + }; + cookie?: never; + }; + requestBody?: { + content: { + "application/json": components["schemas"]["SalesAvailability"]; + }; + }; + responses: { + /** @description Availability successfully updated */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Invalid data input */ + 400: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Availability not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description The provided parameters did not pass validation */ + 422: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Error reserving availability */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Persistence is not enabled */ + 503: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + getReservations: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of Availability */ + id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Retrieved storage availabilities of the node */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Reservation"][]; + }; + }; + /** @description Invalid Availability ID */ + 400: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Availability not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Error getting reservations */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Persistence is not enabled */ + 503: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + createStorageRequest: { + parameters: { + query?: never; + header?: never; + path: { + /** @description CID of the uploaded data that should be stored */ + cid: components["schemas"]["Cid"]; + }; + cookie?: never; + }; + requestBody?: { + content: { + "application/json": components["schemas"]["StorageRequestCreation"]; + }; + }; + responses: { + /** @description Returns the Request ID as decimal string */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": string; + }; + }; + /** @description Invalid or missing Request ID */ + 400: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Request ID not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description The storage request parameters are not valid */ + 422: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Persistence is not enabled */ + 503: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + getPurchases: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Gets all purchase IDs stored in node */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": string[]; + }; + }; + /** @description Persistence is not enabled */ + 503: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + getPurchase: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Hexadecimal ID of a Purchase */ + id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Purchase details */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Purchase"]; + }; + }; + /** @description Invalid or missing Purchase ID */ + 400: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Purchase not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Persistence is not enabled */ + 503: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + getSPR: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Node's SPR */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["SPR"]; + "application/json": components["schemas"]["SPRRead"]; + }; + }; + /** @description Node SPR not ready, try again later */ + 503: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + getPeerId: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Node's Peer ID */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["PeerId"]; + "application/json": components["schemas"]["PeerIdRead"]; + }; + }; + }; + }; + setDebugLogLevel: { + parameters: { + query: { + level: components["schemas"]["LogLevel"]; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successfully log level set */ + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Invalid or missing log level */ + 400: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Well it was bad-bad */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + getDebugInfo: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Node's information */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DebugInfo"]; + }; + }; + }; + }; +} diff --git a/tsconfig.json b/tsconfig.json index ae764b4..4a0b6f6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,6 +14,7 @@ "module": "ESNext", "moduleResolution": "Bundler", "verbatimModuleSyntax": true, - "sourceMap": true + "sourceMap": true, + "noUncheckedIndexedAccess": true } } \ No newline at end of file