@kidus.dev/flowdb 1.0.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.
Files changed (74) hide show
  1. package/README.md +15 -0
  2. package/dist/core/blob/blob.d.ts +25 -0
  3. package/dist/core/blob/blob.d.ts.map +1 -0
  4. package/dist/core/blob/blob.js +57 -0
  5. package/dist/core/blob/blob_disk_driver.d.ts +27 -0
  6. package/dist/core/blob/blob_disk_driver.d.ts.map +1 -0
  7. package/dist/core/blob/blob_disk_driver.js +179 -0
  8. package/dist/core/blob/blob_storage.d.ts +90 -0
  9. package/dist/core/blob/blob_storage.d.ts.map +1 -0
  10. package/dist/core/blob/blob_storage.js +248 -0
  11. package/dist/core/collection/collection.d.ts +99 -0
  12. package/dist/core/collection/collection.d.ts.map +1 -0
  13. package/dist/core/collection/collection.js +226 -0
  14. package/dist/core/collection/document.d.ts +24 -0
  15. package/dist/core/collection/document.d.ts.map +1 -0
  16. package/dist/core/collection/document.js +86 -0
  17. package/dist/core/collection/driver/collection_file_driver.d.ts +20 -0
  18. package/dist/core/collection/driver/collection_file_driver.d.ts.map +1 -0
  19. package/dist/core/collection/driver/collection_file_driver.js +90 -0
  20. package/dist/core/collection/driver/collection_operations.d.ts +43 -0
  21. package/dist/core/collection/driver/collection_operations.d.ts.map +1 -0
  22. package/dist/core/collection/driver/collection_operations.js +278 -0
  23. package/dist/core/collection/query/compares.d.ts +90 -0
  24. package/dist/core/collection/query/compares.d.ts.map +1 -0
  25. package/dist/core/collection/query/compares.js +362 -0
  26. package/dist/core/collection/query/filtering.d.ts +14 -0
  27. package/dist/core/collection/query/filtering.d.ts.map +1 -0
  28. package/dist/core/collection/query/filtering.js +176 -0
  29. package/dist/core/collection/query/query_builder.d.ts +145 -0
  30. package/dist/core/collection/query/query_builder.d.ts.map +1 -0
  31. package/dist/core/collection/query/query_builder.js +196 -0
  32. package/dist/core/collection/query/query_executor.d.ts +87 -0
  33. package/dist/core/collection/query/query_executor.d.ts.map +1 -0
  34. package/dist/core/collection/query/query_executor.js +348 -0
  35. package/dist/core/collection/query/relation.d.ts +29 -0
  36. package/dist/core/collection/query/relation.d.ts.map +1 -0
  37. package/dist/core/collection/query/relation.js +40 -0
  38. package/dist/core/database/backup.d.ts +26 -0
  39. package/dist/core/database/backup.d.ts.map +1 -0
  40. package/dist/core/database/backup.js +114 -0
  41. package/dist/core/database/database.d.ts +57 -0
  42. package/dist/core/database/database.d.ts.map +1 -0
  43. package/dist/core/database/database.js +179 -0
  44. package/dist/core/database/database_file_driver.d.ts +27 -0
  45. package/dist/core/database/database_file_driver.d.ts.map +1 -0
  46. package/dist/core/database/database_file_driver.js +135 -0
  47. package/dist/core/store/store.d.ts +24 -0
  48. package/dist/core/store/store.d.ts.map +1 -0
  49. package/dist/core/store/store.js +54 -0
  50. package/dist/core/store/store_file_driver.d.ts +26 -0
  51. package/dist/core/store/store_file_driver.d.ts.map +1 -0
  52. package/dist/core/store/store_file_driver.js +87 -0
  53. package/dist/tools/encryptor.d.ts +17 -0
  54. package/dist/tools/encryptor.d.ts.map +1 -0
  55. package/dist/tools/encryptor.js +80 -0
  56. package/dist/tools/format.d.ts +10 -0
  57. package/dist/tools/format.d.ts.map +1 -0
  58. package/dist/tools/format.js +40 -0
  59. package/dist/tools/index.d.ts +7 -0
  60. package/dist/tools/index.d.ts.map +1 -0
  61. package/dist/tools/index.js +6 -0
  62. package/dist/tools/json.d.ts +19 -0
  63. package/dist/tools/json.d.ts.map +1 -0
  64. package/dist/tools/json.js +232 -0
  65. package/dist/tools/performance.d.ts +20 -0
  66. package/dist/tools/performance.d.ts.map +1 -0
  67. package/dist/tools/performance.js +53 -0
  68. package/dist/tools/print_colored.d.ts +47 -0
  69. package/dist/tools/print_colored.d.ts.map +1 -0
  70. package/dist/tools/print_colored.js +119 -0
  71. package/dist/tools/random.d.ts +46 -0
  72. package/dist/tools/random.d.ts.map +1 -0
  73. package/dist/tools/random.js +214 -0
  74. package/package.json +40 -0
@@ -0,0 +1,278 @@
1
+ // TypeScript version of CollectionOperations, inspired by the Dart implementation
2
+ import Document from "../document";
3
+ import CollectionFileDriver from "./collection_file_driver";
4
+ import { Encryptor, Random } from "../../../tools";
5
+ export default class CollectionOperations {
6
+ path;
7
+ encrypted;
8
+ fileDriver;
9
+ constructor(params) {
10
+ this.path = params.path;
11
+ this.encrypted = params.encrypted;
12
+ this.fileDriver = new CollectionFileDriver(this.path, new Encryptor({ round: 10, key: params.key }), this.encrypted);
13
+ }
14
+ async create() {
15
+ await this.fileDriver.create();
16
+ }
17
+ createSync() {
18
+ this.fileDriver.createSync();
19
+ }
20
+ async delete() {
21
+ await this.fileDriver.delete();
22
+ }
23
+ deleteSync() {
24
+ this.fileDriver.deleteSync();
25
+ }
26
+ async size() {
27
+ return await this.fileDriver.size();
28
+ }
29
+ sizeSync() {
30
+ return this.fileDriver.sizeSync();
31
+ }
32
+ // ADD
33
+ async add(data) {
34
+ const record = Document.fromJson({ data });
35
+ await this.fileDriver.appendRecords([record.data]);
36
+ return record;
37
+ }
38
+ addSync(data) {
39
+ const record = Document.fromJson({ data });
40
+ this.fileDriver.appendRecordsSync([record.data]);
41
+ return record;
42
+ }
43
+ // ADD MANY
44
+ async addMany(data) {
45
+ const records = data.map((item) => Document.fromJson({ data: item }));
46
+ await this.fileDriver.appendRecords(records.map((item) => item.data));
47
+ return records;
48
+ }
49
+ addManySync(data) {
50
+ const records = data.map((item) => Document.fromJson({ data: item }));
51
+ this.fileDriver.appendRecordsSync(records.map((item) => item.data));
52
+ return records;
53
+ }
54
+ // GET ALL
55
+ async getAll() {
56
+ const lines = await this.fileDriver.readRecords();
57
+ return lines.map((item) => Document.fromJson({ data: item }));
58
+ }
59
+ getAllSync() {
60
+ const lines = this.fileDriver.readRecordsSync();
61
+ return lines.map((item) => Document.fromJson({ data: item }));
62
+ }
63
+ // GET BY ID
64
+ async getById(id) {
65
+ const records = await this.fileDriver.readRecords();
66
+ for (const record of records) {
67
+ if (record["__id"] === id)
68
+ return Document.fromJson({ data: record });
69
+ }
70
+ return null;
71
+ }
72
+ getByIdSync(id) {
73
+ const records = this.fileDriver.readRecordsSync();
74
+ for (const record of records) {
75
+ if (record["__id"] === id)
76
+ return Document.fromJson({ data: record });
77
+ }
78
+ return null;
79
+ }
80
+ async getRandom() {
81
+ const records = await this.fileDriver.readRecords();
82
+ return Random.pickOne(records.map((item) => Document.fromJson({ data: item })));
83
+ }
84
+ getRandomSync() {
85
+ const records = this.fileDriver.readRecordsSync();
86
+ return Random.pickOne(records.map((item) => Document.fromJson({ data: item })));
87
+ }
88
+ async getRandomMany(count) {
89
+ if (count < 0)
90
+ throw new Error("count must be >= 0");
91
+ const records = await this.fileDriver.readRecords();
92
+ return Random.pickMany(records.map((item) => Document.fromJson({ data: item })), { count });
93
+ }
94
+ getRandomManySync(count) {
95
+ if (count < 0)
96
+ throw new Error("count must be >= 0");
97
+ const records = this.fileDriver.readRecordsSync();
98
+ return Random.pickMany(records.map((item) => Document.fromJson({ data: item })), { count });
99
+ }
100
+ // UPDATE ONE DOCUMENT BY ID - Only update 1 record
101
+ async updateOneRecordById(id, data) {
102
+ const records = await this.fileDriver.readRecords();
103
+ let updated = false;
104
+ const output = [];
105
+ let updatedRecord = null;
106
+ for (const record of records) {
107
+ if (!updated && record["__id"] === id) {
108
+ const mergedData = { ...record, ...data };
109
+ const newDoc = Document.fromJson({ data: mergedData });
110
+ output.push(newDoc);
111
+ updatedRecord = newDoc;
112
+ updated = true;
113
+ }
114
+ else {
115
+ output.push(Document.fromJson({ data: record }));
116
+ }
117
+ }
118
+ await this.fileDriver.writeRecords(output.map((item) => item.data));
119
+ return updatedRecord;
120
+ }
121
+ updateOneRecordByIdSync(id, data) {
122
+ const records = this.fileDriver.readRecordsSync();
123
+ let updated = false;
124
+ const output = [];
125
+ let updatedRecord = null;
126
+ for (const record of records) {
127
+ if (!updated && record["__id"] === id) {
128
+ const mergedData = { ...record, ...data };
129
+ const newDoc = Document.fromJson({ data: mergedData });
130
+ output.push(newDoc);
131
+ updatedRecord = newDoc;
132
+ updated = true;
133
+ }
134
+ else {
135
+ output.push(Document.fromJson({ data: record }));
136
+ }
137
+ }
138
+ this.fileDriver.writeRecordsSync(output.map((item) => item.data));
139
+ return updatedRecord;
140
+ }
141
+ // UPDATE MANY DOCUMENTS BY IDS WITH SAME VALUE
142
+ async updateManyRecordsByIdsWithSameValue(ids, data) {
143
+ const records = await this.fileDriver.readRecords();
144
+ const output = [];
145
+ const updatedRecords = [];
146
+ for (const record of records) {
147
+ if (ids.includes(record["__id"])) {
148
+ const mergedData = { ...record, ...data };
149
+ const doc = Document.fromJson({ data: mergedData });
150
+ output.push(doc);
151
+ updatedRecords.push(doc);
152
+ }
153
+ else {
154
+ output.push(Document.fromJson({ data: record }));
155
+ }
156
+ }
157
+ await this.fileDriver.writeRecords(output.map((item) => item.data));
158
+ return updatedRecords;
159
+ }
160
+ updateManyRecordsByIdsWithSameValueSync(ids, data) {
161
+ const records = this.fileDriver.readRecordsSync();
162
+ const output = [];
163
+ const updatedRecords = [];
164
+ for (const record of records) {
165
+ if (ids.includes(record["__id"])) {
166
+ const mergedData = { ...record, ...data };
167
+ const doc = Document.fromJson({ data: mergedData });
168
+ output.push(doc);
169
+ updatedRecords.push(doc);
170
+ }
171
+ else {
172
+ output.push(Document.fromJson({ data: record }));
173
+ }
174
+ }
175
+ this.fileDriver.writeRecordsSync(output.map((item) => item.data));
176
+ return updatedRecords;
177
+ }
178
+ // UPDATE MANY DOCUMENTS BY IDS WITH DIFFERENT VALUES
179
+ async updateManyRecordsByIdsWithDifferentValues(ids, datas) {
180
+ const records = await this.fileDriver.readRecords();
181
+ const output = [];
182
+ const updatedRecords = [];
183
+ for (const record of records) {
184
+ if (ids.includes(record["__id"])) {
185
+ const index = ids.indexOf(record["__id"]);
186
+ const mergedData = { ...record, ...datas[index] };
187
+ const doc = Document.fromJson({ data: mergedData });
188
+ output.push(doc);
189
+ updatedRecords.push(doc);
190
+ }
191
+ else {
192
+ output.push(Document.fromJson({ data: record }));
193
+ }
194
+ }
195
+ await this.fileDriver.writeRecords(output.map((item) => item.data));
196
+ return updatedRecords;
197
+ }
198
+ updateManyRecordsByIdsWithDifferentValuesSync(ids, datas) {
199
+ const records = this.fileDriver.readRecordsSync();
200
+ const output = [];
201
+ const updatedRecords = [];
202
+ for (const record of records) {
203
+ if (ids.includes(record["__id"])) {
204
+ const index = ids.indexOf(record["__id"]);
205
+ const mergedData = { ...record, ...datas[index] };
206
+ const doc = Document.fromJson({ data: mergedData });
207
+ output.push(doc);
208
+ updatedRecords.push(doc);
209
+ }
210
+ else {
211
+ output.push(Document.fromJson({ data: record }));
212
+ }
213
+ }
214
+ this.fileDriver.writeRecordsSync(output.map((item) => item.data));
215
+ return updatedRecords;
216
+ }
217
+ // DELETE ONE DOCUMENT BY ID
218
+ async deleteById(id) {
219
+ const records = await this.fileDriver.readRecords();
220
+ const output = [];
221
+ let deletedRecord = null;
222
+ for (const record of records) {
223
+ if (record["__id"] === id)
224
+ continue;
225
+ output.push(Document.fromJson({ data: record }));
226
+ deletedRecord = Document.fromJson({ data: record });
227
+ }
228
+ await this.fileDriver.writeRecords(output.map((item) => item.data));
229
+ return deletedRecord;
230
+ }
231
+ deleteByIdSync(id) {
232
+ const records = this.fileDriver.readRecordsSync();
233
+ const output = [];
234
+ let deletedRecord = null;
235
+ for (const record of records) {
236
+ if (record["__id"] === id)
237
+ continue;
238
+ output.push(Document.fromJson({ data: record }));
239
+ deletedRecord = Document.fromJson({ data: record });
240
+ }
241
+ this.fileDriver.writeRecordsSync(output.map((item) => item.data));
242
+ return deletedRecord;
243
+ }
244
+ // DELETE MANY BY IDS
245
+ async deleteManyByIds(ids) {
246
+ const records = await this.fileDriver.readRecords();
247
+ const output = [];
248
+ const deletedRecords = [];
249
+ for (const record of records) {
250
+ if (ids.includes(record["__id"]))
251
+ continue;
252
+ output.push(Document.fromJson({ data: record }));
253
+ deletedRecords.push(Document.fromJson({ data: record }));
254
+ }
255
+ await this.fileDriver.writeRecords(output.map((item) => item.data));
256
+ return deletedRecords;
257
+ }
258
+ deleteManyByIdsSync(ids) {
259
+ const records = this.fileDriver.readRecordsSync();
260
+ const output = [];
261
+ const deletedRecords = [];
262
+ for (const record of records) {
263
+ if (ids.includes(record["__id"]))
264
+ continue;
265
+ output.push(Document.fromJson({ data: record }));
266
+ deletedRecords.push(Document.fromJson({ data: record }));
267
+ }
268
+ this.fileDriver.writeRecordsSync(output.map((item) => item.data));
269
+ return deletedRecords;
270
+ }
271
+ // CLEAR
272
+ async clear() {
273
+ await this.fileDriver.writeRecords([]);
274
+ }
275
+ clearSync() {
276
+ this.fileDriver.writeRecordsSync([]);
277
+ }
278
+ }
@@ -0,0 +1,90 @@
1
+ type Compare = {
2
+ compare(other: any): boolean;
3
+ };
4
+ type CompareFactory = (value: any) => Compare;
5
+ export type SortOrder = "asc" | "desc";
6
+ export declare const compareMap: Record<string, CompareFactory>;
7
+ export declare class Filter implements Compare {
8
+ predicate: (other: any) => boolean;
9
+ constructor(predicate: (other: any) => boolean);
10
+ compare(other: any): boolean;
11
+ }
12
+ export declare class Gt implements Compare {
13
+ value: any;
14
+ constructor(value: any);
15
+ compare(other: any): boolean;
16
+ }
17
+ export declare class Gte implements Compare {
18
+ value: any;
19
+ constructor(value: any);
20
+ compare(other: any): boolean;
21
+ }
22
+ export declare class Lt implements Compare {
23
+ value: any;
24
+ constructor(value: any);
25
+ compare(other: any): boolean;
26
+ }
27
+ export declare class Lte implements Compare {
28
+ value: any;
29
+ constructor(value: any);
30
+ compare(other: any): boolean;
31
+ }
32
+ export declare class Eq implements Compare {
33
+ value: any;
34
+ constructor(value: any);
35
+ compare(other: any): boolean;
36
+ }
37
+ export declare class Neq implements Compare {
38
+ value: any;
39
+ constructor(value: any);
40
+ compare(other: any): boolean;
41
+ }
42
+ export declare class Contains implements Compare {
43
+ value: any;
44
+ constructor(value: any);
45
+ compare(other: any): boolean;
46
+ }
47
+ export declare class DoesNotContain implements Compare {
48
+ value: any;
49
+ constructor(value: any);
50
+ compare(other: any): boolean;
51
+ }
52
+ export declare class StartsWith implements Compare {
53
+ value: any;
54
+ constructor(value: any);
55
+ compare(other: any): boolean;
56
+ }
57
+ export declare class EndsWith implements Compare {
58
+ value: any;
59
+ constructor(value: any);
60
+ compare(other: any): boolean;
61
+ }
62
+ export declare class RegexMatch implements Compare {
63
+ pattern: string;
64
+ caseSensitive: boolean;
65
+ multiLine: boolean;
66
+ constructor(pattern: string, caseSensitive?: boolean, multiLine?: boolean);
67
+ compare(value: any): boolean;
68
+ }
69
+ export declare class Between implements Compare {
70
+ range: [any, any];
71
+ includeLower: boolean;
72
+ includeUpper: boolean;
73
+ constructor(range: [any, any], includeLower?: boolean, includeUpper?: boolean);
74
+ compare(value: any): boolean;
75
+ }
76
+ export declare class IsNull implements Compare {
77
+ compare(value: any): boolean;
78
+ }
79
+ export declare class IsNotNull implements Compare {
80
+ compare(value: any): boolean;
81
+ }
82
+ export declare class Empty implements Compare {
83
+ compare(value: any): boolean;
84
+ }
85
+ export declare class NotEmpty implements Compare {
86
+ compare(value: any): boolean;
87
+ }
88
+ export declare function compareFromJson(key: string, value: any): Compare;
89
+ export {};
90
+ //# sourceMappingURL=compares.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compares.d.ts","sourceRoot":"","sources":["../../../../src/core/collection/query/compares.ts"],"names":[],"mappings":"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"}