querysub 0.2.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 (169) hide show
  1. package/.dependency-cruiser.js +304 -0
  2. package/.eslintrc.js +51 -0
  3. package/.github/copilot-instructions.md +1 -0
  4. package/.vscode/settings.json +25 -0
  5. package/bin/deploy.js +4 -0
  6. package/bin/function.js +4 -0
  7. package/bin/server.js +4 -0
  8. package/costsBenefits.txt +112 -0
  9. package/deploy.ts +3 -0
  10. package/inject.ts +1 -0
  11. package/package.json +60 -0
  12. package/prompts.txt +54 -0
  13. package/spec.txt +820 -0
  14. package/src/-a-archives/archiveCache.ts +913 -0
  15. package/src/-a-archives/archives.ts +148 -0
  16. package/src/-a-archives/archivesBackBlaze.ts +792 -0
  17. package/src/-a-archives/archivesDisk.ts +418 -0
  18. package/src/-a-archives/copyLocalToBackblaze.ts +24 -0
  19. package/src/-a-auth/certs.ts +517 -0
  20. package/src/-a-auth/der.ts +122 -0
  21. package/src/-a-auth/ed25519.ts +1015 -0
  22. package/src/-a-auth/node-forge-ed25519.d.ts +17 -0
  23. package/src/-b-authorities/dnsAuthority.ts +203 -0
  24. package/src/-b-authorities/emailAuthority.ts +57 -0
  25. package/src/-c-identity/IdentityController.ts +200 -0
  26. package/src/-d-trust/NetworkTrust2.ts +150 -0
  27. package/src/-e-certs/EdgeCertController.ts +288 -0
  28. package/src/-e-certs/certAuthority.ts +192 -0
  29. package/src/-f-node-discovery/NodeDiscovery.ts +543 -0
  30. package/src/-g-core-values/NodeCapabilities.ts +134 -0
  31. package/src/-g-core-values/oneTimeForward.ts +91 -0
  32. package/src/-h-path-value-serialize/PathValueSerializer.ts +769 -0
  33. package/src/-h-path-value-serialize/stringSerializer.ts +176 -0
  34. package/src/0-path-value-core/LoggingClient.tsx +24 -0
  35. package/src/0-path-value-core/NodePathAuthorities.ts +978 -0
  36. package/src/0-path-value-core/PathController.ts +1 -0
  37. package/src/0-path-value-core/PathValueCommitter.ts +565 -0
  38. package/src/0-path-value-core/PathValueController.ts +231 -0
  39. package/src/0-path-value-core/archiveLocks/ArchiveLocks.ts +154 -0
  40. package/src/0-path-value-core/archiveLocks/ArchiveLocks2.ts +820 -0
  41. package/src/0-path-value-core/archiveLocks/archiveSnapshots.ts +180 -0
  42. package/src/0-path-value-core/debugLogs.ts +90 -0
  43. package/src/0-path-value-core/pathValueArchives.ts +483 -0
  44. package/src/0-path-value-core/pathValueCore.ts +2217 -0
  45. package/src/1-path-client/RemoteWatcher.ts +558 -0
  46. package/src/1-path-client/pathValueClientWatcher.ts +702 -0
  47. package/src/2-proxy/PathValueProxyWatcher.ts +1857 -0
  48. package/src/2-proxy/archiveMoveHarness.ts +376 -0
  49. package/src/2-proxy/garbageCollection.ts +753 -0
  50. package/src/2-proxy/pathDatabaseProxyBase.ts +37 -0
  51. package/src/2-proxy/pathValueProxy.ts +139 -0
  52. package/src/2-proxy/schema2.ts +518 -0
  53. package/src/3-path-functions/PathFunctionHelpers.ts +129 -0
  54. package/src/3-path-functions/PathFunctionRunner.ts +619 -0
  55. package/src/3-path-functions/PathFunctionRunnerMain.ts +67 -0
  56. package/src/3-path-functions/deployBlock.ts +10 -0
  57. package/src/3-path-functions/deployCheck.ts +7 -0
  58. package/src/3-path-functions/deployMain.ts +160 -0
  59. package/src/3-path-functions/pathFunctionLoader.ts +282 -0
  60. package/src/3-path-functions/syncSchema.ts +475 -0
  61. package/src/3-path-functions/tests/functionsTest.ts +135 -0
  62. package/src/3-path-functions/tests/rejectTest.ts +77 -0
  63. package/src/4-dom/css.tsx +29 -0
  64. package/src/4-dom/cssTypes.d.ts +212 -0
  65. package/src/4-dom/qreact.tsx +2322 -0
  66. package/src/4-dom/qreactTest.tsx +417 -0
  67. package/src/4-querysub/Querysub.ts +877 -0
  68. package/src/4-querysub/QuerysubController.ts +620 -0
  69. package/src/4-querysub/copyEvent.ts +0 -0
  70. package/src/4-querysub/permissions.ts +289 -0
  71. package/src/4-querysub/permissionsShared.ts +1 -0
  72. package/src/4-querysub/querysubPrediction.ts +525 -0
  73. package/src/5-diagnostics/FullscreenModal.tsx +67 -0
  74. package/src/5-diagnostics/GenericFormat.tsx +165 -0
  75. package/src/5-diagnostics/Modal.tsx +79 -0
  76. package/src/5-diagnostics/Table.tsx +183 -0
  77. package/src/5-diagnostics/TimeGrouper.tsx +114 -0
  78. package/src/5-diagnostics/diskValueAudit.ts +216 -0
  79. package/src/5-diagnostics/memoryValueAudit.ts +442 -0
  80. package/src/5-diagnostics/nodeMetadata.ts +135 -0
  81. package/src/5-diagnostics/qreactDebug.tsx +309 -0
  82. package/src/5-diagnostics/shared.ts +26 -0
  83. package/src/5-diagnostics/synchronousLagTracking.ts +47 -0
  84. package/src/TestController.ts +35 -0
  85. package/src/allowclient.flag +0 -0
  86. package/src/bits.ts +86 -0
  87. package/src/buffers.ts +69 -0
  88. package/src/config.ts +53 -0
  89. package/src/config2.ts +48 -0
  90. package/src/diagnostics/ActionsHistory.ts +56 -0
  91. package/src/diagnostics/NodeViewer.tsx +503 -0
  92. package/src/diagnostics/SizeLimiter.ts +62 -0
  93. package/src/diagnostics/TimeDebug.tsx +18 -0
  94. package/src/diagnostics/benchmark.ts +139 -0
  95. package/src/diagnostics/errorLogs/ErrorLogController.ts +515 -0
  96. package/src/diagnostics/errorLogs/ErrorLogCore.ts +274 -0
  97. package/src/diagnostics/errorLogs/LogClassifiers.tsx +302 -0
  98. package/src/diagnostics/errorLogs/LogFilterUI.tsx +84 -0
  99. package/src/diagnostics/errorLogs/LogNotify.tsx +101 -0
  100. package/src/diagnostics/errorLogs/LogTimeSelector.tsx +724 -0
  101. package/src/diagnostics/errorLogs/LogViewer.tsx +757 -0
  102. package/src/diagnostics/errorLogs/hookErrors.ts +60 -0
  103. package/src/diagnostics/errorLogs/logFiltering.tsx +149 -0
  104. package/src/diagnostics/heapTag.ts +13 -0
  105. package/src/diagnostics/listenOnDebugger.ts +77 -0
  106. package/src/diagnostics/logs/DiskLoggerPage.tsx +572 -0
  107. package/src/diagnostics/logs/ObjectDisplay.tsx +165 -0
  108. package/src/diagnostics/logs/ansiFormat.ts +108 -0
  109. package/src/diagnostics/logs/diskLogGlobalContext.ts +38 -0
  110. package/src/diagnostics/logs/diskLogger.ts +305 -0
  111. package/src/diagnostics/logs/diskShimConsoleLogs.ts +32 -0
  112. package/src/diagnostics/logs/injectFileLocationToConsole.ts +50 -0
  113. package/src/diagnostics/logs/logGitHashes.ts +30 -0
  114. package/src/diagnostics/managementPages.tsx +289 -0
  115. package/src/diagnostics/periodic.ts +89 -0
  116. package/src/diagnostics/runSaturationTest.ts +416 -0
  117. package/src/diagnostics/satSchema.ts +64 -0
  118. package/src/diagnostics/trackResources.ts +82 -0
  119. package/src/diagnostics/watchdog.ts +55 -0
  120. package/src/errors.ts +132 -0
  121. package/src/forceProduction.ts +3 -0
  122. package/src/fs.ts +72 -0
  123. package/src/heapDumps.ts +666 -0
  124. package/src/https.ts +2 -0
  125. package/src/inject.ts +1 -0
  126. package/src/library-components/ATag.tsx +84 -0
  127. package/src/library-components/Button.tsx +344 -0
  128. package/src/library-components/ButtonSelector.tsx +64 -0
  129. package/src/library-components/DropdownCustom.tsx +151 -0
  130. package/src/library-components/DropdownSelector.tsx +32 -0
  131. package/src/library-components/Input.tsx +334 -0
  132. package/src/library-components/InputLabel.tsx +198 -0
  133. package/src/library-components/InputPicker.tsx +125 -0
  134. package/src/library-components/LazyComponent.tsx +62 -0
  135. package/src/library-components/MeasureHeightCSS.tsx +48 -0
  136. package/src/library-components/MeasuredDiv.tsx +47 -0
  137. package/src/library-components/ShowMore.tsx +51 -0
  138. package/src/library-components/SyncedController.ts +171 -0
  139. package/src/library-components/TimeRangeSelector.tsx +407 -0
  140. package/src/library-components/URLParam.ts +263 -0
  141. package/src/library-components/colors.tsx +14 -0
  142. package/src/library-components/drag.ts +114 -0
  143. package/src/library-components/icons.tsx +692 -0
  144. package/src/library-components/niceStringify.ts +50 -0
  145. package/src/library-components/renderToString.ts +52 -0
  146. package/src/misc/PromiseRace.ts +101 -0
  147. package/src/misc/color.ts +30 -0
  148. package/src/misc/getParentProcessId.cs +53 -0
  149. package/src/misc/getParentProcessId.ts +53 -0
  150. package/src/misc/hash.ts +83 -0
  151. package/src/misc/ipPong.js +13 -0
  152. package/src/misc/networking.ts +2 -0
  153. package/src/misc/random.ts +45 -0
  154. package/src/misc.ts +19 -0
  155. package/src/noserverhotreload.flag +0 -0
  156. package/src/path.ts +226 -0
  157. package/src/persistentLocalStore.ts +37 -0
  158. package/src/promise.ts +15 -0
  159. package/src/server.ts +73 -0
  160. package/src/src.d.ts +1 -0
  161. package/src/test/heapProcess.ts +36 -0
  162. package/src/test/mongoSatTest.tsx +55 -0
  163. package/src/test/satTest.ts +193 -0
  164. package/src/test/test.tsx +552 -0
  165. package/src/zip.ts +92 -0
  166. package/src/zipThreaded.ts +106 -0
  167. package/src/zipThreadedWorker.js +19 -0
  168. package/tsconfig.json +27 -0
  169. package/yarnSpec.txt +56 -0
@@ -0,0 +1,552 @@
1
+ // import { disableMeasurements } from "socket-function/src/profiling/measure";
2
+ // disableMeasurements();
3
+
4
+ import { isNode, list } from "socket-function/src/misc";
5
+ import { logErrors } from "../errors";
6
+ import { watchFilesAndTriggerHotReloading } from "socket-function/hot/HotReloadController";
7
+ import { Querysub } from "../4-querysub/QuerysubController";
8
+ import { red } from "socket-function/src/formatting/logColors";
9
+ import { PermissionsCheck } from "../4-querysub/permissions";
10
+ import { isDeploy } from "../3-path-functions/deployCheck";
11
+ import { formatTime } from "socket-function/src/formatting/format";
12
+
13
+ import { PromiseObj } from "../promise";
14
+ import { Benchmark } from "../diagnostics/benchmark";
15
+ import { formatStats, percent } from "socket-function/src/profiling/statsFormat";
16
+ import { cache } from "socket-function/src/caching";
17
+ import { atomic, atomicObjectWrite, proxyWatcher } from "../2-proxy/PathValueProxyWatcher";
18
+ import { fastHash } from "../misc/hash";
19
+ import { hslToRGB } from "../misc/color";
20
+ import { sat_data, sat_functions } from "../diagnostics/satSchema";
21
+ import { qreact } from "../4-dom/qreact";
22
+
23
+
24
+ // NOTE: In our first test of PathValueSerializer it is about 10X faster than JSONLACKS in parsing.
25
+ // - It will probably be even faster if we do lazy value deserialization
26
+
27
+ // async function test() {
28
+ // let testFile = "C:/Users/quent/shard/backups/querysub.com-4/PathFunctionRunner/lkddfcwz.lkddd8fv.lj9juidm.8b1s28.0.__gACTgA3gEFk1spi.YMm6Zg1AEejUtImU.json";
29
+ // //testFile = "C:/Users/quent/shard/backups/1-querysub.com/PathFunctionRunner/lj1z7won.lj1z5rrz.lj1z3oe0.2zy9m.0.json";
30
+
31
+ // await measureCode(async function test() {
32
+ // JSONLACKS.EXTENDED_PARSER = false;
33
+
34
+ // const testBuffer = measureBlock(function readFile() { return fs.readFileSync(testFile); });
35
+ // let objs = await measureBlock(async function JSONLACKSParse() { return await JSONLACKS.parseLines(testBuffer) as PathValue[]; });
36
+
37
+ // let newBuffer = await pathValueSerializer.serialize(objs, { noLocks: false, compress: true, });
38
+ // let objs2 = await pathValueSerializer.deserialize(newBuffer, {});
39
+
40
+ // console.log(`OLD ${formatNumber(testBuffer.length)} bytes, ${formatNumber(objs.length)} objects`);
41
+ // console.log(`NEW ${formatNumber(newBuffer.map(x => x.length).reduce((a, b) => a + b, 0))} bytes, ${formatNumber(objs2.length)} objects`);
42
+
43
+ // // for (let obj of objs2) {
44
+ // // pathValueSerializer.getPathValue(obj);
45
+ // // }
46
+
47
+ // // ALSO, make sure when we re-serialize, the second serialize is faster, because of the lazy objects (we will have to stop
48
+ // // getting all values first...)
49
+ // /*
50
+ // let newBuffer2 = await pathValueSerializer.serialize(objs2, { noLocks: true });
51
+ // let objs3 = await pathValueSerializer.deserialize(newBuffer2);
52
+ // console.log(`NEW2 ${formatNumber(newBuffer2.map(x => x.length).reduce((a, b) => a + b, 0))} bytes, ${formatNumber(objs3.length)} objects`);
53
+ // for (let obj of objs3) {
54
+ // pathValueSerializer.getPathValue(obj);
55
+ // }
56
+ // //*/
57
+ // }, { thresholdInTable: 0 });
58
+ // }
59
+ // test().catch(console.error).finally(() => process.exit());
60
+
61
+ /*
62
+ // Test passing around basic objects, and then buffers, references, etc
63
+ class TestControllerBase {
64
+ async returnValue<T>(obj: T) {
65
+ return obj;
66
+ }
67
+ }
68
+ const TestController = SocketFunction.register(
69
+ "TestController-94c75a37-06db-4444-b5d0-416922f3adbc",
70
+ new TestControllerBase(),
71
+ () => ({
72
+ returnValue: {},
73
+ }),
74
+ );
75
+
76
+ async function main() {
77
+ let cborxInstance = new cborx.Encoder({ structuredClone: true });
78
+ SocketFunction.WIRE_SERIALIZER = {
79
+ serialize: async obj => [cborxInstance.encode(obj)],
80
+ deserialize: async ([buf]) => cborxInstance.decode(buf),
81
+ };
82
+ if (process.argv.includes("--server")) {
83
+ await SocketFunction.mount({
84
+ public: false,
85
+ port: 5051,
86
+ ...await getThreadKeyCert(),
87
+ });
88
+ return;
89
+ }
90
+
91
+
92
+ // Tests
93
+ // - string
94
+ // - number
95
+ // - object with strings and number
96
+ // - object with references
97
+ // - array of primitives/objects
98
+ // - array of primitives/objects/undefined/null
99
+ // - object with buffers / typed arrays
100
+
101
+ let serverNode = TestController.nodes[getNodeId("b77f134c680b3c537.bb752907afd3de60b.querysub.com", 5051)];
102
+
103
+ async function testString() {
104
+ let str = "test" + Date.now();
105
+ let result = await serverNode.returnValue(str);
106
+ if (result !== str) throw new Error(`Expected ${str}, got ${result}`);
107
+ }
108
+ async function testNumber() {
109
+ let num = Date.now();
110
+ let result = await serverNode.returnValue(num);
111
+ if (result !== num) throw new Error(`Expected ${num}, got ${result}`);
112
+ }
113
+ async function testObject() {
114
+ let obj = {
115
+ test: "test" + Date.now(),
116
+ num: Date.now(),
117
+ };
118
+ let result = await serverNode.returnValue(obj);
119
+ if (result.test !== obj.test) throw new Error(`Expected ${obj.test}, got ${result.test}`);
120
+ if (result.num !== obj.num) throw new Error(`Expected ${obj.num}, got ${result.num}`);
121
+ }
122
+ async function testObjectWithReferences() {
123
+ let objNested = { x: 5 };
124
+ let obj = {
125
+ obj0: objNested,
126
+ obj1: objNested,
127
+ obj2: { x: 5 },
128
+ };
129
+ let result = await serverNode.returnValue(obj);
130
+ if (result.obj0.x !== 5) throw new Error(`Expected ${objNested.x}, got ${result.obj0.x}`);
131
+ if (result.obj1.x !== 5) throw new Error(`Expected ${objNested.x}, got ${result.obj1.x}`);
132
+ if (result.obj2.x !== 5) throw new Error(`Expected ${objNested.x}, got ${result.obj2.x}`);
133
+ if (result.obj0 !== result.obj1) throw new Error(`Expected ${result.obj0}, got ${result.obj1}`);
134
+ if (result.obj0 === result.obj2) throw new Error(`Expected ${result.obj0} !== ${result.obj2}`);
135
+ }
136
+ async function testBasicArray() {
137
+ let arr = ["test" + Date.now(), Date.now()];
138
+ let result = await serverNode.returnValue(arr);
139
+ if (result[0] !== arr[0]) throw new Error(`Expected ${arr[0]}, got ${result[0]}`);
140
+ if (result[1] !== arr[1]) throw new Error(`Expected ${arr[1]}, got ${result[1]}`);
141
+ }
142
+ async function testComplexArray() {
143
+ let arr = [
144
+ "test" + Date.now(),
145
+ Date.now(),
146
+ undefined,
147
+ null
148
+ ];
149
+ let result = await serverNode.returnValue(arr);
150
+ if (result.length !== arr.length) throw new Error(`Expected ${arr.length}, got ${result.length}`);
151
+ for (let i = 0; i < arr.length; i++) {
152
+ if (result[i] !== arr[i]) throw new Error(`Expected ${arr[i]}, got ${result[i]}`);
153
+ }
154
+ }
155
+
156
+ async function testBuffersAndTypedArrays() {
157
+ let obj = {
158
+ test0: Buffer.from(new Float64Array(Array(1024).map(x => Math.random())).buffer),
159
+ test1: new Float64Array([1, 2]),
160
+ test2: new Uint8Array([1, 2]),
161
+ };
162
+ let result = await serverNode.returnValue(obj);
163
+ if (!Buffer.isBuffer(result.test0)) throw new Error(`Expected buffer, got ${result.test0}`);
164
+ if (!result.test0.equals(obj.test0)) throw new Error(`Expected ${obj.test0}, got ${result.test0}`);
165
+ if (!(result.test1 instanceof Float64Array)) throw new Error(`Expected Float64Array, got ${result.test1}`);
166
+ if (!(result.test2 instanceof Uint8Array)) throw new Error(`Expected Uint8Array, got ${result.test2}`);
167
+ if (result.test1[0] !== 1) throw new Error(`Expected 1, got ${result.test1[0]}`);
168
+ if (result.test1[1] !== 2) throw new Error(`Expected 2, got ${result.test1[1]}`);
169
+ if (result.test2[0] !== 1) throw new Error(`Expected 1, got ${result.test2[0]}`);
170
+ if (result.test2[1] !== 2) throw new Error(`Expected 2, got ${result.test2[1]}`);
171
+ }
172
+
173
+ let tests: (() => Promise<void>)[] = [
174
+ testString,
175
+ testNumber,
176
+ testObject,
177
+ testObjectWithReferences,
178
+ testBasicArray,
179
+ testComplexArray,
180
+ testBuffersAndTypedArrays,
181
+ ];
182
+ for (let test of tests) {
183
+ try {
184
+ await test();
185
+ } catch (e: any) {
186
+ console.error(`Failed test ${test.name}, ${e.message}`);
187
+ }
188
+ }
189
+ process.exit();
190
+ }
191
+
192
+ logErrors(main());
193
+ */
194
+
195
+ // async function main() {
196
+ // // Ah, well... we probably won't be reading massive objects anyways. So...
197
+ // // just using cborx with structuredClone is probably good enough?
198
+
199
+ // // let testFile = "C:/Users/quent/shard/backups/querysub.com-4/PathFunctionRunner/lkddfcwz.lkddd8fv.lj9juidm.8b1s28.0.__gACTgA3gEFk1spi.YMm6Zg1AEejUtImU.json";
200
+ // // //testFile = "C:/Users/quent/shard/backups/1-querysub.com/PathFunctionRunner/lj1z7won.lj1z5rrz.lj1z3oe0.2zy9m.0.json";
201
+
202
+ // // const testBuffer = fs.readFileSync(testFile);
203
+ // // let objs = await JSONLACKS.parseLines(testBuffer);
204
+
205
+ // // objs = [
206
+ // // {
207
+ // // test: Buffer.from(new Float64Array(Array(1024 * 1024 * 64).map(x => Math.random())).buffer)
208
+ // // },
209
+ // // {
210
+ // // test: Buffer.from(new Float64Array(Array(1024 * 1024 * 64).map(x => Math.random())).buffer)
211
+ // // },
212
+ // // {
213
+ // // test: Buffer.from(new Float64Array(Array(1024 * 1024 * 64).map(x => Math.random())).buffer)
214
+ // // },
215
+ // // {
216
+ // // test: Buffer.from(new Float64Array(Array(1024 * 1024 * 64).map(x => Math.random())).buffer)
217
+ // // }
218
+ // // ];
219
+
220
+ // // console.log(`${formatNumber(testBuffer.length)} bytes, ${formatNumber(objs.length)} objects`);
221
+
222
+ // // await measureCode(async function runWithMsgpack() {
223
+ // // let binary = measureBlock(function encode() {
224
+ // // return msgpack.encode(objs);
225
+ // // });
226
+ // // let newObjs = measureBlock(function decode() {
227
+ // // return msgpack.decode(binary) as any;
228
+ // // });
229
+ // // console.log(`msgpack = ${formatNumber(binary.length)} bytes, count ${newObjs.length}`);
230
+ // // });
231
+
232
+ // // await measureCode(async function runWithCborx() {
233
+ // // let binary = measureBlock(function encode() {
234
+ // // return cborx.encode(objs);
235
+ // // });
236
+ // // let newObjs = measureBlock(function decode() {
237
+ // // return cborx.decode(binary);
238
+ // // });
239
+ // // console.log(`cborx = ${formatNumber(binary.length)} bytes, count ${newObjs.length}`);
240
+ // // });
241
+
242
+ // // await measureCode(async function runWithCborxStructured() {
243
+ // // let encoder = new cborx.Encoder({ structuredClone: true });
244
+ // // let binary = measureBlock(function encode() {
245
+ // // return encoder.encode(objs);
246
+ // // });
247
+ // // let newObjs = measureBlock(function decode() {
248
+ // // return encoder.decode(binary);
249
+ // // });
250
+ // // console.log(`cborx structured = ${formatNumber(binary.length)} bytes, count ${newObjs.length}`);
251
+ // // });
252
+
253
+
254
+ // // let archives = getArchives("test");
255
+
256
+ // // await archives.set("folder/a.txt", Buffer.from("test" + Date.now()));
257
+ // // await archives.set("folder/b.txt", Buffer.from("test" + Date.now()));
258
+ // // await archives.set("folder/nested/1.txt", Buffer.from("test" + Date.now()));
259
+
260
+ // // console.log("all files", await archives.find(""));
261
+ // // console.log("root folders", await archives.find("", { shallow: true, type: "folders" }));
262
+ // // console.log("all folders", await archives.find("", { type: "folders" }));
263
+ // // console.log("nested files", await archives.find("folder/", { shallow: true, type: "files" }));
264
+ // // console.log("nested folders", await archives.find("folder/", { shallow: true, type: "folders" }));
265
+
266
+ // // process.exit();
267
+
268
+ // // await archives.set("nested/testFile.txt", Buffer.from("test" + Date.now()));
269
+ // // console.log("testResult", (await archives.get("nested/testFile.txt"))?.toString());
270
+ // // let info = await archives.getInfo("nested/testFile.txt");
271
+ // // console.log("info", info);
272
+ // // console.log("files", await archives.find("nested/"));
273
+ // // await archives.del("nested/testFile.txt");
274
+ // // console.log("files", await archives.find("nested/"));
275
+ // // console.log("testResult", (await archives.get("nested/testFile.txt"))?.toString());
276
+
277
+ // // SocketFunction.silent = false;
278
+ // // await SocketFunction.mount({
279
+ // // public: false,
280
+ // // port: 0,
281
+ // // ...await getThreadKeyCert(),
282
+ // // });
283
+ // // watchNodeIds(nodeIds => {
284
+ // // console.log(`Node ids changed at ${new Date().toISOString()}`);
285
+ // // for (let id of nodeIds) {
286
+ // // console.log(` ${id}`);
287
+ // // }
288
+ // // console.log();
289
+ // // });
290
+ // }
291
+
292
+ // logErrors(main());
293
+
294
+
295
+
296
+
297
+ //*
298
+
299
+
300
+ // let { data, functions } = Querysub.createSchema<{
301
+ // ownedValues: {
302
+ // [key: string]: string;
303
+ // },
304
+ // values: {
305
+ // [index: number]: {
306
+ // sum: number;
307
+ // lastUpdated: number;
308
+ // lastUpdatedBy: string;
309
+ // }
310
+ // };
311
+ // }>()({
312
+ // domainName: "querysub.com",
313
+ // functions: {
314
+ // setValues(indexes: number[], value?: number) {
315
+ // for (let index of indexes) {
316
+ // let newValue = value ?? (data().values[index].sum + 1);
317
+ // data().values[index] = {
318
+ // sum: newValue,
319
+ // lastUpdated: Querysub.now(),
320
+ // lastUpdatedBy: Querysub.getCallerMachineId(),
321
+ // };
322
+ // }
323
+ // },
324
+ // setOwnedValue(key: string, value: string) {
325
+ // data().ownedValues[key] = value;
326
+ // }
327
+ // },
328
+ // module,
329
+ // moduleId: "test",
330
+ // functionMetadata: {},
331
+ // permissions: {
332
+ // PERMISSIONS: isRegisteredUserCheck,
333
+ // ownedValues: {
334
+ // ["*"]: {
335
+ // PERMISSIONS: (config) => {
336
+ // return config.pathWildcards?.[0] === config.callerMachineId;
337
+ // },
338
+ // }
339
+ // }
340
+ // }
341
+ // });
342
+
343
+ function isRegisteredUserCheck(): boolean {
344
+ let allowed = Querysub.getCallerIP() === "127.0.0.1";
345
+ if (!allowed) {
346
+ console.log(red(`Permission denied to IP ${JSON.stringify(Querysub.getCallerIP())}`));
347
+ }
348
+ return allowed;
349
+ }
350
+
351
+
352
+
353
+ const INDEX_EXTENT = 300 * 300;
354
+ //const INDEX_EXTENT = 100 * 100;
355
+
356
+ let getNodeHue = cache((nodeId: string) => {
357
+ return fastHash(nodeId) % 360;
358
+ });
359
+
360
+
361
+ class Page extends qreact.Component {
362
+
363
+ state = {
364
+ results: atomicObjectWrite([]) as string[],
365
+ canvas: undefined as undefined | {
366
+ value: HTMLCanvasElement;
367
+ context: CanvasRenderingContext2D;
368
+ },
369
+ writeTime: 0,
370
+ key: "",
371
+ };
372
+
373
+ onUnmount = new PromiseObj();
374
+ componentDidMount(): void {
375
+ let index = 0;
376
+ // NOTE: This ends up being a lot slower, due to the massive overhead of having a watcher
377
+ // with so many watched paths.
378
+ // setInterval(() => {
379
+ // functions.setValues([index++]);
380
+ // }, 100);
381
+ }
382
+ componentWillUnmount(): void {
383
+ this.onUnmount.resolve();
384
+ }
385
+ render() {
386
+ let canvasObj = atomic(this.state.canvas);
387
+ if (canvasObj) {
388
+ let watcher = proxyWatcher.getTriggeredWatcher();
389
+ watcher.pendingWatches.paths = new Set(watcher.lastWatches.paths);
390
+ watcher.pendingWatches.parentPaths = new Set(watcher.lastWatches.parentPaths);
391
+ if (watcher.pendingWatches.paths.size < 1000) {
392
+ for (let v = 0; v < INDEX_EXTENT; v++) {
393
+ sat_data().values[v];
394
+ }
395
+ }
396
+
397
+ let changes = watcher.triggeredByChanges;
398
+ let indexesChanged = new Set<number>();
399
+ if (changes && changes.paths.size < 1000) {
400
+ for (let path of changes?.paths) {
401
+ if (path.startsWith(".,querysub._com.,PathFunctionRunner.,saturationTest.,Data.,values.,")) {
402
+ indexesChanged.add(Number(path.split(".,").at(-2)));
403
+ }
404
+ }
405
+ } else {
406
+ for (let v = 0; v < INDEX_EXTENT; v++) {
407
+ indexesChanged.add(v);
408
+ }
409
+ }
410
+ let { value: canvas, context } = canvasObj;
411
+ let imageData = context.getImageData(0, 0, canvas.width, canvas.height);
412
+ let imageArray = imageData.data;
413
+ for (let v of indexesChanged) {
414
+ let i = v * 4;
415
+ let obj = sat_data().values[v];
416
+ let baseSum = Number(obj);
417
+ let sum = Number(baseSum) % 3;
418
+
419
+ let hue = 180;
420
+ let saturation = (0.5 + sum / 3 * 0.5) * 100;
421
+ let lightness = (0.5 + sum / 3 * 0.5) * 100;
422
+ if (!baseSum) {
423
+ lightness = 100;
424
+ }
425
+
426
+ let rgb = hslToRGB({ h: hue, s: saturation, l: lightness });
427
+
428
+ imageArray[i + 0] = rgb.r;
429
+ imageArray[i + 1] = rgb.g;
430
+ imageArray[i + 2] = rgb.b;
431
+ imageArray[i + 3] = 255;
432
+ }
433
+ context.putImageData(imageData, 0, 0);
434
+ }
435
+
436
+
437
+ return (
438
+ <div>
439
+ <div>Calls {formatStats(Benchmark.getLiveCallStats(), { noColor: true })}</div>
440
+ <div>Rate: {Math.round(Benchmark.getLiveRate() * 1000 * 10) / 10}/s</div>
441
+ <div>Saturated: {percent(Benchmark.saturatedFraction())}</div>
442
+ <div>Predict {Benchmark.predictCount}, received {Benchmark.receivedCount}</div>
443
+ <div>Open {Benchmark.overlapRate.openCount}, time waiting {Benchmark.overlapRate.finishedTime}</div>
444
+ <div>Machine Id {Querysub.getSelfMachineId()}</div>
445
+ {/* <div>
446
+ <label>
447
+ Key <input value={this.state.key} onChange={e => this.state.key = e.currentTarget.value} />
448
+ </label>
449
+ <div>
450
+ Value: <input
451
+ value={data().ownedValues[this.state.key]}
452
+ onChange={e => functions.setOwnedValue(this.state.key, e.currentTarget.value)}
453
+ />
454
+ </div>
455
+ </div>
456
+ <div>
457
+ Owned values keys (should be empty) {Object.keys(data().ownedValues).join(", ")}
458
+ </div> */}
459
+ <div style={{ display: "flex", gap: 10 }}>
460
+ <button onClick={() => {
461
+ sat_functions.setValues([0]);
462
+ }}>
463
+ Single write
464
+ </button>
465
+ <button onClick={() => {
466
+ //functions.setValues(list(INDEX_EXTENT));
467
+ setImmediate(async () => {
468
+ let time = Date.now();
469
+ let call = sat_functions.setValues(list(INDEX_EXTENT), 0);
470
+ //let call = functions.setValues(list(10 * 1000), 0);
471
+ await Benchmark.waitForCallToFinish(call);
472
+ time = Date.now() - time;
473
+ Querysub.serviceWriteDetached(() => {
474
+ this.state.writeTime = time;
475
+ });
476
+ });
477
+ }}>
478
+ Value Fill
479
+ </button>
480
+ <div>
481
+ Write time: {formatTime(this.state.writeTime)}
482
+ </div>
483
+ </div>
484
+ <div>
485
+ <canvas
486
+ width={Math.ceil(Math.sqrt(INDEX_EXTENT))}
487
+ height={Math.ceil(Math.sqrt(INDEX_EXTENT))}
488
+ style={{
489
+ border: "1px solid black",
490
+ zoom: 800 / Math.sqrt(INDEX_EXTENT),
491
+ imageRendering: "pixelated",
492
+ }}
493
+ ref={canvas => {
494
+ if (canvas && canvas !== this.state.canvas?.value) {
495
+ this.state.canvas = atomicObjectWrite({
496
+ value: canvas,
497
+ context: canvas.getContext("2d")!,
498
+ });
499
+ }
500
+ }}
501
+ />
502
+ </div>
503
+ <pre>
504
+ {this.state.results.map(result => <div>{result || <>&nbsp;</>}</div>)}
505
+ </pre>
506
+ </div>
507
+ );
508
+ }
509
+ }
510
+
511
+ async function browserMain() {
512
+ if (isNode()) return;
513
+
514
+ watchFilesAndTriggerHotReloading();
515
+
516
+ //Querysub.debug();
517
+ // ClientWatcher.DEBUG_READS = true;
518
+ // ClientWatcher.DEBUG_WRITES = true;
519
+ // Querysub.DEBUG_CALLS = true;
520
+
521
+ qreact.render(qreact.createElement(Page, {}), document.getElementById("main")!);
522
+ }
523
+
524
+ async function main() {
525
+ if (!isNode()) return;
526
+ if (isDeploy()) return;
527
+ if (module.hotreload) return;
528
+ const edgePort = 5050;
529
+ PermissionsCheck.DEBUG = true;
530
+ // ClientWatcher.DEBUG_READS = true;
531
+ // ClientWatcher.DEBUG_WRITES = true;
532
+ //debugCoreMode();
533
+
534
+ //SocketFunction.silent = false;
535
+ Error.stackTraceLimit = 20;
536
+
537
+ await Querysub.hostServer({
538
+ trustedDomains: ["querysub.com"],
539
+ port: edgePort,
540
+ rootPath: __dirname + "/../../",
541
+ clientsideEntryPoint: "./src/test/test.tsx",
542
+ hotReload: true,
543
+ });
544
+ }
545
+
546
+ module.hotreload = isNode() && process.argv[1].includes("PathFunctionRunnerMain.ts");
547
+ module.noserverhotreload = false;
548
+
549
+ logErrors(main());
550
+ logErrors(browserMain());
551
+
552
+ //*/
package/src/zip.ts ADDED
@@ -0,0 +1,92 @@
1
+ import { isNode } from "socket-function/src/misc";
2
+ import { measureBlock, measureFnc } from "socket-function/src/profiling/measure";
3
+ import zlib from "zlib";
4
+ import * as pako from "pako";
5
+
6
+ import { setFlag } from "socket-function/require/compileFlags";
7
+ import { unzipThreaded } from "./zipThreaded";
8
+ import debugbreak from "debugbreak";
9
+ import { formatNumber } from "socket-function/src/formatting/format";
10
+ import { runInSerial } from "socket-function/src/batching";
11
+ setFlag(require, "pako", "allowclient", true);
12
+
13
+ export class Zip {
14
+ @measureFnc
15
+ public static async gzip(buffer: Buffer, level?: number): Promise<Buffer> {
16
+ if (isNode()) {
17
+ return new Promise((resolve, reject) => {
18
+ zlib.gzip(buffer, { level }, (err: any, result: Buffer) => {
19
+ if (err) reject(err);
20
+ else resolve(result);
21
+ });
22
+ });
23
+ } else {
24
+ // @ts-ignore
25
+ return await doStream(new CompressionStream("gzip"), buffer);
26
+ }
27
+ }
28
+ @measureFnc
29
+ public static async gunzip(buffer: Buffer): Promise<Buffer> {
30
+ return Zip.gunzipUntracked(buffer);
31
+ }
32
+ // A base function, so we can avoid instrumentation for batch calls
33
+ public static async gunzipUntracked(buffer: Buffer): Promise<Buffer> {
34
+ if (isNode()) {
35
+ let test = await unzipThreaded(buffer);
36
+ // let test2 = await new Promise<Buffer>((resolve, reject) => {
37
+ // zlib.gunzip(buffer, (err: any, result: Buffer) => {
38
+ // if (err) reject(err);
39
+ // else resolve(result);
40
+ // });
41
+ // });
42
+ // if (test.length !== test2.length) {
43
+ // debugbreak(2);
44
+ // debugger;
45
+ // }
46
+ // for (let i = 0; i < test.length; i++) {
47
+ // if (test[i] !== test2[i]) {
48
+ // debugbreak(2);
49
+ // debugger;
50
+ // }
51
+ // }
52
+
53
+ return test;
54
+ } else {
55
+ // NOTE: pako seems to be faster, at least clientside.
56
+ // TIMING: 700ms vs 1200ms
57
+ // - This might just be faster for small files.
58
+ return Buffer.from(pako.inflate(buffer));
59
+ // @ts-ignore
60
+ // return await doStream(new DecompressionStream("gzip"), buffer);
61
+ }
62
+ }
63
+
64
+ @measureFnc
65
+ public static async gunzipBatch(buffers: Buffer[]): Promise<Buffer[]> {
66
+ let time = Date.now();
67
+ buffers = await Promise.all(buffers.map(Zip.gunzipUntracked));
68
+ time = Date.now() - time;
69
+ let totalSize = buffers.reduce((acc, buffer) => acc + buffer.length, 0);
70
+ //console.log(`Gunzip ${formatNumber(totalSize)}B at ${formatNumber(totalSize / time * 1000)}B/s`);
71
+ return buffers;
72
+ }
73
+ }
74
+
75
+ async function doStream(stream: GenericTransformStream, buffer: Buffer): Promise<Buffer> {
76
+ let reader = stream.readable.getReader();
77
+ let writer = stream.writable.getWriter();
78
+ let writePromise = writer.write(buffer);
79
+ let closePromise = writer.close();
80
+
81
+ let outputBuffers: Buffer[] = [];
82
+ while (true) {
83
+ let { value, done } = await reader.read();
84
+ if (done) {
85
+ await writePromise;
86
+ await closePromise;
87
+ return Buffer.concat(outputBuffers);
88
+ }
89
+ outputBuffers.push(Buffer.from(value));
90
+ }
91
+
92
+ }