querysub 0.350.0 → 0.351.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.350.0",
3
+ "version": "0.351.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",
@@ -32,7 +32,6 @@
32
32
  "gc-watch-public": "./bin/gc-watch-public.js",
33
33
  "join": "./bin/join.js",
34
34
  "join-public": "./bin/join-public.js",
35
- "merge": "./bin/merge.js",
36
35
  "addsuperuser": "./bin/addsuperuser.js",
37
36
  "error-email": "./bin/error-email.js",
38
37
  "error-im": "./bin/error-im.js"
@@ -51,9 +50,9 @@
51
50
  "js-sha512": "^0.9.0",
52
51
  "node-forge": "https://github.com/sliftist/forge#e618181b469b07bdc70b968b0391beb8ef5fecd6",
53
52
  "pako": "^2.1.0",
54
- "socket-function": "^0.153.0",
53
+ "socket-function": "^1.0.1",
55
54
  "terser": "^5.31.0",
56
- "typesafecss": "^0.23.0",
55
+ "typesafecss": "^0.25.0",
57
56
  "yaml": "^2.5.0",
58
57
  "yargs": "^15.3.1"
59
58
  },
@@ -550,6 +550,8 @@ export class ArchivesBackblaze {
550
550
  // we can remove this line.
551
551
  || err.stack.includes(`400 Bad Request`)
552
552
  || err.stack.includes(`getaddrinfo ENOTFOUND`)
553
+ || err.stack.includes(`ECONNRESET`)
554
+ || err.stack.includes(`ECONNREFUSED`)
553
555
  ) {
554
556
  this.log(err.message + " retrying in 5s");
555
557
  await delay(5000);
@@ -1015,7 +1015,7 @@ export class PathValueProxyWatcher {
1015
1015
  options: WatcherOptions<Result>
1016
1016
  ): SyncWatcher {
1017
1017
  if (isAsyncFunction(options.watchFunction)) {
1018
- throw new Error(`Async functions are not supported in watchers. They must run the caller synchronously. You are likely not using Await anyway, so just remove the async and make it a synchronous function. The caller will be called again whenever the data you access changes, And if you are running this to return a result, it will be rerun until all the data you want is synchronized. Watch function: ${options.watchFunction.toString()}`);
1018
+ throw new Error(`A watcher function cannot be async, it must be synchronous. You probably did Querysub.commitAsync(async () => {}). Just remove the async, and do Querysub.commit(() => {}). The caller will be called again whenever the data you access changes, And if you are running this to return a result, it will be rerun until all the data you want is synchronized. Watch function: ${options.watchFunction.toString()}`);
1019
1019
  }
1020
1020
  // NOTE: Setting an order is needed for rendering, so parents render before children. I believe
1021
1021
  // it is generally what we want, so event triggering is consistent, and fits with any tree based
@@ -74,6 +74,7 @@ function closeModal(id: string) {
74
74
  export function showModal(config: {
75
75
  content: preact.ComponentChild;
76
76
  onClose?: () => void | "abortClose";
77
+ onlyCloseExplicitly?: boolean;
77
78
  }): {
78
79
  close: () => void;
79
80
  } {
@@ -83,6 +84,7 @@ export function showModal(config: {
83
84
  data().modals[id] = atomicObjectWriteNoFreeze({
84
85
  value: config.content,
85
86
  onClose: config.onClose,
87
+ onlyExplicitClose: config.onlyCloseExplicitly,
86
88
  });
87
89
  });
88
90
  function close() {
@@ -94,6 +96,7 @@ export function showModal(config: {
94
96
  export function closeAllModals() {
95
97
  Querysub.commit(() => {
96
98
  for (let [id, obj] of Object.entries(data().modals)) {
99
+ if (obj.onlyExplicitClose) continue;
97
100
  closeModal(id);
98
101
  }
99
102
  });
@@ -548,14 +548,16 @@ export class RecentErrors {
548
548
  });
549
549
 
550
550
  private _recentErrors: LogDatum[] = [];
551
- private updateRecentErrors = runInSerial(async (objs: LogDatum[]) => {
552
- objs = await suppressionList.filterObjsToNonSuppressed(objs);
553
- let newRecentErrors = limitRecentErrors(objs);
551
+ private _lastSentErrors: LogDatum[] = [];
552
+ private updateRecentErrors = runInSerial(async () => {
553
+ let newList = this._recentErrors;
554
+ newList = await suppressionList.filterObjsToNonSuppressed(newList);
555
+ newList = limitRecentErrors(newList);
554
556
  // If any changed
555
- let prev = new Set(this._recentErrors);
556
- let newErrors = new Set(newRecentErrors);
557
+ let prev = new Set(this._lastSentErrors);
558
+ let newErrors = new Set(newList);
557
559
  function hasAnyChanged() {
558
- for (let obj of newRecentErrors) {
560
+ for (let obj of newList) {
559
561
  if (!prev.has(obj)) {
560
562
  return true;
561
563
  }
@@ -567,8 +569,8 @@ export class RecentErrors {
567
569
  }
568
570
  return false;
569
571
  }
572
+ this._lastSentErrors = newList;
570
573
  if (hasAnyChanged()) {
571
- this._recentErrors = newRecentErrors;
572
574
  void this.broadcastUpdate(undefined);
573
575
  }
574
576
  });
@@ -586,7 +588,7 @@ export class RecentErrors {
586
588
  for (let obj of objs) {
587
589
  this._recentErrors.push(obj);
588
590
  }
589
- await this.updateRecentErrors(this._recentErrors);
591
+ await this.updateRecentErrors();
590
592
  });
591
593
 
592
594
  private lastSuppressionList = new Map<string, SuppressionEntry>();
@@ -613,7 +615,7 @@ export class RecentErrors {
613
615
  void this.scanNow({});
614
616
  }
615
617
  this.lastSuppressionList = newSuppressionList;
616
- await this.updateRecentErrors(this._recentErrors);
618
+ await this.updateRecentErrors();
617
619
  });
618
620
 
619
621
  private scannedHashes = new Set<string>();
@@ -636,7 +638,7 @@ export class RecentErrors {
636
638
  noLocalFiles: config.noLocalFiles,
637
639
  });
638
640
  // Filter again, as new suppressions change the errors
639
- await this.updateRecentErrors(this._recentErrors);
641
+ await this.updateRecentErrors();
640
642
  let recentLimit = 0;
641
643
  const applyRecentLimit = () => {
642
644
  if (this._recentErrors.length < MAX_RECENT_ERRORS) return;
@@ -147,7 +147,9 @@ export class ErrorWarning extends qreact.Component {
147
147
  if (recentErrors[0].__matchedOutdatedSuppressionKey) {
148
148
  let key = recentErrors[0].__matchedOutdatedSuppressionKey;
149
149
  topExpired = suppressionList.find(x => x.key === key);
150
-
150
+ }
151
+ function showSpecialCharacters(text: string) {
152
+ return text.replaceAll("\n", "\\n");
151
153
  }
152
154
 
153
155
  return (
@@ -181,12 +183,12 @@ export class ErrorWarning extends qreact.Component {
181
183
  Match Pattern =
182
184
  </div>
183
185
  <div className={css.hsl(200, 40, 40).pad2(4, 2).colorhsl(0, 0, 95)}>
184
- {topExpired.match}
186
+ {showSpecialCharacters(topExpired.match)}
185
187
  </div>
186
188
  </div>
187
189
  }
188
190
  <div className={css.hbox(8).hsl(0, 50, 50).pad2(4, 2).colorhsl(0, 50, 95)}>
189
- ({formatDateJSX(recentErrors[0].time)}) {recentErrors[0].param0} ({recentErrors[0].__NAME__})
191
+ ({formatDateJSX(recentErrors[0].time)}) {showSpecialCharacters(String(recentErrors[0].param0))} ({recentErrors[0].__NAME__})
190
192
  </div>
191
193
 
192
194
  <div className={css.hbox(8).fillWidth}>
@@ -85,7 +85,7 @@ class CloseWrapper extends qreact.Component<{ seqNum: number }> {
85
85
  }
86
86
  }
87
87
  let ensureNotifications = lazy(() => {
88
- showModal({ content: <Notifications /> });
88
+ showModal({ content: <Notifications />, onlyCloseExplicitly: true });
89
89
  });
90
90
 
91
91
  /** Allows capturing the current state so the notification can be closed later on */
@@ -52,9 +52,11 @@ function onMessage(config: {
52
52
  // Detach entirely from any state, as we are triggered from console.error, which may be called in
53
53
  // very fragile states.
54
54
  setImmediate(() => {
55
- let title = stripConsoleRenderedColors(config.message).split("\n")[0];
55
+ let title = stripConsoleRenderedColors(config.message);
56
56
  if (title.startsWith("Error: ")) {
57
- title = title.slice("Error: ".length);
57
+ title = title.slice("Error: ".length).split("\n")[0];
58
+ } else {
59
+ title = title.replaceAll("\n", " ").slice(0, 200);
58
60
  }
59
61
  showNotification({
60
62
  pos: "topRight",
@@ -80,5 +82,5 @@ function onMessage(config: {
80
82
  // \033[38;2;<r>;<g>;<b>m
81
83
 
82
84
  function stripConsoleRenderedColors(text: string) {
83
- return String(text).replaceAll(/\033\[\d+(;\d+)*m/g, "");
84
- }
85
+ return String(text).replaceAll(/\x1b\[\d+(;\d+)*m/g, "");
86
+ }