querysub 0.403.0 → 0.405.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 (108) hide show
  1. package/.cursorrules +2 -0
  2. package/bin/audit-imports.js +4 -0
  3. package/bin/join.js +1 -1
  4. package/package.json +7 -4
  5. package/spec.txt +77 -0
  6. package/src/-a-archives/archiveCache.ts +9 -4
  7. package/src/-a-archives/archivesBackBlaze.ts +1039 -1039
  8. package/src/-a-auth/certs.ts +0 -12
  9. package/src/-c-identity/IdentityController.ts +12 -3
  10. package/src/-f-node-discovery/NodeDiscovery.ts +32 -26
  11. package/src/-g-core-values/NodeCapabilities.ts +12 -2
  12. package/src/0-path-value-core/AuthorityLookup.ts +239 -0
  13. package/src/0-path-value-core/LockWatcher2.ts +150 -0
  14. package/src/0-path-value-core/PathRouter.ts +543 -0
  15. package/src/0-path-value-core/PathRouterRouteOverride.ts +72 -0
  16. package/src/0-path-value-core/PathRouterServerAuthoritySpec.tsx +73 -0
  17. package/src/0-path-value-core/PathValueCommitter.ts +222 -488
  18. package/src/0-path-value-core/PathValueController.ts +277 -239
  19. package/src/0-path-value-core/PathWatcher.ts +534 -0
  20. package/src/0-path-value-core/ShardPrefixes.ts +31 -0
  21. package/src/0-path-value-core/ValidStateComputer.ts +303 -0
  22. package/src/0-path-value-core/archiveLocks/ArchiveLocks.ts +1 -1
  23. package/src/0-path-value-core/archiveLocks/ArchiveLocks2.ts +80 -44
  24. package/src/0-path-value-core/archiveLocks/archiveSnapshots.ts +13 -16
  25. package/src/0-path-value-core/auditLogs.ts +2 -0
  26. package/src/0-path-value-core/hackedPackedPathParentFiltering.ts +97 -0
  27. package/src/0-path-value-core/pathValueArchives.ts +491 -492
  28. package/src/0-path-value-core/pathValueCore.ts +195 -1496
  29. package/src/0-path-value-core/startupAuthority.ts +74 -0
  30. package/src/1-path-client/RemoteWatcher.ts +90 -82
  31. package/src/1-path-client/pathValueClientWatcher.ts +808 -815
  32. package/src/2-proxy/PathValueProxyWatcher.ts +10 -8
  33. package/src/2-proxy/archiveMoveHarness.ts +182 -214
  34. package/src/2-proxy/garbageCollection.ts +9 -8
  35. package/src/2-proxy/schema2.ts +21 -1
  36. package/src/3-path-functions/PathFunctionHelpers.ts +206 -180
  37. package/src/3-path-functions/PathFunctionRunner.ts +943 -766
  38. package/src/3-path-functions/PathFunctionRunnerMain.ts +5 -3
  39. package/src/3-path-functions/pathFunctionLoader.ts +2 -2
  40. package/src/3-path-functions/syncSchema.ts +596 -521
  41. package/src/4-deploy/deployFunctions.ts +19 -4
  42. package/src/4-deploy/deployGetFunctionsInner.ts +8 -2
  43. package/src/4-deploy/deployMain.ts +51 -68
  44. package/src/4-deploy/edgeClientWatcher.tsx +6 -1
  45. package/src/4-deploy/edgeNodes.ts +2 -2
  46. package/src/4-dom/qreact.tsx +2 -4
  47. package/src/4-dom/qreactTest.tsx +7 -13
  48. package/src/4-querysub/Querysub.ts +21 -8
  49. package/src/4-querysub/QuerysubController.ts +45 -29
  50. package/src/4-querysub/permissions.ts +2 -2
  51. package/src/4-querysub/querysubPrediction.ts +80 -70
  52. package/src/4-querysub/schemaHelpers.ts +5 -1
  53. package/src/5-diagnostics/GenericFormat.tsx +14 -9
  54. package/src/archiveapps/archiveGCEntry.tsx +9 -2
  55. package/src/archiveapps/archiveJoinEntry.ts +96 -84
  56. package/src/bits.ts +19 -0
  57. package/src/config.ts +21 -3
  58. package/src/config2.ts +23 -48
  59. package/src/deployManager/components/DeployPage.tsx +7 -3
  60. package/src/deployManager/machineSchema.ts +4 -1
  61. package/src/diagnostics/ActionsHistory.ts +3 -8
  62. package/src/diagnostics/AuditLogPage.tsx +2 -3
  63. package/src/diagnostics/FunctionCallInfo.tsx +141 -0
  64. package/src/diagnostics/FunctionCallInfoState.ts +162 -0
  65. package/src/diagnostics/MachineThreadInfo.tsx +1 -1
  66. package/src/diagnostics/NodeViewer.tsx +37 -48
  67. package/src/diagnostics/SyncTestPage.tsx +241 -0
  68. package/src/diagnostics/auditImportViolations.ts +185 -0
  69. package/src/diagnostics/listenOnDebugger.ts +3 -3
  70. package/src/diagnostics/logs/IndexedLogs/BufferUnitSet.ts +10 -4
  71. package/src/diagnostics/logs/IndexedLogs/IndexedLogs.ts +2 -2
  72. package/src/diagnostics/logs/IndexedLogs/LogViewer3.tsx +24 -22
  73. package/src/diagnostics/logs/IndexedLogs/moveIndexLogsToPublic.ts +1 -1
  74. package/src/diagnostics/logs/diskLogGlobalContext.ts +1 -0
  75. package/src/diagnostics/logs/errorNotifications2/logWatcher.ts +1 -3
  76. package/src/diagnostics/logs/lifeCycleAnalysis/LifeCycleEntryEditor.tsx +34 -16
  77. package/src/diagnostics/logs/lifeCycleAnalysis/LifeCycleEntryReadMode.tsx +4 -6
  78. package/src/diagnostics/logs/lifeCycleAnalysis/LifeCycleInstanceTableView.tsx +36 -5
  79. package/src/diagnostics/logs/lifeCycleAnalysis/LifeCyclePage.tsx +19 -5
  80. package/src/diagnostics/logs/lifeCycleAnalysis/LifeCycleRenderer.tsx +15 -7
  81. package/src/diagnostics/logs/lifeCycleAnalysis/NestedLifeCycleInfo.tsx +28 -106
  82. package/src/diagnostics/logs/lifeCycleAnalysis/lifeCycleMatching.ts +2 -0
  83. package/src/diagnostics/logs/lifeCycleAnalysis/lifeCycleMisc.ts +0 -0
  84. package/src/diagnostics/logs/lifeCycleAnalysis/lifeCycleSearch.tsx +18 -7
  85. package/src/diagnostics/logs/lifeCycleAnalysis/lifeCycles.tsx +3 -0
  86. package/src/diagnostics/managementPages.tsx +10 -3
  87. package/src/diagnostics/misc-pages/ArchiveViewer.tsx +20 -26
  88. package/src/diagnostics/misc-pages/ArchiveViewerTree.tsx +6 -4
  89. package/src/diagnostics/misc-pages/ComponentSyncStats.tsx +2 -2
  90. package/src/diagnostics/misc-pages/LocalWatchViewer.tsx +7 -9
  91. package/src/diagnostics/misc-pages/SnapshotViewer.tsx +23 -12
  92. package/src/diagnostics/misc-pages/archiveViewerShared.tsx +1 -1
  93. package/src/diagnostics/pathAuditer.ts +486 -0
  94. package/src/diagnostics/pathAuditerCallback.ts +20 -0
  95. package/src/diagnostics/watchdog.ts +8 -1
  96. package/src/library-components/URLParam.ts +1 -1
  97. package/src/misc/hash.ts +1 -0
  98. package/src/path.ts +21 -7
  99. package/src/server.ts +54 -47
  100. package/src/user-implementation/loginEmail.tsx +1 -1
  101. package/tempnotes.txt +65 -0
  102. package/test.ts +298 -97
  103. package/src/0-path-value-core/NodePathAuthorities.ts +0 -1057
  104. package/src/0-path-value-core/PathController.ts +0 -1
  105. package/src/5-diagnostics/diskValueAudit.ts +0 -218
  106. package/src/5-diagnostics/memoryValueAudit.ts +0 -438
  107. package/src/archiveapps/archiveMergeEntry.tsx +0 -48
  108. package/src/archiveapps/lockTest.ts +0 -127
@@ -246,6 +246,24 @@ export class Schema2Fncs {
246
246
  public static schema2ToTypeString(schema: Schema2): string {
247
247
  return schema2ToTypeString(schema);
248
248
  }
249
+
250
+ /** Uses * for wildcards */
251
+ public static getLookups(schema: Schema2): string[][] {
252
+ let internalType = typeDefCached(schema);
253
+ let lookupPaths = new Set<string>();
254
+
255
+ for (let def of internalType.defs) {
256
+ for (let i = 0; i < def.path.length; i++) {
257
+ if (def.path[i] === WildCard) {
258
+ let lookupPath = def.path.slice(0, i);
259
+ let stringPath = lookupPath.map(p => p === WildCard ? "*" : p as string);
260
+ lookupPaths.add(JSON.stringify(stringPath));
261
+ }
262
+ }
263
+ }
264
+
265
+ return Array.from(lookupPaths).map(p => JSON.parse(p));
266
+ }
249
267
  }
250
268
 
251
269
  /*
@@ -699,7 +717,7 @@ function isDefParentOrEqualMatch(defPath: SchemaPath, path: string[]) {
699
717
  return true;
700
718
  }
701
719
 
702
- // let x = t.lookup({
720
+ // let x = ({
703
721
  // name: t.string,
704
722
  // num: t.number,
705
723
  // defaultedNum: t.number(1),
@@ -720,6 +738,8 @@ function isDefParentOrEqualMatch(defPath: SchemaPath, path: string[]) {
720
738
  // }),
721
739
  // }
722
740
  // });
741
+ // let lookups = Schema2Fncs.getLookups(x);
742
+ // console.log(lookups);
723
743
  // console.log(typeDefCached(x));
724
744
 
725
745
  // console.log("name", Schema2Fncs.isAtomic(x, "read", ["x", "name"]));
@@ -1,181 +1,207 @@
1
- import { getOwnMachineId } from "../-a-auth/certs";
2
- import { atomicObjectWrite, proxyWatcher, specialObjectWriteSymbol } from "../2-proxy/PathValueProxyWatcher";
3
- import { pathValueCommitter } from "../0-path-value-core/PathValueController";
4
- import { getNextTime } from "../0-path-value-core/pathValueCore";
5
- import { FunctionSpec, functionSchema, CallSpec, commitCall } from "./PathFunctionRunner";
6
- import { logErrors } from "../errors";
7
- import { FunctionMetadata } from "./syncSchema";
8
- import debugbreak from "debugbreak";
9
- import cborx from "cbor-x";
10
- import { lazy } from "socket-function/src/caching";
11
- import { secureRandom } from "../misc/random";
12
- import { isDefined } from "../misc";
13
- import { blue, green, red } from "socket-function/src/formatting/logColors";
14
- import { getPathStr2 } from "../path";
15
- import { isNode, sort } from "socket-function/src/misc";
16
- import { decodeCborx, encodeCborx } from "../misc/cloneHelpers";
17
- import { parseFilterable } from "../misc/filterable";
18
- import { interceptCalls } from "../-0-hooks/hooks";
19
-
20
- // NOTE: We could deploy single functions, but... we will almost always be updating all functions at
21
- // once, because keeping everything on the same git hash reduces a lot of potential bugs.
22
- export async function replaceFunctions(config: {
23
- functions: FunctionSpec[];
24
- }) {
25
- await proxyWatcher.commitFunction({
26
- debugName: "replaceFunctions",
27
- watchFunction() {
28
- function debugFunction(func: FunctionSpec) {
29
- return `${func.DomainName}:${func.FilePath}:${func.ModuleId}:${func.FunctionId}`;
30
- }
31
-
32
- let { functions } = config;
33
- let domainsNames = new Set(functions.map(x => x.DomainName));
34
- if (domainsNames.size !== 1) {
35
- throw new Error(`Tried to deploy functions with multiple domains, ${JSON.stringify(domainsNames)}`);
36
- }
37
- let domainName = Array.from(domainsNames)[0];
38
-
39
- let base = functionSchema()[domainName].PathFunctionRunner;
40
- let previousFunctions = Object.values(base).flatMap(x => Object.values(x.Sources)).filter(isDefined);
41
-
42
- function getFunctionName(func: FunctionSpec) {
43
- return getPathStr2(func.ModuleId, func.FunctionId);
44
- }
45
-
46
- let currentFunctions = functions;
47
-
48
- let previousHashes = new Set(previousFunctions.map(x => JSON.stringify(x)));
49
- let currentHashes = new Set(currentFunctions.map(x => JSON.stringify(x)));
50
-
51
- let prevFunctionNames = new Set(previousFunctions.map(getFunctionName));
52
- let currentFunctionNames = new Set(currentFunctions.map(getFunctionName));
53
-
54
- let messages: {
55
- text: string;
56
- order: number;
57
- }[] = [];
58
-
59
- for (let previous of previousFunctions) {
60
- if (!currentFunctionNames.has(getFunctionName(previous))) {
61
- messages.push({ text: `Removing\t ${red(debugFunction(previous))}`, order: 3 });
62
- base[previous.ModuleId].Sources[previous.FunctionId] = undefined;
63
- }
64
- }
65
-
66
- console.log();
67
- for (let func of currentFunctions) {
68
- if (previousHashes.has(JSON.stringify(func))) {
69
- messages.push({ text: `Unchanged\t ${debugFunction(func)}`, order: 0 });
70
- continue;
71
- }
72
- if (!prevFunctionNames.has(getFunctionName(func))) {
73
- messages.push({ text: `Deploying new\t ${green(debugFunction(func))}`, order: 2 });
74
- } else {
75
- messages.push({ text: `Deploying\t ${blue(debugFunction(func))}`, order: 1 });
76
- }
77
- base[func.ModuleId] = specialObjectWriteSymbol as any;
78
- base[func.ModuleId].Sources[func.FunctionId] = atomicObjectWrite(func);
79
- }
80
-
81
- if (proxyWatcher.isAllSynced()) {
82
- sort(messages, x => -x.order);
83
- for (let message of messages) {
84
- console.log(message.text);
85
- }
86
- }
87
- }
88
- });
89
-
90
- await pathValueCommitter.waitForValuesToCommit();
91
- }
92
-
93
- export const writeCall = {
94
- value: async (callSpec: CallSpec, metadata: FunctionMetadata) => {
95
- commitCall(callSpec);
96
- await pathValueCommitter.waitForValuesToCommit();
97
- }
98
- };
99
-
100
- export async function runCall(call: CallSpec, metadata: FunctionMetadata) {
101
- return await writeCall.value(call, metadata);
102
- }
103
-
104
-
105
- export interface CallInterceptor<T> {
106
- onCall: (call: CallSpec, metadata: FunctionMetadata) => void;
107
- code: () => T;
108
- }
109
-
110
- let curInterceptor: CallInterceptor<unknown> | undefined = undefined;
111
- export function interceptCallsBase<T>(
112
- interceptor: CallInterceptor<T>
113
- ) {
114
- let prev = curInterceptor;
115
- curInterceptor = interceptor;
116
- try {
117
- return interceptor.code();
118
- } finally {
119
- curInterceptor = prev;
120
- }
121
- }
122
- interceptCalls.declare(interceptCallsBase);
123
-
124
- /** Writes the function call allowing interceptors to capture it (vs runCall which just runs it). */
125
- export function writeFunctionCall(config: {
126
- domainName: string;
127
- moduleId: string;
128
- functionId: string;
129
- args: unknown[];
130
- metadata: FunctionMetadata,
131
- }) {
132
- let { domainName, moduleId, functionId, args, metadata } = config;
133
-
134
- let now = Date.now();
135
- // IMPORTANT! CallId MUST be secure, otherwise other users can guess it, and read our calls
136
- // (which could contain secret data).
137
- // secureRandom() is pretty good... combined with date it should be hard enough to guess
138
- // - date adds about 10 bits of randomness (an attacker might be able to guess within a second
139
- // the time a specific call was made)
140
- // - secureRandom adds at more 64 bits of randomess, but in reality it is probably less
141
- // - ALSO, if they don't guess the call within the event remove window... it will be be deleted,
142
- // which gives them about a minute to guess it...
143
- let callId = now + "_" + secureRandom();
144
- let argsEncoded = encodeArgs(args);
145
- let callSpec: CallSpec = {
146
- argsEncoded,
147
- ModuleId: moduleId,
148
- CallId: callId,
149
- DomainName: domainName,
150
- FunctionId: functionId,
151
- runAtTime: getNextTime(),
152
- callerMachineId: getOwnMachineId(),
153
- // Will be updated by Querysub to be correct (unless we are directly writing, then...
154
- // this is fine).
155
- callerIP: "127.0.0.1",
156
- };
157
- if (!isNode()) {
158
- // Get the "setfncfilter" querystring parameter
159
- let url = new URL(window.location.href);
160
- let setfncfilter = url.searchParams.get("setfncfilter");
161
- if (setfncfilter) {
162
- callSpec.filterable = parseFilterable(setfncfilter);
163
- }
164
- }
165
-
166
- if (curInterceptor) {
167
- curInterceptor.onCall(callSpec, metadata);
168
- } else {
169
- logErrors(writeCall.value(callSpec, metadata));
170
- }
171
-
172
- return callSpec;
173
- }
174
-
175
- export function parseArgs(call: CallSpec): unknown[] {
176
- return decodeCborx(Buffer.from(call.argsEncoded, "base64"));
177
- }
178
-
179
- export function encodeArgs(args: unknown[]) {
180
- return encodeCborx(args).toString("base64");
1
+ import { getOwnMachineId } from "../-a-auth/certs";
2
+ import { atomicObjectWrite, proxyWatcher, specialObjectWriteSymbol } from "../2-proxy/PathValueProxyWatcher";
3
+ import { pathValueCommitter } from "../0-path-value-core/PathValueController";
4
+ import { getNextTime, getTimeUnique } from "../0-path-value-core/pathValueCore";
5
+ import { FunctionSpec, functionSchema, CallSpec, commitCall } from "./PathFunctionRunner";
6
+ import { logErrors } from "../errors";
7
+ import { FunctionMetadata, getCallIdOverride } from "./syncSchema";
8
+ import debugbreak from "debugbreak";
9
+ import cborx from "cbor-x";
10
+ import { cache, lazy } from "socket-function/src/caching";
11
+ import { secureRandom } from "../misc/random";
12
+ import { isDefined } from "../misc";
13
+ import { blue, green, red } from "socket-function/src/formatting/logColors";
14
+ import { getPathStr2 } from "../path";
15
+ import { isNode, sort } from "socket-function/src/misc";
16
+ import { decodeCborx, encodeCborx } from "../misc/cloneHelpers";
17
+ import { parseFilterable } from "../misc/filterable";
18
+ import { interceptCalls } from "../-0-hooks/hooks";
19
+ import { createRoutingOverrideKey } from "../0-path-value-core/PathRouterRouteOverride";
20
+ import { PathRouter } from "../0-path-value-core/PathRouter";
21
+ import { getPathFromProxy } from "../2-proxy/pathValueProxy";
22
+ import { getDomain } from "../config";
23
+
24
+ // NOTE: We could deploy single functions, but... we will almost always be updating all functions at
25
+ // once, because keeping everything on the same git hash reduces a lot of potential bugs.
26
+ export async function replaceFunctions(config: {
27
+ functions: FunctionSpec[];
28
+ }) {
29
+ await proxyWatcher.commitFunction({
30
+ debugName: "replaceFunctions",
31
+ watchFunction() {
32
+ function debugFunction(func: FunctionSpec) {
33
+ return `${func.DomainName}:${func.FilePath}:${func.ModuleId}:${func.FunctionId}`;
34
+ }
35
+
36
+ let { functions } = config;
37
+ let domainsNames = new Set(functions.map(x => x.DomainName));
38
+ if (domainsNames.size !== 1) {
39
+ throw new Error(`Tried to deploy functions with multiple domains, ${JSON.stringify(domainsNames)}`);
40
+ }
41
+ let domainName = Array.from(domainsNames)[0];
42
+
43
+ let base = functionSchema()[domainName].PathFunctionRunner;
44
+ let previousFunctions = Object.values(base).flatMap(x => Object.values(x.Sources)).filter(isDefined);
45
+
46
+ function getFunctionName(func: FunctionSpec) {
47
+ return getPathStr2(func.ModuleId, func.FunctionId);
48
+ }
49
+
50
+ let currentFunctions = functions;
51
+
52
+ let previousHashes = new Set(previousFunctions.map(x => JSON.stringify(x)));
53
+ let currentHashes = new Set(currentFunctions.map(x => JSON.stringify(x)));
54
+
55
+ let prevFunctionNames = new Set(previousFunctions.map(getFunctionName));
56
+ let currentFunctionNames = new Set(currentFunctions.map(getFunctionName));
57
+
58
+ let messages: {
59
+ text: string;
60
+ order: number;
61
+ }[] = [];
62
+
63
+ for (let previous of previousFunctions) {
64
+ if (!currentFunctionNames.has(getFunctionName(previous))) {
65
+ messages.push({ text: `Removing\t ${red(debugFunction(previous))}`, order: 3 });
66
+ base[previous.ModuleId].Sources[previous.FunctionId] = undefined;
67
+ }
68
+ }
69
+
70
+ console.log();
71
+ for (let func of currentFunctions) {
72
+ if (previousHashes.has(JSON.stringify(func))) {
73
+ messages.push({ text: `Unchanged\t ${debugFunction(func)}`, order: 0 });
74
+ continue;
75
+ }
76
+ if (!prevFunctionNames.has(getFunctionName(func))) {
77
+ messages.push({ text: `Deploying new\t ${green(debugFunction(func))}`, order: 2 });
78
+ } else {
79
+ messages.push({ text: `Deploying\t ${blue(debugFunction(func))}`, order: 1 });
80
+ }
81
+ base[func.ModuleId] = specialObjectWriteSymbol as any;
82
+ base[func.ModuleId].Sources[func.FunctionId] = atomicObjectWrite(func);
83
+ }
84
+
85
+ if (proxyWatcher.isAllSynced()) {
86
+ sort(messages, x => -x.order);
87
+ for (let message of messages) {
88
+ console.log(message.text);
89
+ }
90
+ }
91
+ }
92
+ });
93
+
94
+ await pathValueCommitter.waitForValuesToCommit();
95
+ }
96
+
97
+ export const writeCall = {
98
+ value: async (callSpec: CallSpec, metadata: FunctionMetadata) => {
99
+ commitCall(callSpec);
100
+ await pathValueCommitter.waitForValuesToCommit();
101
+ }
102
+ };
103
+
104
+ export async function runCall(call: CallSpec, metadata: FunctionMetadata) {
105
+ return await writeCall.value(call, metadata);
106
+ }
107
+
108
+
109
+ export interface CallInterceptor<T> {
110
+ onCall: (call: CallSpec, metadata: FunctionMetadata) => void;
111
+ code: () => T;
112
+ }
113
+
114
+ let curInterceptor: CallInterceptor<unknown> | undefined = undefined;
115
+ export function interceptCallsBase<T>(
116
+ interceptor: CallInterceptor<T>
117
+ ) {
118
+ let prev = curInterceptor;
119
+ curInterceptor = interceptor;
120
+ try {
121
+ return interceptor.code();
122
+ } finally {
123
+ curInterceptor = prev;
124
+ }
125
+ }
126
+ interceptCalls.declare(interceptCallsBase);
127
+
128
+
129
+ let getFunctionRunnerPrefix = cache((moduleId: string) => {
130
+ // We really want to remap it to the data prefix. However, if the user hasn't provided this to us, I guess we can just remap to whoever's watching the call. There has to be a server watching that anyway.
131
+ let path = getPathFromProxy(functionSchema()[getDomain()].PathFunctionRunner[moduleId].Calls);
132
+ if (!path) throw new Error(`getPathFromProxy was used wrong in getFunctionRunnerPrefix?`);
133
+ return path;
134
+ });
135
+
136
+ /** Writes the function call allowing interceptors to capture it (vs runCall which just runs it). */
137
+ export function writeFunctionCall(config: {
138
+ domainName: string;
139
+ moduleId: string;
140
+ functionId: string;
141
+ args: unknown[];
142
+ metadata: FunctionMetadata,
143
+ }) {
144
+ let { domainName, moduleId, functionId, args, metadata } = config;
145
+
146
+ // NOTE: Having this be an always-increasing time means that at least if it's the same client making the call ID, the numbers will always be increasing. So we can go from the call ID to determine the order of the calls, which is extremely useful.
147
+ let now = getTimeUnique();
148
+ // IMPORTANT! CallId MUST be secure, otherwise other users can guess it, and read our calls
149
+ // (which could contain secret data).
150
+ // secureRandom() is pretty good... combined with date it should be hard enough to guess
151
+ // - date adds about 10 bits of randomness (an attacker might be able to guess within a second
152
+ // the time a specific call was made)
153
+ // - secureRandom adds at more 64 bits of randomess, but in reality it is probably less
154
+ // - ALSO, if they don't guess the call within the event remove window... it will be be deleted,
155
+ // which gives them about a minute to guess it...
156
+ let callId = now + "_" + secureRandom();
157
+
158
+ // We HAVE to override the routing id, otherwise PathFunctionRunner secondary sharding won't work
159
+ callId = getCallIdOverride({
160
+ moduleId,
161
+ functionId,
162
+ callId,
163
+ args,
164
+ }) || createRoutingOverrideKey({
165
+ originalKey: callId,
166
+ routeKey: callId,
167
+ remappedPrefix: getFunctionRunnerPrefix(moduleId),
168
+ });
169
+
170
+ let argsEncoded = encodeArgs(args);
171
+ let callSpec: CallSpec = {
172
+ argsEncoded,
173
+ ModuleId: moduleId,
174
+ CallId: callId,
175
+ DomainName: domainName,
176
+ FunctionId: functionId,
177
+ runAtTime: getNextTime(),
178
+ callerMachineId: getOwnMachineId(),
179
+ // Will be updated by Querysub to be correct (unless we are directly writing, then...
180
+ // this is fine).
181
+ callerIP: "127.0.0.1",
182
+ };
183
+ if (!isNode()) {
184
+ // Get the "setfncfilter" querystring parameter
185
+ let url = new URL(window.location.href);
186
+ let setfncfilter = url.searchParams.get("setfncfilter");
187
+ if (setfncfilter) {
188
+ callSpec.filterable = parseFilterable(setfncfilter);
189
+ }
190
+ }
191
+
192
+ if (curInterceptor) {
193
+ curInterceptor.onCall(callSpec, metadata);
194
+ } else {
195
+ logErrors(writeCall.value(callSpec, metadata));
196
+ }
197
+
198
+ return callSpec;
199
+ }
200
+
201
+ export function parseArgs(call: CallSpec): unknown[] {
202
+ return decodeCborx(Buffer.from(call.argsEncoded, "base64"));
203
+ }
204
+
205
+ export function encodeArgs(args: unknown[]) {
206
+ return encodeCborx(args).toString("base64");
181
207
  }