querysub 0.312.0 → 0.313.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/.cursorrules +1 -1
- package/costsBenefits.txt +4 -1
- package/package.json +3 -2
- package/spec.txt +23 -18
- package/src/-0-hooks/hooks.ts +1 -1
- package/src/-a-archives/archives.ts +16 -3
- package/src/-a-archives/archivesBackBlaze.ts +51 -3
- package/src/-a-archives/archivesLimitedCache.ts +175 -0
- package/src/-a-archives/archivesPrivateFileSystem.ts +299 -0
- package/src/-a-auth/certs.ts +58 -31
- package/src/-b-authorities/cdnAuthority.ts +2 -2
- package/src/-b-authorities/dnsAuthority.ts +3 -2
- package/src/-c-identity/IdentityController.ts +3 -2
- package/src/-d-trust/NetworkTrust2.ts +17 -19
- package/src/-e-certs/EdgeCertController.ts +3 -4
- package/src/-e-certs/certAuthority.ts +1 -2
- package/src/-f-node-discovery/NodeDiscovery.ts +9 -7
- package/src/-g-core-values/NodeCapabilities.ts +6 -1
- package/src/0-path-value-core/NodePathAuthorities.ts +1 -1
- package/src/0-path-value-core/PathValueCommitter.ts +3 -3
- package/src/0-path-value-core/PathValueController.ts +3 -3
- package/src/0-path-value-core/archiveLocks/ArchiveLocks2.ts +15 -37
- package/src/0-path-value-core/pathValueCore.ts +4 -3
- package/src/3-path-functions/PathFunctionRunner.ts +2 -2
- package/src/4-dom/qreact.tsx +4 -3
- package/src/4-querysub/Querysub.ts +2 -2
- package/src/4-querysub/QuerysubController.ts +2 -2
- package/src/5-diagnostics/GenericFormat.tsx +1 -0
- package/src/5-diagnostics/Table.tsx +3 -0
- package/src/5-diagnostics/diskValueAudit.ts +2 -1
- package/src/5-diagnostics/nodeMetadata.ts +0 -1
- package/src/deployManager/components/MachineDetailPage.tsx +9 -1
- package/src/deployManager/components/ServiceDetailPage.tsx +10 -1
- package/src/diagnostics/NodeViewer.tsx +3 -4
- package/src/diagnostics/logs/FastArchiveAppendable.ts +748 -0
- package/src/diagnostics/logs/FastArchiveController.ts +524 -0
- package/src/diagnostics/logs/FastArchiveViewer.tsx +863 -0
- package/src/diagnostics/logs/LogViewer2.tsx +349 -0
- package/src/diagnostics/logs/TimeRangeSelector.tsx +94 -0
- package/src/diagnostics/logs/diskLogger.ts +135 -305
- package/src/diagnostics/logs/diskShimConsoleLogs.ts +6 -29
- package/src/diagnostics/logs/errorNotifications/ErrorNotificationController.ts +577 -0
- package/src/diagnostics/logs/errorNotifications/ErrorSuppressionUI.tsx +225 -0
- package/src/diagnostics/logs/errorNotifications/ErrorWarning.tsx +207 -0
- package/src/diagnostics/logs/importLogsEntry.ts +38 -0
- package/src/diagnostics/logs/injectFileLocationToConsole.ts +7 -17
- package/src/diagnostics/logs/lifeCycleAnalysis/lifeCycles.tsx +0 -0
- package/src/diagnostics/logs/lifeCycleAnalysis/spec.md +151 -0
- package/src/diagnostics/managementPages.tsx +7 -16
- package/src/diagnostics/misc-pages/ComponentSyncStats.tsx +0 -1
- package/src/diagnostics/periodic.ts +5 -0
- package/src/diagnostics/watchdog.ts +2 -2
- package/src/functional/SocketChannel.ts +67 -0
- package/src/library-components/Input.tsx +1 -1
- package/src/library-components/InputLabel.tsx +5 -2
- package/src/misc.ts +111 -0
- package/src/src.d.ts +34 -1
- package/src/user-implementation/userData.ts +4 -3
- package/test.ts +13 -0
- package/testEntry2.ts +29 -0
- package/src/diagnostics/errorLogs/ErrorLogController.ts +0 -535
- package/src/diagnostics/errorLogs/ErrorLogCore.ts +0 -274
- package/src/diagnostics/errorLogs/LogClassifiers.tsx +0 -308
- package/src/diagnostics/errorLogs/LogFilterUI.tsx +0 -84
- package/src/diagnostics/errorLogs/LogNotify.tsx +0 -101
- package/src/diagnostics/errorLogs/LogTimeSelector.tsx +0 -723
- package/src/diagnostics/errorLogs/LogViewer.tsx +0 -757
- package/src/diagnostics/errorLogs/logFiltering.tsx +0 -149
- package/src/diagnostics/logs/DiskLoggerPage.tsx +0 -613
|
@@ -28,7 +28,7 @@ import { addComponentButton } from "../5-diagnostics/qreactDebug";
|
|
|
28
28
|
import { closeAllModals } from "../5-diagnostics/Modal";
|
|
29
29
|
import { delay } from "socket-function/src/batching";
|
|
30
30
|
|
|
31
|
-
const
|
|
31
|
+
const ErrorWarning = createLazyComponent(() => import("./logs/errorNotifications/ErrorWarning"))("ErrorWarning");
|
|
32
32
|
|
|
33
33
|
export const managementPageURL = new URLParam("managementpage", "");
|
|
34
34
|
export const showingManagementURL = new URLParam("showingmanagement", false);
|
|
@@ -63,6 +63,9 @@ export async function registerManagementPages2(config: {
|
|
|
63
63
|
title?: string;
|
|
64
64
|
}[];
|
|
65
65
|
}) {
|
|
66
|
+
// Wait, so this happens asynchronously
|
|
67
|
+
await delay(0);
|
|
68
|
+
|
|
66
69
|
if (registeredModule) {
|
|
67
70
|
if (registeredModule === config.module) return;
|
|
68
71
|
throw new Error(`registerManagementPages2 called with a different module than previously registered. This will break isManagementUser, and so is not allowed.`);
|
|
@@ -84,20 +87,8 @@ export async function registerManagementPages2(config: {
|
|
|
84
87
|
});
|
|
85
88
|
inputPages.push({
|
|
86
89
|
title: "Logs",
|
|
87
|
-
componentName: "
|
|
88
|
-
|
|
89
|
-
getModule: () => import("./logs/DiskLoggerPage"),
|
|
90
|
-
});
|
|
91
|
-
inputPages.push({
|
|
92
|
-
title: "Error Notifications",
|
|
93
|
-
componentName: "LogViewer",
|
|
94
|
-
controllerName: "LogViewerController",
|
|
95
|
-
getModule: () => import("./errorLogs/LogViewer"),
|
|
96
|
-
});
|
|
97
|
-
inputPages.push({
|
|
98
|
-
title: "Error Classes",
|
|
99
|
-
componentName: "LogClassifiers",
|
|
100
|
-
getModule: () => import("./errorLogs/LogClassifiers"),
|
|
90
|
+
componentName: "LogViewer2",
|
|
91
|
+
getModule: () => import("./logs/LogViewer2"),
|
|
101
92
|
});
|
|
102
93
|
inputPages.push({
|
|
103
94
|
title: "Audit Paths",
|
|
@@ -319,7 +310,7 @@ class ManagementRoot extends qreact.Component {
|
|
|
319
310
|
`}
|
|
320
311
|
</style>
|
|
321
312
|
<div class={css.fillWidth.hbox(30, 10).wrap.hsl(245, 25, 60).pad2(10).pointerEvents("all")}>
|
|
322
|
-
<
|
|
313
|
+
<ErrorWarning />
|
|
323
314
|
{pages.map(page =>
|
|
324
315
|
<ATag values={[{ param: managementPageURL, value: page.componentName }]}>{page.title}</ATag>
|
|
325
316
|
)}
|
|
@@ -10,7 +10,6 @@ import { formatNumber, formatPercent, formatTime } from "socket-function/src/for
|
|
|
10
10
|
import { nextId, sort } from "socket-function/src/misc";
|
|
11
11
|
import { ATag } from "../../library-components/ATag";
|
|
12
12
|
import { managementPageURL, showingManagementURL } from "../../diagnostics/managementPages";
|
|
13
|
-
import { filterURL } from "../../diagnostics/logs/DiskLoggerPage";
|
|
14
13
|
import { watchShowLocalPaths, watchValueType } from "./LocalWatchViewer";
|
|
15
14
|
import { filtersURL, viewMode } from "./archiveViewerShared";
|
|
16
15
|
import { proxyWatcher } from "../../2-proxy/PathValueProxyWatcher";
|
|
@@ -6,6 +6,11 @@ import { nodeDiscoveryShutdown } from "../-f-node-discovery/NodeDiscovery";
|
|
|
6
6
|
import { authorityStorage } from "../0-path-value-core/pathValueCore";
|
|
7
7
|
import { red } from "socket-function/src/formatting/logColors";
|
|
8
8
|
|
|
9
|
+
// Import querysub, so all the hooks we use will exist at some point
|
|
10
|
+
setImmediate(async () => {
|
|
11
|
+
await import("../4-querysub/QuerysubController");
|
|
12
|
+
});
|
|
13
|
+
|
|
9
14
|
let periodicFncs: (() => void)[] = [];
|
|
10
15
|
export function registerPeriodic(fnc: () => void) {
|
|
11
16
|
periodicFncs.push(fnc);
|
|
@@ -6,10 +6,10 @@ import debugbreak from "debugbreak";
|
|
|
6
6
|
import { registerPeriodic } from "./periodic";
|
|
7
7
|
import { getOwnMachineId } from "../-a-auth/certs";
|
|
8
8
|
import { SocketFunction } from "socket-function/SocketFunction";
|
|
9
|
-
import { logDisk } from "./logs/diskLogger";
|
|
10
9
|
import { formatPercent, formatTime } from "socket-function/src/formatting/format";
|
|
11
10
|
import { pathWatcher } from "../0-path-value-core/pathValueCore";
|
|
12
11
|
import { addStatPeriodic, addStatSumPeriodic, addTimeProfileDistribution, registerNodeMetadata } from "../-0-hooks/hooks";
|
|
12
|
+
import { logDisk } from "./logs/diskLogger";
|
|
13
13
|
|
|
14
14
|
let lastProfile: MeasureProfile | undefined;
|
|
15
15
|
|
|
@@ -72,7 +72,7 @@ function logProfileMeasuresTimingsNow() {
|
|
|
72
72
|
measureObj = startMeasure();
|
|
73
73
|
function diskLogMeasureObj(table: FormattedMeasureTable | undefined) {
|
|
74
74
|
if (!table) return;
|
|
75
|
-
logDisk(table.title, table.entries);
|
|
75
|
+
logDisk("log", table.title, { entries: table.entries });
|
|
76
76
|
}
|
|
77
77
|
diskLogMeasureObj(logMeasureTable(profile, {
|
|
78
78
|
name: `watchdog at ${new Date().toLocaleString()}`,
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { SocketFunction } from "socket-function/SocketFunction";
|
|
2
|
+
import { lazy } from "socket-function/src/caching";
|
|
3
|
+
import { getAllNodeIds, watchNodeIds } from "../-f-node-discovery/NodeDiscovery";
|
|
4
|
+
import { requiresNetworkTrustHook } from "../-d-trust/NetworkTrust2";
|
|
5
|
+
import { errorToUndefinedSilent } from "../errors";
|
|
6
|
+
import { assertIsManagementUser } from "../diagnostics/managementPages";
|
|
7
|
+
|
|
8
|
+
export class SocketChannel<T> {
|
|
9
|
+
constructor(private globalUniqueChannelName: string) { }
|
|
10
|
+
private controller = SocketFunction.register(
|
|
11
|
+
this.globalUniqueChannelName,
|
|
12
|
+
// Why do we have to cast here? Odd...
|
|
13
|
+
() => this as {
|
|
14
|
+
_internal_onMessage: (message: T) => Promise<void>;
|
|
15
|
+
_internal_watchMessages: () => Promise<void>;
|
|
16
|
+
},
|
|
17
|
+
() => ({
|
|
18
|
+
_internal_onMessage: { hooks: [assertIsManagementUser] },
|
|
19
|
+
_internal_watchMessages: { hooks: [assertIsManagementUser] },
|
|
20
|
+
}),
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
private localWatchers = new Set<(message: T) => void>();
|
|
24
|
+
// Has to be public for SocketFunction, don't call this externally
|
|
25
|
+
public async _internal_onMessage(message: T) {
|
|
26
|
+
for (let watcher of this.localWatchers) {
|
|
27
|
+
// Ignore errors (let the unhandled promise rejection handler log them)
|
|
28
|
+
void (async () => {
|
|
29
|
+
await watcher(message);
|
|
30
|
+
})();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
private remoteWatchers = new Set<string>();
|
|
35
|
+
public async _internal_watchMessages() {
|
|
36
|
+
let caller = SocketFunction.getCaller();
|
|
37
|
+
this.remoteWatchers.add(caller.nodeId);
|
|
38
|
+
SocketFunction.onNextDisconnect(caller.nodeId, () => {
|
|
39
|
+
this.remoteWatchers.delete(caller.nodeId);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public broadcast(message: T) {
|
|
44
|
+
void Array.from(this.remoteWatchers).map(async (nodeId) => {
|
|
45
|
+
try {
|
|
46
|
+
await this.controller.nodes[nodeId]._internal_onMessage(message);
|
|
47
|
+
} catch {
|
|
48
|
+
this.remoteWatchers.delete(nodeId);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
private watchAllNodes = lazy(async () => {
|
|
54
|
+
watchNodeIds((nodeIds) => {
|
|
55
|
+
for (let nodeId of nodeIds) {
|
|
56
|
+
void errorToUndefinedSilent(this.controller.nodes[nodeId]._internal_watchMessages());
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
public watch(callback: (message: T) => void) {
|
|
61
|
+
void this.watchAllNodes();
|
|
62
|
+
this.localWatchers.add(callback);
|
|
63
|
+
return () => {
|
|
64
|
+
this.localWatchers.delete(callback);
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -27,7 +27,7 @@ export type InputProps = (
|
|
|
27
27
|
noEnterKeyCommit?: boolean;
|
|
28
28
|
noFocusSelect?: boolean;
|
|
29
29
|
inputKey?: string;
|
|
30
|
-
fillWidth?: boolean;
|
|
30
|
+
fillWidth?: boolean | number;
|
|
31
31
|
|
|
32
32
|
/** By default, we don't accept value updates when focused. This prevents the user's
|
|
33
33
|
* typing from being interrupted by a value update. However, this flag will
|
|
@@ -27,7 +27,7 @@ export type InputLabelProps = Omit<InputProps, "label" | "title"> & {
|
|
|
27
27
|
|
|
28
28
|
tooltip?: string;
|
|
29
29
|
|
|
30
|
-
fillWidth?: boolean;
|
|
30
|
+
fillWidth?: boolean | number;
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
function roundToDecimals(value: number, decimals: number) {
|
|
@@ -152,7 +152,10 @@ export class InputLabel extends qreact.Component<InputLabelProps> {
|
|
|
152
152
|
+ " trigger-hover "
|
|
153
153
|
+ props.outerClass
|
|
154
154
|
+ (props.flavor === "large" && css.fontSize(18, "soft"))
|
|
155
|
-
+ (props.fillWidth &&
|
|
155
|
+
+ (props.fillWidth &&
|
|
156
|
+
css.flexGrow(typeof props.fillWidth === "number" ? props.fillWidth : 1)
|
|
157
|
+
.alignSelf("stretch")
|
|
158
|
+
)
|
|
156
159
|
}>
|
|
157
160
|
<div
|
|
158
161
|
class={
|
package/src/misc.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { canHaveChildren } from "socket-function/src/types";
|
|
2
|
+
|
|
1
3
|
// TIMING: About 20MB/s
|
|
2
4
|
export function createRandomText(count: number): string {
|
|
3
5
|
let text = "";
|
|
@@ -61,4 +63,113 @@ export function mostCommon<T>(array: T[]): T | undefined {
|
|
|
61
63
|
counts.set(item, (counts.get(item) || 0) + 1);
|
|
62
64
|
}
|
|
63
65
|
return Array.from(counts.entries()).sort((a, b) => b[1] - a[1])[0]?.[0];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
export function parsePath(path: string): { dir: string; name: string } {
|
|
70
|
+
path = path.replaceAll("\\", "/");
|
|
71
|
+
let lastSlash = path.lastIndexOf("/");
|
|
72
|
+
if (lastSlash === -1) return { dir: "", name: path };
|
|
73
|
+
return { dir: path.slice(0, lastSlash + 1), name: path.slice(lastSlash + 1) };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Loses spaces in keys and values
|
|
77
|
+
export function toFileNameKVP(kvp: { [key: string]: string }): string {
|
|
78
|
+
function s(v: string) {
|
|
79
|
+
return v.replaceAll(" ", "_");
|
|
80
|
+
}
|
|
81
|
+
return " " + Object.entries(kvp).map(([key, value]) => `${s(key)}=${s(value)}`).join(" ") + " ";
|
|
82
|
+
}
|
|
83
|
+
export function parseFileNameKVP(fileName: string): { [key: string]: string } {
|
|
84
|
+
let parts = fileName.trim().split(" ");
|
|
85
|
+
let obj: { [key: string]: string } = {};
|
|
86
|
+
for (let part of parts) {
|
|
87
|
+
let [key, value] = part.split("=");
|
|
88
|
+
obj[key] = value || key;
|
|
89
|
+
}
|
|
90
|
+
return obj;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Copied object until maxFields is reached. */
|
|
94
|
+
export function partialCopyObject(data: unknown, maxFields: number = 500): unknown {
|
|
95
|
+
try {
|
|
96
|
+
let fieldCount = 0;
|
|
97
|
+
const seen = new WeakSet();
|
|
98
|
+
|
|
99
|
+
function copy(value: unknown): unknown {
|
|
100
|
+
// Handle primitives
|
|
101
|
+
if (!canHaveChildren(value)) {
|
|
102
|
+
return value;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Check for circular references
|
|
106
|
+
if (seen.has(value as object)) {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
seen.add(value as object);
|
|
110
|
+
|
|
111
|
+
// Check if we've hit the field limit
|
|
112
|
+
if (fieldCount >= maxFields) {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (Array.isArray(value)) {
|
|
117
|
+
const result: unknown[] = [];
|
|
118
|
+
for (const item of value) {
|
|
119
|
+
fieldCount++;
|
|
120
|
+
if (fieldCount >= maxFields) break;
|
|
121
|
+
result.push(copy(item));
|
|
122
|
+
}
|
|
123
|
+
seen.delete(value);
|
|
124
|
+
return result;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Handle plain objects
|
|
128
|
+
const result: Record<string, unknown> = {};
|
|
129
|
+
for (const key of Object.keys(value as object)) {
|
|
130
|
+
fieldCount++;
|
|
131
|
+
if (fieldCount >= maxFields) break;
|
|
132
|
+
result[key] = copy((value as Record<string, unknown>)[key]);
|
|
133
|
+
}
|
|
134
|
+
seen.delete(value);
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return copy(data) as any;
|
|
139
|
+
} catch (e: any) {
|
|
140
|
+
return { errorCopying: e.messsage } as any;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function sum(array: number[]): number {
|
|
145
|
+
return array.reduce((a, b) => a + b, 0);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export function matchFilter(filter: { value: string }, value: string) {
|
|
149
|
+
let filterValue = filter.value.toLowerCase().trim();
|
|
150
|
+
if (!filterValue) return true;
|
|
151
|
+
value = value.toLowerCase().trim();
|
|
152
|
+
return filterValue.split("|").some(part =>
|
|
153
|
+
part.split("&").every(part =>
|
|
154
|
+
value.includes(part.trim())
|
|
155
|
+
)
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
export const applyFilter = matchFilter;
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
export function streamToIteratable<T>(reader: {
|
|
162
|
+
read(): Promise<{ value: T; done: false } | { done: true; value?: T }>;
|
|
163
|
+
}): AsyncIterable<T> {
|
|
164
|
+
return {
|
|
165
|
+
[Symbol.asyncIterator]: async function* () {
|
|
166
|
+
while (true) {
|
|
167
|
+
const { done, value } = await reader.read();
|
|
168
|
+
if (done) {
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
yield value;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
};
|
|
64
175
|
}
|
package/src/src.d.ts
CHANGED
|
@@ -1 +1,34 @@
|
|
|
1
|
-
/// <reference path="./-a-auth/node-forge-ed25519.d.ts" />
|
|
1
|
+
/// <reference path="./-a-auth/node-forge-ed25519.d.ts" />
|
|
2
|
+
|
|
3
|
+
interface FileSystemDirectoryHandle {
|
|
4
|
+
[Symbol.asyncIterator](): AsyncIterator<[string, FileSystemFileHandle | FileSystemDirectoryHandle]>;
|
|
5
|
+
requestPermission(config: { mode: "read" | "readwrite" }): Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface FileSystemFileHandle {
|
|
9
|
+
getFile(): File;
|
|
10
|
+
createWritable(): FileSystemWritableFileStream;
|
|
11
|
+
createSyncAccessHandle(): Promise<FileSystemSyncAccessHandle>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface FileSystemSyncAccessHandle {
|
|
15
|
+
read(buffer: ArrayBuffer | ArrayBufferView, options?: { at: number }): number;
|
|
16
|
+
write(buffer: ArrayBuffer | ArrayBufferView, options?: { at: number }): number;
|
|
17
|
+
truncate(newSize: number): void;
|
|
18
|
+
flush(): void;
|
|
19
|
+
close(): void;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface Window {
|
|
23
|
+
showSaveFilePicker(config?: {
|
|
24
|
+
types: {
|
|
25
|
+
description: string; accept: { [mimeType: string]: string[] }
|
|
26
|
+
}[];
|
|
27
|
+
}): Promise<FileSystemFileHandle>;
|
|
28
|
+
showDirectoryPicker(): Promise<FileSystemDirectoryHandle>;
|
|
29
|
+
showOpenFilePicker(config?: {
|
|
30
|
+
types: {
|
|
31
|
+
description: string; accept: { [mimeType: string]: string[] }
|
|
32
|
+
}[];
|
|
33
|
+
}): Promise<FileSystemFileHandle[]>;
|
|
34
|
+
}
|
|
@@ -16,6 +16,7 @@ import { delay } from "socket-function/src/batching";
|
|
|
16
16
|
import { enableErrorNotifications } from "../library-components/errorNotifications";
|
|
17
17
|
import { clamp } from "../misc";
|
|
18
18
|
import { sha256 } from "js-sha256";
|
|
19
|
+
import { logDisk } from "../diagnostics/logs/diskLogger";
|
|
19
20
|
|
|
20
21
|
/*
|
|
21
22
|
IMPORTANT!
|
|
@@ -606,7 +607,7 @@ function sendLoginEmail(config: {
|
|
|
606
607
|
);
|
|
607
608
|
if (alreadyAllowed) {
|
|
608
609
|
data().machineSecure[machineId].userId = userId;
|
|
609
|
-
|
|
610
|
+
logDisk("log", `User ${userId} already allowed for current ip and machine id, no need to send email.`);
|
|
610
611
|
return;
|
|
611
612
|
}
|
|
612
613
|
}
|
|
@@ -780,14 +781,14 @@ function inviteUser(config: { email: string }) {
|
|
|
780
781
|
Querysub.ignorePermissionsChecks(() => {
|
|
781
782
|
let curUserObj = getUserObjAssert();
|
|
782
783
|
if (config.email in curUserObj.invitedUsers2) {
|
|
783
|
-
|
|
784
|
+
logDisk("log", `User ${config.email} already invited`);
|
|
784
785
|
return;
|
|
785
786
|
}
|
|
786
787
|
// If the user already exists, don't invite
|
|
787
788
|
const { email } = config;
|
|
788
789
|
let userId = atomic(data().secure.emailToUserId[email]) || createNewUserId();
|
|
789
790
|
if (userId in data().users) {
|
|
790
|
-
|
|
791
|
+
logDisk("log", `User ${userId} already exists, no need to invite`);
|
|
791
792
|
return;
|
|
792
793
|
}
|
|
793
794
|
|
package/test.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Querysub } from "./src/4-querysub/QuerysubController";
|
|
2
|
+
// Import querysub, so inject is run
|
|
3
|
+
Querysub;
|
|
4
|
+
import { formatTime } from "socket-function/src/formatting/format";
|
|
5
|
+
import { getMachineId, getOwnMachineId } from "./src/-a-auth/certs";
|
|
6
|
+
import { testLogs } from "./src/diagnostics/logs/LogViewer2";
|
|
7
|
+
import { shutdown } from "./src/diagnostics/periodic";
|
|
8
|
+
import crypto from "crypto";
|
|
9
|
+
import { testMain } from "./testEntry2";
|
|
10
|
+
|
|
11
|
+
testMain().catch(console.error).finally(() => {
|
|
12
|
+
process.exit(0);
|
|
13
|
+
});
|
package/testEntry2.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { delay } from "socket-function/src/batching";
|
|
2
|
+
import { getOwnMachineId } from "./src/-a-auth/certs";
|
|
3
|
+
import { getOwnThreadId } from "./src/-f-node-discovery/NodeDiscovery";
|
|
4
|
+
import { shutdown } from "./src/diagnostics/periodic";
|
|
5
|
+
|
|
6
|
+
export async function testMain() {
|
|
7
|
+
await delay(0);
|
|
8
|
+
console.log(getOwnThreadId());
|
|
9
|
+
console.error(`Test warning for ErrorWarning testing`);
|
|
10
|
+
console.log(getOwnThreadId());
|
|
11
|
+
await shutdown();
|
|
12
|
+
//await Querysub.hostService("test");
|
|
13
|
+
// for (let i = 0; i < 1000 * 10; i++) {
|
|
14
|
+
// for (let j = 0; j < 1000; j++) {
|
|
15
|
+
// testLogs.append({
|
|
16
|
+
// time: Date.now(),
|
|
17
|
+
// message: `Test message ${i}`,
|
|
18
|
+
// randomString: crypto.randomBytes(16).toString(),
|
|
19
|
+
// randomValue: Math.random(),
|
|
20
|
+
// });
|
|
21
|
+
// }
|
|
22
|
+
// await testLogs.flushNow();
|
|
23
|
+
// }
|
|
24
|
+
// await shutdown();
|
|
25
|
+
}
|
|
26
|
+
async function main() {
|
|
27
|
+
|
|
28
|
+
}
|
|
29
|
+
|