@peers-app/peers-sdk 0.1.4

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 (234) hide show
  1. package/README.md +1 -0
  2. package/dist/context/data-context.d.ts +31 -0
  3. package/dist/context/data-context.js +56 -0
  4. package/dist/context/index.d.ts +3 -0
  5. package/dist/context/index.js +19 -0
  6. package/dist/context/user-context-singleton.d.ts +11 -0
  7. package/dist/context/user-context-singleton.js +121 -0
  8. package/dist/context/user-context.d.ts +55 -0
  9. package/dist/context/user-context.js +205 -0
  10. package/dist/data/assistants.d.ts +68 -0
  11. package/dist/data/assistants.js +64 -0
  12. package/dist/data/change-tracking.d.ts +219 -0
  13. package/dist/data/change-tracking.js +119 -0
  14. package/dist/data/channels.d.ts +29 -0
  15. package/dist/data/channels.js +25 -0
  16. package/dist/data/data-locks.d.ts +37 -0
  17. package/dist/data/data-locks.js +180 -0
  18. package/dist/data/data-locks.test.d.ts +1 -0
  19. package/dist/data/data-locks.test.js +456 -0
  20. package/dist/data/device-sync-info.d.ts +19 -0
  21. package/dist/data/device-sync-info.js +24 -0
  22. package/dist/data/devices.d.ts +51 -0
  23. package/dist/data/devices.js +36 -0
  24. package/dist/data/embeddings.d.ts +47 -0
  25. package/dist/data/embeddings.js +36 -0
  26. package/dist/data/files/file-read-stream.d.ts +27 -0
  27. package/dist/data/files/file-read-stream.js +195 -0
  28. package/dist/data/files/file-write-stream.d.ts +20 -0
  29. package/dist/data/files/file-write-stream.js +113 -0
  30. package/dist/data/files/file.types.d.ts +47 -0
  31. package/dist/data/files/file.types.js +55 -0
  32. package/dist/data/files/files.d.ts +28 -0
  33. package/dist/data/files/files.js +127 -0
  34. package/dist/data/files/files.test.d.ts +1 -0
  35. package/dist/data/files/files.test.js +728 -0
  36. package/dist/data/files/index.d.ts +4 -0
  37. package/dist/data/files/index.js +23 -0
  38. package/dist/data/group-member-roles.d.ts +9 -0
  39. package/dist/data/group-member-roles.js +25 -0
  40. package/dist/data/group-members.d.ts +39 -0
  41. package/dist/data/group-members.js +68 -0
  42. package/dist/data/group-members.test.d.ts +1 -0
  43. package/dist/data/group-members.test.js +287 -0
  44. package/dist/data/group-permissions.d.ts +8 -0
  45. package/dist/data/group-permissions.js +73 -0
  46. package/dist/data/group-share.d.ts +50 -0
  47. package/dist/data/group-share.js +196 -0
  48. package/dist/data/groups.d.ts +50 -0
  49. package/dist/data/groups.js +73 -0
  50. package/dist/data/groups.test.d.ts +1 -0
  51. package/dist/data/groups.test.js +153 -0
  52. package/dist/data/index.d.ts +31 -0
  53. package/dist/data/index.js +47 -0
  54. package/dist/data/knowledge/knowledge-frames.d.ts +34 -0
  55. package/dist/data/knowledge/knowledge-frames.js +34 -0
  56. package/dist/data/knowledge/knowledge-links.d.ts +30 -0
  57. package/dist/data/knowledge/knowledge-links.js +25 -0
  58. package/dist/data/knowledge/knowledge-values.d.ts +35 -0
  59. package/dist/data/knowledge/knowledge-values.js +35 -0
  60. package/dist/data/knowledge/peer-types.d.ts +112 -0
  61. package/dist/data/knowledge/peer-types.js +27 -0
  62. package/dist/data/knowledge/predicates.d.ts +34 -0
  63. package/dist/data/knowledge/predicates.js +27 -0
  64. package/dist/data/messages.d.ts +57 -0
  65. package/dist/data/messages.js +97 -0
  66. package/dist/data/orm/client-proxy.data-source.d.ts +27 -0
  67. package/dist/data/orm/client-proxy.data-source.js +65 -0
  68. package/dist/data/orm/cursor.d.ts +25 -0
  69. package/dist/data/orm/cursor.js +47 -0
  70. package/dist/data/orm/cursor.test.d.ts +1 -0
  71. package/dist/data/orm/cursor.test.js +315 -0
  72. package/dist/data/orm/data-query.d.ts +96 -0
  73. package/dist/data/orm/data-query.js +208 -0
  74. package/dist/data/orm/data-query.mongo.d.ts +17 -0
  75. package/dist/data/orm/data-query.mongo.js +267 -0
  76. package/dist/data/orm/data-query.mongo.test.d.ts +1 -0
  77. package/dist/data/orm/data-query.mongo.test.js +398 -0
  78. package/dist/data/orm/data-query.sqlite.d.ts +14 -0
  79. package/dist/data/orm/data-query.sqlite.js +297 -0
  80. package/dist/data/orm/data-query.sqlite.test.d.ts +1 -0
  81. package/dist/data/orm/data-query.sqlite.test.js +377 -0
  82. package/dist/data/orm/data-query.test.d.ts +1 -0
  83. package/dist/data/orm/data-query.test.js +553 -0
  84. package/dist/data/orm/decorators.d.ts +6 -0
  85. package/dist/data/orm/decorators.js +21 -0
  86. package/dist/data/orm/dependency-injection.test.d.ts +1 -0
  87. package/dist/data/orm/dependency-injection.test.js +171 -0
  88. package/dist/data/orm/doc.d.ts +26 -0
  89. package/dist/data/orm/doc.js +124 -0
  90. package/dist/data/orm/event-registry.d.ts +24 -0
  91. package/dist/data/orm/event-registry.js +40 -0
  92. package/dist/data/orm/event-registry.test.d.ts +1 -0
  93. package/dist/data/orm/event-registry.test.js +44 -0
  94. package/dist/data/orm/factory.d.ts +8 -0
  95. package/dist/data/orm/factory.js +147 -0
  96. package/dist/data/orm/index.d.ts +16 -0
  97. package/dist/data/orm/index.js +32 -0
  98. package/dist/data/orm/multi-cursors.d.ts +11 -0
  99. package/dist/data/orm/multi-cursors.js +146 -0
  100. package/dist/data/orm/multi-cursors.test.d.ts +1 -0
  101. package/dist/data/orm/multi-cursors.test.js +455 -0
  102. package/dist/data/orm/sql-db.d.ts +6 -0
  103. package/dist/data/orm/sql-db.js +2 -0
  104. package/dist/data/orm/sql.data-source.d.ts +38 -0
  105. package/dist/data/orm/sql.data-source.js +379 -0
  106. package/dist/data/orm/sql.data-source.test.d.ts +1 -0
  107. package/dist/data/orm/sql.data-source.test.js +406 -0
  108. package/dist/data/orm/subscribable.data-source.d.ts +25 -0
  109. package/dist/data/orm/subscribable.data-source.js +72 -0
  110. package/dist/data/orm/table-container-events.test.d.ts +1 -0
  111. package/dist/data/orm/table-container-events.test.js +93 -0
  112. package/dist/data/orm/table-container.d.ts +39 -0
  113. package/dist/data/orm/table-container.js +96 -0
  114. package/dist/data/orm/table-definitions.system.d.ts +9 -0
  115. package/dist/data/orm/table-definitions.system.js +29 -0
  116. package/dist/data/orm/table-definitions.type.d.ts +19 -0
  117. package/dist/data/orm/table-definitions.type.js +2 -0
  118. package/dist/data/orm/table-dependencies.d.ts +32 -0
  119. package/dist/data/orm/table-dependencies.js +2 -0
  120. package/dist/data/orm/table.d.ts +42 -0
  121. package/dist/data/orm/table.event-source.test.d.ts +1 -0
  122. package/dist/data/orm/table.event-source.test.js +341 -0
  123. package/dist/data/orm/table.js +244 -0
  124. package/dist/data/orm/types.d.ts +20 -0
  125. package/dist/data/orm/types.js +115 -0
  126. package/dist/data/orm/types.test.d.ts +1 -0
  127. package/dist/data/orm/types.test.js +71 -0
  128. package/dist/data/package-permissions.d.ts +7 -0
  129. package/dist/data/package-permissions.js +18 -0
  130. package/dist/data/packages.d.ts +92 -0
  131. package/dist/data/packages.js +90 -0
  132. package/dist/data/peer-events/peer-event-handlers.d.ts +21 -0
  133. package/dist/data/peer-events/peer-event-handlers.js +28 -0
  134. package/dist/data/peer-events/peer-event-types.d.ts +119 -0
  135. package/dist/data/peer-events/peer-event-types.js +29 -0
  136. package/dist/data/peer-events/peer-events.d.ts +41 -0
  137. package/dist/data/peer-events/peer-events.js +102 -0
  138. package/dist/data/persistent-vars.d.ts +87 -0
  139. package/dist/data/persistent-vars.js +230 -0
  140. package/dist/data/tool-tests.d.ts +37 -0
  141. package/dist/data/tool-tests.js +27 -0
  142. package/dist/data/tools.d.ts +358 -0
  143. package/dist/data/tools.js +48 -0
  144. package/dist/data/user-permissions.d.ts +15 -0
  145. package/dist/data/user-permissions.js +39 -0
  146. package/dist/data/user-permissions.test.d.ts +1 -0
  147. package/dist/data/user-permissions.test.js +252 -0
  148. package/dist/data/users.d.ts +38 -0
  149. package/dist/data/users.js +73 -0
  150. package/dist/data/workflow-logs.d.ts +106 -0
  151. package/dist/data/workflow-logs.js +67 -0
  152. package/dist/data/workflow-runs.d.ts +103 -0
  153. package/dist/data/workflow-runs.js +313 -0
  154. package/dist/data/workflows.d.ts +16 -0
  155. package/dist/data/workflows.js +21 -0
  156. package/dist/device/connection.d.ts +41 -0
  157. package/dist/device/connection.js +249 -0
  158. package/dist/device/connection.test.d.ts +1 -0
  159. package/dist/device/connection.test.js +292 -0
  160. package/dist/device/device-election.d.ts +36 -0
  161. package/dist/device/device-election.js +137 -0
  162. package/dist/device/device.d.ts +22 -0
  163. package/dist/device/device.js +110 -0
  164. package/dist/device/device.test.d.ts +1 -0
  165. package/dist/device/device.test.js +203 -0
  166. package/dist/device/get-trust-level.d.ts +3 -0
  167. package/dist/device/get-trust-level.js +87 -0
  168. package/dist/device/socket.type.d.ts +20 -0
  169. package/dist/device/socket.type.js +15 -0
  170. package/dist/device/streamed-socket.d.ts +27 -0
  171. package/dist/device/streamed-socket.js +154 -0
  172. package/dist/device/streamed-socket.test.d.ts +1 -0
  173. package/dist/device/streamed-socket.test.js +44 -0
  174. package/dist/events.d.ts +35 -0
  175. package/dist/events.js +128 -0
  176. package/dist/index.d.ts +33 -0
  177. package/dist/index.js +50 -0
  178. package/dist/keys.d.ts +51 -0
  179. package/dist/keys.js +234 -0
  180. package/dist/keys.test.d.ts +1 -0
  181. package/dist/keys.test.js +215 -0
  182. package/dist/mentions.d.ts +9 -0
  183. package/dist/mentions.js +46 -0
  184. package/dist/observable.d.ts +19 -0
  185. package/dist/observable.js +112 -0
  186. package/dist/observable.test.d.ts +1 -0
  187. package/dist/observable.test.js +183 -0
  188. package/dist/package-loader/get-require.d.ts +10 -0
  189. package/dist/package-loader/get-require.js +31 -0
  190. package/dist/package-loader/index.d.ts +1 -0
  191. package/dist/package-loader/index.js +17 -0
  192. package/dist/package-loader/package-loader.d.ts +16 -0
  193. package/dist/package-loader/package-loader.js +102 -0
  194. package/dist/peers-ui/peers-ui.d.ts +15 -0
  195. package/dist/peers-ui/peers-ui.js +23 -0
  196. package/dist/peers-ui/peers-ui.types.d.ts +35 -0
  197. package/dist/peers-ui/peers-ui.types.js +3 -0
  198. package/dist/rpc-types.d.ts +45 -0
  199. package/dist/rpc-types.js +47 -0
  200. package/dist/serial-json.d.ts +5 -0
  201. package/dist/serial-json.js +186 -0
  202. package/dist/serial-json.test.d.ts +1 -0
  203. package/dist/serial-json.test.js +86 -0
  204. package/dist/system-ids.d.ts +6 -0
  205. package/dist/system-ids.js +10 -0
  206. package/dist/tools/index.d.ts +1 -0
  207. package/dist/tools/index.js +17 -0
  208. package/dist/tools/tools-factory.d.ts +5 -0
  209. package/dist/tools/tools-factory.js +34 -0
  210. package/dist/types/app-nav.d.ts +18 -0
  211. package/dist/types/app-nav.js +10 -0
  212. package/dist/types/assistant-runner-args.d.ts +9 -0
  213. package/dist/types/assistant-runner-args.js +2 -0
  214. package/dist/types/field-type.d.ts +37 -0
  215. package/dist/types/field-type.js +26 -0
  216. package/dist/types/peer-device.d.ts +40 -0
  217. package/dist/types/peer-device.js +14 -0
  218. package/dist/types/peers-package.d.ts +23 -0
  219. package/dist/types/peers-package.js +2 -0
  220. package/dist/types/workflow-logger.d.ts +2 -0
  221. package/dist/types/workflow-logger.js +2 -0
  222. package/dist/types/workflow-run-context.d.ts +12 -0
  223. package/dist/types/workflow-run-context.js +2 -0
  224. package/dist/types/workflow.d.ts +72 -0
  225. package/dist/types/workflow.js +24 -0
  226. package/dist/types/zod-types.d.ts +7 -0
  227. package/dist/types/zod-types.js +12 -0
  228. package/dist/users.query.d.ts +13 -0
  229. package/dist/users.query.js +134 -0
  230. package/dist/utils.d.ts +39 -0
  231. package/dist/utils.js +240 -0
  232. package/dist/utils.test.d.ts +1 -0
  233. package/dist/utils.test.js +140 -0
  234. package/package.json +50 -0
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cursorUnion = cursorUnion;
4
+ exports.sortLikeSQL = sortLikeSQL;
5
+ exports.queryMerge = queryMerge;
6
+ exports.cursorMap = cursorMap;
7
+ exports.cursorFilter = cursorFilter;
8
+ const data_query_1 = require("./data-query");
9
+ function cursorUnion(cursors) {
10
+ let currentCursorIndex = 0;
11
+ const cursor = {
12
+ value: null,
13
+ next: async (skipPast) => {
14
+ if (currentCursorIndex >= cursors.length) {
15
+ cursor.value = null;
16
+ return null;
17
+ }
18
+ const currentCursor = cursors[currentCursorIndex];
19
+ const nextValue = await currentCursor.next(skipPast);
20
+ if (nextValue === null) {
21
+ currentCursorIndex++;
22
+ return cursor.next(skipPast);
23
+ }
24
+ cursor.value = nextValue;
25
+ return nextValue;
26
+ },
27
+ };
28
+ return (0, data_query_1.iterableCursor)(cursor);
29
+ }
30
+ function sortLikeSQL(sortByFields, valueA, valueB) {
31
+ for (const field of sortByFields) {
32
+ const isDesc = field.startsWith('-');
33
+ const key = isDesc ? field.slice(1) : field;
34
+ let a = valueA[key];
35
+ let b = valueB[key];
36
+ if (typeof a === 'string' && (b == null || b === undefined)) {
37
+ return isDesc ? -1 : 1;
38
+ }
39
+ if (typeof b === 'string' && (a == null || a === undefined)) {
40
+ return isDesc ? 1 : -1;
41
+ }
42
+ // convert undefined to -Infinity to preserve SQL-like sorting behavior
43
+ a = valueA[key] ?? -Infinity;
44
+ b = valueB[key] ?? -Infinity;
45
+ if (a < b)
46
+ return isDesc ? 1 : -1;
47
+ if (a > b)
48
+ return isDesc ? -1 : 1;
49
+ }
50
+ return 0;
51
+ }
52
+ function queryMerge(dataSources, filter = {}, opts = {}) {
53
+ if (dataSources.length === 0) {
54
+ const cursor = {
55
+ value: null,
56
+ next: async () => {
57
+ cursor.value = null;
58
+ return null;
59
+ },
60
+ };
61
+ return (0, data_query_1.iterableCursor)(cursor);
62
+ }
63
+ const primaryKeyName = dataSources[0].primaryKeyName;
64
+ const sortBy = (opts.sortBy?.length ? opts.sortBy : [primaryKeyName]);
65
+ // Create cursors for each data source
66
+ const cursors = dataSources.map(dataSource => (0, data_query_1.dataSourceCursor)(dataSource, filter, opts));
67
+ // Keep track of the current "head" value from each cursor
68
+ const heads = new Array(cursors.length).fill(null);
69
+ let initialized = false;
70
+ const cursor = {
71
+ value: null,
72
+ next: async (skipPast) => {
73
+ // Initialize all cursors on first call
74
+ if (!initialized) {
75
+ await Promise.all(cursors.map(async (cursor, i) => {
76
+ heads[i] = await cursor.next(skipPast);
77
+ }));
78
+ initialized = true;
79
+ }
80
+ // Find the next item according to sort order
81
+ let nextIndex = -1;
82
+ let nextValue = null;
83
+ for (let i = 0; i < heads.length; i++) {
84
+ const currentHead = heads[i];
85
+ if (currentHead !== null) {
86
+ if (nextValue === null || sortLikeSQL(sortBy, currentHead, nextValue) < 0) {
87
+ nextIndex = i;
88
+ nextValue = currentHead;
89
+ }
90
+ }
91
+ }
92
+ if (nextValue === null) {
93
+ cursor.value = null;
94
+ return null;
95
+ }
96
+ // Consume the selected value and get the next from that cursor
97
+ heads[nextIndex] = await cursors[nextIndex].next();
98
+ cursor.value = nextValue;
99
+ return nextValue;
100
+ },
101
+ };
102
+ return (0, data_query_1.iterableCursor)(cursor);
103
+ }
104
+ function cursorMap(sourceCursor, mapFn) {
105
+ const cursor = {
106
+ value: null,
107
+ next: async (skipPast) => {
108
+ if (skipPast !== undefined) {
109
+ throw new Error('skipPast is not supported for cursorMap since the mapped cursor has a different type than the source cursor');
110
+ }
111
+ const sourceValue = await sourceCursor.next();
112
+ if (sourceValue === null) {
113
+ cursor.value = null;
114
+ return null;
115
+ }
116
+ const mappedValue = await mapFn(sourceValue);
117
+ cursor.value = mappedValue;
118
+ return mappedValue;
119
+ },
120
+ };
121
+ return (0, data_query_1.iterableCursor)(cursor);
122
+ }
123
+ function cursorFilter(sourceCursor, filterFn) {
124
+ const cursor = {
125
+ value: null,
126
+ next: async (skipPast) => {
127
+ if (skipPast !== undefined) {
128
+ throw new Error('skipPast is not supported for cursorFilter since filtering changes the cursor iteration order');
129
+ }
130
+ while (true) {
131
+ const sourceValue = await sourceCursor.next();
132
+ if (sourceValue === null) {
133
+ cursor.value = null;
134
+ return null;
135
+ }
136
+ const shouldInclude = await filterFn(sourceValue);
137
+ if (shouldInclude) {
138
+ cursor.value = sourceValue;
139
+ return sourceValue;
140
+ }
141
+ // Continue to next item if this one doesn't match the filter
142
+ }
143
+ },
144
+ };
145
+ return (0, data_query_1.iterableCursor)(cursor);
146
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,455 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const multi_cursors_1 = require("./multi-cursors");
4
+ const data_query_1 = require("./data-query");
5
+ const factory_1 = require("./factory");
6
+ const field_type_1 = require("../../types/field-type");
7
+ function createMockCursor(items) {
8
+ let index = 0;
9
+ const cursor = {
10
+ value: null,
11
+ next: async (skipPast) => {
12
+ if (index >= items.length) {
13
+ cursor.value = null;
14
+ return null;
15
+ }
16
+ cursor.value = items[index];
17
+ index++;
18
+ return cursor.value;
19
+ },
20
+ };
21
+ return (0, data_query_1.iterableCursor)(cursor);
22
+ }
23
+ describe('cursorUnion', () => {
24
+ it('should return items from first cursor, then second cursor in order', async () => {
25
+ const cursor1 = createMockCursor([1, 2, 3]);
26
+ const cursor2 = createMockCursor([4, 5, 6]);
27
+ const unionCursor = (0, multi_cursors_1.cursorUnion)([cursor1, cursor2]);
28
+ const results = [];
29
+ for await (const item of unionCursor) {
30
+ results.push(item);
31
+ }
32
+ expect(results).toEqual([1, 2, 3, 4, 5, 6]);
33
+ });
34
+ it('should handle empty cursors gracefully', async () => {
35
+ const cursor1 = createMockCursor([1, 2]);
36
+ const cursor2 = createMockCursor([]);
37
+ const cursor3 = createMockCursor([3, 4]);
38
+ const unionCursor = (0, multi_cursors_1.cursorUnion)([cursor1, cursor2, cursor3]);
39
+ const results = [];
40
+ for await (const item of unionCursor) {
41
+ results.push(item);
42
+ }
43
+ expect(results).toEqual([1, 2, 3, 4]);
44
+ });
45
+ it('should return empty result when all cursors are empty', async () => {
46
+ const cursor1 = createMockCursor([]);
47
+ const cursor2 = createMockCursor([]);
48
+ const unionCursor = (0, multi_cursors_1.cursorUnion)([cursor1, cursor2]);
49
+ const results = [];
50
+ for await (const item of unionCursor) {
51
+ results.push(item);
52
+ }
53
+ expect(results).toEqual([]);
54
+ });
55
+ it('should work with single cursor', async () => {
56
+ const cursor1 = createMockCursor(['a', 'b', 'c']);
57
+ const unionCursor = (0, multi_cursors_1.cursorUnion)([cursor1]);
58
+ const results = [];
59
+ for await (const item of unionCursor) {
60
+ results.push(item);
61
+ }
62
+ expect(results).toEqual(['a', 'b', 'c']);
63
+ });
64
+ it('should work with no cursors', async () => {
65
+ const unionCursor = (0, multi_cursors_1.cursorUnion)([]);
66
+ const results = [];
67
+ for await (const item of unionCursor) {
68
+ results.push(item);
69
+ }
70
+ expect(results).toEqual([]);
71
+ });
72
+ it('should work with manual next() calls', async () => {
73
+ const cursor1 = createMockCursor([10, 20]);
74
+ const cursor2 = createMockCursor([30, 40]);
75
+ const unionCursor = (0, multi_cursors_1.cursorUnion)([cursor1, cursor2]);
76
+ const results = [];
77
+ while (await unionCursor.next()) {
78
+ results.push(unionCursor.value);
79
+ }
80
+ expect(results).toEqual([10, 20, 30, 40]);
81
+ });
82
+ it('should handle different data types', async () => {
83
+ const cursor1 = createMockCursor([{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }]);
84
+ const cursor2 = createMockCursor([{ id: 3, name: 'Bob' }]);
85
+ const unionCursor = (0, multi_cursors_1.cursorUnion)([cursor1, cursor2]);
86
+ const results = [];
87
+ for await (const item of unionCursor) {
88
+ results.push(item);
89
+ }
90
+ expect(results).toEqual([
91
+ { id: 1, name: 'John' },
92
+ { id: 2, name: 'Jane' },
93
+ { id: 3, name: 'Bob' }
94
+ ]);
95
+ });
96
+ it('should maintain cursor.value correctly', async () => {
97
+ const cursor1 = createMockCursor(['first', 'second']);
98
+ const cursor2 = createMockCursor(['third']);
99
+ const unionCursor = (0, multi_cursors_1.cursorUnion)([cursor1, cursor2]);
100
+ // First item
101
+ await unionCursor.next();
102
+ expect(unionCursor.value).toBe('first');
103
+ // Second item
104
+ await unionCursor.next();
105
+ expect(unionCursor.value).toBe('second');
106
+ // Third item (from second cursor)
107
+ await unionCursor.next();
108
+ expect(unionCursor.value).toBe('third');
109
+ // End of data
110
+ const result = await unionCursor.next();
111
+ expect(result).toBeNull();
112
+ expect(unionCursor.value).toBeNull();
113
+ });
114
+ });
115
+ function createMockDataSource(items, tableName, primaryKeyName = 'id') {
116
+ return (0, factory_1.arrayAsTable)(items, {
117
+ name: tableName,
118
+ primaryKeyName
119
+ });
120
+ }
121
+ describe('sortLikeSQL', () => {
122
+ it('should sort by ascending field correctly', () => {
123
+ const a = { id: 1, name: 'Alice' };
124
+ const b = { id: 2, name: 'Bob' };
125
+ expect((0, multi_cursors_1.sortLikeSQL)(['id'], a, b)).toBe(-1); // a < b
126
+ expect((0, multi_cursors_1.sortLikeSQL)(['id'], b, a)).toBe(1); // b > a
127
+ expect((0, multi_cursors_1.sortLikeSQL)(['id'], a, a)).toBe(0); // a === a
128
+ });
129
+ it('should sort by descending field correctly', () => {
130
+ const a = { id: 1, name: 'Alice' };
131
+ const b = { id: 2, name: 'Bob' };
132
+ expect((0, multi_cursors_1.sortLikeSQL)(['-id'], a, b)).toBe(1); // a > b (desc)
133
+ expect((0, multi_cursors_1.sortLikeSQL)(['-id'], b, a)).toBe(-1); // b < a (desc)
134
+ expect((0, multi_cursors_1.sortLikeSQL)(['-id'], a, a)).toBe(0); // a === a
135
+ });
136
+ it('should handle multiple sort fields', () => {
137
+ const a = { name: 'Alice', age: 25 };
138
+ const b = { name: 'Alice', age: 30 };
139
+ const c = { name: 'Bob', age: 25 };
140
+ // First by name, then by age
141
+ expect((0, multi_cursors_1.sortLikeSQL)(['name', 'age'], a, b)).toBe(-1); // same name, a.age < b.age
142
+ expect((0, multi_cursors_1.sortLikeSQL)(['name', 'age'], a, c)).toBe(-1); // a.name < c.name
143
+ expect((0, multi_cursors_1.sortLikeSQL)(['name', 'age'], c, a)).toBe(1); // c.name > a.name
144
+ });
145
+ it('should handle null/undefined values like SQL', () => {
146
+ const a = { id: 1, name: null };
147
+ const b = { id: 2, name: 'Bob' };
148
+ const c = { id: 3 }; // name is undefined
149
+ expect((0, multi_cursors_1.sortLikeSQL)(['name'], a, b)).toBe(-1); // null < string (treated as -Infinity)
150
+ expect((0, multi_cursors_1.sortLikeSQL)(['name'], c, b)).toBe(-1); // undefined < string (treated as -Infinity)
151
+ expect((0, multi_cursors_1.sortLikeSQL)(['name'], a, c)).toBe(0); // null === undefined (both -Infinity)
152
+ });
153
+ });
154
+ describe('queryMerge', () => {
155
+ it('should merge data from multiple sources in sorted order', async () => {
156
+ const dataSource1 = createMockDataSource([
157
+ { id: 1, name: 'Alice' },
158
+ { id: 3, name: 'Charlie' },
159
+ { id: 5, name: 'Eve' },
160
+ ], 'table1');
161
+ const dataSource2 = createMockDataSource([
162
+ { id: 2, name: 'Bob' },
163
+ { id: 4, name: 'David' },
164
+ { id: 6, name: 'Frank' },
165
+ ], 'table2');
166
+ const cursor = (0, multi_cursors_1.queryMerge)([dataSource1, dataSource2]);
167
+ const results = [];
168
+ for await (const item of cursor) {
169
+ results.push(item);
170
+ }
171
+ expect(results.map(r => r.id)).toEqual([1, 2, 3, 4, 5, 6]);
172
+ expect(results.map(r => r.name)).toEqual(['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank']);
173
+ });
174
+ it('should handle empty data sources', async () => {
175
+ const dataSource1 = (0, factory_1.arrayAsTable)([], {
176
+ name: 'table1',
177
+ primaryKeyName: 'id',
178
+ fields: [
179
+ { name: 'id', type: field_type_1.FieldType.number },
180
+ { name: 'name', type: field_type_1.FieldType.string }
181
+ ]
182
+ });
183
+ const dataSource2 = createMockDataSource([
184
+ { id: 1, name: 'Alice' },
185
+ ], 'table2');
186
+ const cursor = (0, multi_cursors_1.queryMerge)([dataSource1, dataSource2]);
187
+ const results = [];
188
+ for await (const item of cursor) {
189
+ results.push(item);
190
+ }
191
+ expect(results).toEqual([{ id: 1, name: 'Alice' }]);
192
+ });
193
+ it('should handle no data sources', async () => {
194
+ const cursor = (0, multi_cursors_1.queryMerge)([]);
195
+ const results = [];
196
+ for await (const item of cursor) {
197
+ results.push(item);
198
+ }
199
+ expect(results).toEqual([]);
200
+ });
201
+ it('should respect custom sort order', async () => {
202
+ // Use pre-sorted data to avoid arrayAsTable sorting issues
203
+ const dataSource1 = createMockDataSource([
204
+ { id: 1, name: 'Alice', age: 30 },
205
+ { id: 3, name: 'Charlie', age: 25 },
206
+ ], 'table1');
207
+ const dataSource2 = createMockDataSource([
208
+ { id: 2, name: 'Bob', age: 28 },
209
+ { id: 4, name: 'David', age: 22 },
210
+ ], 'table2');
211
+ // Sort by name ascending - data sources already have data in correct order
212
+ const cursor = (0, multi_cursors_1.queryMerge)([dataSource1, dataSource2], {}, { sortBy: ['name'] });
213
+ const results = [];
214
+ for await (const item of cursor) {
215
+ results.push(item);
216
+ }
217
+ expect(results.map(r => r.name)).toEqual(['Alice', 'Bob', 'Charlie', 'David']);
218
+ });
219
+ it('should work with single data source', async () => {
220
+ const dataSource = createMockDataSource([
221
+ { id: 1, name: 'Alice' },
222
+ { id: 2, name: 'Bob' },
223
+ { id: 3, name: 'Charlie' },
224
+ ], 'table1');
225
+ const cursor = (0, multi_cursors_1.queryMerge)([dataSource]);
226
+ const results = [];
227
+ for await (const item of cursor) {
228
+ results.push(item);
229
+ }
230
+ // Should be sorted by id (default primary key sort)
231
+ expect(results.map(r => r.id)).toEqual([1, 2, 3]);
232
+ });
233
+ it('should work with manual next() calls', async () => {
234
+ const dataSource1 = createMockDataSource([{ id: 1, name: 'Alice' }], 'table1');
235
+ const dataSource2 = createMockDataSource([{ id: 2, name: 'Bob' }], 'table2');
236
+ const cursor = (0, multi_cursors_1.queryMerge)([dataSource1, dataSource2]);
237
+ const results = [];
238
+ while (await cursor.next()) {
239
+ results.push(cursor.value);
240
+ }
241
+ expect(results.map(r => r?.id)).toEqual([1, 2]);
242
+ });
243
+ });
244
+ describe('cursorMap', () => {
245
+ it('should map cursor values using synchronous function', async () => {
246
+ const sourceCursor = createMockCursor([1, 2, 3, 4, 5]);
247
+ const mappedCursor = (0, multi_cursors_1.cursorMap)(sourceCursor, (x) => x * 2);
248
+ const results = [];
249
+ for await (const item of mappedCursor) {
250
+ results.push(item);
251
+ }
252
+ expect(results).toEqual([2, 4, 6, 8, 10]);
253
+ });
254
+ it('should map cursor values using async function', async () => {
255
+ const sourceCursor = createMockCursor(['a', 'b', 'c']);
256
+ const mappedCursor = (0, multi_cursors_1.cursorMap)(sourceCursor, async (x) => {
257
+ // Simulate async operation
258
+ await new Promise(resolve => setTimeout(resolve, 1));
259
+ return x.toUpperCase();
260
+ });
261
+ const results = [];
262
+ for await (const item of mappedCursor) {
263
+ results.push(item);
264
+ }
265
+ expect(results).toEqual(['A', 'B', 'C']);
266
+ });
267
+ it('should transform data types correctly', async () => {
268
+ const sourceCursor = createMockCursor([
269
+ { id: 1, name: 'Alice', age: 25 },
270
+ { id: 2, name: 'Bob', age: 30 },
271
+ { id: 3, name: 'Charlie', age: 35 }
272
+ ]);
273
+ const mappedCursor = (0, multi_cursors_1.cursorMap)(sourceCursor, (person) => `${person.name} is ${person.age} years old`);
274
+ const results = [];
275
+ for await (const item of mappedCursor) {
276
+ results.push(item);
277
+ }
278
+ expect(results).toEqual([
279
+ 'Alice is 25 years old',
280
+ 'Bob is 30 years old',
281
+ 'Charlie is 35 years old'
282
+ ]);
283
+ });
284
+ it('should handle empty cursors', async () => {
285
+ const sourceCursor = createMockCursor([]);
286
+ const mappedCursor = (0, multi_cursors_1.cursorMap)(sourceCursor, (x) => x * 2);
287
+ const results = [];
288
+ for await (const item of mappedCursor) {
289
+ results.push(item);
290
+ }
291
+ expect(results).toEqual([]);
292
+ });
293
+ it('should work with manual next() calls', async () => {
294
+ const sourceCursor = createMockCursor([10, 20, 30]);
295
+ const mappedCursor = (0, multi_cursors_1.cursorMap)(sourceCursor, (x) => x / 10);
296
+ const results = [];
297
+ while (await mappedCursor.next()) {
298
+ results.push(mappedCursor.value);
299
+ }
300
+ expect(results).toEqual([1, 2, 3]);
301
+ });
302
+ it('should maintain cursor.value correctly', async () => {
303
+ const sourceCursor = createMockCursor(['hello', 'world']);
304
+ const mappedCursor = (0, multi_cursors_1.cursorMap)(sourceCursor, (x) => x.length);
305
+ // First item
306
+ await mappedCursor.next();
307
+ expect(mappedCursor.value).toBe(5);
308
+ // Second item
309
+ await mappedCursor.next();
310
+ expect(mappedCursor.value).toBe(5);
311
+ // End of data
312
+ const result = await mappedCursor.next();
313
+ expect(result).toBeNull();
314
+ expect(mappedCursor.value).toBeNull();
315
+ });
316
+ it('should handle async errors in map function', async () => {
317
+ const sourceCursor = createMockCursor([1, 2, 3]);
318
+ const mappedCursor = (0, multi_cursors_1.cursorMap)(sourceCursor, async (x) => {
319
+ if (x === 2) {
320
+ throw new Error('Test error');
321
+ }
322
+ return x * 2;
323
+ });
324
+ const results = [];
325
+ let errorCaught = false;
326
+ try {
327
+ for await (const item of mappedCursor) {
328
+ results.push(item);
329
+ }
330
+ }
331
+ catch (error) {
332
+ errorCaught = true;
333
+ expect(error.message).toBe('Test error');
334
+ }
335
+ expect(errorCaught).toBe(true);
336
+ expect(results).toEqual([2]); // Only first item before error
337
+ });
338
+ it('should throw error when skipPast is used', async () => {
339
+ const sourceCursor = createMockCursor([1, 2, 3]);
340
+ const mappedCursor = (0, multi_cursors_1.cursorMap)(sourceCursor, (x) => x * 2);
341
+ await expect(mappedCursor.next(4)).rejects.toThrow('skipPast is not supported for cursorMap since the mapped cursor has a different type than the source cursor');
342
+ });
343
+ });
344
+ describe('cursorFilter', () => {
345
+ it('should filter cursor values using synchronous predicate', async () => {
346
+ const sourceCursor = createMockCursor([1, 2, 3, 4, 5, 6]);
347
+ const filteredCursor = (0, multi_cursors_1.cursorFilter)(sourceCursor, (x) => x % 2 === 0);
348
+ const results = [];
349
+ for await (const item of filteredCursor) {
350
+ results.push(item);
351
+ }
352
+ expect(results).toEqual([2, 4, 6]);
353
+ });
354
+ it('should filter cursor values using async predicate', async () => {
355
+ const sourceCursor = createMockCursor(['apple', 'banana', 'cherry', 'date']);
356
+ const filteredCursor = (0, multi_cursors_1.cursorFilter)(sourceCursor, async (x) => {
357
+ // Simulate async operation
358
+ await new Promise(resolve => setTimeout(resolve, 1));
359
+ return x.length > 5;
360
+ });
361
+ const results = [];
362
+ for await (const item of filteredCursor) {
363
+ results.push(item);
364
+ }
365
+ expect(results).toEqual(['banana', 'cherry']);
366
+ });
367
+ it('should filter objects based on properties', async () => {
368
+ const sourceCursor = createMockCursor([
369
+ { id: 1, name: 'Alice', age: 25 },
370
+ { id: 2, name: 'Bob', age: 30 },
371
+ { id: 3, name: 'Charlie', age: 35 },
372
+ { id: 4, name: 'David', age: 20 }
373
+ ]);
374
+ const filteredCursor = (0, multi_cursors_1.cursorFilter)(sourceCursor, (person) => person.age >= 30);
375
+ const results = [];
376
+ for await (const item of filteredCursor) {
377
+ results.push(item);
378
+ }
379
+ expect(results).toEqual([
380
+ { id: 2, name: 'Bob', age: 30 },
381
+ { id: 3, name: 'Charlie', age: 35 }
382
+ ]);
383
+ });
384
+ it('should handle empty cursors', async () => {
385
+ const sourceCursor = createMockCursor([]);
386
+ const filteredCursor = (0, multi_cursors_1.cursorFilter)(sourceCursor, (x) => x > 0);
387
+ const results = [];
388
+ for await (const item of filteredCursor) {
389
+ results.push(item);
390
+ }
391
+ expect(results).toEqual([]);
392
+ });
393
+ it('should handle cursors where no items match filter', async () => {
394
+ const sourceCursor = createMockCursor([1, 2, 3, 4, 5]);
395
+ const filteredCursor = (0, multi_cursors_1.cursorFilter)(sourceCursor, (x) => x > 10);
396
+ const results = [];
397
+ for await (const item of filteredCursor) {
398
+ results.push(item);
399
+ }
400
+ expect(results).toEqual([]);
401
+ });
402
+ it('should work with manual next() calls', async () => {
403
+ const sourceCursor = createMockCursor([10, 15, 20, 25, 30]);
404
+ const filteredCursor = (0, multi_cursors_1.cursorFilter)(sourceCursor, (x) => x >= 20);
405
+ const results = [];
406
+ while (await filteredCursor.next()) {
407
+ results.push(filteredCursor.value);
408
+ }
409
+ expect(results).toEqual([20, 25, 30]);
410
+ });
411
+ it('should maintain cursor.value correctly', async () => {
412
+ const sourceCursor = createMockCursor(['hello', 'hi', 'world', 'test']);
413
+ const filteredCursor = (0, multi_cursors_1.cursorFilter)(sourceCursor, (x) => x.length > 3);
414
+ // First item
415
+ await filteredCursor.next();
416
+ expect(filteredCursor.value).toBe('hello');
417
+ // Second item
418
+ await filteredCursor.next();
419
+ expect(filteredCursor.value).toBe('world');
420
+ // Third item
421
+ await filteredCursor.next();
422
+ expect(filteredCursor.value).toBe('test');
423
+ // End of data
424
+ const result = await filteredCursor.next();
425
+ expect(result).toBeNull();
426
+ expect(filteredCursor.value).toBeNull();
427
+ });
428
+ it('should throw error when skipPast is used', async () => {
429
+ const sourceCursor = createMockCursor([1, 2, 3]);
430
+ const filteredCursor = (0, multi_cursors_1.cursorFilter)(sourceCursor, (x) => x > 1);
431
+ await expect(filteredCursor.next(2)).rejects.toThrow('skipPast is not supported for cursorFilter since filtering changes the cursor iteration order');
432
+ });
433
+ it('should handle async errors in filter function', async () => {
434
+ const sourceCursor = createMockCursor([1, 2, 3]);
435
+ const filteredCursor = (0, multi_cursors_1.cursorFilter)(sourceCursor, async (x) => {
436
+ if (x === 2) {
437
+ throw new Error('Filter error');
438
+ }
439
+ return x > 0;
440
+ });
441
+ const results = [];
442
+ let errorCaught = false;
443
+ try {
444
+ for await (const item of filteredCursor) {
445
+ results.push(item);
446
+ }
447
+ }
448
+ catch (error) {
449
+ errorCaught = true;
450
+ expect(error.message).toBe('Filter error');
451
+ }
452
+ expect(errorCaught).toBe(true);
453
+ expect(results).toEqual([1]); // Only first item before error
454
+ });
455
+ });
@@ -0,0 +1,6 @@
1
+ export interface ISqlDb {
2
+ get: (sql: string, params?: any) => Promise<any>;
3
+ all: (sql: string, params?: any) => Promise<any[]>;
4
+ exec: (sql: string, params?: any) => Promise<void>;
5
+ close: () => Promise<void>;
6
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,38 @@
1
+ import { z } from "zod";
2
+ import { FieldType, IField } from "../../types/field-type";
3
+ import { DataFilter, ICursorIterable, IDataQueryParams, IDataSource } from "./data-query";
4
+ import { ITableMetaData } from "./types";
5
+ import { ISqlDb } from "./sql-db";
6
+ export declare class SQLDataSource<T extends {
7
+ [key: string]: any;
8
+ }> implements IDataSource<T> {
9
+ readonly db: ISqlDb;
10
+ readonly metaData: ITableMetaData;
11
+ readonly schema: z.AnyZodObject;
12
+ readonly tableName: string;
13
+ readonly primaryKeyName: string;
14
+ constructor(db: ISqlDb, metaData: ITableMetaData, schema?: z.AnyZodObject);
15
+ private buildTableSql;
16
+ private ensureTableAndIndexesExist;
17
+ private ensureTableIsNewest;
18
+ private tableBuild;
19
+ initTable(force?: boolean): Promise<boolean>;
20
+ get(id: string): Promise<T | undefined>;
21
+ list(filter?: DataFilter<T>, opts?: IDataQueryParams<T>): Promise<T[]>;
22
+ count(filter?: DataFilter<T>): Promise<number>;
23
+ cursor(filter?: DataFilter<T>, opts?: IDataQueryParams<T>): ICursorIterable<T>;
24
+ findOne(filter?: DataFilter<T>, opts?: {
25
+ enforceUnique?: boolean;
26
+ }): Promise<T | undefined>;
27
+ save(record: T): Promise<T>;
28
+ sqlRecordToJsRecord(record: any): T;
29
+ insert(record: T): Promise<T>;
30
+ update(record: T): Promise<T>;
31
+ delete(idOrRecord: string | T): Promise<void>;
32
+ dropTableIfExists(): Promise<void>;
33
+ clearTable(): Promise<void>;
34
+ initRecord(data?: Partial<T>): T;
35
+ }
36
+ export declare function jsValueToSqlValue(value: any, escapeQuote?: boolean): any;
37
+ export declare function sqlValueToJsValue(value: any, fieldType: FieldType, isArray: boolean): any;
38
+ export declare function globalDefaultValues(field: IField): {};