@hashgrid/sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +88 -0
- package/dist/client.d.ts +12 -0
- package/dist/client.js +114 -0
- package/dist/exceptions.d.ts +18 -0
- package/dist/exceptions.js +46 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +22 -0
- package/dist/resources.d.ts +58 -0
- package/dist/resources.js +141 -0
- package/package.json +44 -0
- package/src/client.ts +162 -0
- package/src/exceptions.ts +47 -0
- package/src/index.ts +22 -0
- package/src/resources.ts +244 -0
- package/tsconfig.json +26 -0
package/README.md
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Hashgrid Client
|
|
2
|
+
|
|
3
|
+
TypeScript/JavaScript SDK for the Hashgrid DNA Protocol API.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @hashgrid/sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { Hashgrid, Message } from "@hashgrid/sdk";
|
|
15
|
+
|
|
16
|
+
async function main() {
|
|
17
|
+
// Connect to grid
|
|
18
|
+
const grid = await Hashgrid.connect("your-api-key");
|
|
19
|
+
|
|
20
|
+
// Listen for ticks and process messages
|
|
21
|
+
for await (const tick of grid.listen()) {
|
|
22
|
+
for await (const node of grid.nodes()) {
|
|
23
|
+
const messages = await node.recv();
|
|
24
|
+
if (messages.length === 0) {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const replies = messages.map((msg) =>
|
|
28
|
+
new Message(
|
|
29
|
+
msg.peer_id,
|
|
30
|
+
"Hello, fellow grid peer!",
|
|
31
|
+
msg.round,
|
|
32
|
+
0.9
|
|
33
|
+
)
|
|
34
|
+
);
|
|
35
|
+
await node.send(replies);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
main();
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Resources
|
|
44
|
+
|
|
45
|
+
The SDK provides the following resources:
|
|
46
|
+
|
|
47
|
+
- **`Grid`** - Grid connection with `listen()` and `nodes()` methods
|
|
48
|
+
- **`Node`** - Node with `recv()`, `send()`, `update()`, and `delete()` methods
|
|
49
|
+
- **`Edge`** - Edge data model
|
|
50
|
+
- **`User`** - User data model
|
|
51
|
+
- **`Quota`** - Quota data model
|
|
52
|
+
- **`Message`** - Message for recv/send operations
|
|
53
|
+
- **`Status`** - Status response from send operations
|
|
54
|
+
|
|
55
|
+
## Examples
|
|
56
|
+
|
|
57
|
+
See the `examples/` directory for example implementations.
|
|
58
|
+
|
|
59
|
+
## Error Handling
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
import {
|
|
63
|
+
HashgridError,
|
|
64
|
+
HashgridAPIError,
|
|
65
|
+
HashgridAuthenticationError,
|
|
66
|
+
HashgridNotFoundError,
|
|
67
|
+
HashgridValidationError,
|
|
68
|
+
} from "@hashgrid/sdk";
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
const grid = await Hashgrid.connect("invalid-key");
|
|
72
|
+
} catch (error) {
|
|
73
|
+
if (error instanceof HashgridAuthenticationError) {
|
|
74
|
+
console.log("Authentication failed");
|
|
75
|
+
} else if (error instanceof HashgridAPIError) {
|
|
76
|
+
console.log(`API error: ${error.message}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## API Reference
|
|
82
|
+
|
|
83
|
+
For detailed API documentation, see the official Hashgrid DNA documentation.
|
|
84
|
+
|
|
85
|
+
## License
|
|
86
|
+
|
|
87
|
+
MIT
|
|
88
|
+
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Main Hashgrid client class. */
|
|
2
|
+
import { Grid } from "./resources";
|
|
3
|
+
export declare class Hashgrid {
|
|
4
|
+
private api_key?;
|
|
5
|
+
private base_url;
|
|
6
|
+
private timeout;
|
|
7
|
+
constructor(api_key?: string, base_url?: string, timeout?: number);
|
|
8
|
+
private _getHeaders;
|
|
9
|
+
_request(method: string, endpoint: string, params?: Record<string, any>, json_data?: any): Promise<any>;
|
|
10
|
+
_handleResponse(response: Response): Promise<any>;
|
|
11
|
+
static connect(api_key?: string, base_url?: string, timeout?: number): Promise<Grid>;
|
|
12
|
+
}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/** Main Hashgrid client class. */
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.Hashgrid = void 0;
|
|
5
|
+
const exceptions_1 = require("./exceptions");
|
|
6
|
+
const resources_1 = require("./resources");
|
|
7
|
+
class Hashgrid {
|
|
8
|
+
constructor(api_key, base_url = "https://dna.hashgrid.ai", timeout = 30000) {
|
|
9
|
+
this.api_key = api_key;
|
|
10
|
+
this.base_url = base_url.replace(/\/$/, "");
|
|
11
|
+
this.timeout = timeout;
|
|
12
|
+
}
|
|
13
|
+
_getHeaders() {
|
|
14
|
+
const headers = {
|
|
15
|
+
"Content-Type": "application/json",
|
|
16
|
+
Accept: "application/json",
|
|
17
|
+
};
|
|
18
|
+
if (this.api_key) {
|
|
19
|
+
headers["Authorization"] = `Bearer ${this.api_key}`;
|
|
20
|
+
}
|
|
21
|
+
return headers;
|
|
22
|
+
}
|
|
23
|
+
async _request(method, endpoint, params, json_data) {
|
|
24
|
+
let url;
|
|
25
|
+
if (endpoint.startsWith("http://") || endpoint.startsWith("https://")) {
|
|
26
|
+
url = endpoint;
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
const base = this.base_url.endsWith("/") ? this.base_url.slice(0, -1) : this.base_url;
|
|
30
|
+
const path = endpoint.startsWith("/") ? endpoint : `/${endpoint}`;
|
|
31
|
+
url = `${base}${path}`;
|
|
32
|
+
}
|
|
33
|
+
if (params) {
|
|
34
|
+
const searchParams = new URLSearchParams();
|
|
35
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
36
|
+
searchParams.append(key, String(value));
|
|
37
|
+
});
|
|
38
|
+
url += `?${searchParams.toString()}`;
|
|
39
|
+
}
|
|
40
|
+
const headers = this._getHeaders();
|
|
41
|
+
const controller = new AbortController();
|
|
42
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
43
|
+
const options = {
|
|
44
|
+
method,
|
|
45
|
+
headers,
|
|
46
|
+
signal: controller.signal,
|
|
47
|
+
};
|
|
48
|
+
if (json_data !== undefined) {
|
|
49
|
+
options.body = JSON.stringify(json_data);
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
const response = await fetch(url, options);
|
|
53
|
+
clearTimeout(timeoutId);
|
|
54
|
+
return await this._handleResponse(response);
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
clearTimeout(timeoutId);
|
|
58
|
+
if (error.name === "AbortError") {
|
|
59
|
+
throw new exceptions_1.HashgridAPIError(`Request timeout after ${this.timeout}ms`);
|
|
60
|
+
}
|
|
61
|
+
throw new exceptions_1.HashgridAPIError(`Request failed: ${error.message}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async _handleResponse(response) {
|
|
65
|
+
try {
|
|
66
|
+
if (!response.ok) {
|
|
67
|
+
if (response.status === 401) {
|
|
68
|
+
throw new exceptions_1.HashgridAuthenticationError("Authentication failed. Check your API key.", response.status, response);
|
|
69
|
+
}
|
|
70
|
+
else if (response.status === 404) {
|
|
71
|
+
throw new exceptions_1.HashgridNotFoundError("Resource not found", response.status, response);
|
|
72
|
+
}
|
|
73
|
+
else if (response.status === 422) {
|
|
74
|
+
const errorData = response.headers.get("content-type")?.includes("application/json")
|
|
75
|
+
? await response.json().catch(() => ({}))
|
|
76
|
+
: {};
|
|
77
|
+
throw new exceptions_1.HashgridValidationError(errorData.message || "Validation error", response.status, response);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
const errorData = response.headers.get("content-type")?.includes("application/json")
|
|
81
|
+
? await response.json().catch(() => ({}))
|
|
82
|
+
: {};
|
|
83
|
+
throw new exceptions_1.HashgridAPIError(errorData.message || `API error: ${response.status}`, response.status, response);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (!response.body) {
|
|
87
|
+
return {};
|
|
88
|
+
}
|
|
89
|
+
const contentType = response.headers.get("content-type");
|
|
90
|
+
if (contentType?.includes("application/json")) {
|
|
91
|
+
return await response.json();
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
return { content: await response.text() };
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
if (error instanceof exceptions_1.HashgridAPIError ||
|
|
99
|
+
error instanceof exceptions_1.HashgridAuthenticationError ||
|
|
100
|
+
error instanceof exceptions_1.HashgridNotFoundError ||
|
|
101
|
+
error instanceof exceptions_1.HashgridValidationError) {
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
104
|
+
throw new exceptions_1.HashgridAPIError(`Response handling failed: ${error}`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
static async connect(api_key, base_url = "https://dna.hashgrid.ai", timeout = 30000) {
|
|
108
|
+
const client = new Hashgrid(api_key, base_url, timeout);
|
|
109
|
+
const data = await client._request("GET", "/api/v1");
|
|
110
|
+
const grid = new resources_1.Grid(data.name, data.tick, client);
|
|
111
|
+
return grid;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
exports.Hashgrid = Hashgrid;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** Custom exceptions for the Hashgrid client. */
|
|
2
|
+
export declare class HashgridError extends Error {
|
|
3
|
+
constructor(message: string);
|
|
4
|
+
}
|
|
5
|
+
export declare class HashgridAPIError extends HashgridError {
|
|
6
|
+
status_code?: number;
|
|
7
|
+
response?: Response;
|
|
8
|
+
constructor(message: string, status_code?: number, response?: Response);
|
|
9
|
+
}
|
|
10
|
+
export declare class HashgridAuthenticationError extends HashgridAPIError {
|
|
11
|
+
constructor(message: string, status_code?: number, response?: Response);
|
|
12
|
+
}
|
|
13
|
+
export declare class HashgridNotFoundError extends HashgridAPIError {
|
|
14
|
+
constructor(message: string, status_code?: number, response?: Response);
|
|
15
|
+
}
|
|
16
|
+
export declare class HashgridValidationError extends HashgridAPIError {
|
|
17
|
+
constructor(message: string, status_code?: number, response?: Response);
|
|
18
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/** Custom exceptions for the Hashgrid client. */
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.HashgridValidationError = exports.HashgridNotFoundError = exports.HashgridAuthenticationError = exports.HashgridAPIError = exports.HashgridError = void 0;
|
|
5
|
+
class HashgridError extends Error {
|
|
6
|
+
constructor(message) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = "HashgridError";
|
|
9
|
+
Object.setPrototypeOf(this, HashgridError.prototype);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
exports.HashgridError = HashgridError;
|
|
13
|
+
class HashgridAPIError extends HashgridError {
|
|
14
|
+
constructor(message, status_code, response) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.name = "HashgridAPIError";
|
|
17
|
+
this.status_code = status_code;
|
|
18
|
+
this.response = response;
|
|
19
|
+
Object.setPrototypeOf(this, HashgridAPIError.prototype);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.HashgridAPIError = HashgridAPIError;
|
|
23
|
+
class HashgridAuthenticationError extends HashgridAPIError {
|
|
24
|
+
constructor(message, status_code, response) {
|
|
25
|
+
super(message, status_code, response);
|
|
26
|
+
this.name = "HashgridAuthenticationError";
|
|
27
|
+
Object.setPrototypeOf(this, HashgridAuthenticationError.prototype);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.HashgridAuthenticationError = HashgridAuthenticationError;
|
|
31
|
+
class HashgridNotFoundError extends HashgridAPIError {
|
|
32
|
+
constructor(message, status_code, response) {
|
|
33
|
+
super(message, status_code, response);
|
|
34
|
+
this.name = "HashgridNotFoundError";
|
|
35
|
+
Object.setPrototypeOf(this, HashgridNotFoundError.prototype);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.HashgridNotFoundError = HashgridNotFoundError;
|
|
39
|
+
class HashgridValidationError extends HashgridAPIError {
|
|
40
|
+
constructor(message, status_code, response) {
|
|
41
|
+
super(message, status_code, response);
|
|
42
|
+
this.name = "HashgridValidationError";
|
|
43
|
+
Object.setPrototypeOf(this, HashgridValidationError.prototype);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
exports.HashgridValidationError = HashgridValidationError;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hashgrid Client - TypeScript/JavaScript SDK
|
|
3
|
+
*/
|
|
4
|
+
export { Hashgrid } from "./client";
|
|
5
|
+
export { HashgridError, HashgridAPIError, HashgridAuthenticationError, HashgridNotFoundError, HashgridValidationError, } from "./exceptions";
|
|
6
|
+
export { Grid, User, Quota, Node, Edge, Message, Status, } from "./resources";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Hashgrid Client - TypeScript/JavaScript SDK
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Status = exports.Message = exports.Edge = exports.Node = exports.Quota = exports.User = exports.Grid = exports.HashgridValidationError = exports.HashgridNotFoundError = exports.HashgridAuthenticationError = exports.HashgridAPIError = exports.HashgridError = exports.Hashgrid = void 0;
|
|
7
|
+
var client_1 = require("./client");
|
|
8
|
+
Object.defineProperty(exports, "Hashgrid", { enumerable: true, get: function () { return client_1.Hashgrid; } });
|
|
9
|
+
var exceptions_1 = require("./exceptions");
|
|
10
|
+
Object.defineProperty(exports, "HashgridError", { enumerable: true, get: function () { return exceptions_1.HashgridError; } });
|
|
11
|
+
Object.defineProperty(exports, "HashgridAPIError", { enumerable: true, get: function () { return exceptions_1.HashgridAPIError; } });
|
|
12
|
+
Object.defineProperty(exports, "HashgridAuthenticationError", { enumerable: true, get: function () { return exceptions_1.HashgridAuthenticationError; } });
|
|
13
|
+
Object.defineProperty(exports, "HashgridNotFoundError", { enumerable: true, get: function () { return exceptions_1.HashgridNotFoundError; } });
|
|
14
|
+
Object.defineProperty(exports, "HashgridValidationError", { enumerable: true, get: function () { return exceptions_1.HashgridValidationError; } });
|
|
15
|
+
var resources_1 = require("./resources");
|
|
16
|
+
Object.defineProperty(exports, "Grid", { enumerable: true, get: function () { return resources_1.Grid; } });
|
|
17
|
+
Object.defineProperty(exports, "User", { enumerable: true, get: function () { return resources_1.User; } });
|
|
18
|
+
Object.defineProperty(exports, "Quota", { enumerable: true, get: function () { return resources_1.Quota; } });
|
|
19
|
+
Object.defineProperty(exports, "Node", { enumerable: true, get: function () { return resources_1.Node; } });
|
|
20
|
+
Object.defineProperty(exports, "Edge", { enumerable: true, get: function () { return resources_1.Edge; } });
|
|
21
|
+
Object.defineProperty(exports, "Message", { enumerable: true, get: function () { return resources_1.Message; } });
|
|
22
|
+
Object.defineProperty(exports, "Status", { enumerable: true, get: function () { return resources_1.Status; } });
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/** Hashgrid API resources. */
|
|
2
|
+
import { Hashgrid } from "./client";
|
|
3
|
+
export declare class User {
|
|
4
|
+
user_id: string;
|
|
5
|
+
name: string;
|
|
6
|
+
is_superuser: boolean;
|
|
7
|
+
quota_id: string;
|
|
8
|
+
constructor(user_id: string, name: string, is_superuser: boolean, quota_id: string);
|
|
9
|
+
}
|
|
10
|
+
export declare class Quota {
|
|
11
|
+
quota_id: string;
|
|
12
|
+
name: string;
|
|
13
|
+
capacity: number;
|
|
14
|
+
constructor(quota_id: string, name: string, capacity: number);
|
|
15
|
+
}
|
|
16
|
+
export declare class Edge {
|
|
17
|
+
node_id: string;
|
|
18
|
+
peer_id: string;
|
|
19
|
+
recv_message: string;
|
|
20
|
+
send_message: string | null;
|
|
21
|
+
score: number | null;
|
|
22
|
+
round: number;
|
|
23
|
+
constructor(node_id: string, peer_id: string, recv_message: string, send_message: string | null, score: number | null, round: number);
|
|
24
|
+
}
|
|
25
|
+
export declare class Message {
|
|
26
|
+
peer_id: string;
|
|
27
|
+
message: string;
|
|
28
|
+
round: number;
|
|
29
|
+
score: number | null;
|
|
30
|
+
constructor(peer_id: string, message: string, round: number, score?: number | null);
|
|
31
|
+
}
|
|
32
|
+
export declare class Status {
|
|
33
|
+
peer_id: string;
|
|
34
|
+
success: boolean;
|
|
35
|
+
constructor(peer_id: string, success: boolean);
|
|
36
|
+
}
|
|
37
|
+
export declare class Grid {
|
|
38
|
+
name: string;
|
|
39
|
+
tick: number;
|
|
40
|
+
private _client;
|
|
41
|
+
constructor(name: string, tick: number, client: Hashgrid);
|
|
42
|
+
listen(poll_interval?: number): AsyncGenerator<number>;
|
|
43
|
+
nodes(): AsyncGenerator<Node>;
|
|
44
|
+
create_node(name: string, message?: string, capacity?: number): Promise<Node>;
|
|
45
|
+
}
|
|
46
|
+
export declare class Node {
|
|
47
|
+
node_id: string;
|
|
48
|
+
owner_id: string;
|
|
49
|
+
name: string;
|
|
50
|
+
message: string;
|
|
51
|
+
capacity: number;
|
|
52
|
+
private _client;
|
|
53
|
+
constructor(node_id: string, owner_id: string, name: string, message: string, capacity: number, client: Hashgrid);
|
|
54
|
+
recv(): Promise<Message[]>;
|
|
55
|
+
send(replies: Message[]): Promise<Status[]>;
|
|
56
|
+
update(name?: string, message?: string, capacity?: number): Promise<Node>;
|
|
57
|
+
delete(): Promise<void>;
|
|
58
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/** Hashgrid API resources. */
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.Node = exports.Grid = exports.Status = exports.Message = exports.Edge = exports.Quota = exports.User = void 0;
|
|
5
|
+
class User {
|
|
6
|
+
constructor(user_id, name, is_superuser, quota_id) {
|
|
7
|
+
this.user_id = user_id;
|
|
8
|
+
this.name = name;
|
|
9
|
+
this.is_superuser = is_superuser;
|
|
10
|
+
this.quota_id = quota_id;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
exports.User = User;
|
|
14
|
+
class Quota {
|
|
15
|
+
constructor(quota_id, name, capacity) {
|
|
16
|
+
this.quota_id = quota_id;
|
|
17
|
+
this.name = name;
|
|
18
|
+
this.capacity = capacity;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
exports.Quota = Quota;
|
|
22
|
+
class Edge {
|
|
23
|
+
constructor(node_id, peer_id, recv_message, send_message, score, round) {
|
|
24
|
+
this.node_id = node_id;
|
|
25
|
+
this.peer_id = peer_id;
|
|
26
|
+
this.recv_message = recv_message;
|
|
27
|
+
this.send_message = send_message;
|
|
28
|
+
this.score = score;
|
|
29
|
+
this.round = round;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
exports.Edge = Edge;
|
|
33
|
+
class Message {
|
|
34
|
+
constructor(peer_id, message, round, score = null) {
|
|
35
|
+
this.peer_id = peer_id;
|
|
36
|
+
this.message = message;
|
|
37
|
+
this.round = round;
|
|
38
|
+
this.score = score;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
exports.Message = Message;
|
|
42
|
+
class Status {
|
|
43
|
+
constructor(peer_id, success) {
|
|
44
|
+
this.peer_id = peer_id;
|
|
45
|
+
this.success = success;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
exports.Status = Status;
|
|
49
|
+
class Grid {
|
|
50
|
+
constructor(name, tick, client) {
|
|
51
|
+
this.name = name;
|
|
52
|
+
this.tick = tick;
|
|
53
|
+
this._client = client;
|
|
54
|
+
}
|
|
55
|
+
async *listen(poll_interval = 30000) {
|
|
56
|
+
let last_tick = -1;
|
|
57
|
+
while (true) {
|
|
58
|
+
try {
|
|
59
|
+
const data = await this._client._request("GET", "/api/v1");
|
|
60
|
+
this.name = data.name;
|
|
61
|
+
this.tick = data.tick;
|
|
62
|
+
const current_tick = this.tick;
|
|
63
|
+
if (current_tick !== last_tick) {
|
|
64
|
+
yield current_tick;
|
|
65
|
+
last_tick = current_tick;
|
|
66
|
+
}
|
|
67
|
+
await new Promise((resolve) => setTimeout(resolve, poll_interval));
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
console.warn(`Error while listening for ticks: ${error}`);
|
|
71
|
+
await new Promise((resolve) => setTimeout(resolve, poll_interval * 2));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
async *nodes() {
|
|
76
|
+
const data = await this._client._request("GET", "/api/v1/node");
|
|
77
|
+
for (const item of data) {
|
|
78
|
+
yield new Node(item.node_id, item.owner_id, item.name, item.message, item.capacity, this._client);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
async create_node(name, message = "", capacity = 100) {
|
|
82
|
+
const json_data = { name, message, capacity };
|
|
83
|
+
const data = await this._client._request("POST", "/api/v1/node", undefined, json_data);
|
|
84
|
+
return new Node(data.node_id, data.owner_id, data.name, data.message, data.capacity, this._client);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
exports.Grid = Grid;
|
|
88
|
+
class Node {
|
|
89
|
+
constructor(node_id, owner_id, name, message, capacity, client) {
|
|
90
|
+
this.node_id = node_id;
|
|
91
|
+
this.owner_id = owner_id;
|
|
92
|
+
this.name = name;
|
|
93
|
+
this.message = message;
|
|
94
|
+
this.capacity = capacity;
|
|
95
|
+
this._client = client;
|
|
96
|
+
}
|
|
97
|
+
async recv() {
|
|
98
|
+
const data = await this._client._request("GET", `/api/v1/node/${this.node_id}/recv`);
|
|
99
|
+
return data.map((item) => new Message(item.peer_id, item.message, item.round, item.score ?? null));
|
|
100
|
+
}
|
|
101
|
+
async send(replies) {
|
|
102
|
+
const json_data = replies.map((msg) => {
|
|
103
|
+
const obj = {
|
|
104
|
+
peer_id: msg.peer_id,
|
|
105
|
+
message: msg.message,
|
|
106
|
+
round: msg.round,
|
|
107
|
+
};
|
|
108
|
+
if (msg.score !== null) {
|
|
109
|
+
obj.score = msg.score;
|
|
110
|
+
}
|
|
111
|
+
return obj;
|
|
112
|
+
});
|
|
113
|
+
const data = await this._client._request("POST", `/api/v1/node/${this.node_id}/send`, undefined, json_data);
|
|
114
|
+
return data.map((item) => new Status(item.peer_id, item.success));
|
|
115
|
+
}
|
|
116
|
+
async update(name, message, capacity) {
|
|
117
|
+
const json_data = {};
|
|
118
|
+
if (name !== undefined)
|
|
119
|
+
json_data.name = name;
|
|
120
|
+
if (message !== undefined)
|
|
121
|
+
json_data.message = message;
|
|
122
|
+
if (capacity !== undefined)
|
|
123
|
+
json_data.capacity = capacity;
|
|
124
|
+
if (Object.keys(json_data).length === 0) {
|
|
125
|
+
return this;
|
|
126
|
+
}
|
|
127
|
+
const data = await this._client._request("PUT", `/api/v1/node/${this.node_id}`, undefined, json_data);
|
|
128
|
+
// Update local attributes
|
|
129
|
+
if (data.name !== undefined)
|
|
130
|
+
this.name = data.name;
|
|
131
|
+
if (data.message !== undefined)
|
|
132
|
+
this.message = data.message;
|
|
133
|
+
if (data.capacity !== undefined)
|
|
134
|
+
this.capacity = data.capacity;
|
|
135
|
+
return this;
|
|
136
|
+
}
|
|
137
|
+
async delete() {
|
|
138
|
+
await this._client._request("DELETE", `/api/v1/node/${this.node_id}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
exports.Node = Node;
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hashgrid/sdk",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Hashgrid TypeScript/JavaScript SDK",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"browser": {
|
|
8
|
+
"./dist/index.js": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.js",
|
|
14
|
+
"types": "./dist/index.d.ts"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc",
|
|
19
|
+
"prepublishOnly": "npm run build"
|
|
20
|
+
},
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/hashgrid-labs/sdk.git"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"hashgrid",
|
|
27
|
+
"client",
|
|
28
|
+
"sdk"
|
|
29
|
+
],
|
|
30
|
+
"author": "Hashgrid",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"bugs": {
|
|
33
|
+
"url": "https://github.com/hashgrid-labs/sdk/issues"
|
|
34
|
+
},
|
|
35
|
+
"homepage": "https://github.com/hashgrid-labs/sdk#readme",
|
|
36
|
+
"dependencies": {},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@types/node": "^20.0.0",
|
|
39
|
+
"typescript": "^5.0.0"
|
|
40
|
+
},
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=18.0.0"
|
|
43
|
+
}
|
|
44
|
+
}
|
package/src/client.ts
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/** Main Hashgrid client class. */
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
HashgridAPIError,
|
|
5
|
+
HashgridAuthenticationError,
|
|
6
|
+
HashgridNotFoundError,
|
|
7
|
+
HashgridValidationError,
|
|
8
|
+
} from "./exceptions";
|
|
9
|
+
import { Grid } from "./resources";
|
|
10
|
+
|
|
11
|
+
export class Hashgrid {
|
|
12
|
+
private api_key?: string;
|
|
13
|
+
private base_url: string;
|
|
14
|
+
private timeout: number;
|
|
15
|
+
|
|
16
|
+
constructor(
|
|
17
|
+
api_key?: string,
|
|
18
|
+
base_url: string = "https://dna.hashgrid.ai",
|
|
19
|
+
timeout: number = 30000
|
|
20
|
+
) {
|
|
21
|
+
this.api_key = api_key;
|
|
22
|
+
this.base_url = base_url.replace(/\/$/, "");
|
|
23
|
+
this.timeout = timeout;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
private _getHeaders(): Record<string, string> {
|
|
27
|
+
const headers: Record<string, string> = {
|
|
28
|
+
"Content-Type": "application/json",
|
|
29
|
+
Accept: "application/json",
|
|
30
|
+
};
|
|
31
|
+
if (this.api_key) {
|
|
32
|
+
headers["Authorization"] = `Bearer ${this.api_key}`;
|
|
33
|
+
}
|
|
34
|
+
return headers;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async _request(
|
|
38
|
+
method: string,
|
|
39
|
+
endpoint: string,
|
|
40
|
+
params?: Record<string, any>,
|
|
41
|
+
json_data?: any
|
|
42
|
+
): Promise<any> {
|
|
43
|
+
let url: string;
|
|
44
|
+
if (endpoint.startsWith("http://") || endpoint.startsWith("https://")) {
|
|
45
|
+
url = endpoint;
|
|
46
|
+
} else {
|
|
47
|
+
const base = this.base_url.endsWith("/") ? this.base_url.slice(0, -1) : this.base_url;
|
|
48
|
+
const path = endpoint.startsWith("/") ? endpoint : `/${endpoint}`;
|
|
49
|
+
url = `${base}${path}`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (params) {
|
|
53
|
+
const searchParams = new URLSearchParams();
|
|
54
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
55
|
+
searchParams.append(key, String(value));
|
|
56
|
+
});
|
|
57
|
+
url += `?${searchParams.toString()}`;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const headers = this._getHeaders();
|
|
61
|
+
const controller = new AbortController();
|
|
62
|
+
const timeoutId: ReturnType<typeof setTimeout> = setTimeout(() => controller.abort(), this.timeout);
|
|
63
|
+
|
|
64
|
+
const options: {
|
|
65
|
+
method: string;
|
|
66
|
+
headers: Record<string, string>;
|
|
67
|
+
signal: AbortSignal;
|
|
68
|
+
body?: string;
|
|
69
|
+
} = {
|
|
70
|
+
method,
|
|
71
|
+
headers,
|
|
72
|
+
signal: controller.signal,
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
if (json_data !== undefined) {
|
|
76
|
+
options.body = JSON.stringify(json_data);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
const response = await fetch(url, options);
|
|
81
|
+
clearTimeout(timeoutId);
|
|
82
|
+
return await this._handleResponse(response);
|
|
83
|
+
} catch (error: any) {
|
|
84
|
+
clearTimeout(timeoutId);
|
|
85
|
+
if (error.name === "AbortError") {
|
|
86
|
+
throw new HashgridAPIError(`Request timeout after ${this.timeout}ms`);
|
|
87
|
+
}
|
|
88
|
+
throw new HashgridAPIError(`Request failed: ${error.message}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async _handleResponse(response: Response): Promise<any> {
|
|
93
|
+
try {
|
|
94
|
+
if (!response.ok) {
|
|
95
|
+
if (response.status === 401) {
|
|
96
|
+
throw new HashgridAuthenticationError(
|
|
97
|
+
"Authentication failed. Check your API key.",
|
|
98
|
+
response.status,
|
|
99
|
+
response
|
|
100
|
+
);
|
|
101
|
+
} else if (response.status === 404) {
|
|
102
|
+
throw new HashgridNotFoundError(
|
|
103
|
+
"Resource not found",
|
|
104
|
+
response.status,
|
|
105
|
+
response
|
|
106
|
+
);
|
|
107
|
+
} else if (response.status === 422) {
|
|
108
|
+
const errorData = response.headers.get("content-type")?.includes("application/json")
|
|
109
|
+
? await response.json().catch(() => ({}))
|
|
110
|
+
: {};
|
|
111
|
+
throw new HashgridValidationError(
|
|
112
|
+
errorData.message || "Validation error",
|
|
113
|
+
response.status,
|
|
114
|
+
response
|
|
115
|
+
);
|
|
116
|
+
} else {
|
|
117
|
+
const errorData = response.headers.get("content-type")?.includes("application/json")
|
|
118
|
+
? await response.json().catch(() => ({}))
|
|
119
|
+
: {};
|
|
120
|
+
throw new HashgridAPIError(
|
|
121
|
+
errorData.message || `API error: ${response.status}`,
|
|
122
|
+
response.status,
|
|
123
|
+
response
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (!response.body) {
|
|
129
|
+
return {};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const contentType = response.headers.get("content-type");
|
|
133
|
+
if (contentType?.includes("application/json")) {
|
|
134
|
+
return await response.json();
|
|
135
|
+
} else {
|
|
136
|
+
return { content: await response.text() };
|
|
137
|
+
}
|
|
138
|
+
} catch (error) {
|
|
139
|
+
if (
|
|
140
|
+
error instanceof HashgridAPIError ||
|
|
141
|
+
error instanceof HashgridAuthenticationError ||
|
|
142
|
+
error instanceof HashgridNotFoundError ||
|
|
143
|
+
error instanceof HashgridValidationError
|
|
144
|
+
) {
|
|
145
|
+
throw error;
|
|
146
|
+
}
|
|
147
|
+
throw new HashgridAPIError(`Response handling failed: ${error}`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
static async connect(
|
|
152
|
+
api_key?: string,
|
|
153
|
+
base_url: string = "https://dna.hashgrid.ai",
|
|
154
|
+
timeout: number = 30000
|
|
155
|
+
): Promise<Grid> {
|
|
156
|
+
const client = new Hashgrid(api_key, base_url, timeout);
|
|
157
|
+
const data = await client._request("GET", "/api/v1");
|
|
158
|
+
const grid = new Grid(data.name, data.tick, client);
|
|
159
|
+
return grid;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/** Custom exceptions for the Hashgrid client. */
|
|
2
|
+
|
|
3
|
+
export class HashgridError extends Error {
|
|
4
|
+
constructor(message: string) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = "HashgridError";
|
|
7
|
+
Object.setPrototypeOf(this, HashgridError.prototype);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export class HashgridAPIError extends HashgridError {
|
|
12
|
+
status_code?: number;
|
|
13
|
+
response?: Response;
|
|
14
|
+
|
|
15
|
+
constructor(message: string, status_code?: number, response?: Response) {
|
|
16
|
+
super(message);
|
|
17
|
+
this.name = "HashgridAPIError";
|
|
18
|
+
this.status_code = status_code;
|
|
19
|
+
this.response = response;
|
|
20
|
+
Object.setPrototypeOf(this, HashgridAPIError.prototype);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export class HashgridAuthenticationError extends HashgridAPIError {
|
|
25
|
+
constructor(message: string, status_code?: number, response?: Response) {
|
|
26
|
+
super(message, status_code, response);
|
|
27
|
+
this.name = "HashgridAuthenticationError";
|
|
28
|
+
Object.setPrototypeOf(this, HashgridAuthenticationError.prototype);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export class HashgridNotFoundError extends HashgridAPIError {
|
|
33
|
+
constructor(message: string, status_code?: number, response?: Response) {
|
|
34
|
+
super(message, status_code, response);
|
|
35
|
+
this.name = "HashgridNotFoundError";
|
|
36
|
+
Object.setPrototypeOf(this, HashgridNotFoundError.prototype);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export class HashgridValidationError extends HashgridAPIError {
|
|
41
|
+
constructor(message: string, status_code?: number, response?: Response) {
|
|
42
|
+
super(message, status_code, response);
|
|
43
|
+
this.name = "HashgridValidationError";
|
|
44
|
+
Object.setPrototypeOf(this, HashgridValidationError.prototype);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hashgrid Client - TypeScript/JavaScript SDK
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export { Hashgrid } from "./client";
|
|
6
|
+
export {
|
|
7
|
+
HashgridError,
|
|
8
|
+
HashgridAPIError,
|
|
9
|
+
HashgridAuthenticationError,
|
|
10
|
+
HashgridNotFoundError,
|
|
11
|
+
HashgridValidationError,
|
|
12
|
+
} from "./exceptions";
|
|
13
|
+
export {
|
|
14
|
+
Grid,
|
|
15
|
+
User,
|
|
16
|
+
Quota,
|
|
17
|
+
Node,
|
|
18
|
+
Edge,
|
|
19
|
+
Message,
|
|
20
|
+
Status,
|
|
21
|
+
} from "./resources";
|
|
22
|
+
|
package/src/resources.ts
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/** Hashgrid API resources. */
|
|
2
|
+
|
|
3
|
+
import { Hashgrid } from "./client";
|
|
4
|
+
|
|
5
|
+
export class User {
|
|
6
|
+
user_id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
is_superuser: boolean;
|
|
9
|
+
quota_id: string;
|
|
10
|
+
|
|
11
|
+
constructor(
|
|
12
|
+
user_id: string,
|
|
13
|
+
name: string,
|
|
14
|
+
is_superuser: boolean,
|
|
15
|
+
quota_id: string
|
|
16
|
+
) {
|
|
17
|
+
this.user_id = user_id;
|
|
18
|
+
this.name = name;
|
|
19
|
+
this.is_superuser = is_superuser;
|
|
20
|
+
this.quota_id = quota_id;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export class Quota {
|
|
25
|
+
quota_id: string;
|
|
26
|
+
name: string;
|
|
27
|
+
capacity: number;
|
|
28
|
+
|
|
29
|
+
constructor(quota_id: string, name: string, capacity: number) {
|
|
30
|
+
this.quota_id = quota_id;
|
|
31
|
+
this.name = name;
|
|
32
|
+
this.capacity = capacity;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export class Edge {
|
|
37
|
+
node_id: string;
|
|
38
|
+
peer_id: string;
|
|
39
|
+
recv_message: string;
|
|
40
|
+
send_message: string | null;
|
|
41
|
+
score: number | null;
|
|
42
|
+
round: number;
|
|
43
|
+
|
|
44
|
+
constructor(
|
|
45
|
+
node_id: string,
|
|
46
|
+
peer_id: string,
|
|
47
|
+
recv_message: string,
|
|
48
|
+
send_message: string | null,
|
|
49
|
+
score: number | null,
|
|
50
|
+
round: number
|
|
51
|
+
) {
|
|
52
|
+
this.node_id = node_id;
|
|
53
|
+
this.peer_id = peer_id;
|
|
54
|
+
this.recv_message = recv_message;
|
|
55
|
+
this.send_message = send_message;
|
|
56
|
+
this.score = score;
|
|
57
|
+
this.round = round;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export class Message {
|
|
62
|
+
peer_id: string;
|
|
63
|
+
message: string;
|
|
64
|
+
round: number;
|
|
65
|
+
score: number | null;
|
|
66
|
+
|
|
67
|
+
constructor(
|
|
68
|
+
peer_id: string,
|
|
69
|
+
message: string,
|
|
70
|
+
round: number,
|
|
71
|
+
score: number | null = null
|
|
72
|
+
) {
|
|
73
|
+
this.peer_id = peer_id;
|
|
74
|
+
this.message = message;
|
|
75
|
+
this.round = round;
|
|
76
|
+
this.score = score;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export class Status {
|
|
81
|
+
peer_id: string;
|
|
82
|
+
success: boolean;
|
|
83
|
+
|
|
84
|
+
constructor(peer_id: string, success: boolean) {
|
|
85
|
+
this.peer_id = peer_id;
|
|
86
|
+
this.success = success;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export class Grid {
|
|
91
|
+
name: string;
|
|
92
|
+
tick: number;
|
|
93
|
+
private _client: Hashgrid;
|
|
94
|
+
|
|
95
|
+
constructor(name: string, tick: number, client: Hashgrid) {
|
|
96
|
+
this.name = name;
|
|
97
|
+
this.tick = tick;
|
|
98
|
+
this._client = client;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async *listen(poll_interval: number = 30000): AsyncGenerator<number> {
|
|
102
|
+
let last_tick = -1;
|
|
103
|
+
while (true) {
|
|
104
|
+
try {
|
|
105
|
+
const data = await this._client._request("GET", "/api/v1");
|
|
106
|
+
this.name = data.name;
|
|
107
|
+
this.tick = data.tick;
|
|
108
|
+
const current_tick = this.tick;
|
|
109
|
+
|
|
110
|
+
if (current_tick !== last_tick) {
|
|
111
|
+
yield current_tick;
|
|
112
|
+
last_tick = current_tick;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
await new Promise((resolve) => setTimeout(resolve, poll_interval));
|
|
116
|
+
} catch (error) {
|
|
117
|
+
console.warn(`Error while listening for ticks: ${error}`);
|
|
118
|
+
await new Promise((resolve) => setTimeout(resolve, poll_interval * 2));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async *nodes(): AsyncGenerator<Node> {
|
|
124
|
+
const data = await this._client._request("GET", "/api/v1/node");
|
|
125
|
+
for (const item of data) {
|
|
126
|
+
yield new Node(
|
|
127
|
+
item.node_id,
|
|
128
|
+
item.owner_id,
|
|
129
|
+
item.name,
|
|
130
|
+
item.message,
|
|
131
|
+
item.capacity,
|
|
132
|
+
this._client
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
async create_node(
|
|
138
|
+
name: string,
|
|
139
|
+
message: string = "",
|
|
140
|
+
capacity: number = 100
|
|
141
|
+
): Promise<Node> {
|
|
142
|
+
const json_data = { name, message, capacity };
|
|
143
|
+
const data = await this._client._request("POST", "/api/v1/node", undefined, json_data);
|
|
144
|
+
return new Node(
|
|
145
|
+
data.node_id,
|
|
146
|
+
data.owner_id,
|
|
147
|
+
data.name,
|
|
148
|
+
data.message,
|
|
149
|
+
data.capacity,
|
|
150
|
+
this._client
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export class Node {
|
|
156
|
+
node_id: string;
|
|
157
|
+
owner_id: string;
|
|
158
|
+
name: string;
|
|
159
|
+
message: string;
|
|
160
|
+
capacity: number;
|
|
161
|
+
private _client: Hashgrid;
|
|
162
|
+
|
|
163
|
+
constructor(
|
|
164
|
+
node_id: string,
|
|
165
|
+
owner_id: string,
|
|
166
|
+
name: string,
|
|
167
|
+
message: string,
|
|
168
|
+
capacity: number,
|
|
169
|
+
client: Hashgrid
|
|
170
|
+
) {
|
|
171
|
+
this.node_id = node_id;
|
|
172
|
+
this.owner_id = owner_id;
|
|
173
|
+
this.name = name;
|
|
174
|
+
this.message = message;
|
|
175
|
+
this.capacity = capacity;
|
|
176
|
+
this._client = client;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
async recv(): Promise<Message[]> {
|
|
180
|
+
const data = await this._client._request(
|
|
181
|
+
"GET",
|
|
182
|
+
`/api/v1/node/${this.node_id}/recv`
|
|
183
|
+
);
|
|
184
|
+
return data.map(
|
|
185
|
+
(item: any) =>
|
|
186
|
+
new Message(item.peer_id, item.message, item.round, item.score ?? null)
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
async send(replies: Message[]): Promise<Status[]> {
|
|
191
|
+
const json_data = replies.map((msg) => {
|
|
192
|
+
const obj: any = {
|
|
193
|
+
peer_id: msg.peer_id,
|
|
194
|
+
message: msg.message,
|
|
195
|
+
round: msg.round,
|
|
196
|
+
};
|
|
197
|
+
if (msg.score !== null) {
|
|
198
|
+
obj.score = msg.score;
|
|
199
|
+
}
|
|
200
|
+
return obj;
|
|
201
|
+
});
|
|
202
|
+
const data = await this._client._request(
|
|
203
|
+
"POST",
|
|
204
|
+
`/api/v1/node/${this.node_id}/send`,
|
|
205
|
+
undefined,
|
|
206
|
+
json_data
|
|
207
|
+
);
|
|
208
|
+
return data.map((item: any) => new Status(item.peer_id, item.success));
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
async update(
|
|
212
|
+
name?: string,
|
|
213
|
+
message?: string,
|
|
214
|
+
capacity?: number
|
|
215
|
+
): Promise<Node> {
|
|
216
|
+
const json_data: any = {};
|
|
217
|
+
if (name !== undefined) json_data.name = name;
|
|
218
|
+
if (message !== undefined) json_data.message = message;
|
|
219
|
+
if (capacity !== undefined) json_data.capacity = capacity;
|
|
220
|
+
|
|
221
|
+
if (Object.keys(json_data).length === 0) {
|
|
222
|
+
return this;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const data = await this._client._request(
|
|
226
|
+
"PUT",
|
|
227
|
+
`/api/v1/node/${this.node_id}`,
|
|
228
|
+
undefined,
|
|
229
|
+
json_data
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
// Update local attributes
|
|
233
|
+
if (data.name !== undefined) this.name = data.name;
|
|
234
|
+
if (data.message !== undefined) this.message = data.message;
|
|
235
|
+
if (data.capacity !== undefined) this.capacity = data.capacity;
|
|
236
|
+
|
|
237
|
+
return this;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
async delete(): Promise<void> {
|
|
241
|
+
await this._client._request("DELETE", `/api/v1/node/${this.node_id}`);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"lib": [
|
|
6
|
+
"ES2020",
|
|
7
|
+
"DOM"
|
|
8
|
+
],
|
|
9
|
+
"declaration": true,
|
|
10
|
+
"outDir": "./dist",
|
|
11
|
+
"rootDir": "./src",
|
|
12
|
+
"strict": true,
|
|
13
|
+
"esModuleInterop": true,
|
|
14
|
+
"skipLibCheck": true,
|
|
15
|
+
"forceConsistentCasingInFileNames": true,
|
|
16
|
+
"resolveJsonModule": true,
|
|
17
|
+
"moduleResolution": "node"
|
|
18
|
+
},
|
|
19
|
+
"include": [
|
|
20
|
+
"src/**/*"
|
|
21
|
+
],
|
|
22
|
+
"exclude": [
|
|
23
|
+
"node_modules",
|
|
24
|
+
"dist"
|
|
25
|
+
]
|
|
26
|
+
}
|