querysub 0.469.0 → 0.471.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "querysub",
3
- "version": "0.469.0",
3
+ "version": "0.471.0",
4
4
  "main": "index.js",
5
5
  "license": "MIT",
6
6
  "note1": "note on node-forge fork, see https://github.com/digitalbazaar/forge/issues/744 for details",
@@ -66,7 +66,7 @@
66
66
  "node-forge": "https://github.com/sliftist/forge#e618181b469b07bdc70b968b0391beb8ef5fecd6",
67
67
  "pako": "^2.1.0",
68
68
  "peggy": "^5.0.6",
69
- "socket-function": "^1.1.34",
69
+ "socket-function": "^1.1.35",
70
70
  "terser": "^5.31.0",
71
71
  "typesafecss": "^0.29.0",
72
72
  "yaml": "^2.5.0",
@@ -54,7 +54,12 @@ export function IdentityController_getReconnectNodeIdAssert(callerContext: Calle
54
54
  return callerContext.nodeId;
55
55
  }
56
56
  let reconnectId = IdentityController_getReconnectNodeId(callerContext);
57
- if (!reconnectId) throw new Error(`Caller did not mount before connecting. This call requires the caller to be listening.`);
57
+ if (!reconnectId) {
58
+ console.error(`Caller did not mount before connecting. This call requires the caller to be listening.`, {
59
+ callerNodeId: callerContext.nodeId,
60
+ });
61
+ throw new Error(`Caller did not mount before connecting. This call requires the caller to be listening.`);
62
+ }
58
63
  return reconnectId;
59
64
  }
60
65
  export function IdentityController_getSecureIP(callerContext: CallerContext): string {
@@ -1664,7 +1664,7 @@ export class PathValueProxyWatcher {
1664
1664
 
1665
1665
  let maxLocks = watcher.options.maxLocksOverride || DEFAULT_MAX_LOCKS;
1666
1666
  if (locks.length > maxLocks) {
1667
- throw new Error(`Too many locks for ${watcher.debugName} (${locks.length} > ${maxLocks}). Use Querysub.noLocks(() => ...) around code that is accessing too many values, assuming you don't want to lock them. You can override max locks with maxLocksOverride (in options / functionMetadata).`);
1667
+ throw new Error(`Too many locks for ${watcher.debugName} (${locks.length} > ${maxLocks}). Use Querysub.noLocks(() => ...) around code that is accessing too many values, assuming you don't want to lock them. You can override max locks with maxLocksOverride (in options / functionMetadata). Some locks are ${JSON.stringify(locks.slice(0, 3).map(x => ({ path: x.path, startTime: x.startTime, endTime: x.endTime })))}.`);
1668
1668
  }
1669
1669
 
1670
1670
 
@@ -58,7 +58,7 @@ export type FunctionMetadata<Schema = unknown, F = unknown> = {
58
58
  // NOTE: Eventually we might want to support dynamic paths per call, so we can supported nested lookups.
59
59
  // - We also need to support specifying on the lookup that the key is in the nested lookup, which means hashing has to support wildcards, etc. All-in-all the whole change is very complicated, and only needed for hypothetical cases (data().worlds[region][id]...), which could probably be flattened anyways to just a single lookup (data().worlds[region + "-" + id]...)
60
60
  /** This should identify the most common lookup accessed, and then give the path to that lookup and the key that we're using to access it. */
61
- keyOverride?: {
61
+ keyOverride: {
62
62
  getPrefix: (data: () => Schema) => unknown;
63
63
  getKey: (...args: Args<F>) => string;
64
64
  };
@@ -275,7 +275,7 @@ type SyncSchemaResult<Schema> = {
275
275
  moduleId: string;
276
276
  module: NodeJS.Module;
277
277
  functions: Functions;
278
- functionMetadata?: { [name in keyof Functions]?: FunctionMetadata<Schema, Functions[name]> };
278
+ functionMetadata: { [name in keyof Functions]: FunctionMetadata<Schema, Functions[name]> };
279
279
  /** Provide access to [Querysub.CALL_PERMISSIONS_KEY] to allow function calls (or provide access at the root). */
280
280
  permissions?: SchemaToPermissions<Schema> & {
281
281
  [CALL_PERMISSIONS_KEY]?: {
@@ -326,7 +326,14 @@ let { data, functions } = Querysub.createSchema<{
326
326
  },
327
327
  module,
328
328
  moduleId: "qreactTest",
329
- functionMetadata: {},
329
+ functionMetadata: {
330
+ setValue: {
331
+ keyOverride: {
332
+ getPrefix: data => data().values,
333
+ getKey: (key: string) => key,
334
+ },
335
+ },
336
+ },
330
337
  permissions: {
331
338
  PERMISSIONS: isSuperUserPERMISSIONS
332
339
  }
@@ -95,9 +95,13 @@ export class LogViewer3 extends qreact.Component {
95
95
  getPaths(): TimeFilePathWithSize[] {
96
96
  let paths: TimeFilePathWithSize[] = [];
97
97
  if (savedPathsURL.value) {
98
- const compressed = Buffer.from(savedPathsURL.value, "base64");
99
- const decompressed = Zip.gunzipSync(compressed);
100
- paths = JSON.parse(decompressed.toString("utf8"));
98
+ try {
99
+ const compressed = Buffer.from(savedPathsURL.value, "base64");
100
+ const decompressed = Zip.gunzipSync(compressed);
101
+ paths = JSON.parse(decompressed.toString("utf8"));
102
+ } catch (e: any) {
103
+ console.warn(`Error parsing saved paths: ${e.stack}`);
104
+ }
101
105
  } else {
102
106
  paths = this.state.paths;
103
107
  }
@@ -7,8 +7,14 @@ import { logErrors } from "../../errors";
7
7
  import { addGlobalContext } from "./diskLogger";
8
8
  import child_process from "child_process";
9
9
  import { getNodeIdLocation } from "socket-function/src/nodeCache";
10
+ import { getGitRefLive } from "../../4-deploy/git";
10
11
 
11
12
  export function addBuiltInContext() {
13
+ let __gitHash = "";
14
+ setImmediate(async () => {
15
+ __gitHash = await getGitRefLive();
16
+ });
17
+
12
18
  addGlobalContext(() => {
13
19
  let nodeId = getOwnNodeId();
14
20
  let nodeParts = getNodeIdLocation(nodeId);
@@ -25,6 +31,7 @@ export function addBuiltInContext() {
25
31
  __os: process.platform,
26
32
  __pid: process.pid,
27
33
  __call: SocketFunction.TOTAL_CALLS,
34
+ __gitHash: __gitHash,
28
35
  };
29
36
  });
30
37
  const getHostname = lazy(() => child_process.execSync("hostname").toString().trim());
@@ -183,6 +183,7 @@ const { data } = syncSchema<{
183
183
  functions: {},
184
184
  module,
185
185
  moduleId: "urlSync",
186
+ functionMetadata: {},
186
187
  permissions: {},
187
188
  });
188
189
 
@@ -285,11 +285,125 @@ const { data, functions } = Querysub.syncSchema<{
285
285
  functionMetadata: {
286
286
  // There's no point to predict sending emails, or inviting users, or registering the page load time or sending discord messages, As the main function of these can only be done server-side.
287
287
  // verifyMachineId is used when logging in with the login token. We could predict it, but there's no real reason to because if we do, all of our reads are gonna fail until it runs, Which will actually be really confusing to the user and look like a bug.
288
- sendLoginEmail: { nopredict: true },
289
- verifyMachineId: { nopredict: true },
290
- inviteUser: { nopredict: true },
291
- registerPageLoadTime: { nopredict: true },
292
- testSendDiscordMessage: { nopredict: true },
288
+ sendLoginEmail: {
289
+ nopredict: true,
290
+ keyOverride: {
291
+ getPrefix: data => data().secure.emailToUserId,
292
+ getKey: config => config.email,
293
+ },
294
+ },
295
+ verifyMachineId: {
296
+ nopredict: true,
297
+ keyOverride: {
298
+ getPrefix: data => data().users,
299
+ getKey: config => config.loginToken.split("_")[1],
300
+ },
301
+ },
302
+ inviteUser: {
303
+ nopredict: true,
304
+ keyOverride: {
305
+ getPrefix: data => data().users,
306
+ getKey: () => getCurrentUserAssert(),
307
+ },
308
+ },
309
+ registerPageLoadTime: {
310
+ nopredict: true,
311
+ keyOverride: {
312
+ getPrefix: data => data().users,
313
+ getKey: () => getCurrentUser() ?? Querysub.getCallerMachineId(),
314
+ },
315
+ },
316
+ testSendDiscordMessage: {
317
+ nopredict: true,
318
+ keyOverride: {
319
+ getPrefix: data => data().secure,
320
+ getKey: () => "notifyDiscordWebhookURL",
321
+ },
322
+ },
323
+ updateSettings: {
324
+ keyOverride: {
325
+ getPrefix: data => data().users,
326
+ getKey: () => getCurrentUserAssert(),
327
+ },
328
+ },
329
+ logoutCurrent: {
330
+ keyOverride: {
331
+ getPrefix: data => data().users,
332
+ getKey: () => getCurrentUser() ?? Querysub.getCallerMachineId(),
333
+ },
334
+ },
335
+ logoutSpecific: {
336
+ keyOverride: {
337
+ getPrefix: data => data().users,
338
+ getKey: () => getCurrentUserAssert(),
339
+ },
340
+ },
341
+ removeLoginToken: {
342
+ keyOverride: {
343
+ getPrefix: data => data().users,
344
+ getKey: () => getCurrentUserAssert(),
345
+ },
346
+ },
347
+ specialResetLogins: {
348
+ keyOverride: {
349
+ getPrefix: data => data().users,
350
+ getKey: config => config.userId,
351
+ },
352
+ },
353
+ specialBlockIP: {
354
+ keyOverride: {
355
+ getPrefix: data => data().secure.blockedIPs,
356
+ getKey: config => config.ip,
357
+ },
358
+ },
359
+ specialUnblockIP: {
360
+ keyOverride: {
361
+ getPrefix: data => data().secure.blockedIPs,
362
+ getKey: config => config.ip,
363
+ },
364
+ },
365
+ specialSetInviteCount: {
366
+ keyOverride: {
367
+ getPrefix: data => data().users,
368
+ getKey: config => config.userId,
369
+ },
370
+ },
371
+ setPostmarkAPIKey: {
372
+ keyOverride: {
373
+ getPrefix: data => data().secure,
374
+ getKey: () => "postmarkAPIKey",
375
+ },
376
+ },
377
+ setNotifyDiscordWebhookURL: {
378
+ keyOverride: {
379
+ getPrefix: data => data().secure,
380
+ getKey: () => "notifyDiscordWebhookURL",
381
+ },
382
+ },
383
+ setOpenRouterAPIKey: {
384
+ keyOverride: {
385
+ getPrefix: data => data().secure,
386
+ getKey: () => "openRouterAPIKey",
387
+ },
388
+ },
389
+ specialSetUserType: {
390
+ keyOverride: {
391
+ getPrefix: data => data().users,
392
+ getKey: config => config.userId,
393
+ },
394
+ },
395
+ banUser: {
396
+ keyOverride: {
397
+ getPrefix: data => data().users,
398
+ getKey: config => config.userId,
399
+ },
400
+ },
401
+ unbanUser: {
402
+ keyOverride: {
403
+ getPrefix: data => data().users,
404
+ getKey: config => config.userId,
405
+ },
406
+ },
293
407
  },
294
408
  });
295
409