Add delete endpoint

This commit is contained in:
Arnaud 2025-05-30 12:58:16 +02:00
parent a437e593f0
commit d3f5d1dea5
No known key found for this signature in database
GPG Key ID: B8FBC178F10CA7AE
8 changed files with 150 additions and 9 deletions

View File

@ -406,6 +406,21 @@ const cid = "QmYyQSo1c1Ym7orWxLYvCrM2EmxFTANf8wXmmE7DWjhx5N";
const result = await data.localDownload(cid);
```
#### delete
Deletes either a single block or an entire dataset from the local node.
Does nothing if the dataset is not locally available.
- cid (string, required)
- returns ""
Example:
```js
const cid = "QmYyQSo1c1Ym7orWxLYvCrM2EmxFTANf8wXmmE7DWjhx5N";
const result = await data.delete(cid);
```
### Debug
The following API assume that you have already a node module loaded, example:

View File

@ -50,6 +50,10 @@ components:
type: string
description: The amount of tokens paid per byte per second per slot to hosts the client is willing to pay
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
Duration:
type: integer
format: int64
@ -120,6 +124,9 @@ components:
revision:
type: string
example: 0c647d8
contracts:
type: string
example: 0b537c7
PeersTable:
type: object
@ -198,6 +205,7 @@ components:
required:
- id
- totalRemainingCollateral
- freeSize
allOf:
- $ref: "#/components/schemas/SalesAvailability"
- type: object
@ -320,8 +328,7 @@ components:
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
$ref: "#/components/schemas/CollateralPerByte"
expiry:
type: integer
format: int64
@ -351,6 +358,8 @@ components:
$ref: "#/components/schemas/ProofProbability"
pricePerBytePerSecond:
$ref: "#/components/schemas/PricePerBytePerSecond"
collateralPerByte:
$ref: "#/components/schemas/CollateralPerByte"
maxSlotLoss:
type: integer
format: int64
@ -392,7 +401,7 @@ components:
description: Description of the Request's state
enum:
- cancelled
- error
- errored
- failed
- finished
- pending
@ -586,6 +595,8 @@ paths:
text/plain:
schema:
type: string
"422":
description: The mimetype of the filename is invalid
"500":
description: Well it was bad-bad and the upload did not work out
@ -617,6 +628,26 @@ paths:
"500":
description: Well it was bad-bad
delete:
summary: "Deletes either a single block or an entire dataset from the local node."
tags: [Data]
operationId: deleteLocal
parameters:
- in: path
name: cid
required: true
schema:
$ref: "#/components/schemas/Cid"
description: Block or dataset to be deleted.
responses:
"204":
description: Data was successfully deleted.
"400":
description: Invalid CID is specified
"500":
description: There was an error during deletion
"/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."

View File

@ -38,6 +38,26 @@ describe("data", () => {
assert.ok(treeCid);
});
it("delete a file a locally", async () => {
const content = "b".repeat(131072);
const strategy = new NodeUploadStategy(content);
const res = data.upload(strategy);
const cid = await res.result;
assert.ok(cid.error == false);
assert.ok(cid.data);
let cids = await data.cids();
assert.ok(cids.error == false);
assert.ok(cids.data.content.find((c) => c.cid == cid.data));
const del = await data.delete(cid.data);
assert.ok(del.error == false);
cids = await data.cids();
assert.ok(cids.error == false);
assert.notOk(cids.data.content.find((c) => c.cid == cid.data));
});
it("updates the space available when storing data", async () => {
const content = crypto.randomBytes(16).toString("hex");

View File

@ -132,4 +132,18 @@ export class CodexData {
headers: FetchAuthBuilder.build(this.auth),
});
}
/**
* Deletes either a single block or an entire dataset
* from the local node. Does nothing
* if the dataset is not locally available.
*/
async delete(cid: string): Promise<SafeValue<string>> {
const url = this.url + Api.config.prefix + `/data/${cid}`;
return Fetch.safeText(url, {
method: "DELETE",
headers: FetchAuthBuilder.build(this.auth),
});
}
}

View File

@ -40,3 +40,8 @@ export interface UploadStategy {
): Promise<SafeValue<string>>;
abort(): void;
}
// paths["/data/{cid}"]["delete"]["responses"][204]["content"];
export type CodexDeleteResponse = "";
export type CodexDelete = CodexDeleteResponse;

View File

@ -300,7 +300,7 @@ export class CodexMarketplace {
data: purchases.map((p) =>
p.error
? ({
state: "error",
state: "errored",
error: p.data.message,
requestId: "",
} satisfies CodexPurchase)

View File

@ -55,7 +55,8 @@ export interface paths {
get: operations["downloadLocal"];
put?: never;
post?: never;
delete?: never;
/** Deletes either a single block or an entire dataset from the local node. */
delete: operations["deleteLocal"];
options?: never;
head?: never;
patch?: never;
@ -380,6 +381,8 @@ export interface components {
EthereumAddress: string;
/** @description The amount of tokens paid per byte per second per slot to hosts the client is willing to pay */
PricePerBytePerSecond: string;
/** @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 The duration of the request in seconds
@ -416,6 +419,8 @@ export interface components {
version?: string;
/** @example 0c647d8 */
revision?: string;
/** @example 0b537c7 */
contracts?: string;
};
PeersTable: {
localNode: components["schemas"]["Node"];
@ -459,7 +464,7 @@ export interface components {
* Format: int64
* @description Unused size of availability's storage in bytes as decimal string
*/
readonly freeSize?: number;
readonly freeSize: number;
/** @description Total collateral effective (in amount of tokens) that can be used for matching requests */
readonly totalRemainingCollateral: string;
};
@ -518,8 +523,7 @@ export interface components {
* @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;
collateralPerByte: components["schemas"]["CollateralPerByte"];
/**
* 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.
@ -540,6 +544,7 @@ export interface components {
duration: components["schemas"]["Duration"];
proofProbability: components["schemas"]["ProofProbability"];
pricePerBytePerSecond: components["schemas"]["PricePerBytePerSecond"];
collateralPerByte: components["schemas"]["CollateralPerByte"];
/**
* Format: int64
* @description Max slots that can be lost without data considered to be lost
@ -561,7 +566,7 @@ export interface components {
* @description Description of the Request's state
* @enum {string}
*/
state: "cancelled" | "error" | "failed" | "finished" | "pending" | "started" | "submitted" | "unknown";
state: "cancelled" | "errored" | "failed" | "finished" | "pending" | "started" | "submitted" | "unknown";
/** @description If Request failed, then here is presented the error message */
error?: string | null;
request?: components["schemas"]["StorageRequest"];
@ -737,6 +742,13 @@ export interface operations {
"text/plain": string;
};
};
/** @description The mimetype of the filename is invalid */
422: {
headers: {
[name: string]: unknown;
};
content?: never;
};
/** @description Well it was bad-bad and the upload did not work out */
500: {
headers: {
@ -790,6 +802,41 @@ export interface operations {
};
};
};
deleteLocal: {
parameters: {
query?: never;
header?: never;
path: {
/** @description Block or dataset to be deleted. */
cid: components["schemas"]["Cid"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Data was successfully deleted. */
204: {
headers: {
[name: string]: unknown;
};
content?: never;
};
/** @description Invalid CID is specified */
400: {
headers: {
[name: string]: unknown;
};
content?: never;
};
/** @description There was an error during deletion */
500: {
headers: {
[name: string]: unknown;
};
content?: never;
};
};
};
downloadNetwork: {
parameters: {
query?: never;

9
vitest.config.js Normal file
View File

@ -0,0 +1,9 @@
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
// run tests sequentially, not in parallel
// number of workers set to 1 disables parallelism
maxThreads: 1,
},
});