chain-db-ts 0.0.2 → 1.0.0-rc.1

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.
@@ -1,19 +1,86 @@
1
1
  import { ChainDB } from './chain-db';
2
+ import { Criteria, CriteriaAdvanced } from './types';
2
3
  declare class Table<Model> {
3
4
  table: Model;
4
- private contract_id;
5
+ private name;
5
6
  private db;
6
- constructor(table: Model, contract_id: string, db: ChainDB);
7
+ constructor(name: string, db: ChainDB);
7
8
  /**
8
- * Persist table data on chain
9
+ * Persist table data changes
9
10
  */
10
11
  persist(): Promise<void>;
12
+ /**
13
+ * Update data of the last table's item (or create a new item if there is none).
14
+ * This ensures that no new item is created.
15
+ */
16
+ update(): Promise<void>;
11
17
  /**
12
18
  * Get the history of changes. A list of transactions from the most recent to the most old
13
19
  * in a range of depth
14
- * @param depth
20
+ * @param limit
21
+ */
22
+ getHistory(limit: number): Promise<Model[]>;
23
+ /**
24
+ * Refetch the table data
25
+ */
26
+ refetch(): Promise<void>;
27
+ /**
28
+ * Check if the table is empty
29
+ */
30
+ isEmpty(): boolean;
31
+ /**
32
+ * Get the table's name
33
+ */
34
+ getName(): string;
35
+ /**
36
+ * Find items in the table using basic criteria with exact matches
37
+ * @param criteria Object with fields and values to match exactly, e.g.: {age: 44, name: "john"}
38
+ * @param limit Maximum number of items to return (default: 1000)
39
+ * @param reverse If true, returns items in reverse order (default: true)
40
+ * @returns Array of found items matching the criteria
41
+ * @example
42
+ * // Find items where age is 44
43
+ * table.findWhere({
44
+ * age: 44,
45
+ * })
46
+ *
47
+ * // Find items with multiple criteria
48
+ * table.findWhere({
49
+ * age: 44,
50
+ * name: "john",
51
+ * active: true,
52
+ * score: 100
53
+ * })
54
+ */
55
+ findWhere(criteria: Criteria<Model>, limit?: number, reverse?: boolean): Promise<Model[]>;
56
+ /**
57
+ * Find items in the table using advanced criteria with operators
58
+ * @param criteria Array of criteria to filter items. Each criteria contains:
59
+ * - field: The field name to filter
60
+ * - operator: The operator to use in comparison. Available operators:
61
+ * - Eq (==) Equal
62
+ * - Ne (!=) Not Equal
63
+ * - Gt (>) Greater Than
64
+ * - Ge (>=) Greater Than or Equal
65
+ * - Lt (<) Less Than
66
+ * - Le (<=) Less Than or Equal
67
+ * - Contains: Check if field contains value (for strings and arrays)
68
+ * - StartsWith: Check if field starts with value (for strings)
69
+ * - EndsWith: Check if field ends with value (for strings)
70
+ * - value: The value to compare against
71
+ * @param limit Maximum number of items to return (default: 1000)
72
+ * @param reverse If true, returns items in reverse order (default: true)
73
+ * @returns Array of found items matching the criteria
74
+ * @example
75
+ * // Find items where greeting contains "arg"
76
+ * table.findWhereAdvanced([
77
+ * {
78
+ * field: "greeting",
79
+ * operator: Operators.Contains,
80
+ * value: "hello"
81
+ * }
82
+ * ])
15
83
  */
16
- getHistory(depth: number): Promise<Model[]>;
84
+ findWhereAdvanced(criteria: CriteriaAdvanced<Model>[], limit?: number, reverse?: boolean): Promise<Model[]>;
17
85
  }
18
- export declare const get: <Model>(db: ChainDB, table_name: string, model: Model) => Promise<Table<Model>>;
19
- export {};
86
+ export default Table;
package/features/table.js CHANGED
@@ -35,43 +35,73 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
35
35
  }
36
36
  };
37
37
  import axios from 'axios';
38
- import { CONTRACT_PAYLOAD, CONTRACT_TRANSACTION, CONTRACT_TRANSACTIONS_PAYLOAD } from './constants';
39
- import { TransactionType } from './types';
38
+ import { FIND_WHERE_ADVANCED, FIND_WHERE_BASIC, GET_HISTORY, GET_TABLE, PERSIST_NEW_DATA, UPDATE_LAST_ITEM, } from './constants';
40
39
  import { post } from './utils';
41
40
  var Table = /** @class */ (function () {
42
- function Table(table, contract_id, db) {
43
- this.contract_id = '';
44
- this.table = table;
45
- this.contract_id = contract_id;
41
+ function Table(name, db) {
42
+ this.name = '';
43
+ this.table = {};
44
+ this.name = name;
46
45
  this.db = db;
47
46
  }
48
47
  /**
49
- * Persist table data on chain
48
+ * Persist table data changes
50
49
  */
51
50
  Table.prototype.persist = function () {
52
51
  return __awaiter(this, void 0, void 0, function () {
53
- var url, contract_data, body, _a;
54
- return __generator(this, function (_b) {
55
- switch (_b.label) {
52
+ var url, body, response, e_1;
53
+ return __generator(this, function (_a) {
54
+ switch (_a.label) {
56
55
  case 0:
57
- url = "".concat(this.db.api).concat(CONTRACT_TRANSACTION);
58
- contract_data = JSON.stringify(this.table);
56
+ url = "".concat(this.db.server).concat(PERSIST_NEW_DATA(this.name));
59
57
  body = {
60
- tx_type: TransactionType.CONTRACT,
61
- contract_id: this.contract_id,
62
- db_access_key: this.db.access_key,
63
- data: contract_data
58
+ data: this.table
64
59
  };
65
- _b.label = 1;
60
+ _a.label = 1;
66
61
  case 1:
67
- _b.trys.push([1, 3, , 4]);
68
- return [4 /*yield*/, post(url, body)];
62
+ _a.trys.push([1, 3, , 4]);
63
+ return [4 /*yield*/, post(url, body, this.db.auth)];
69
64
  case 2:
70
- _b.sent();
65
+ response = _a.sent();
66
+ if (!response.data.success) {
67
+ throw new Error(response.data.message);
68
+ }
69
+ return [3 /*break*/, 4];
70
+ case 3:
71
+ e_1 = _a.sent();
72
+ throw new Error("Something went wrong with persist operation: ".concat(e_1.message || String(e_1)));
73
+ case 4: return [2 /*return*/];
74
+ }
75
+ });
76
+ });
77
+ };
78
+ /**
79
+ * Update data of the last table's item (or create a new item if there is none).
80
+ * This ensures that no new item is created.
81
+ */
82
+ Table.prototype.update = function () {
83
+ return __awaiter(this, void 0, void 0, function () {
84
+ var url, body, response, e_2;
85
+ return __generator(this, function (_a) {
86
+ switch (_a.label) {
87
+ case 0:
88
+ url = "".concat(this.db.server).concat(UPDATE_LAST_ITEM(this.name));
89
+ body = {
90
+ data: this.table
91
+ };
92
+ _a.label = 1;
93
+ case 1:
94
+ _a.trys.push([1, 3, , 4]);
95
+ return [4 /*yield*/, post(url, body, this.db.auth)];
96
+ case 2:
97
+ response = _a.sent();
98
+ if (!response.data.success) {
99
+ throw new Error(response.data.message);
100
+ }
71
101
  return [3 /*break*/, 4];
72
102
  case 3:
73
- _a = _b.sent();
74
- throw new Error('Something went wrong!');
103
+ e_2 = _a.sent();
104
+ throw new Error("Something went wrong with update operation: ".concat(e_2.message || String(e_2)));
75
105
  case 4: return [2 /*return*/];
76
106
  }
77
107
  });
@@ -80,32 +110,182 @@ var Table = /** @class */ (function () {
80
110
  /**
81
111
  * Get the history of changes. A list of transactions from the most recent to the most old
82
112
  * in a range of depth
83
- * @param depth
113
+ * @param limit
84
114
  */
85
- Table.prototype.getHistory = function (depth) {
115
+ Table.prototype.getHistory = function (limit) {
86
116
  return __awaiter(this, void 0, void 0, function () {
87
- var url, contract_response, contract_data_json_list, transaction_data, _a;
88
- return __generator(this, function (_b) {
89
- switch (_b.label) {
117
+ var url, response, e_3;
118
+ return __generator(this, function (_a) {
119
+ switch (_a.label) {
90
120
  case 0:
91
- url = "".concat(this.db.api).concat(CONTRACT_TRANSACTIONS_PAYLOAD, "/").concat(this.contract_id, "/").concat(this.db.access_key, "/").concat(depth);
92
- _b.label = 1;
121
+ url = "".concat(this.db.server).concat(GET_HISTORY(this.name, limit));
122
+ _a.label = 1;
93
123
  case 1:
94
- _b.trys.push([1, 3, , 4]);
95
- return [4 /*yield*/, axios.get(url)];
124
+ _a.trys.push([1, 3, , 4]);
125
+ return [4 /*yield*/, axios.get(url, { headers: { Authorization: "Basic ".concat(this.db.auth) } })];
96
126
  case 2:
97
- contract_response = _b.sent();
98
- contract_data_json_list = contract_response.data;
99
- transaction_data = contract_data_json_list.map(function (transaction) { return transaction.data; });
100
- // Return empty if theres no data
101
- if (contract_data_json_list.length === 1 && contract_data_json_list[0].tx_type === TransactionType.NONE) {
102
- return [2 /*return*/, []];
127
+ response = _a.sent();
128
+ if (!response.data.success) {
129
+ throw new Error(response.data.message);
103
130
  }
104
131
  // Return data. Only table fields, e.g.: [{fieldA: 'Hi', filedB: 22}]
105
- return [2 /*return*/, transaction_data];
132
+ return [2 /*return*/, response.data.data];
133
+ case 3:
134
+ e_3 = _a.sent();
135
+ throw new Error("Something went wrong with getHistory operation: ".concat(e_3.message || String(e_3)));
136
+ case 4: return [2 /*return*/];
137
+ }
138
+ });
139
+ });
140
+ };
141
+ /**
142
+ * Refetch the table data
143
+ */
144
+ Table.prototype.refetch = function () {
145
+ return __awaiter(this, void 0, void 0, function () {
146
+ var url, response, e_4;
147
+ return __generator(this, function (_a) {
148
+ switch (_a.label) {
149
+ case 0:
150
+ url = "".concat(this.db.server).concat(GET_TABLE(this.name));
151
+ _a.label = 1;
152
+ case 1:
153
+ _a.trys.push([1, 3, , 4]);
154
+ return [4 /*yield*/, axios.get(url, { headers: { Authorization: "Basic ".concat(this.db.auth) } })];
155
+ case 2:
156
+ response = _a.sent();
157
+ this.table = response.data.data ? response.data.data : {};
158
+ return [3 /*break*/, 4];
159
+ case 3:
160
+ e_4 = _a.sent();
161
+ throw new Error("Something went wrong with refetch operation: ".concat(e_4.message || String(e_4)));
162
+ case 4: return [2 /*return*/];
163
+ }
164
+ });
165
+ });
166
+ };
167
+ /**
168
+ * Check if the table is empty
169
+ */
170
+ Table.prototype.isEmpty = function () {
171
+ return Object.keys(this.table).length === 0;
172
+ };
173
+ /**
174
+ * Get the table's name
175
+ */
176
+ Table.prototype.getName = function () {
177
+ return this.name;
178
+ };
179
+ /**
180
+ * Find items in the table using basic criteria with exact matches
181
+ * @param criteria Object with fields and values to match exactly, e.g.: {age: 44, name: "john"}
182
+ * @param limit Maximum number of items to return (default: 1000)
183
+ * @param reverse If true, returns items in reverse order (default: true)
184
+ * @returns Array of found items matching the criteria
185
+ * @example
186
+ * // Find items where age is 44
187
+ * table.findWhere({
188
+ * age: 44,
189
+ * })
190
+ *
191
+ * // Find items with multiple criteria
192
+ * table.findWhere({
193
+ * age: 44,
194
+ * name: "john",
195
+ * active: true,
196
+ * score: 100
197
+ * })
198
+ */
199
+ Table.prototype.findWhere = function (criteria, limit, reverse) {
200
+ if (limit === void 0) { limit = 1000; }
201
+ if (reverse === void 0) { reverse = true; }
202
+ return __awaiter(this, void 0, void 0, function () {
203
+ var url, body, response, e_5;
204
+ return __generator(this, function (_a) {
205
+ switch (_a.label) {
206
+ case 0:
207
+ url = "".concat(this.db.server).concat(FIND_WHERE_BASIC(this.name));
208
+ body = {
209
+ criteria: criteria,
210
+ limit: limit,
211
+ reverse: reverse
212
+ };
213
+ _a.label = 1;
214
+ case 1:
215
+ _a.trys.push([1, 3, , 4]);
216
+ return [4 /*yield*/, post(url, body, this.db.auth)];
217
+ case 2:
218
+ response = _a.sent();
219
+ if (!response.data.success) {
220
+ throw new Error(response.data.message);
221
+ }
222
+ // Return found data. Only table fields, e.g.: [{fieldA: 'Hi', filedB: 22}]
223
+ return [2 /*return*/, response.data.data];
106
224
  case 3:
107
- _a = _b.sent();
108
- throw new Error('Something went wrong!');
225
+ e_5 = _a.sent();
226
+ throw new Error("Something went wrong with findWhere operation: ".concat(e_5.message || String(e_5)));
227
+ case 4: return [2 /*return*/];
228
+ }
229
+ });
230
+ });
231
+ };
232
+ // TODO: Implement documentation
233
+ /**
234
+ * Find items in the table using advanced criteria with operators
235
+ * @param criteria Array of criteria to filter items. Each criteria contains:
236
+ * - field: The field name to filter
237
+ * - operator: The operator to use in comparison. Available operators:
238
+ * - Eq (==) Equal
239
+ * - Ne (!=) Not Equal
240
+ * - Gt (>) Greater Than
241
+ * - Ge (>=) Greater Than or Equal
242
+ * - Lt (<) Less Than
243
+ * - Le (<=) Less Than or Equal
244
+ * - Contains: Check if field contains value (for strings and arrays)
245
+ * - StartsWith: Check if field starts with value (for strings)
246
+ * - EndsWith: Check if field ends with value (for strings)
247
+ * - value: The value to compare against
248
+ * @param limit Maximum number of items to return (default: 1000)
249
+ * @param reverse If true, returns items in reverse order (default: true)
250
+ * @returns Array of found items matching the criteria
251
+ * @example
252
+ * // Find items where greeting contains "arg"
253
+ * table.findWhereAdvanced([
254
+ * {
255
+ * field: "greeting",
256
+ * operator: Operators.Contains,
257
+ * value: "hello"
258
+ * }
259
+ * ])
260
+ */
261
+ Table.prototype.findWhereAdvanced = function (criteria, limit, reverse) {
262
+ if (limit === void 0) { limit = 1000; }
263
+ if (reverse === void 0) { reverse = true; }
264
+ return __awaiter(this, void 0, void 0, function () {
265
+ var url, body, response, e_6;
266
+ return __generator(this, function (_a) {
267
+ switch (_a.label) {
268
+ case 0:
269
+ url = "".concat(this.db.server).concat(FIND_WHERE_ADVANCED(this.name));
270
+ body = {
271
+ criteria: criteria,
272
+ limit: limit,
273
+ reverse: reverse
274
+ };
275
+ _a.label = 1;
276
+ case 1:
277
+ _a.trys.push([1, 3, , 4]);
278
+ return [4 /*yield*/, post(url, body, this.db.auth)];
279
+ case 2:
280
+ response = _a.sent();
281
+ if (!response.data.success) {
282
+ throw new Error(response.data.message);
283
+ }
284
+ // Return found data. Only table fields, e.g.: [{fieldA: 'Hi', filedB: 22}]
285
+ return [2 /*return*/, response.data.data];
286
+ case 3:
287
+ e_6 = _a.sent();
288
+ throw new Error("Something went wrong with findWhereAdvanced operation: ".concat(e_6.message || String(e_6)));
109
289
  case 4: return [2 /*return*/];
110
290
  }
111
291
  });
@@ -113,31 +293,4 @@ var Table = /** @class */ (function () {
113
293
  };
114
294
  return Table;
115
295
  }());
116
- export var get = function (db, table_name, model) { return __awaiter(void 0, void 0, void 0, function () {
117
- var contract_id, url, contract_response, contract_data_json, table_1, table, _a;
118
- return __generator(this, function (_b) {
119
- switch (_b.label) {
120
- case 0:
121
- contract_id = db.access.parse(db.name, table_name);
122
- url = "".concat(db.api).concat(CONTRACT_PAYLOAD, "/").concat(contract_id, "/").concat(db.access_key);
123
- _b.label = 1;
124
- case 1:
125
- _b.trys.push([1, 3, , 4]);
126
- return [4 /*yield*/, axios.get(url)];
127
- case 2:
128
- contract_response = _b.sent();
129
- contract_data_json = contract_response.data;
130
- // If there's already a table (contract) with data, then, fetch its data
131
- if (contract_data_json.tx_type === TransactionType.CONTRACT) {
132
- table_1 = new Table(contract_data_json.data, contract_id, db);
133
- return [2 /*return*/, table_1];
134
- }
135
- table = new Table(model, contract_id, db);
136
- return [2 /*return*/, table];
137
- case 3:
138
- _a = _b.sent();
139
- throw new Error('Something went wrong!');
140
- case 4: return [2 /*return*/];
141
- }
142
- });
143
- }); };
296
+ export default Table;
@@ -1,29 +1,53 @@
1
1
  export type BasicResponse<D> = {
2
2
  success: boolean;
3
- error_msg: string;
3
+ message: string;
4
4
  data?: D;
5
5
  };
6
- export type SignedUserAccount = {
7
- id: string;
8
- user_name: string;
9
- units: number;
6
+ export type Connection = {
7
+ server: string | null;
8
+ database: string;
9
+ user: string;
10
+ password: string;
10
11
  };
11
- export type TransferUnitsRegistry = {
12
- from: string;
13
- to: string;
14
- units: number;
12
+ export type Criteria<Model> = Partial<Record<keyof Model, string | number | boolean>>;
13
+ export type CriteriaAdvanced<Model> = {
14
+ field: Partial<keyof Model>;
15
+ /**
16
+ * @see Operators
17
+ */
18
+ operator: string;
19
+ value: string | number | boolean;
15
20
  };
16
- export declare enum TransactionType {
17
- NONE = "NONE",
18
- ACCOUNT = "ACCOUNT",
19
- CONTRACT = "CONTRACT",
20
- TRANSFER = "TRANSFER"
21
- }
22
- export type ContractTransactionData<Model> = {
23
- tx_type: TransactionType;
24
- contract_id: string;
25
- timestamp?: number;
26
- data: Model;
27
- block_hash: string;
28
- block_height: number;
21
+ /**
22
+ * Operators for the advanced criteria
23
+ * @see https://docs.chaindb.com/docs/query-language/ (TODO)
24
+ */
25
+ export declare const Operators: {
26
+ EQUAL: string;
27
+ NOT_EQUAL: string;
28
+ GREATER_THAN: string;
29
+ GREATER_THAN_OR_EQUAL: string;
30
+ LESS_THAN: string;
31
+ LESS_THAN_OR_EQUAL: string;
32
+ CONTAINS: string;
33
+ STARTS_WITH: string;
34
+ ENDS_WITH: string;
29
35
  };
36
+ export declare const EventTypes: {
37
+ TABLE_PERSIST: string;
38
+ TABLE_UPDATE: string;
39
+ };
40
+ export type EventData = {
41
+ event_type: string;
42
+ database: string;
43
+ table: string;
44
+ /**
45
+ * Data of the event (also to/from the table)
46
+ */
47
+ data: Record<string, any>;
48
+ /**
49
+ * Timestamp of the event
50
+ */
51
+ timestamp: number;
52
+ };
53
+ export type EventCallback = (data: EventData) => void;
package/features/types.js CHANGED
@@ -1,7 +1,29 @@
1
- export var TransactionType;
2
- (function (TransactionType) {
3
- TransactionType["NONE"] = "NONE";
4
- TransactionType["ACCOUNT"] = "ACCOUNT";
5
- TransactionType["CONTRACT"] = "CONTRACT";
6
- TransactionType["TRANSFER"] = "TRANSFER";
7
- })(TransactionType || (TransactionType = {}));
1
+ /**
2
+ * Operators for the advanced criteria
3
+ * @see https://docs.chaindb.com/docs/query-language/ (TODO)
4
+ */
5
+ export var Operators = {
6
+ // (==)
7
+ EQUAL: 'Eq',
8
+ // (!=)
9
+ NOT_EQUAL: 'Ne',
10
+ // (>)
11
+ GREATER_THAN: 'Gt',
12
+ // (>=)
13
+ GREATER_THAN_OR_EQUAL: 'Ge',
14
+ // (<)
15
+ LESS_THAN: 'Lt',
16
+ // (<=)
17
+ LESS_THAN_OR_EQUAL: 'Le',
18
+ // (for strings and arrays)
19
+ CONTAINS: 'Contains',
20
+ // (for strings)
21
+ STARTS_WITH: 'StartsWith',
22
+ // (for strings)
23
+ ENDS_WITH: 'EndsWith'
24
+ };
25
+ // Events
26
+ export var EventTypes = {
27
+ TABLE_PERSIST: 'TablePersist',
28
+ TABLE_UPDATE: 'TableUpdate'
29
+ };
@@ -1 +1,2 @@
1
- export declare const post: (url: string, body: any) => Promise<import("axios").AxiosResponse<any, any>>;
1
+ import { BasicResponse } from './types';
2
+ export declare const post: (url: string, body: any, auth?: string) => Promise<import("axios").AxiosResponse<BasicResponse<any>, any>>;
package/features/utils.js CHANGED
@@ -1,4 +1,7 @@
1
1
  import axios from 'axios';
2
- export var post = function (url, body) {
3
- return axios.post(url, body, { headers: { 'content-type': 'application/json' } });
2
+ export var post = function (url, body, auth) {
3
+ if (auth === void 0) { auth = ''; }
4
+ return axios.post(url, body, {
5
+ headers: { 'content-type': 'application/json', Authorization: "Basic ".concat(auth) }
6
+ });
4
7
  };
package/index.d.ts CHANGED
@@ -1,3 +1,2 @@
1
1
  export { ChainDB, connect } from './features/chain-db';
2
- export { Access } from './features/access';
3
- export { BasicResponse, SignedUserAccount } from './features/types';
2
+ export { BasicResponse, Operators, CriteriaAdvanced, Criteria, EventTypes, EventData, EventCallback, } from './features/types';
package/index.js CHANGED
@@ -1,2 +1,2 @@
1
1
  export { ChainDB, connect } from './features/chain-db';
2
- export { Access } from './features/access';
2
+ export { Operators, EventTypes, } from './features/types';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chain-db-ts",
3
- "version": "0.0.2",
3
+ "version": "1.0.0-rc.1",
4
4
  "description": "Chain DB Client for Javascript/Typescript Node apps.",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "module": "./index.js",
@@ -26,7 +26,7 @@
26
26
  "license": "MIT",
27
27
  "devDependencies": {
28
28
  "@types/node": "^18.15.5",
29
- "@types/sha256": "^0.2.0",
29
+ "@types/ws": "^8.5.14",
30
30
  "nodemon": "^3.0.1",
31
31
  "ts-node": "^10.9.1",
32
32
  "tslib": "^2.5.0",
@@ -35,6 +35,8 @@
35
35
  "repository": "git://github.com/wpdas/chain-db-ts.git",
36
36
  "dependencies": {
37
37
  "axios": "^1.4.0",
38
- "sha256": "^0.2.0"
38
+ "bufferutil": "^4.0.9",
39
+ "utf-8-validate": "^6.0.5",
40
+ "ws": "^8.18.1"
39
41
  }
40
42
  }