@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,244 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Table = void 0;
4
+ exports.getIconClassName = getIconClassName;
5
+ const data_query_1 = require("./data-query");
6
+ const doc_1 = require("./doc");
7
+ const subscribable_data_source_1 = require("./subscribable.data-source");
8
+ const types_1 = require("./types");
9
+ const utils_1 = require("../../utils");
10
+ const rpc_types_1 = require("../../rpc-types");
11
+ const lodash_1 = require("lodash");
12
+ class Table {
13
+ tableName;
14
+ primaryKeyName;
15
+ schema;
16
+ dataChangedEmitter;
17
+ dataChanged;
18
+ localOperationCache = new Map();
19
+ dataSource;
20
+ metaData;
21
+ groupId;
22
+ constructor(metaData, deps) {
23
+ this.metaData = metaData;
24
+ this.dataSource = deps.dataSource;
25
+ this.schema = deps.schema || (0, types_1.fieldsToSchema)(metaData.fields);
26
+ this.groupId = deps.groupId;
27
+ this.tableName = (0, utils_1.getFullTableName)(metaData);
28
+ this.primaryKeyName = metaData.primaryKeyName;
29
+ // Event setup with explicit dependency
30
+ const eventName = this.tableName + "_DataChanged";
31
+ this.dataChangedEmitter = deps.eventRegistry.getEmitter(eventName);
32
+ this.dataChanged = this.dataChangedEmitter.event;
33
+ if (rpc_types_1.isClient) {
34
+ // hack to not emit duplicate events from local client tables
35
+ this.dataChangedEmitter.emit = lodash_1.noop;
36
+ }
37
+ // Validation (works for both patterns since this.metaData is set)
38
+ const primaryKeyIsValid = this.metaData.fields.find(f => f.name === this.metaData.primaryKeyName);
39
+ if (!primaryKeyIsValid) {
40
+ throw new Error(`Table "${this.tableName}", primary key "${this.metaData.primaryKeyName}" is not a valid field name`);
41
+ }
42
+ // Find any underlying SubscribableDataSource to intercept its events
43
+ let subscribableDataSource = undefined;
44
+ let _dataSource = this.dataSource;
45
+ while (!subscribableDataSource && _dataSource) {
46
+ if (_dataSource instanceof subscribable_data_source_1.SubscribableDataSource) {
47
+ subscribableDataSource = _dataSource;
48
+ break;
49
+ }
50
+ else {
51
+ // traverse to the underlying data source to try to find a SubscribableDataSource
52
+ _dataSource = _dataSource.dataSource;
53
+ }
54
+ }
55
+ // Event setup is now handled in constructor above
56
+ // Intercept and forward events with appropriate source marking
57
+ if (subscribableDataSource) {
58
+ subscribableDataSource.dataChanged.subscribe((event) => {
59
+ const recordId = this.getRecordId(event.dataObject);
60
+ const cacheKey = `${recordId}-${event.op}`;
61
+ if (!this.localOperationCache.has(cacheKey)) {
62
+ this.dataChangedEmitter.emit({
63
+ dataObject: event.dataObject,
64
+ op: event.op,
65
+ source: 'remote',
66
+ });
67
+ }
68
+ });
69
+ }
70
+ }
71
+ getRecordId(record) {
72
+ return record[this.primaryKeyName];
73
+ }
74
+ setLocalOperation(recordId, operation) {
75
+ const cacheKey = `${recordId}-${operation}`;
76
+ this.localOperationCache.set(cacheKey, true);
77
+ }
78
+ clearLocalOperation(recordId, operation) {
79
+ const cacheKey = `${recordId}-${operation}`;
80
+ this.localOperationCache.delete(cacheKey);
81
+ }
82
+ cachedRecords = {};
83
+ async get(id, opts = {}) {
84
+ const { useCache } = opts;
85
+ let cacheTtlMs = opts.cacheTtlMs || 1000 * 30; // cache ttl default is 30 seconds
86
+ if (useCache && this.cachedRecords[id]) {
87
+ return this.cachedRecords[id];
88
+ }
89
+ const promise = new Promise(async (resolve, reject) => {
90
+ try {
91
+ let record;
92
+ record = await this.dataSource.get(id);
93
+ if (!record) {
94
+ cacheTtlMs = 1000; // very short cache ttl for non-existent records
95
+ }
96
+ resolve(record);
97
+ }
98
+ catch (err) {
99
+ cacheTtlMs = 1000; // very short cache ttl on error
100
+ reject(err);
101
+ }
102
+ finally {
103
+ setTimeout(() => {
104
+ delete this.cachedRecords[id];
105
+ }, cacheTtlMs);
106
+ }
107
+ });
108
+ if (useCache) {
109
+ this.cachedRecords[id] = promise;
110
+ }
111
+ return promise;
112
+ }
113
+ async list(filter = {}, opts = {}) {
114
+ return this.dataSource.list(filter, opts);
115
+ }
116
+ ;
117
+ async count(filter = {}) {
118
+ return (0, data_query_1.dataSourceCount)(this.dataSource, filter);
119
+ }
120
+ ;
121
+ cursor(filter = {}, opts = {}) {
122
+ return (0, data_query_1.dataSourceCursor)(this.dataSource, filter, opts);
123
+ }
124
+ async findOne(filter = {}, opts = {}) {
125
+ if (!opts?.enforceUnique) {
126
+ const records = await this.list(filter, { pageSize: 1 });
127
+ return records[0];
128
+ }
129
+ else {
130
+ const records = await this.list(filter, { pageSize: 2 });
131
+ if (records.length > 1) {
132
+ throw new Error(`Matched more than one record for ${this.tableName} with query ${JSON.stringify(filter)}`);
133
+ }
134
+ return records[0];
135
+ }
136
+ }
137
+ async save(record, opts) {
138
+ const recordId = this.getRecordId(record);
139
+ if (recordId) {
140
+ delete this.cachedRecords[recordId];
141
+ }
142
+ const isInsert = !recordId || !(await this.get(recordId));
143
+ const operation = isInsert ? 'insert' : 'update';
144
+ this.setLocalOperation(recordId, operation);
145
+ let result;
146
+ try {
147
+ // if (isInsert) {
148
+ // result = await this.dataSource.insert(record);
149
+ // } else {
150
+ // result = await this.dataSource.update(record);
151
+ // }
152
+ result = await this.dataSource.save(record, opts);
153
+ }
154
+ finally {
155
+ this.clearLocalOperation(recordId, operation);
156
+ }
157
+ this.dataChangedEmitter.emit({
158
+ dataObject: result,
159
+ op: operation,
160
+ source: 'local',
161
+ });
162
+ return result;
163
+ }
164
+ async insert(record) {
165
+ const recordId = this.getRecordId(record);
166
+ this.setLocalOperation(recordId, 'insert');
167
+ let result;
168
+ try {
169
+ result = await this.dataSource.insert(record);
170
+ }
171
+ finally {
172
+ this.clearLocalOperation(recordId, 'insert');
173
+ }
174
+ this.dataChangedEmitter.emit({
175
+ dataObject: result,
176
+ op: 'insert',
177
+ source: 'local',
178
+ });
179
+ return result;
180
+ }
181
+ async update(record) {
182
+ delete this.cachedRecords[record[this.metaData.primaryKeyName]];
183
+ const recordId = this.getRecordId(record);
184
+ this.setLocalOperation(recordId, 'update');
185
+ let result;
186
+ try {
187
+ result = await this.dataSource.update(record);
188
+ }
189
+ finally {
190
+ this.clearLocalOperation(recordId, 'update');
191
+ }
192
+ this.dataChangedEmitter.emit({
193
+ dataObject: result,
194
+ op: 'update',
195
+ source: 'local',
196
+ });
197
+ return result;
198
+ }
199
+ async delete(idOrRecord) {
200
+ const primaryKey = typeof idOrRecord === 'string' ? idOrRecord : idOrRecord[this.metaData.primaryKeyName];
201
+ const existingRecord = typeof idOrRecord === 'object' ? idOrRecord : await this.get(primaryKey);
202
+ delete this.cachedRecords[primaryKey];
203
+ if (!existingRecord) {
204
+ return; // nothing to delete
205
+ }
206
+ this.setLocalOperation(primaryKey, 'delete');
207
+ try {
208
+ await this.dataSource.delete(idOrRecord);
209
+ }
210
+ finally {
211
+ this.clearLocalOperation(primaryKey, 'delete');
212
+ }
213
+ this.dataChangedEmitter.emit({
214
+ dataObject: existingRecord,
215
+ op: 'delete',
216
+ source: 'local',
217
+ });
218
+ }
219
+ initRecord(data = {}) {
220
+ const defaults = {};
221
+ for (const field of this.metaData.fields) {
222
+ const zodField = this.schema.shape[field.name];
223
+ const value = zodField.safeParse(data[field.name]);
224
+ if (value.success) {
225
+ // @ts-ignore
226
+ defaults[field.name] = value.data;
227
+ }
228
+ }
229
+ return { ...defaults, ...data };
230
+ }
231
+ initDoc(record) {
232
+ return (0, doc_1.initDoc)(record, this);
233
+ }
234
+ getDoc(id) {
235
+ // TODO figure out the best way to make this work with react+observables
236
+ const doc = (0, doc_1.initDoc)({ [this.metaData.primaryKeyName]: id }, this);
237
+ // doc.load();
238
+ return doc;
239
+ }
240
+ }
241
+ exports.Table = Table;
242
+ function getIconClassName(table) {
243
+ return table.metaData.iconClassName ?? 'bi bi-question';
244
+ }
@@ -0,0 +1,20 @@
1
+ import { z } from 'zod';
2
+ import { IField } from '../../types/field-type';
3
+ export interface ITableMetaData {
4
+ tableId?: string;
5
+ name: string;
6
+ description: string;
7
+ primaryKeyName: string;
8
+ fields: IField[];
9
+ indexes?: {
10
+ fields: (string | {
11
+ name: string;
12
+ order: 'ASC' | 'DESC';
13
+ })[];
14
+ unique?: true;
15
+ }[];
16
+ iconClassName?: string;
17
+ localOnly?: boolean;
18
+ }
19
+ export declare function fieldsToSchema(fields: IField[]): z.AnyZodObject;
20
+ export declare function schemaToFields(schema: z.AnyZodObject): IField[];
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fieldsToSchema = fieldsToSchema;
4
+ exports.schemaToFields = schemaToFields;
5
+ const zod_1 = require("zod");
6
+ const field_type_1 = require("../../types/field-type");
7
+ const utils_1 = require("../../utils");
8
+ function fieldsToSchema(fields) {
9
+ let argsSchema = zod_1.z.object({});
10
+ for (const argSchema of fields) {
11
+ const { name, description, type, isArray, defaultValue, optional } = argSchema;
12
+ let propertyType;
13
+ switch (type) {
14
+ case 'id':
15
+ propertyType = zod_1.z.string().refine((id => (0, utils_1.isid)(id)), { message: 'Invalid id' });
16
+ break;
17
+ case 'string':
18
+ propertyType = zod_1.z.string();
19
+ break;
20
+ case 'number':
21
+ propertyType = zod_1.z.number();
22
+ break;
23
+ case 'boolean':
24
+ propertyType = zod_1.z.boolean();
25
+ break;
26
+ case 'Date':
27
+ propertyType = zod_1.z.date();
28
+ break;
29
+ case 'object':
30
+ propertyType = zod_1.z.object({});
31
+ break;
32
+ default:
33
+ propertyType = zod_1.z.any();
34
+ }
35
+ if (isArray) {
36
+ propertyType = propertyType.array();
37
+ }
38
+ if (optional) {
39
+ propertyType = propertyType.optional();
40
+ }
41
+ if (defaultValue) {
42
+ // @ts-ignore
43
+ propertyType = propertyType.default(defaultValue);
44
+ }
45
+ propertyType = propertyType.describe(description);
46
+ const newProperty = { [name]: propertyType };
47
+ argsSchema = argsSchema.extend(newProperty);
48
+ }
49
+ return argsSchema;
50
+ }
51
+ function schemaToFields(schema) {
52
+ const fields = [];
53
+ for (const name of Object.keys(schema.shape)) {
54
+ const field = schema.shape[name];
55
+ let type = field_type_1.FieldType.any;
56
+ let _def = field._def;
57
+ let isArray = undefined;
58
+ while (true) {
59
+ if (_def.typeName === 'ZodArray') {
60
+ isArray = true;
61
+ }
62
+ if (_def.innerType) {
63
+ _def = _def.innerType._def;
64
+ continue;
65
+ }
66
+ if (_def.type) {
67
+ _def = _def.type._def;
68
+ continue;
69
+ }
70
+ break;
71
+ }
72
+ switch (_def.typeName) {
73
+ case 'ZodString':
74
+ type = field_type_1.FieldType.string;
75
+ break;
76
+ case 'ZodNumber':
77
+ type = field_type_1.FieldType.number;
78
+ break;
79
+ case 'ZodBoolean':
80
+ type = field_type_1.FieldType.boolean;
81
+ break;
82
+ case 'ZodDate':
83
+ type = field_type_1.FieldType.Date;
84
+ break;
85
+ case 'ZodObject':
86
+ type = field_type_1.FieldType.object;
87
+ break;
88
+ case 'ZodNativeEnum':
89
+ // number or string
90
+ const hasNumber = Object.values(_def.values).some(v => typeof v === 'number');
91
+ type = hasNumber ? field_type_1.FieldType.number : field_type_1.FieldType.string;
92
+ break;
93
+ default:
94
+ type = field_type_1.FieldType.any;
95
+ }
96
+ if ((name === 'id' || name.endsWith('Id')) && type === 'string') {
97
+ type = field_type_1.FieldType.id;
98
+ }
99
+ if (!isArray && field._def.typeName === 'ZodArray') {
100
+ isArray = true;
101
+ // isArray = field._def.typeName === 'ZodArray' || undefined;
102
+ }
103
+ const optional = field._def.typeName === 'ZodOptional' || undefined;
104
+ const description = field._def.description;
105
+ const defaultValue = field._def.defaultValue;
106
+ const newField = { name, type, isArray, optional, description, defaultValue };
107
+ Object.keys(newField).forEach(k => {
108
+ // @ts-ignore
109
+ if (newField[k] === undefined)
110
+ delete newField[k];
111
+ });
112
+ fields.push(newField);
113
+ }
114
+ return fields;
115
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const zod_1 = require("zod");
4
+ const types_1 = require("./types");
5
+ const field_type_1 = require("../../types/field-type");
6
+ const utils_1 = require("../../utils");
7
+ describe('types', () => {
8
+ it('fieldsToSchema', () => {
9
+ const someDate = new Date();
10
+ const groupFields = [
11
+ { name: 'groupId', description: 'The id of the group', type: field_type_1.FieldType.id },
12
+ { name: 'groupName', description: 'The name of the group', type: field_type_1.FieldType.string },
13
+ { name: 'groupDescription', description: 'The description of the group', type: field_type_1.FieldType.string },
14
+ { name: 'createdAt', description: 'The date the group was created', type: field_type_1.FieldType.Date, defaultValue: () => someDate },
15
+ { name: 'owningUserIds', description: 'The ids of the users who own the group', type: field_type_1.FieldType.string, isArray: true },
16
+ { name: 'isPublic', description: 'Whether the group is public or private', type: field_type_1.FieldType.boolean, optional: true },
17
+ { name: 'fileIds', description: 'The ids of files attached to this chat entry', type: field_type_1.FieldType.string, isArray: true, optional: true },
18
+ ];
19
+ const groupSchema = (0, types_1.fieldsToSchema)(groupFields);
20
+ const groupSchemaExpected = zod_1.z.object({
21
+ groupId: zod_1.z.string().describe('The id of the group'),
22
+ groupName: zod_1.z.string().describe('The name of the group'),
23
+ groupDescription: zod_1.z.string().describe('The description of the group'),
24
+ createdAt: zod_1.z.date().describe('The date the group was created').default(() => someDate),
25
+ owningUserIds: zod_1.z.string().array().describe('The ids of the users who own the group'),
26
+ isPublic: zod_1.z.boolean().optional().describe('Whether the group is public or private'),
27
+ fileIds: zod_1.z.string().array().optional().describe('The ids of files attached to this chat entry'),
28
+ });
29
+ const aGroup = {
30
+ groupId: (0, utils_1.newid)(),
31
+ groupName: 'group',
32
+ groupDescription: 'group description',
33
+ createdAt: new Date(),
34
+ owningUserIds: ['1'],
35
+ isPublic: true,
36
+ };
37
+ const aGroup2 = { ...aGroup, createdAt: undefined };
38
+ const r1 = groupSchema.parse(aGroup2);
39
+ const r1e = groupSchemaExpected.parse(aGroup2);
40
+ expect(r1.createdAt).toEqual(someDate);
41
+ expect(r1e.createdAt).toEqual(someDate);
42
+ // @ts-expect-error
43
+ delete aGroup.groupId;
44
+ expect(() => groupSchema.parse(aGroup)).toThrow('groupId');
45
+ expect(() => groupSchemaExpected.parse(aGroup)).toThrow('groupId');
46
+ });
47
+ it('schemaToFields', () => {
48
+ const groupSchema = zod_1.z.object({
49
+ groupId: zod_1.z.string().describe('The id of the group'),
50
+ groupName: zod_1.z.string().describe('The name of the group'),
51
+ groupDescription: zod_1.z.string().describe('The description of the group'),
52
+ createdAt: zod_1.z.date().describe('The date the group was created'), //.default(() => new Date()),
53
+ owningUserIds: zod_1.z.string().array().describe('The ids of the users who own the group'),
54
+ isPublic: zod_1.z.boolean().optional().describe('Whether the group is public or private'),
55
+ instructionResults: zod_1.z.any().array().describe('The results of the instructions that have been run.'),
56
+ fileIds: zod_1.z.string().array().optional().describe('The ids of files attached to this chat entry'),
57
+ });
58
+ const groupFields = (0, types_1.schemaToFields)(groupSchema);
59
+ const groupFieldsExpected = [
60
+ { name: 'groupId', description: 'The id of the group', type: field_type_1.FieldType.id },
61
+ { name: 'groupName', description: 'The name of the group', type: field_type_1.FieldType.string },
62
+ { name: 'groupDescription', description: 'The description of the group', type: field_type_1.FieldType.string },
63
+ { name: 'createdAt', description: 'The date the group was created', type: field_type_1.FieldType.Date, }, //defaultValue: () => new Date() },
64
+ { name: 'owningUserIds', description: 'The ids of the users who own the group', type: field_type_1.FieldType.string, isArray: true },
65
+ { name: 'isPublic', description: 'Whether the group is public or private', type: field_type_1.FieldType.boolean, optional: true },
66
+ { name: 'instructionResults', description: 'The results of the instructions that have been run.', type: field_type_1.FieldType.any, isArray: true },
67
+ { name: 'fileIds', description: 'The ids of files attached to this chat entry', type: field_type_1.FieldType.string, isArray: true, optional: true },
68
+ ];
69
+ expect(groupFields).toEqual(groupFieldsExpected);
70
+ });
71
+ });
@@ -0,0 +1,7 @@
1
+ import type { IPackage } from './packages';
2
+ /**
3
+ * Verifies that a package update signature is valid, throws on invalid signature
4
+ * @param packageObj The package record to verify
5
+ * @throws Error if signature is invalid or unauthorized
6
+ */
7
+ export declare function verifyPackageSignature(packageObj: IPackage, groupId: string): Promise<void>;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.verifyPackageSignature = verifyPackageSignature;
4
+ const keys_1 = require("../keys");
5
+ const group_permissions_1 = require("./group-permissions");
6
+ /**
7
+ * Verifies that a package update signature is valid, throws on invalid signature
8
+ * @param packageObj The package record to verify
9
+ * @throws Error if signature is invalid or unauthorized
10
+ */
11
+ async function verifyPackageSignature(packageObj, groupId) {
12
+ (0, keys_1.verifyObjectSignature)(packageObj);
13
+ const signerPublicKey = (0, keys_1.getPublicKeyFromObjectSignature)(packageObj) ?? '';
14
+ const signerRole = await (0, group_permissions_1.getUserRoleFromPublicKey)(groupId, signerPublicKey);
15
+ if (signerRole < group_permissions_1.GroupMemberRole.Admin) {
16
+ throw new Error('Only group admins can create or update packages');
17
+ }
18
+ }
@@ -0,0 +1,92 @@
1
+ import { z } from "zod";
2
+ import type { DataContext } from "../context/data-context";
3
+ import { ISaveOptions, Table } from "./orm";
4
+ declare const schema: z.ZodObject<{
5
+ packageId: z.ZodString;
6
+ name: z.ZodString;
7
+ description: z.ZodString;
8
+ createdBy: z.ZodString;
9
+ localPath: z.ZodString;
10
+ disabled: z.ZodOptional<z.ZodBoolean>;
11
+ remoteRepo: z.ZodOptional<z.ZodString>;
12
+ appNavs: z.ZodOptional<z.ZodArray<z.ZodObject<{
13
+ name: z.ZodString;
14
+ displayName: z.ZodOptional<z.ZodString>;
15
+ iconClassName: z.ZodString;
16
+ navigationPath: z.ZodString;
17
+ }, "strip", z.ZodTypeAny, {
18
+ name: string;
19
+ iconClassName: string;
20
+ navigationPath: string;
21
+ displayName?: string | undefined;
22
+ }, {
23
+ name: string;
24
+ iconClassName: string;
25
+ navigationPath: string;
26
+ displayName?: string | undefined;
27
+ }>, "many">>;
28
+ packageBundleFileId: z.ZodString;
29
+ packageBundleFileHash: z.ZodString;
30
+ routesBundleFileId: z.ZodOptional<z.ZodString>;
31
+ routesBundleFileHash: z.ZodOptional<z.ZodString>;
32
+ uiBundleFileId: z.ZodOptional<z.ZodString>;
33
+ uiBundleFileHash: z.ZodOptional<z.ZodString>;
34
+ signature: z.ZodString;
35
+ }, "strip", z.ZodTypeAny, {
36
+ name: string;
37
+ description: string;
38
+ signature: string;
39
+ createdBy: string;
40
+ packageId: string;
41
+ localPath: string;
42
+ packageBundleFileId: string;
43
+ packageBundleFileHash: string;
44
+ disabled?: boolean | undefined;
45
+ remoteRepo?: string | undefined;
46
+ appNavs?: {
47
+ name: string;
48
+ iconClassName: string;
49
+ navigationPath: string;
50
+ displayName?: string | undefined;
51
+ }[] | undefined;
52
+ routesBundleFileId?: string | undefined;
53
+ routesBundleFileHash?: string | undefined;
54
+ uiBundleFileId?: string | undefined;
55
+ uiBundleFileHash?: string | undefined;
56
+ }, {
57
+ name: string;
58
+ description: string;
59
+ signature: string;
60
+ createdBy: string;
61
+ packageId: string;
62
+ localPath: string;
63
+ packageBundleFileId: string;
64
+ packageBundleFileHash: string;
65
+ disabled?: boolean | undefined;
66
+ remoteRepo?: string | undefined;
67
+ appNavs?: {
68
+ name: string;
69
+ iconClassName: string;
70
+ navigationPath: string;
71
+ displayName?: string | undefined;
72
+ }[] | undefined;
73
+ routesBundleFileId?: string | undefined;
74
+ routesBundleFileHash?: string | undefined;
75
+ uiBundleFileId?: string | undefined;
76
+ uiBundleFileHash?: string | undefined;
77
+ }>;
78
+ export type IPackage = z.infer<typeof schema>;
79
+ export declare class PackagesTable extends Table<IPackage> {
80
+ static isPassthrough: boolean;
81
+ insert(packageObj: IPackage, opts?: ISaveOptions): Promise<IPackage>;
82
+ update(packageObj: IPackage, opts?: ISaveOptions): Promise<IPackage>;
83
+ save(packageObj: IPackage, opts?: ISaveOptions): Promise<IPackage>;
84
+ signAndSave(packageObj: IPackage, opts?: ISaveOptions): Promise<IPackage>;
85
+ private static addSignatureToPackage;
86
+ static enablePackageSigning(fn: (packageObj: IPackage) => IPackage): void;
87
+ delete(packageId: string): Promise<void>;
88
+ }
89
+ export declare function Packages(dataContext?: DataContext): PackagesTable;
90
+ export declare const packagesRootDir: import("./persistent-vars").PersistentVar<string>;
91
+ export declare const reloadPackagesOnPageRefresh: import("./persistent-vars").PersistentVar<boolean>;
92
+ export {};
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.reloadPackagesOnPageRefresh = exports.packagesRootDir = exports.PackagesTable = void 0;
4
+ exports.Packages = Packages;
5
+ const zod_1 = require("zod");
6
+ const app_nav_1 = require("../types/app-nav");
7
+ const types_1 = require("./orm/types");
8
+ const persistent_vars_1 = require("./persistent-vars");
9
+ const table_definitions_system_1 = require("./orm/table-definitions.system");
10
+ const context_1 = require("../context");
11
+ const orm_1 = require("./orm");
12
+ const package_permissions_1 = require("./package-permissions");
13
+ const schema = zod_1.z.object({
14
+ packageId: zod_1.z.string(),
15
+ name: zod_1.z.string(),
16
+ description: zod_1.z.string(),
17
+ createdBy: zod_1.z.string().describe('The user who created the package'),
18
+ localPath: zod_1.z.string().describe('The local path where the package is stored'),
19
+ disabled: zod_1.z.boolean().optional().describe("Whether the package's components should be loaded and included in the app runtime"),
20
+ remoteRepo: zod_1.z.string().optional().describe('The remote repository where the package is stored'),
21
+ appNavs: app_nav_1.appNavSchema.array().optional().describe('The app navigation items that this package provides'),
22
+ packageBundleFileId: zod_1.z.string().describe('File ID of the package bundle (required)'),
23
+ packageBundleFileHash: zod_1.z.string().describe('Hash of the package bundle file (required)'),
24
+ routesBundleFileId: zod_1.z.string().optional().describe('File ID of the routes bundle (optional)'),
25
+ routesBundleFileHash: zod_1.z.string().optional().describe('Hash of the routes bundle (optional)'),
26
+ uiBundleFileId: zod_1.z.string().optional().describe('File ID of the UI bundle (optional)'),
27
+ uiBundleFileHash: zod_1.z.string().optional().describe('Hash of the UI bundle (optional)'),
28
+ signature: zod_1.z.string().describe('The signed hash of this data excluding the signature itself'),
29
+ });
30
+ const metaData = {
31
+ name: 'Packages',
32
+ description: 'The Peers packages that this computer is aware of (some may be disabled)',
33
+ primaryKeyName: 'packageId',
34
+ iconClassName: 'bi bi-box-fill',
35
+ fields: (0, types_1.schemaToFields)(schema),
36
+ };
37
+ class PackagesTable extends orm_1.Table {
38
+ static isPassthrough = false;
39
+ async insert(packageObj, opts) {
40
+ return this.save(packageObj, opts);
41
+ }
42
+ async update(packageObj, opts) {
43
+ return this.save(packageObj, opts);
44
+ }
45
+ async save(packageObj, opts) {
46
+ if (PackagesTable.isPassthrough) {
47
+ return super.save(packageObj, opts);
48
+ }
49
+ if (!this.groupId) {
50
+ // users can do whatever they want to packages in their personal space
51
+ return super.save(packageObj, opts);
52
+ }
53
+ try {
54
+ await (0, package_permissions_1.verifyPackageSignature)(packageObj, this.groupId);
55
+ }
56
+ catch (err) {
57
+ throw new Error('Package verification failed. Did you mean to call `signAndSave`?', { cause: err });
58
+ }
59
+ return super.save(packageObj, opts);
60
+ }
61
+ async signAndSave(packageObj, opts) {
62
+ if (!PackagesTable.addSignatureToPackage) {
63
+ throw new Error('Package signing is not enabled. Call PackagesTable.enablePackageSigning(fn) to enable it.');
64
+ }
65
+ packageObj = await PackagesTable.addSignatureToPackage(packageObj);
66
+ return super.save(packageObj, opts);
67
+ }
68
+ static addSignatureToPackage = undefined;
69
+ static enablePackageSigning(fn) {
70
+ this.addSignatureToPackage = fn;
71
+ }
72
+ async delete(packageId) {
73
+ // anyone (with write permissions) can delete packages since that isn't a security risk (unless something else is relying on a package to be present?)
74
+ return super.delete(packageId);
75
+ // const userContext = await getUserContext();
76
+ // const userContextPackages = Packages(userContext.userDataContext);
77
+ // if (userContextPackages === this) {
78
+ // return super.delete(packageId);
79
+ // }
80
+ // throw new Error('Only deleting packages from the user context Packages table is allowed');
81
+ }
82
+ }
83
+ exports.PackagesTable = PackagesTable;
84
+ (0, table_definitions_system_1.registerSystemTableDefinition)(metaData, schema, PackagesTable);
85
+ function Packages(dataContext) {
86
+ return (0, context_1.getTableContainer)(dataContext).getTable(metaData, schema, PackagesTable);
87
+ }
88
+ exports.packagesRootDir = (0, persistent_vars_1.deviceVar)('packagesRootDir', { defaultValue: '~/peers-packages' });
89
+ exports.reloadPackagesOnPageRefresh = (0, persistent_vars_1.deviceVar)('reloadPackagesOnPageRefresh', { defaultValue: true, });
90
+ // export const packageLocalPathsResolved = persistentVar<{ [packageId: string]: string}>('packageLocalPathsResolved', { defaultValue: {}, scope: 'device' });