@concavejs/docstore-better-sqlite3 0.0.1-alpha.15 → 0.0.1-alpha.16
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/dist/index.js +724 -469
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1051,19 +1051,7 @@ function hexToString(hex) {
|
|
|
1051
1051
|
const buffer = hexToArrayBuffer(hex);
|
|
1052
1052
|
return new TextDecoder().decode(buffer);
|
|
1053
1053
|
}
|
|
1054
|
-
|
|
1055
|
-
if (!developerId) {
|
|
1056
|
-
return null;
|
|
1057
|
-
}
|
|
1058
|
-
for (const separator of [DOC_ID_SEPARATOR, LEGACY_DOC_ID_SEPARATOR]) {
|
|
1059
|
-
const parts = developerId.split(separator);
|
|
1060
|
-
if (parts.length === 2 && parts[0] && parts[1]) {
|
|
1061
|
-
return { table: parts[0], internalId: parts[1] };
|
|
1062
|
-
}
|
|
1063
|
-
}
|
|
1064
|
-
return null;
|
|
1065
|
-
}
|
|
1066
|
-
var BYTE_TO_HEX, HEX_TO_NIBBLE, DOC_ID_SEPARATOR = ":", LEGACY_DOC_ID_SEPARATOR = ";";
|
|
1054
|
+
var BYTE_TO_HEX, HEX_TO_NIBBLE;
|
|
1067
1055
|
var init_utils = __esm(() => {
|
|
1068
1056
|
BYTE_TO_HEX = [];
|
|
1069
1057
|
for (let i2 = 0;i2 < 256; i2++) {
|
|
@@ -3311,7 +3299,7 @@ async function listSystemFunctions(options = {}) {
|
|
|
3311
3299
|
const listing = filteredListings[i2];
|
|
3312
3300
|
const result = analysisResults[i2];
|
|
3313
3301
|
if (result.status === "rejected") {
|
|
3314
|
-
if (!
|
|
3302
|
+
if (!isExpectedNonFunctionModuleLoadError(result.reason)) {
|
|
3315
3303
|
console.warn(`Failed to analyze module "${listing.path}":`, result.reason);
|
|
3316
3304
|
}
|
|
3317
3305
|
continue;
|
|
@@ -3472,7 +3460,10 @@ async function discoverCronSpecs(options = {}) {
|
|
|
3472
3460
|
}
|
|
3473
3461
|
return cronSpecs;
|
|
3474
3462
|
}
|
|
3475
|
-
function
|
|
3463
|
+
function isExpectedNonFunctionModuleLoadError(error) {
|
|
3464
|
+
return isNpmPackageResolutionError(error) || isStubbedComponentDependencyError(error);
|
|
3465
|
+
}
|
|
3466
|
+
function isNpmPackageResolutionError(error) {
|
|
3476
3467
|
if (!(error instanceof Error))
|
|
3477
3468
|
return false;
|
|
3478
3469
|
const causes = error.causes;
|
|
@@ -3488,6 +3479,15 @@ function isNpmPackageError(error) {
|
|
|
3488
3479
|
return !modulePath.startsWith(".") && !modulePath.startsWith("/");
|
|
3489
3480
|
});
|
|
3490
3481
|
}
|
|
3482
|
+
function isStubbedComponentDependencyError(error) {
|
|
3483
|
+
if (!(error instanceof Error))
|
|
3484
|
+
return false;
|
|
3485
|
+
if (error.message.includes("could not be resolved while bundling component modules") && error.message.includes("only an error if this module is loaded at runtime")) {
|
|
3486
|
+
return true;
|
|
3487
|
+
}
|
|
3488
|
+
const causes = error.causes;
|
|
3489
|
+
return Array.isArray(causes) && causes.some((cause) => isStubbedComponentDependencyError(cause));
|
|
3490
|
+
}
|
|
3491
3491
|
var moduleAnalysisCache, moduleLoaderApiPromise = null, unsubscribeModuleLoader = null;
|
|
3492
3492
|
var init_function_introspection = __esm(() => {
|
|
3493
3493
|
init_analysis();
|
|
@@ -5415,6 +5415,10 @@ function parseBoolean(value) {
|
|
|
5415
5415
|
return;
|
|
5416
5416
|
return value.toLowerCase() === "true" || value === "1";
|
|
5417
5417
|
}
|
|
5418
|
+
function isDevEnvironment(env) {
|
|
5419
|
+
const environment = getEnvValue("ENVIRONMENT", env) ?? getEnvValue("CONCAVE_ENVIRONMENT", env) ?? getEnvValue("NODE_ENV", env);
|
|
5420
|
+
return environment === "development" || parseBoolean(getEnvValue("CONCAVE_DEV", env)) === true;
|
|
5421
|
+
}
|
|
5418
5422
|
function parseNumber(value) {
|
|
5419
5423
|
if (!value)
|
|
5420
5424
|
return;
|
|
@@ -5424,8 +5428,7 @@ function parseNumber(value) {
|
|
|
5424
5428
|
function resolveAdminAuthConfigFromEnv(env) {
|
|
5425
5429
|
const token = getEnvValue("ADMIN_TOKEN", env) ?? getEnvValue("CONCAVE_ADMIN_TOKEN", env) ?? getEnvValue("CONCAVE_ADMIN_KEY", env);
|
|
5426
5430
|
const allowInsecure = parseBoolean(getEnvValue("CONCAVE_ALLOW_INSECURE_ADMIN", env)) ?? parseBoolean(getEnvValue("ALLOW_INSECURE_ADMIN", env));
|
|
5427
|
-
const
|
|
5428
|
-
const allowInsecureFromEnv = allowInsecure ?? environment === "development";
|
|
5431
|
+
const allowInsecureFromEnv = allowInsecure ?? isDevEnvironment(env);
|
|
5429
5432
|
if (!token && !allowInsecureFromEnv) {
|
|
5430
5433
|
return;
|
|
5431
5434
|
}
|
|
@@ -5437,8 +5440,7 @@ function resolveAdminAuthConfigFromEnv(env) {
|
|
|
5437
5440
|
function resolveSystemAuthConfigFromEnv(env) {
|
|
5438
5441
|
const token = getEnvValue("SYSTEM_TOKEN", env) ?? getEnvValue("CONCAVE_SYSTEM_TOKEN", env) ?? getEnvValue("CONCAVE_SYSTEM_KEY", env);
|
|
5439
5442
|
const allowInsecure = parseBoolean(getEnvValue("CONCAVE_ALLOW_INSECURE_SYSTEM", env)) ?? parseBoolean(getEnvValue("ALLOW_INSECURE_SYSTEM", env));
|
|
5440
|
-
const
|
|
5441
|
-
const allowInsecureFromEnv = allowInsecure ?? environment === "development";
|
|
5443
|
+
const allowInsecureFromEnv = allowInsecure ?? isDevEnvironment(env);
|
|
5442
5444
|
if (!token && !allowInsecureFromEnv) {
|
|
5443
5445
|
return;
|
|
5444
5446
|
}
|
|
@@ -5658,35 +5660,35 @@ var init_jwt = __esm(() => {
|
|
|
5658
5660
|
|
|
5659
5661
|
// ../core/dist/auth/auth-context.js
|
|
5660
5662
|
function getAuthContext() {
|
|
5661
|
-
return
|
|
5663
|
+
return userIdentityContextStorage.getStore();
|
|
5662
5664
|
}
|
|
5663
|
-
function
|
|
5664
|
-
return
|
|
5665
|
+
function getResolvedAuthContext() {
|
|
5666
|
+
return resolvedAuthContextStorage.getStore();
|
|
5665
5667
|
}
|
|
5666
|
-
async function runWithAuth(auth, fn,
|
|
5667
|
-
return
|
|
5668
|
+
async function runWithAuth(auth, fn, resolvedAuthContext) {
|
|
5669
|
+
return resolvedAuthContextStorage.run(resolvedAuthContext, () => userIdentityContextStorage.run(auth, fn));
|
|
5668
5670
|
}
|
|
5669
|
-
var AUTH_CONTEXT_SYMBOL,
|
|
5671
|
+
var AUTH_CONTEXT_SYMBOL, RESOLVED_AUTH_CONTEXT_SYMBOL, globalAuthContext, userIdentityContextStorage, resolvedAuthContextStorage;
|
|
5670
5672
|
var init_auth_context = __esm(() => {
|
|
5671
5673
|
init_context_storage();
|
|
5672
5674
|
AUTH_CONTEXT_SYMBOL = Symbol.for("@concavejs/core/auth-context");
|
|
5673
|
-
|
|
5675
|
+
RESOLVED_AUTH_CONTEXT_SYMBOL = Symbol.for("@concavejs/core/resolved-auth-context");
|
|
5674
5676
|
globalAuthContext = globalThis;
|
|
5675
|
-
|
|
5676
|
-
|
|
5677
|
+
userIdentityContextStorage = globalAuthContext[AUTH_CONTEXT_SYMBOL] ?? new ContextStorage;
|
|
5678
|
+
resolvedAuthContextStorage = globalAuthContext[RESOLVED_AUTH_CONTEXT_SYMBOL] ?? new ContextStorage;
|
|
5677
5679
|
if (!globalAuthContext[AUTH_CONTEXT_SYMBOL]) {
|
|
5678
|
-
globalAuthContext[AUTH_CONTEXT_SYMBOL] =
|
|
5680
|
+
globalAuthContext[AUTH_CONTEXT_SYMBOL] = userIdentityContextStorage;
|
|
5679
5681
|
}
|
|
5680
|
-
if (!globalAuthContext[
|
|
5681
|
-
globalAuthContext[
|
|
5682
|
+
if (!globalAuthContext[RESOLVED_AUTH_CONTEXT_SYMBOL]) {
|
|
5683
|
+
globalAuthContext[RESOLVED_AUTH_CONTEXT_SYMBOL] = resolvedAuthContextStorage;
|
|
5682
5684
|
}
|
|
5683
5685
|
});
|
|
5684
5686
|
|
|
5685
|
-
// ../core/dist/auth/
|
|
5686
|
-
function
|
|
5687
|
+
// ../core/dist/auth/resolved-auth-context.js
|
|
5688
|
+
function anonymousAuthContext() {
|
|
5687
5689
|
return { kind: "none", scopes: [] };
|
|
5688
5690
|
}
|
|
5689
|
-
function
|
|
5691
|
+
function userAuthContext(identity, token, tenantId) {
|
|
5690
5692
|
const email = identity.email;
|
|
5691
5693
|
const subject = identity.subject;
|
|
5692
5694
|
return {
|
|
@@ -5698,7 +5700,7 @@ function userPrincipal(identity, token, tenantId) {
|
|
|
5698
5700
|
label: email ?? subject
|
|
5699
5701
|
};
|
|
5700
5702
|
}
|
|
5701
|
-
function
|
|
5703
|
+
function adminAuthContext(opts = {}) {
|
|
5702
5704
|
return {
|
|
5703
5705
|
kind: "admin",
|
|
5704
5706
|
scopes: opts.scopes ?? ["*"],
|
|
@@ -5708,7 +5710,7 @@ function adminPrincipal(opts = {}) {
|
|
|
5708
5710
|
label: opts.label ?? "admin"
|
|
5709
5711
|
};
|
|
5710
5712
|
}
|
|
5711
|
-
function
|
|
5713
|
+
function systemAuthContext(opts = {}) {
|
|
5712
5714
|
return {
|
|
5713
5715
|
kind: "system",
|
|
5714
5716
|
scopes: opts.scopes ?? ["*"],
|
|
@@ -5717,48 +5719,122 @@ function systemPrincipal(opts = {}) {
|
|
|
5717
5719
|
label: opts.label ?? "system"
|
|
5718
5720
|
};
|
|
5719
5721
|
}
|
|
5720
|
-
function hasCapability(
|
|
5721
|
-
if (
|
|
5722
|
+
function hasCapability(authContext, capability) {
|
|
5723
|
+
if (authContext.kind === "none" || authContext.kind === "user") {
|
|
5722
5724
|
return false;
|
|
5723
5725
|
}
|
|
5724
|
-
if (
|
|
5726
|
+
if (authContext.scopes.includes("*")) {
|
|
5725
5727
|
return true;
|
|
5726
5728
|
}
|
|
5727
|
-
return
|
|
5729
|
+
return authContext.scopes.includes(capability);
|
|
5728
5730
|
}
|
|
5729
|
-
function canCallInternal(
|
|
5730
|
-
return
|
|
5731
|
+
function canCallInternal(authContext) {
|
|
5732
|
+
return authContext.kind === "admin" || authContext.kind === "system" || authContext.kind === "service";
|
|
5731
5733
|
}
|
|
5732
|
-
function canAccessComponents(
|
|
5733
|
-
return
|
|
5734
|
+
function canAccessComponents(authContext) {
|
|
5735
|
+
return authContext.kind === "admin" || authContext.kind === "system";
|
|
5734
5736
|
}
|
|
5735
5737
|
function isAuthPrivileged(auth) {
|
|
5736
5738
|
return auth?.tokenType === "Admin" || auth?.tokenType === "System";
|
|
5737
5739
|
}
|
|
5738
|
-
function
|
|
5739
|
-
switch (
|
|
5740
|
+
function resolvedAuthContextToWireAuthContext(authContext) {
|
|
5741
|
+
switch (authContext.kind) {
|
|
5742
|
+
case "admin":
|
|
5743
|
+
return { tokenType: "Admin", token: authContext.token, userIdentity: authContext.userIdentity };
|
|
5744
|
+
case "system":
|
|
5745
|
+
return { tokenType: "System", token: authContext.token, userIdentity: authContext.userIdentity };
|
|
5746
|
+
case "user":
|
|
5747
|
+
return { tokenType: "User", token: authContext.token, userIdentity: authContext.userIdentity };
|
|
5748
|
+
case "service":
|
|
5749
|
+
return { tokenType: "Admin", token: authContext.token, userIdentity: authContext.userIdentity };
|
|
5750
|
+
default:
|
|
5751
|
+
return { tokenType: "None" };
|
|
5752
|
+
}
|
|
5753
|
+
}
|
|
5754
|
+
function wireAuthContextToResolvedAuthContext(authContext, tenantId) {
|
|
5755
|
+
switch (authContext.tokenType) {
|
|
5740
5756
|
case "Admin":
|
|
5741
|
-
return
|
|
5742
|
-
token:
|
|
5757
|
+
return adminAuthContext({
|
|
5758
|
+
token: authContext.token,
|
|
5743
5759
|
tenantId,
|
|
5744
|
-
impersonating:
|
|
5760
|
+
impersonating: authContext.userIdentity,
|
|
5745
5761
|
label: "admin"
|
|
5746
5762
|
});
|
|
5747
5763
|
case "System":
|
|
5748
|
-
return
|
|
5749
|
-
token:
|
|
5764
|
+
return systemAuthContext({
|
|
5765
|
+
token: authContext.token,
|
|
5750
5766
|
tenantId,
|
|
5751
5767
|
label: "system"
|
|
5752
5768
|
});
|
|
5753
5769
|
case "User":
|
|
5754
|
-
if (
|
|
5755
|
-
return
|
|
5770
|
+
if (authContext.userIdentity) {
|
|
5771
|
+
return userAuthContext(authContext.userIdentity, authContext.token, tenantId);
|
|
5756
5772
|
}
|
|
5757
|
-
return
|
|
5773
|
+
return anonymousAuthContext();
|
|
5758
5774
|
default:
|
|
5759
|
-
return
|
|
5775
|
+
return anonymousAuthContext();
|
|
5776
|
+
}
|
|
5777
|
+
}
|
|
5778
|
+
|
|
5779
|
+
// ../core/dist/auth/execution-auth.js
|
|
5780
|
+
function isResolvedAuthContext(value) {
|
|
5781
|
+
return value !== null && typeof value === "object" && "kind" in value && "scopes" in value && !("tokenType" in value);
|
|
5782
|
+
}
|
|
5783
|
+
function isWireAuthContext(value) {
|
|
5784
|
+
if (value === null || typeof value !== "object" || !("tokenType" in value)) {
|
|
5785
|
+
return false;
|
|
5786
|
+
}
|
|
5787
|
+
const tokenType = value.tokenType;
|
|
5788
|
+
return tokenType === "Admin" || tokenType === "System" || tokenType === "User" || tokenType === "None";
|
|
5789
|
+
}
|
|
5790
|
+
function resolveExecutionAuth(auth, tenantId) {
|
|
5791
|
+
if (isResolvedAuthContext(auth)) {
|
|
5792
|
+
return {
|
|
5793
|
+
authContext: auth,
|
|
5794
|
+
userIdentity: auth.userIdentity,
|
|
5795
|
+
wireAuthContext: resolvedAuthContextToWireAuthContext(auth),
|
|
5796
|
+
executorAuth: resolvedAuthContextToWireAuthContext(auth)
|
|
5797
|
+
};
|
|
5798
|
+
}
|
|
5799
|
+
if (isWireAuthContext(auth)) {
|
|
5800
|
+
const wireAuthContext = normalizeWireAuthContext(auth);
|
|
5801
|
+
return {
|
|
5802
|
+
authContext: wireAuthContextToResolvedAuthContext(wireAuthContext, tenantId),
|
|
5803
|
+
userIdentity: wireAuthContext.userIdentity,
|
|
5804
|
+
wireAuthContext,
|
|
5805
|
+
executorAuth: wireAuthContext
|
|
5806
|
+
};
|
|
5807
|
+
}
|
|
5808
|
+
if (auth) {
|
|
5809
|
+
return {
|
|
5810
|
+
authContext: userAuthContext(auth, undefined, tenantId),
|
|
5811
|
+
userIdentity: auth,
|
|
5812
|
+
executorAuth: auth
|
|
5813
|
+
};
|
|
5760
5814
|
}
|
|
5815
|
+
return {
|
|
5816
|
+
authContext: anonymousAuthContext(),
|
|
5817
|
+
wireAuthContext: { tokenType: "None" },
|
|
5818
|
+
executorAuth: undefined
|
|
5819
|
+
};
|
|
5761
5820
|
}
|
|
5821
|
+
function normalizeWireAuthContext(auth) {
|
|
5822
|
+
if (auth.tokenType !== "User" || auth.userIdentity || !auth.token) {
|
|
5823
|
+
return auth;
|
|
5824
|
+
}
|
|
5825
|
+
const userIdentity = identityFromTrustedToken(auth.token);
|
|
5826
|
+
if (!userIdentity) {
|
|
5827
|
+
return auth;
|
|
5828
|
+
}
|
|
5829
|
+
return {
|
|
5830
|
+
...auth,
|
|
5831
|
+
userIdentity
|
|
5832
|
+
};
|
|
5833
|
+
}
|
|
5834
|
+
var init_execution_auth = __esm(() => {
|
|
5835
|
+
init_jwt();
|
|
5836
|
+
init_auth_context();
|
|
5837
|
+
});
|
|
5762
5838
|
|
|
5763
5839
|
// ../core/dist/auth/auth-resolver.js
|
|
5764
5840
|
function isLikelyJwt(token) {
|
|
@@ -5809,10 +5885,10 @@ class DefaultAuthResolver {
|
|
|
5809
5885
|
const token = request.token;
|
|
5810
5886
|
const tenantId = request.tenantId ?? this.config.tenantId;
|
|
5811
5887
|
if (!token && hint === "auto") {
|
|
5812
|
-
return {
|
|
5888
|
+
return { authContext: anonymousAuthContext() };
|
|
5813
5889
|
}
|
|
5814
5890
|
if (hint === "None") {
|
|
5815
|
-
return {
|
|
5891
|
+
return { authContext: anonymousAuthContext() };
|
|
5816
5892
|
}
|
|
5817
5893
|
if (hint === "Admin") {
|
|
5818
5894
|
return this.resolveAdmin(token, request.impersonating, tenantId);
|
|
@@ -5835,7 +5911,7 @@ class DefaultAuthResolver {
|
|
|
5835
5911
|
if (token) {
|
|
5836
5912
|
return this.resolveUser(token, tenantId);
|
|
5837
5913
|
}
|
|
5838
|
-
return {
|
|
5914
|
+
return { authContext: anonymousAuthContext() };
|
|
5839
5915
|
}
|
|
5840
5916
|
isInsecureAdminFallbackEnabled() {
|
|
5841
5917
|
if (this.config.allowInsecure) {
|
|
@@ -5855,13 +5931,13 @@ class DefaultAuthResolver {
|
|
|
5855
5931
|
return scoped;
|
|
5856
5932
|
}
|
|
5857
5933
|
this.assertAdminToken(token);
|
|
5858
|
-
const
|
|
5934
|
+
const authContext = adminAuthContext({
|
|
5859
5935
|
token,
|
|
5860
5936
|
tenantId,
|
|
5861
5937
|
impersonating,
|
|
5862
5938
|
label: "admin"
|
|
5863
5939
|
});
|
|
5864
|
-
return {
|
|
5940
|
+
return { authContext, userIdentity: impersonating };
|
|
5865
5941
|
}
|
|
5866
5942
|
async resolveSystem(token, impersonating, tenantId) {
|
|
5867
5943
|
const scoped = await this.tryResolveScopedManagementJwt(token, "System", tenantId, impersonating);
|
|
@@ -5869,16 +5945,16 @@ class DefaultAuthResolver {
|
|
|
5869
5945
|
return scoped;
|
|
5870
5946
|
}
|
|
5871
5947
|
this.assertSystemToken(token);
|
|
5872
|
-
const
|
|
5948
|
+
const authContext = systemAuthContext({
|
|
5873
5949
|
token,
|
|
5874
5950
|
tenantId,
|
|
5875
5951
|
label: "system"
|
|
5876
5952
|
});
|
|
5877
|
-
return {
|
|
5953
|
+
return { authContext, userIdentity: impersonating };
|
|
5878
5954
|
}
|
|
5879
5955
|
async resolveUser(token, tenantId) {
|
|
5880
5956
|
if (!token) {
|
|
5881
|
-
return {
|
|
5957
|
+
return { authContext: anonymousAuthContext() };
|
|
5882
5958
|
}
|
|
5883
5959
|
const providers = this.config.jwtProviders;
|
|
5884
5960
|
if (providers && providers.length > 0) {
|
|
@@ -5886,8 +5962,8 @@ class DefaultAuthResolver {
|
|
|
5886
5962
|
for (const providerConfig of providers) {
|
|
5887
5963
|
try {
|
|
5888
5964
|
const identity2 = await verifyJwtAndGetIdentity(token, providerConfig);
|
|
5889
|
-
const
|
|
5890
|
-
return {
|
|
5965
|
+
const authContext2 = userAuthContext(identity2, token, tenantId);
|
|
5966
|
+
return { authContext: authContext2, userIdentity: identity2 };
|
|
5891
5967
|
} catch (error) {
|
|
5892
5968
|
errors2.push(error instanceof Error ? error : new Error(String(error)));
|
|
5893
5969
|
}
|
|
@@ -5895,8 +5971,8 @@ class DefaultAuthResolver {
|
|
|
5895
5971
|
if (this.config.jwtConfig) {
|
|
5896
5972
|
try {
|
|
5897
5973
|
const identity2 = await verifyJwtAndGetIdentity(token, this.config.jwtConfig);
|
|
5898
|
-
const
|
|
5899
|
-
return {
|
|
5974
|
+
const authContext2 = userAuthContext(identity2, token, tenantId);
|
|
5975
|
+
return { authContext: authContext2, userIdentity: identity2 };
|
|
5900
5976
|
} catch (error) {
|
|
5901
5977
|
errors2.push(error instanceof Error ? error : new Error(String(error)));
|
|
5902
5978
|
}
|
|
@@ -5905,8 +5981,8 @@ class DefaultAuthResolver {
|
|
|
5905
5981
|
throw new JWTValidationError("INVALID_TOKEN", `JWT verification failed for all providers: ${messages}`);
|
|
5906
5982
|
}
|
|
5907
5983
|
const identity = await verifyJwtAndGetIdentity(token, this.config.jwtConfig);
|
|
5908
|
-
const
|
|
5909
|
-
return {
|
|
5984
|
+
const authContext = userAuthContext(identity, token, tenantId);
|
|
5985
|
+
return { authContext, userIdentity: identity };
|
|
5910
5986
|
}
|
|
5911
5987
|
isAdminToken(token) {
|
|
5912
5988
|
return !!this.config.adminAuth?.token && token === this.config.adminAuth.token;
|
|
@@ -6017,24 +6093,24 @@ class DefaultAuthResolver {
|
|
|
6017
6093
|
}
|
|
6018
6094
|
}
|
|
6019
6095
|
const label = readStringClaim(claims, cfg.labelClaim ?? "email") ?? readStringClaim(claims, "sub") ?? undefined;
|
|
6020
|
-
const
|
|
6096
|
+
const authContextTenantId = tokenTenantId ?? tenantId;
|
|
6021
6097
|
if (expectedType === "Admin") {
|
|
6022
|
-
const
|
|
6098
|
+
const authContext2 = adminAuthContext({
|
|
6023
6099
|
token,
|
|
6024
|
-
tenantId:
|
|
6100
|
+
tenantId: authContextTenantId,
|
|
6025
6101
|
scopes: effectiveScopes,
|
|
6026
6102
|
impersonating,
|
|
6027
6103
|
label
|
|
6028
6104
|
});
|
|
6029
|
-
return {
|
|
6105
|
+
return { authContext: authContext2, userIdentity: impersonating };
|
|
6030
6106
|
}
|
|
6031
|
-
const
|
|
6107
|
+
const authContext = systemAuthContext({
|
|
6032
6108
|
token,
|
|
6033
|
-
tenantId:
|
|
6109
|
+
tenantId: authContextTenantId,
|
|
6034
6110
|
scopes: effectiveScopes,
|
|
6035
6111
|
label
|
|
6036
6112
|
});
|
|
6037
|
-
return {
|
|
6113
|
+
return { authContext, userIdentity: impersonating };
|
|
6038
6114
|
}
|
|
6039
6115
|
}
|
|
6040
6116
|
|
|
@@ -6186,44 +6262,44 @@ var init_auth_resolver = __esm(() => {
|
|
|
6186
6262
|
|
|
6187
6263
|
// ../core/dist/auth/authorization-policy.js
|
|
6188
6264
|
class DefaultAuthorizationPolicy {
|
|
6189
|
-
authorize(
|
|
6265
|
+
authorize(authContext, action) {
|
|
6190
6266
|
switch (action.kind) {
|
|
6191
6267
|
case "call_function":
|
|
6192
|
-
return this.authorizeCallFunction(
|
|
6268
|
+
return this.authorizeCallFunction(authContext, action);
|
|
6193
6269
|
case "call_system_function":
|
|
6194
|
-
return this.authorizeSystemFunction(
|
|
6270
|
+
return this.authorizeSystemFunction(authContext, action);
|
|
6195
6271
|
case "access_component":
|
|
6196
|
-
return this.authorizeComponentAccess(
|
|
6272
|
+
return this.authorizeComponentAccess(authContext, action);
|
|
6197
6273
|
case "management_operation":
|
|
6198
|
-
return this.authorizeManagementOp(
|
|
6274
|
+
return this.authorizeManagementOp(authContext, action);
|
|
6199
6275
|
case "custom":
|
|
6200
6276
|
return deny(`Custom action '${action.name}' not handled by default policy`);
|
|
6201
6277
|
}
|
|
6202
6278
|
}
|
|
6203
|
-
authorizeCallFunction(
|
|
6204
|
-
if (action.isInternal && !canCallInternal(
|
|
6279
|
+
authorizeCallFunction(authContext, action) {
|
|
6280
|
+
if (action.isInternal && !canCallInternal(authContext)) {
|
|
6205
6281
|
return deny("Internal functions require admin, system, or service authentication", "FORBIDDEN_INTERNAL");
|
|
6206
6282
|
}
|
|
6207
|
-
if (action.componentPath && !canAccessComponents(
|
|
6283
|
+
if (action.componentPath && !canAccessComponents(authContext)) {
|
|
6208
6284
|
return deny("Component-scoped function calls require admin or system authentication", "FORBIDDEN_COMPONENT");
|
|
6209
6285
|
}
|
|
6210
6286
|
return ALLOWED;
|
|
6211
6287
|
}
|
|
6212
|
-
authorizeSystemFunction(
|
|
6213
|
-
if (!canCallInternal(
|
|
6288
|
+
authorizeSystemFunction(authContext, action) {
|
|
6289
|
+
if (!canCallInternal(authContext)) {
|
|
6214
6290
|
return deny(`System function '${action.functionName}' requires admin, system, or service authentication`, "FORBIDDEN_SYSTEM");
|
|
6215
6291
|
}
|
|
6216
6292
|
return ALLOWED;
|
|
6217
6293
|
}
|
|
6218
|
-
authorizeComponentAccess(
|
|
6219
|
-
if (!canAccessComponents(
|
|
6294
|
+
authorizeComponentAccess(authContext, _action) {
|
|
6295
|
+
if (!canAccessComponents(authContext)) {
|
|
6220
6296
|
return deny("Component access requires admin or system authentication", "FORBIDDEN_COMPONENT");
|
|
6221
6297
|
}
|
|
6222
6298
|
return ALLOWED;
|
|
6223
6299
|
}
|
|
6224
|
-
authorizeManagementOp(
|
|
6225
|
-
if (!hasCapability(
|
|
6226
|
-
return deny(`
|
|
6300
|
+
authorizeManagementOp(authContext, action) {
|
|
6301
|
+
if (!hasCapability(authContext, action.capability)) {
|
|
6302
|
+
return deny(`ResolvedAuthContext lacks required capability '${action.capability}'` + (action.resource ? ` for resource '${action.resource}'` : ""), "FORBIDDEN_CAPABILITY");
|
|
6227
6303
|
}
|
|
6228
6304
|
return ALLOWED;
|
|
6229
6305
|
}
|
|
@@ -6231,8 +6307,8 @@ class DefaultAuthorizationPolicy {
|
|
|
6231
6307
|
function deny(reason, code2) {
|
|
6232
6308
|
return { allowed: false, reason, code: code2 };
|
|
6233
6309
|
}
|
|
6234
|
-
function requireAuthorization(
|
|
6235
|
-
const decision = policy.authorize(
|
|
6310
|
+
function requireAuthorization(authContext, action, policy = defaultAuthorizationPolicy) {
|
|
6311
|
+
const decision = policy.authorize(authContext, action);
|
|
6236
6312
|
if (!decision.allowed) {
|
|
6237
6313
|
const err = new Error(decision.reason);
|
|
6238
6314
|
err.code = decision.code ?? "FORBIDDEN";
|
|
@@ -6255,6 +6331,7 @@ var init_auth_config_service = __esm(() => {
|
|
|
6255
6331
|
var init_auth = __esm(() => {
|
|
6256
6332
|
init_jwt();
|
|
6257
6333
|
init_auth_context();
|
|
6334
|
+
init_execution_auth();
|
|
6258
6335
|
init_auth_resolver();
|
|
6259
6336
|
init_authorization_policy();
|
|
6260
6337
|
init_auth_config_service();
|
|
@@ -6353,6 +6430,7 @@ function createTableRegistrySnapshot(tables, partial) {
|
|
|
6353
6430
|
fullName: table.fullName,
|
|
6354
6431
|
isSystem: table.isSystem,
|
|
6355
6432
|
visibility: table.visibility,
|
|
6433
|
+
state: table.state,
|
|
6356
6434
|
createdAt: table.createdAt
|
|
6357
6435
|
})).sort((a, b) => a.tableNumber - b.tableNumber);
|
|
6358
6436
|
const updatedAt = partial?.updatedAt ?? Date.now();
|
|
@@ -6969,11 +7047,11 @@ var init_system_tables = __esm(() => {
|
|
|
6969
7047
|
|
|
6970
7048
|
// ../core/dist/system/internal.js
|
|
6971
7049
|
function requireSystemCapability(capability) {
|
|
6972
|
-
const
|
|
6973
|
-
if (!
|
|
7050
|
+
const authContext = getResolvedAuthContext();
|
|
7051
|
+
if (!authContext) {
|
|
6974
7052
|
throw new Error("System functions require authentication context");
|
|
6975
7053
|
}
|
|
6976
|
-
requireAuthorization(
|
|
7054
|
+
requireAuthorization(authContext, { kind: "management_operation", capability });
|
|
6977
7055
|
}
|
|
6978
7056
|
function createSystemFunctions(deps) {
|
|
6979
7057
|
const { query, mutation } = deps;
|
|
@@ -8327,8 +8405,8 @@ Path: ${formatPath(path)}
|
|
|
8327
8405
|
Value: ${formatValue(value)}
|
|
8328
8406
|
Validator: v.id("${validator2.tableName}")`);
|
|
8329
8407
|
}
|
|
8330
|
-
const
|
|
8331
|
-
if (!
|
|
8408
|
+
const tableName = tableNameFromConvexId(value, options);
|
|
8409
|
+
if (!tableName || !isMatchingValidatorTable(tableName, validator2.tableName, options.componentPath)) {
|
|
8332
8410
|
throw new Error(`Value does not match validator.
|
|
8333
8411
|
Path: ${formatPath(path)}
|
|
8334
8412
|
Value: ${formatValue(value)}
|
|
@@ -8336,14 +8414,10 @@ Validator: v.id("${validator2.tableName}")`);
|
|
|
8336
8414
|
}
|
|
8337
8415
|
return;
|
|
8338
8416
|
}
|
|
8339
|
-
|
|
8340
|
-
if (!tableName || !isMatchingValidatorTable(tableName, validator2.tableName, options.componentPath)) {
|
|
8341
|
-
throw new Error(`Value does not match validator.
|
|
8417
|
+
throw new Error(`Value does not match validator.
|
|
8342
8418
|
Path: ${formatPath(path)}
|
|
8343
8419
|
Value: ${formatValue(value)}
|
|
8344
8420
|
Validator: v.id("${validator2.tableName}")`);
|
|
8345
|
-
}
|
|
8346
|
-
return;
|
|
8347
8421
|
}
|
|
8348
8422
|
case "array": {
|
|
8349
8423
|
if (!Array.isArray(value)) {
|
|
@@ -8412,13 +8486,6 @@ Validator: v.object({...})`);
|
|
|
8412
8486
|
}
|
|
8413
8487
|
}
|
|
8414
8488
|
}
|
|
8415
|
-
function tableNameFromId(id) {
|
|
8416
|
-
const parts = deserializeDeveloperId(id);
|
|
8417
|
-
if (!parts) {
|
|
8418
|
-
return null;
|
|
8419
|
-
}
|
|
8420
|
-
return hexToString(parts.table);
|
|
8421
|
-
}
|
|
8422
8489
|
function tableNameFromConvexId(id, options) {
|
|
8423
8490
|
try {
|
|
8424
8491
|
const decoded = decodeDocumentId(id);
|
|
@@ -8534,7 +8601,6 @@ function isSimpleObject2(value) {
|
|
|
8534
8601
|
}
|
|
8535
8602
|
var ValidatorError, referencedTableNamesCache;
|
|
8536
8603
|
var init_validator2 = __esm(() => {
|
|
8537
|
-
init_utils();
|
|
8538
8604
|
init_interface2();
|
|
8539
8605
|
init_module_loader();
|
|
8540
8606
|
init_id_codec();
|
|
@@ -8631,60 +8697,7 @@ var GLOBALS_TABLE_SCHEMA = `
|
|
|
8631
8697
|
`;
|
|
8632
8698
|
// ../core/dist/abstractions/runtime-services.js
|
|
8633
8699
|
function resolveRuntimeServices(services) {
|
|
8634
|
-
|
|
8635
|
-
return services;
|
|
8636
|
-
}
|
|
8637
|
-
const storageCapabilities = resolveStorageCapabilities(services);
|
|
8638
|
-
return {
|
|
8639
|
-
...services,
|
|
8640
|
-
blobstore: storageCapabilities.blobs?.store,
|
|
8641
|
-
searchstore: storageCapabilities.search,
|
|
8642
|
-
vecstore: storageCapabilities.vector,
|
|
8643
|
-
storageCapabilities
|
|
8644
|
-
};
|
|
8645
|
-
}
|
|
8646
|
-
function isResolvedRuntimeServices(services) {
|
|
8647
|
-
return "storageCapabilities" in services;
|
|
8648
|
-
}
|
|
8649
|
-
function resolveStorageCapabilities(services) {
|
|
8650
|
-
const blobCapability = resolveBlobCapability(services.capabilities?.blobs);
|
|
8651
|
-
const searchCapability = resolveSearchCapability(services.capabilities?.search, services.docstore);
|
|
8652
|
-
const vectorCapability = resolveVectorCapability(services.capabilities?.vector, services.docstore);
|
|
8653
|
-
return {
|
|
8654
|
-
...blobCapability ? { blobs: blobCapability } : {},
|
|
8655
|
-
...searchCapability ? { search: searchCapability } : {},
|
|
8656
|
-
...vectorCapability ? { vector: vectorCapability } : {}
|
|
8657
|
-
};
|
|
8658
|
-
}
|
|
8659
|
-
function resolveBlobCapability(capability) {
|
|
8660
|
-
if (!capability) {
|
|
8661
|
-
return;
|
|
8662
|
-
}
|
|
8663
|
-
if (!isBlobCapabilityObject(capability)) {
|
|
8664
|
-
throw new Error("storage.blobstore must be false or an object with a BlobStore in storage.blobstore.store");
|
|
8665
|
-
}
|
|
8666
|
-
if (capability.consistency !== "atomic" && capability.consistency !== "eventual") {
|
|
8667
|
-
throw new Error('storage.blobstore.consistency must be "atomic" or "eventual"');
|
|
8668
|
-
}
|
|
8669
|
-
return {
|
|
8670
|
-
store: capability.store,
|
|
8671
|
-
consistency: capability.consistency
|
|
8672
|
-
};
|
|
8673
|
-
}
|
|
8674
|
-
function isBlobCapabilityObject(capability) {
|
|
8675
|
-
return typeof capability === "object" && capability !== null && typeof capability.store?.store === "function" && typeof capability.store?.get === "function" && typeof capability.store?.delete === "function" && typeof capability.store?.getUrl === "function";
|
|
8676
|
-
}
|
|
8677
|
-
function resolveSearchCapability(capability, _docstore) {
|
|
8678
|
-
if (capability === false) {
|
|
8679
|
-
return;
|
|
8680
|
-
}
|
|
8681
|
-
return capability;
|
|
8682
|
-
}
|
|
8683
|
-
function resolveVectorCapability(capability, _docstore) {
|
|
8684
|
-
if (capability === false) {
|
|
8685
|
-
return;
|
|
8686
|
-
}
|
|
8687
|
-
return capability;
|
|
8700
|
+
return services;
|
|
8688
8701
|
}
|
|
8689
8702
|
// ../core/dist/abstractions/storage-spec.js
|
|
8690
8703
|
var CAPABILITY_MAP_KEYS = new Set([
|
|
@@ -8693,10 +8706,7 @@ var CAPABILITY_MAP_KEYS = new Set([
|
|
|
8693
8706
|
"search",
|
|
8694
8707
|
"vecstore",
|
|
8695
8708
|
"transaction",
|
|
8696
|
-
"close"
|
|
8697
|
-
"documents",
|
|
8698
|
-
"blobs",
|
|
8699
|
-
"vector"
|
|
8709
|
+
"close"
|
|
8700
8710
|
]);
|
|
8701
8711
|
|
|
8702
8712
|
// ../core/dist/index.js
|
|
@@ -8847,6 +8857,7 @@ init_interface();
|
|
|
8847
8857
|
// ../core/dist/queryengine/developer-id.js
|
|
8848
8858
|
init_utils();
|
|
8849
8859
|
init_id_codec();
|
|
8860
|
+
var LEGACY_INTERNAL_DOCUMENT_ID_RE = /^([0-9a-fA-F]+):([0-9a-fA-F]{32})$/;
|
|
8850
8861
|
function parseDeveloperId(developerId) {
|
|
8851
8862
|
if (isValidDocumentId(developerId)) {
|
|
8852
8863
|
try {
|
|
@@ -8856,13 +8867,11 @@ function parseDeveloperId(developerId) {
|
|
|
8856
8867
|
internalId: internalIdToHex(decoded.internalId),
|
|
8857
8868
|
tableNumber: decoded.tableNumber
|
|
8858
8869
|
};
|
|
8859
|
-
} catch {
|
|
8860
|
-
|
|
8861
|
-
|
|
8862
|
-
if (!parts) {
|
|
8863
|
-
return null;
|
|
8870
|
+
} catch {
|
|
8871
|
+
return null;
|
|
8872
|
+
}
|
|
8864
8873
|
}
|
|
8865
|
-
return
|
|
8874
|
+
return parseLegacyInternalDocumentId(developerId);
|
|
8866
8875
|
}
|
|
8867
8876
|
async function parseDeveloperIdWithTableRegistry(developerId, tableRegistry) {
|
|
8868
8877
|
if (isValidDocumentId(developerId)) {
|
|
@@ -8896,6 +8905,20 @@ function parseStorageId(storageId) {
|
|
|
8896
8905
|
}
|
|
8897
8906
|
return null;
|
|
8898
8907
|
}
|
|
8908
|
+
function parseLegacyInternalDocumentId(developerId) {
|
|
8909
|
+
const match = LEGACY_INTERNAL_DOCUMENT_ID_RE.exec(developerId);
|
|
8910
|
+
if (!match) {
|
|
8911
|
+
return null;
|
|
8912
|
+
}
|
|
8913
|
+
const table = match[1].toLowerCase();
|
|
8914
|
+
if (table.length === 0 || table.length % 2 !== 0) {
|
|
8915
|
+
return null;
|
|
8916
|
+
}
|
|
8917
|
+
return {
|
|
8918
|
+
table,
|
|
8919
|
+
internalId: match[2].toLowerCase()
|
|
8920
|
+
};
|
|
8921
|
+
}
|
|
8899
8922
|
function isTablePlaceholder(table) {
|
|
8900
8923
|
return table.startsWith("#");
|
|
8901
8924
|
}
|
|
@@ -9026,6 +9049,123 @@ class UncommittedWrites {
|
|
|
9026
9049
|
}
|
|
9027
9050
|
}
|
|
9028
9051
|
|
|
9052
|
+
// ../core/dist/transactor/occ-transaction.js
|
|
9053
|
+
init_udf_trace();
|
|
9054
|
+
|
|
9055
|
+
// ../core/dist/limits/transaction-headroom.js
|
|
9056
|
+
init_values();
|
|
9057
|
+
var MEBIBYTE = 1024 * 1024;
|
|
9058
|
+
var TRANSACTION_HEADROOM_LIMITS = {
|
|
9059
|
+
bytesRead: 16 * MEBIBYTE,
|
|
9060
|
+
bytesWritten: 16 * MEBIBYTE,
|
|
9061
|
+
databaseQueries: 4096,
|
|
9062
|
+
documentsRead: 32000,
|
|
9063
|
+
documentsWritten: 16000,
|
|
9064
|
+
functionsScheduled: 1000,
|
|
9065
|
+
scheduledFunctionArgsBytes: 16 * MEBIBYTE
|
|
9066
|
+
};
|
|
9067
|
+
var encoder = new TextEncoder;
|
|
9068
|
+
function remaining(limit, used) {
|
|
9069
|
+
return Math.max(0, limit - used);
|
|
9070
|
+
}
|
|
9071
|
+
function estimateConvexValueBytes(value) {
|
|
9072
|
+
const json = JSON.stringify(convexToJson(value));
|
|
9073
|
+
return encoder.encode(json).byteLength;
|
|
9074
|
+
}
|
|
9075
|
+
|
|
9076
|
+
class TransactionHeadroomTracker {
|
|
9077
|
+
bytesRead = 0;
|
|
9078
|
+
documentsRead = 0;
|
|
9079
|
+
databaseQueries = 0;
|
|
9080
|
+
functionsScheduled = 0;
|
|
9081
|
+
scheduledFunctionArgsBytes = 0;
|
|
9082
|
+
bytesWritten = 0;
|
|
9083
|
+
writtenDocuments = new Map;
|
|
9084
|
+
recordDatabaseQuery(count = 1) {
|
|
9085
|
+
this.databaseQueries += count;
|
|
9086
|
+
}
|
|
9087
|
+
recordRead(value) {
|
|
9088
|
+
this.documentsRead += 1;
|
|
9089
|
+
this.bytesRead += estimateConvexValueBytes(value);
|
|
9090
|
+
}
|
|
9091
|
+
recordReads(values) {
|
|
9092
|
+
for (const value of values) {
|
|
9093
|
+
this.recordRead(value);
|
|
9094
|
+
}
|
|
9095
|
+
}
|
|
9096
|
+
recordScheduledFunction(args) {
|
|
9097
|
+
this.functionsScheduled += 1;
|
|
9098
|
+
this.scheduledFunctionArgsBytes += estimateConvexValueBytes(args);
|
|
9099
|
+
}
|
|
9100
|
+
trackWrittenDocument(documentKey, value) {
|
|
9101
|
+
const nextBytes = estimateConvexValueBytes(value);
|
|
9102
|
+
const previousBytes = this.writtenDocuments.get(documentKey);
|
|
9103
|
+
if (previousBytes !== undefined) {
|
|
9104
|
+
this.bytesWritten -= previousBytes;
|
|
9105
|
+
}
|
|
9106
|
+
this.writtenDocuments.set(documentKey, nextBytes);
|
|
9107
|
+
this.bytesWritten += nextBytes;
|
|
9108
|
+
}
|
|
9109
|
+
snapshot() {
|
|
9110
|
+
return {
|
|
9111
|
+
bytesRead: this.bytesRead,
|
|
9112
|
+
documentsRead: this.documentsRead,
|
|
9113
|
+
databaseQueries: this.databaseQueries,
|
|
9114
|
+
functionsScheduled: this.functionsScheduled,
|
|
9115
|
+
scheduledFunctionArgsBytes: this.scheduledFunctionArgsBytes,
|
|
9116
|
+
bytesWritten: this.bytesWritten,
|
|
9117
|
+
writtenDocuments: new Map(this.writtenDocuments)
|
|
9118
|
+
};
|
|
9119
|
+
}
|
|
9120
|
+
restore(snapshot) {
|
|
9121
|
+
this.bytesRead = snapshot.bytesRead;
|
|
9122
|
+
this.documentsRead = snapshot.documentsRead;
|
|
9123
|
+
this.databaseQueries = snapshot.databaseQueries;
|
|
9124
|
+
this.functionsScheduled = snapshot.functionsScheduled;
|
|
9125
|
+
this.scheduledFunctionArgsBytes = snapshot.scheduledFunctionArgsBytes;
|
|
9126
|
+
this.bytesWritten = snapshot.bytesWritten;
|
|
9127
|
+
this.writtenDocuments.clear();
|
|
9128
|
+
for (const [documentKey, bytes] of snapshot.writtenDocuments) {
|
|
9129
|
+
this.writtenDocuments.set(documentKey, bytes);
|
|
9130
|
+
}
|
|
9131
|
+
}
|
|
9132
|
+
getHeadroom() {
|
|
9133
|
+
return {
|
|
9134
|
+
bytesRead: {
|
|
9135
|
+
used: this.bytesRead,
|
|
9136
|
+
remaining: remaining(TRANSACTION_HEADROOM_LIMITS.bytesRead, this.bytesRead)
|
|
9137
|
+
},
|
|
9138
|
+
bytesWritten: {
|
|
9139
|
+
used: this.bytesWritten,
|
|
9140
|
+
remaining: remaining(TRANSACTION_HEADROOM_LIMITS.bytesWritten, this.bytesWritten)
|
|
9141
|
+
},
|
|
9142
|
+
databaseQueries: {
|
|
9143
|
+
used: this.databaseQueries,
|
|
9144
|
+
remaining: remaining(TRANSACTION_HEADROOM_LIMITS.databaseQueries, this.databaseQueries)
|
|
9145
|
+
},
|
|
9146
|
+
documentsRead: {
|
|
9147
|
+
used: this.documentsRead,
|
|
9148
|
+
remaining: remaining(TRANSACTION_HEADROOM_LIMITS.documentsRead, this.documentsRead)
|
|
9149
|
+
},
|
|
9150
|
+
documentsWritten: {
|
|
9151
|
+
used: this.writtenDocuments.size,
|
|
9152
|
+
remaining: remaining(TRANSACTION_HEADROOM_LIMITS.documentsWritten, this.writtenDocuments.size)
|
|
9153
|
+
},
|
|
9154
|
+
functionsScheduled: {
|
|
9155
|
+
used: this.functionsScheduled,
|
|
9156
|
+
remaining: remaining(TRANSACTION_HEADROOM_LIMITS.functionsScheduled, this.functionsScheduled)
|
|
9157
|
+
},
|
|
9158
|
+
scheduledFunctionArgsBytes: {
|
|
9159
|
+
used: this.scheduledFunctionArgsBytes,
|
|
9160
|
+
remaining: remaining(TRANSACTION_HEADROOM_LIMITS.scheduledFunctionArgsBytes, this.scheduledFunctionArgsBytes)
|
|
9161
|
+
}
|
|
9162
|
+
};
|
|
9163
|
+
}
|
|
9164
|
+
}
|
|
9165
|
+
|
|
9166
|
+
// ../core/dist/transactor/occ-commit.js
|
|
9167
|
+
init_udf_trace();
|
|
9168
|
+
|
|
9029
9169
|
// ../core/dist/transactor/occ-validation.js
|
|
9030
9170
|
init_interface();
|
|
9031
9171
|
init_interface();
|
|
@@ -9063,7 +9203,7 @@ function createDocumentReadValidationMap(docstore, documentReads) {
|
|
|
9063
9203
|
if (pendingIds.length === 0) {
|
|
9064
9204
|
return;
|
|
9065
9205
|
}
|
|
9066
|
-
return docstore.
|
|
9206
|
+
return docstore.getMany(pendingIds);
|
|
9067
9207
|
}
|
|
9068
9208
|
async function validateDocumentRead(docstore, key, readVersion, currentDocsPromise) {
|
|
9069
9209
|
const parsedId = parseDocumentIdKey(key);
|
|
@@ -9120,7 +9260,7 @@ async function validateIndexRangeRead(docstore, indexId, startKey, endKey, readT
|
|
|
9120
9260
|
const interval = { start: startKey, end: endKey };
|
|
9121
9261
|
const validationReadTimestamp = resolveValidationReadTimestamp(docstore, readTimestamp);
|
|
9122
9262
|
const currentDocIds = new Set;
|
|
9123
|
-
for await (const [, doc] of docstore.
|
|
9263
|
+
for await (const [, doc] of docstore.indexScan(encodedIndexId, encodedTableId, validationReadTimestamp, interval, Order.Asc)) {
|
|
9124
9264
|
currentDocIds.add(documentIdKey(doc.value.id));
|
|
9125
9265
|
}
|
|
9126
9266
|
for (const docId of currentDocIds) {
|
|
@@ -9159,119 +9299,47 @@ function resolveValidationReadTimestamp(docstore, minimumTimestamp) {
|
|
|
9159
9299
|
return latestKnownTimestamp > minimumTimestamp ? latestKnownTimestamp : minimumTimestamp;
|
|
9160
9300
|
}
|
|
9161
9301
|
|
|
9162
|
-
// ../core/dist/transactor/occ-
|
|
9302
|
+
// ../core/dist/transactor/occ-commit.js
|
|
9163
9303
|
init_commit_lock();
|
|
9164
|
-
|
|
9165
|
-
|
|
9166
|
-
|
|
9167
|
-
|
|
9168
|
-
|
|
9169
|
-
|
|
9170
|
-
|
|
9171
|
-
|
|
9172
|
-
|
|
9173
|
-
|
|
9174
|
-
|
|
9175
|
-
|
|
9176
|
-
|
|
9177
|
-
|
|
9178
|
-
var encoder = new TextEncoder;
|
|
9179
|
-
function remaining(limit, used) {
|
|
9180
|
-
return Math.max(0, limit - used);
|
|
9181
|
-
}
|
|
9182
|
-
function estimateConvexValueBytes(value) {
|
|
9183
|
-
const json = JSON.stringify(convexToJson(value));
|
|
9184
|
-
return encoder.encode(json).byteLength;
|
|
9185
|
-
}
|
|
9186
|
-
|
|
9187
|
-
class TransactionHeadroomTracker {
|
|
9188
|
-
bytesRead = 0;
|
|
9189
|
-
documentsRead = 0;
|
|
9190
|
-
databaseQueries = 0;
|
|
9191
|
-
functionsScheduled = 0;
|
|
9192
|
-
scheduledFunctionArgsBytes = 0;
|
|
9193
|
-
bytesWritten = 0;
|
|
9194
|
-
writtenDocuments = new Map;
|
|
9195
|
-
recordDatabaseQuery(count = 1) {
|
|
9196
|
-
this.databaseQueries += count;
|
|
9197
|
-
}
|
|
9198
|
-
recordRead(value) {
|
|
9199
|
-
this.documentsRead += 1;
|
|
9200
|
-
this.bytesRead += estimateConvexValueBytes(value);
|
|
9201
|
-
}
|
|
9202
|
-
recordReads(values) {
|
|
9203
|
-
for (const value of values) {
|
|
9204
|
-
this.recordRead(value);
|
|
9304
|
+
async function commitOccWrites(request) {
|
|
9305
|
+
let committedTimestamp = 0n;
|
|
9306
|
+
const runCommit = async () => {
|
|
9307
|
+
await withTraceSpan("occ.validate_read_set", "transaction", async () => {
|
|
9308
|
+
await validateReadSetForCommit(request.docstore, request.readChecks, request.writtenDocKeys);
|
|
9309
|
+
}, {
|
|
9310
|
+
readCheckCount: request.readChecks.length
|
|
9311
|
+
});
|
|
9312
|
+
committedTimestamp = await request.allocateCommitTimestamp();
|
|
9313
|
+
addTraceEvent("occ.commit_timestamp_allocated", {
|
|
9314
|
+
commitTimestamp: committedTimestamp.toString()
|
|
9315
|
+
});
|
|
9316
|
+
for (const entry of request.writeEntries) {
|
|
9317
|
+
entry.ts = committedTimestamp;
|
|
9205
9318
|
}
|
|
9206
|
-
|
|
9207
|
-
|
|
9208
|
-
this.functionsScheduled += 1;
|
|
9209
|
-
this.scheduledFunctionArgsBytes += estimateConvexValueBytes(args);
|
|
9210
|
-
}
|
|
9211
|
-
trackWrittenDocument(documentKey, value) {
|
|
9212
|
-
const nextBytes = estimateConvexValueBytes(value);
|
|
9213
|
-
const previousBytes = this.writtenDocuments.get(documentKey);
|
|
9214
|
-
if (previousBytes !== undefined) {
|
|
9215
|
-
this.bytesWritten -= previousBytes;
|
|
9319
|
+
for (const indexEntry of request.indexEntries) {
|
|
9320
|
+
indexEntry.ts = committedTimestamp;
|
|
9216
9321
|
}
|
|
9217
|
-
|
|
9218
|
-
|
|
9219
|
-
|
|
9220
|
-
|
|
9221
|
-
|
|
9222
|
-
|
|
9223
|
-
|
|
9224
|
-
databaseQueries: this.databaseQueries,
|
|
9225
|
-
functionsScheduled: this.functionsScheduled,
|
|
9226
|
-
scheduledFunctionArgsBytes: this.scheduledFunctionArgsBytes,
|
|
9227
|
-
bytesWritten: this.bytesWritten,
|
|
9228
|
-
writtenDocuments: new Map(this.writtenDocuments)
|
|
9229
|
-
};
|
|
9230
|
-
}
|
|
9231
|
-
restore(snapshot) {
|
|
9232
|
-
this.bytesRead = snapshot.bytesRead;
|
|
9233
|
-
this.documentsRead = snapshot.documentsRead;
|
|
9234
|
-
this.databaseQueries = snapshot.databaseQueries;
|
|
9235
|
-
this.functionsScheduled = snapshot.functionsScheduled;
|
|
9236
|
-
this.scheduledFunctionArgsBytes = snapshot.scheduledFunctionArgsBytes;
|
|
9237
|
-
this.bytesWritten = snapshot.bytesWritten;
|
|
9238
|
-
this.writtenDocuments.clear();
|
|
9239
|
-
for (const [documentKey, bytes] of snapshot.writtenDocuments) {
|
|
9240
|
-
this.writtenDocuments.set(documentKey, bytes);
|
|
9322
|
+
if (request.writeEntries.length > 0 || request.indexEntries.size > 0) {
|
|
9323
|
+
await withTraceSpan("occ.persist_writes", "storage", async () => {
|
|
9324
|
+
await request.docstore.write(request.writeEntries, request.indexEntries, "Error");
|
|
9325
|
+
}, {
|
|
9326
|
+
documentCount: request.writeEntries.length,
|
|
9327
|
+
indexUpdateCount: request.indexEntries.size
|
|
9328
|
+
});
|
|
9241
9329
|
}
|
|
9330
|
+
};
|
|
9331
|
+
try {
|
|
9332
|
+
await commitWithDerivedSync(request.docstore, { searchstore: request.searchstore, vecstore: request.vecstore }, request.writeEntries, runCommit);
|
|
9333
|
+
} catch (error) {
|
|
9334
|
+
if (error instanceof ConflictError) {
|
|
9335
|
+
addTraceEvent("occ.conflict", {
|
|
9336
|
+
message: error.message
|
|
9337
|
+
});
|
|
9338
|
+
throw error;
|
|
9339
|
+
}
|
|
9340
|
+
throw error;
|
|
9242
9341
|
}
|
|
9243
|
-
|
|
9244
|
-
return {
|
|
9245
|
-
bytesRead: {
|
|
9246
|
-
used: this.bytesRead,
|
|
9247
|
-
remaining: remaining(TRANSACTION_HEADROOM_LIMITS.bytesRead, this.bytesRead)
|
|
9248
|
-
},
|
|
9249
|
-
bytesWritten: {
|
|
9250
|
-
used: this.bytesWritten,
|
|
9251
|
-
remaining: remaining(TRANSACTION_HEADROOM_LIMITS.bytesWritten, this.bytesWritten)
|
|
9252
|
-
},
|
|
9253
|
-
databaseQueries: {
|
|
9254
|
-
used: this.databaseQueries,
|
|
9255
|
-
remaining: remaining(TRANSACTION_HEADROOM_LIMITS.databaseQueries, this.databaseQueries)
|
|
9256
|
-
},
|
|
9257
|
-
documentsRead: {
|
|
9258
|
-
used: this.documentsRead,
|
|
9259
|
-
remaining: remaining(TRANSACTION_HEADROOM_LIMITS.documentsRead, this.documentsRead)
|
|
9260
|
-
},
|
|
9261
|
-
documentsWritten: {
|
|
9262
|
-
used: this.writtenDocuments.size,
|
|
9263
|
-
remaining: remaining(TRANSACTION_HEADROOM_LIMITS.documentsWritten, this.writtenDocuments.size)
|
|
9264
|
-
},
|
|
9265
|
-
functionsScheduled: {
|
|
9266
|
-
used: this.functionsScheduled,
|
|
9267
|
-
remaining: remaining(TRANSACTION_HEADROOM_LIMITS.functionsScheduled, this.functionsScheduled)
|
|
9268
|
-
},
|
|
9269
|
-
scheduledFunctionArgsBytes: {
|
|
9270
|
-
used: this.scheduledFunctionArgsBytes,
|
|
9271
|
-
remaining: remaining(TRANSACTION_HEADROOM_LIMITS.scheduledFunctionArgsBytes, this.scheduledFunctionArgsBytes)
|
|
9272
|
-
}
|
|
9273
|
-
};
|
|
9274
|
-
}
|
|
9342
|
+
return committedTimestamp;
|
|
9275
9343
|
}
|
|
9276
9344
|
|
|
9277
9345
|
// ../core/dist/transactor/occ-transaction.js
|
|
@@ -9426,7 +9494,7 @@ class OccMutationTransaction {
|
|
|
9426
9494
|
const requests = Array.from(this.pendingLatestFetches.values());
|
|
9427
9495
|
this.pendingLatestFetches.clear();
|
|
9428
9496
|
try {
|
|
9429
|
-
const fetched = await withTraceSpan("tx.
|
|
9497
|
+
const fetched = await withTraceSpan("tx.getManyLatest", "storage", () => this.docstore.getMany(requests.map((request) => request.id), this.snapshotTimestamp), { documentCount: requests.length });
|
|
9430
9498
|
for (const request of requests) {
|
|
9431
9499
|
const key = documentIdKey(request.id);
|
|
9432
9500
|
const latest = fetched.get(key) ?? null;
|
|
@@ -9455,7 +9523,7 @@ class OccMutationTransaction {
|
|
|
9455
9523
|
missingIds.push(id);
|
|
9456
9524
|
}
|
|
9457
9525
|
if (missingIds.length > 0) {
|
|
9458
|
-
const fetched = await withTraceSpan("tx.
|
|
9526
|
+
const fetched = await withTraceSpan("tx.getManyLatest", "storage", () => this.docstore.getMany(missingIds, this.snapshotTimestamp), { documentCount: missingIds.length });
|
|
9459
9527
|
for (const id of missingIds) {
|
|
9460
9528
|
const key = documentIdKey(id);
|
|
9461
9529
|
const latest = fetched.get(key) ?? null;
|
|
@@ -9586,43 +9654,16 @@ class OccMutationTransaction {
|
|
|
9586
9654
|
stagedIndexCount: indexEntries.size,
|
|
9587
9655
|
readCheckCount: readChecks.length
|
|
9588
9656
|
});
|
|
9589
|
-
|
|
9590
|
-
|
|
9591
|
-
|
|
9592
|
-
|
|
9593
|
-
|
|
9594
|
-
|
|
9595
|
-
|
|
9596
|
-
|
|
9597
|
-
|
|
9598
|
-
|
|
9599
|
-
});
|
|
9600
|
-
for (const entry of writeEntries) {
|
|
9601
|
-
entry.ts = committedTimestamp;
|
|
9602
|
-
}
|
|
9603
|
-
for (const indexEntry of indexEntries) {
|
|
9604
|
-
indexEntry.ts = committedTimestamp;
|
|
9605
|
-
}
|
|
9606
|
-
if (writeEntries.length > 0 || indexEntries.size > 0) {
|
|
9607
|
-
await withTraceSpan("occ.persist_writes", "storage", async () => {
|
|
9608
|
-
await this.docstore.write(writeEntries, indexEntries, "Error");
|
|
9609
|
-
}, {
|
|
9610
|
-
documentCount: writeEntries.length,
|
|
9611
|
-
indexUpdateCount: indexEntries.size
|
|
9612
|
-
});
|
|
9613
|
-
}
|
|
9614
|
-
};
|
|
9615
|
-
try {
|
|
9616
|
-
await commitWithDerivedSync(this.docstore, { searchstore: this.searchstore, vecstore: this.vecstore }, writeEntries, runCommit);
|
|
9617
|
-
} catch (error) {
|
|
9618
|
-
if (error instanceof ConflictError) {
|
|
9619
|
-
addTraceEvent("occ.conflict", {
|
|
9620
|
-
message: error.message
|
|
9621
|
-
});
|
|
9622
|
-
throw error;
|
|
9623
|
-
}
|
|
9624
|
-
throw error;
|
|
9625
|
-
}
|
|
9657
|
+
const committedTimestamp = await commitOccWrites({
|
|
9658
|
+
docstore: this.docstore,
|
|
9659
|
+
searchstore: this.searchstore,
|
|
9660
|
+
vecstore: this.vecstore,
|
|
9661
|
+
writeEntries,
|
|
9662
|
+
indexEntries,
|
|
9663
|
+
readChecks,
|
|
9664
|
+
writtenDocKeys,
|
|
9665
|
+
allocateCommitTimestamp: () => this.allocateCommitTimestamp()
|
|
9666
|
+
});
|
|
9626
9667
|
setCurrentTraceSpanAttributes({
|
|
9627
9668
|
committedTimestamp: committedTimestamp.toString()
|
|
9628
9669
|
});
|
|
@@ -9650,6 +9691,7 @@ class SchemaService {
|
|
|
9650
9691
|
tableCache = new Map;
|
|
9651
9692
|
schemaValidator;
|
|
9652
9693
|
componentPath;
|
|
9694
|
+
tableRegistry;
|
|
9653
9695
|
runtimeMetadataSnapshot;
|
|
9654
9696
|
constructor(componentPath, tableRegistry, runtimeMetadataSnapshot) {
|
|
9655
9697
|
this.componentPath = componentPath;
|
|
@@ -9860,7 +9902,7 @@ class SnapshotDocAccess {
|
|
|
9860
9902
|
missingIds.push(id);
|
|
9861
9903
|
}
|
|
9862
9904
|
if (missingIds.length > 0) {
|
|
9863
|
-
const fetched = await withTraceSpan("doc_access.
|
|
9905
|
+
const fetched = await withTraceSpan("doc_access.getMany", "storage", () => this.docstore.getMany(missingIds, snapshotTimestamp), { documentCount: missingIds.length });
|
|
9864
9906
|
for (const id of missingIds) {
|
|
9865
9907
|
const docKey = documentIdKey(id);
|
|
9866
9908
|
const cacheKey = `${snapshotTimestamp}:${documentIdKey(id)}`;
|
|
@@ -9906,7 +9948,7 @@ class SnapshotDocAccess {
|
|
|
9906
9948
|
this.pendingLatestBatches.delete(snapshotTimestamp);
|
|
9907
9949
|
const requests = Array.from(batch.values());
|
|
9908
9950
|
try {
|
|
9909
|
-
const results = await withTraceSpan("doc_access.
|
|
9951
|
+
const results = await withTraceSpan("doc_access.getMany", "storage", () => this.docstore.getMany(requests.map((request) => request.id), snapshotTimestamp), { documentCount: requests.length });
|
|
9910
9952
|
for (const request of requests) {
|
|
9911
9953
|
request.resolve(results.get(documentIdKey(request.id)) ?? null);
|
|
9912
9954
|
}
|
|
@@ -9927,7 +9969,7 @@ class SnapshotDocAccess {
|
|
|
9927
9969
|
hasTransaction() {
|
|
9928
9970
|
return false;
|
|
9929
9971
|
}
|
|
9930
|
-
|
|
9972
|
+
getIndexReader() {
|
|
9931
9973
|
return this.docstore;
|
|
9932
9974
|
}
|
|
9933
9975
|
getWriteVersion() {
|
|
@@ -9983,7 +10025,7 @@ class TransactionalDocAccess {
|
|
|
9983
10025
|
hasTransaction() {
|
|
9984
10026
|
return true;
|
|
9985
10027
|
}
|
|
9986
|
-
|
|
10028
|
+
getIndexReader() {
|
|
9987
10029
|
return this.docstore;
|
|
9988
10030
|
}
|
|
9989
10031
|
getWriteVersion() {
|
|
@@ -10174,7 +10216,7 @@ function rangeExpressionsToIndexBounds(expressions, indexFields) {
|
|
|
10174
10216
|
}
|
|
10175
10217
|
return { start, end };
|
|
10176
10218
|
}
|
|
10177
|
-
async function executeIndexQuery(
|
|
10219
|
+
async function executeIndexQuery(indexReader, tableName, indexName, indexFields, expressions, order, limit, cursor, snapshotTimestamp, onDocumentRead, options) {
|
|
10178
10220
|
return withTraceSpan("query.index.scan", "storage", async () => {
|
|
10179
10221
|
const tableId = stringToHex(tableName);
|
|
10180
10222
|
const indexId = stringToHex(`${tableName}:${indexName}`);
|
|
@@ -10196,8 +10238,8 @@ async function executeIndexQuery(docstore, tableName, indexName, indexFields, ex
|
|
|
10196
10238
|
}
|
|
10197
10239
|
const results = [];
|
|
10198
10240
|
const scanLimit = limit !== null ? limit + 1 : Number.MAX_SAFE_INTEGER;
|
|
10199
|
-
const
|
|
10200
|
-
const canUseResumePushdown = resumeIndexKey !== null && typeof
|
|
10241
|
+
const bulkIndexReader = indexReader;
|
|
10242
|
+
const canUseResumePushdown = resumeIndexKey !== null && typeof bulkIndexReader.indexScanRowsAfterKey === "function";
|
|
10201
10243
|
const skippingNeedsInMemoryPass = cursor !== null;
|
|
10202
10244
|
const pushdownLimit = limit !== null && !skippingNeedsInMemoryPass ? scanLimit : undefined;
|
|
10203
10245
|
let count = 0;
|
|
@@ -10235,21 +10277,21 @@ async function executeIndexQuery(docstore, tableName, indexName, indexFields, ex
|
|
|
10235
10277
|
addTraceEvent("query.index.scan.pushdown_resume", {
|
|
10236
10278
|
resumeMode: "index_key"
|
|
10237
10279
|
});
|
|
10238
|
-
const rows = await
|
|
10280
|
+
const rows = await bulkIndexReader.indexScanRowsAfterKey(indexId, tableId, readTimestamp, interval, indexOrder, resumeIndexKey, pushdownLimit);
|
|
10239
10281
|
for (const [indexKey, document] of rows) {
|
|
10240
10282
|
if (!processRow(indexKey, document)) {
|
|
10241
10283
|
break;
|
|
10242
10284
|
}
|
|
10243
10285
|
}
|
|
10244
|
-
} else if (typeof
|
|
10245
|
-
const rows = await
|
|
10286
|
+
} else if (typeof bulkIndexReader.indexScanRows === "function") {
|
|
10287
|
+
const rows = await bulkIndexReader.indexScanRows(indexId, tableId, readTimestamp, interval, indexOrder, pushdownLimit);
|
|
10246
10288
|
for (const [indexKey, document] of rows) {
|
|
10247
10289
|
if (!processRow(indexKey, document)) {
|
|
10248
10290
|
break;
|
|
10249
10291
|
}
|
|
10250
10292
|
}
|
|
10251
10293
|
} else {
|
|
10252
|
-
const generator =
|
|
10294
|
+
const generator = indexReader.indexScan(indexId, tableId, readTimestamp, interval, indexOrder, pushdownLimit);
|
|
10253
10295
|
for await (const [indexKey, document] of generator) {
|
|
10254
10296
|
if (!processRow(indexKey, document)) {
|
|
10255
10297
|
break;
|
|
@@ -10951,7 +10993,7 @@ async function executeIndexRangePlan(plan, cursor, limit, deps) {
|
|
|
10951
10993
|
let paginationResult;
|
|
10952
10994
|
let usedFallback = false;
|
|
10953
10995
|
try {
|
|
10954
|
-
const indexResult = await executeIndexQuery(deps.docStore.
|
|
10996
|
+
const indexResult = await executeIndexQuery(deps.docStore.getIndexReader(), plan.fullTableName, plan.indexDescriptor, plan.indexFields, plan.expressions, plan.order, limit, cursor, deps.context.snapshotTimestamp, observedDocuments ? (latestDoc) => {
|
|
10955
10997
|
observedDocuments.set(documentIdKey(latestDoc.value.id), latestDoc);
|
|
10956
10998
|
} : undefined, {
|
|
10957
10999
|
bounds: { start, end }
|
|
@@ -12083,19 +12125,30 @@ function getSyscallApiProfile(id = "convex-1.0") {
|
|
|
12083
12125
|
}
|
|
12084
12126
|
|
|
12085
12127
|
// ../core/dist/kernel/syscalls/capabilities.js
|
|
12086
|
-
var
|
|
12087
|
-
|
|
12088
|
-
|
|
12089
|
-
|
|
12090
|
-
|
|
12091
|
-
|
|
12092
|
-
|
|
12093
|
-
|
|
12094
|
-
|
|
12095
|
-
|
|
12128
|
+
var UDF_SYSCALL_CAPABILITIES = {
|
|
12129
|
+
query: ["databaseRead", "nestedQuery", "functionHandle", "transactionHeadroom"],
|
|
12130
|
+
mutation: [
|
|
12131
|
+
"databaseRead",
|
|
12132
|
+
"databaseWrite",
|
|
12133
|
+
"nestedQuery",
|
|
12134
|
+
"nestedMutation",
|
|
12135
|
+
"functionHandle",
|
|
12136
|
+
"mutationScheduler",
|
|
12137
|
+
"transactionHeadroom"
|
|
12138
|
+
],
|
|
12139
|
+
action: ["nestedQuery", "nestedMutation", "nestedAction", "actionSearch", "functionHandle", "actionScheduler"],
|
|
12140
|
+
httpAction: ["nestedQuery", "nestedMutation", "nestedAction", "actionSearch", "functionHandle", "actionScheduler"]
|
|
12096
12141
|
};
|
|
12142
|
+
var NESTED_UDF_CAPABILITY = {
|
|
12143
|
+
query: "nestedQuery",
|
|
12144
|
+
mutation: "nestedMutation",
|
|
12145
|
+
action: "nestedAction"
|
|
12146
|
+
};
|
|
12147
|
+
function hasSyscallCapability(udfType, capability) {
|
|
12148
|
+
return UDF_SYSCALL_CAPABILITIES[udfType].includes(capability);
|
|
12149
|
+
}
|
|
12097
12150
|
function assertSyscallCapability(udfType, capability, operation) {
|
|
12098
|
-
if (
|
|
12151
|
+
if (hasSyscallCapability(udfType, capability)) {
|
|
12099
12152
|
return;
|
|
12100
12153
|
}
|
|
12101
12154
|
throw new Error(`${operation} not available in ${formatUdfType(udfType)}`);
|
|
@@ -12114,6 +12167,12 @@ function formatUdfType(udfType) {
|
|
|
12114
12167
|
}
|
|
12115
12168
|
|
|
12116
12169
|
// ../core/dist/kernel/syscalls/action-syscalls.js
|
|
12170
|
+
var NESTED_UDF_OPERATION = {
|
|
12171
|
+
query: "Nested queries",
|
|
12172
|
+
mutation: "Nested mutations",
|
|
12173
|
+
action: "Nested actions"
|
|
12174
|
+
};
|
|
12175
|
+
|
|
12117
12176
|
class ActionSyscalls {
|
|
12118
12177
|
context;
|
|
12119
12178
|
queryRuntime;
|
|
@@ -12139,7 +12198,7 @@ class ActionSyscalls {
|
|
|
12139
12198
|
router.registerAsync(this.ops.createFunctionHandle, (args) => this.handleCreateFunctionHandle(args));
|
|
12140
12199
|
}
|
|
12141
12200
|
async handleActionQuery(args) {
|
|
12142
|
-
this.
|
|
12201
|
+
this.requireNestedCall("query");
|
|
12143
12202
|
const target = resolveFunctionTarget(args, this.context.componentPath);
|
|
12144
12203
|
const udfArguments = normalizeUdfArgsPayload(args.args);
|
|
12145
12204
|
return await this.invocationManager.execute(target.udfPath, udfArguments, "query", target.componentPath);
|
|
@@ -12173,15 +12232,8 @@ class ActionSyscalls {
|
|
|
12173
12232
|
assertSyscallCapability(this.context.udfType, "actionSearch", "Search");
|
|
12174
12233
|
return this.queryRuntime.runSearchAction(args.query);
|
|
12175
12234
|
}
|
|
12176
|
-
requireNestedQuery() {
|
|
12177
|
-
assertSyscallCapability(this.context.udfType, "nestedQuery", "Nested queries");
|
|
12178
|
-
}
|
|
12179
12235
|
requireNestedCall(type) {
|
|
12180
|
-
|
|
12181
|
-
this.requireNestedQuery();
|
|
12182
|
-
return;
|
|
12183
|
-
}
|
|
12184
|
-
assertSyscallCapability(this.context.udfType, type === "mutation" ? "nestedMutation" : "nestedAction", type === "mutation" ? "Nested mutations" : "Nested actions");
|
|
12236
|
+
assertSyscallCapability(this.context.udfType, NESTED_UDF_CAPABILITY[type], NESTED_UDF_OPERATION[type]);
|
|
12185
12237
|
}
|
|
12186
12238
|
}
|
|
12187
12239
|
|
|
@@ -12517,7 +12569,7 @@ class HeadroomSyscalls {
|
|
|
12517
12569
|
router.registerAsync(this.ops.headroom, async () => this.handleHeadroom());
|
|
12518
12570
|
}
|
|
12519
12571
|
handleHeadroom() {
|
|
12520
|
-
if (this.context.udfType
|
|
12572
|
+
if (!hasSyscallCapability(this.context.udfType, "transactionHeadroom")) {
|
|
12521
12573
|
throw new Error(`Unknown async operation: ${this.ops.headroom}`);
|
|
12522
12574
|
}
|
|
12523
12575
|
return this.context.getTransactionHeadroom();
|
|
@@ -12538,14 +12590,14 @@ class IdentitySyscalls {
|
|
|
12538
12590
|
}
|
|
12539
12591
|
handleGetUserIdentity() {
|
|
12540
12592
|
this.context.markAuthAccessed();
|
|
12541
|
-
const
|
|
12542
|
-
if (!
|
|
12593
|
+
const authContext = this.context.authContext;
|
|
12594
|
+
if (!authContext) {
|
|
12543
12595
|
return null;
|
|
12544
12596
|
}
|
|
12545
|
-
if (
|
|
12546
|
-
return
|
|
12597
|
+
if (authContext.userIdentity) {
|
|
12598
|
+
return authContext.userIdentity;
|
|
12547
12599
|
}
|
|
12548
|
-
const token =
|
|
12600
|
+
const token = authContext.token;
|
|
12549
12601
|
if (!token) {
|
|
12550
12602
|
return null;
|
|
12551
12603
|
}
|
|
@@ -12584,14 +12636,16 @@ class JsSyscallRouter {
|
|
|
12584
12636
|
|
|
12585
12637
|
// ../core/dist/kernel/syscalls/query-syscalls.js
|
|
12586
12638
|
class QuerySyscalls {
|
|
12587
|
-
queryRuntime;
|
|
12588
12639
|
nextQueryId = 1;
|
|
12589
12640
|
queryResults = {};
|
|
12590
12641
|
pendingQueries = {};
|
|
12642
|
+
context;
|
|
12643
|
+
queryRuntime;
|
|
12591
12644
|
ops;
|
|
12592
|
-
constructor(
|
|
12593
|
-
this.
|
|
12594
|
-
this.
|
|
12645
|
+
constructor(options) {
|
|
12646
|
+
this.context = options.context;
|
|
12647
|
+
this.queryRuntime = options.queryRuntime;
|
|
12648
|
+
this.ops = options.ops ?? CONVEX_1_0_SYSCALL_API.query;
|
|
12595
12649
|
}
|
|
12596
12650
|
register(router) {
|
|
12597
12651
|
router.registerSync(this.ops.queryStream, (args) => this.handleQueryStream(args));
|
|
@@ -12600,18 +12654,21 @@ class QuerySyscalls {
|
|
|
12600
12654
|
router.registerAsync(this.ops.queryPage, (args) => this.handleQueryPage(args));
|
|
12601
12655
|
}
|
|
12602
12656
|
handleQueryStream(args) {
|
|
12657
|
+
this.requireDatabaseRead();
|
|
12603
12658
|
const { query } = args;
|
|
12604
12659
|
const queryId = this.nextQueryId++;
|
|
12605
12660
|
this.pendingQueries[queryId] = query;
|
|
12606
12661
|
return { queryId };
|
|
12607
12662
|
}
|
|
12608
12663
|
handleQueryCleanup(args) {
|
|
12664
|
+
this.requireDatabaseRead();
|
|
12609
12665
|
const queryId = args.queryId;
|
|
12610
12666
|
delete this.pendingQueries[queryId];
|
|
12611
12667
|
delete this.queryResults[queryId];
|
|
12612
12668
|
return {};
|
|
12613
12669
|
}
|
|
12614
12670
|
async handleQueryStreamNext(args) {
|
|
12671
|
+
this.requireDatabaseRead();
|
|
12615
12672
|
const queryId = args.queryId;
|
|
12616
12673
|
if (this.pendingQueries[queryId]) {
|
|
12617
12674
|
const query = this.pendingQueries[queryId];
|
|
@@ -12631,6 +12688,7 @@ class QuerySyscalls {
|
|
|
12631
12688
|
return { value, done: false };
|
|
12632
12689
|
}
|
|
12633
12690
|
async handleQueryPage(args) {
|
|
12691
|
+
this.requireDatabaseRead();
|
|
12634
12692
|
const { query, cursor, pageSize } = args;
|
|
12635
12693
|
if (cursor === "_end_cursor") {
|
|
12636
12694
|
return {
|
|
@@ -12646,6 +12704,9 @@ class QuerySyscalls {
|
|
|
12646
12704
|
continueCursor: paginatedResult.hasMore ? paginatedResult.nextCursor : "_end_cursor"
|
|
12647
12705
|
};
|
|
12648
12706
|
}
|
|
12707
|
+
requireDatabaseRead() {
|
|
12708
|
+
assertSyscallCapability(this.context.udfType, "databaseRead", "Database reads");
|
|
12709
|
+
}
|
|
12649
12710
|
}
|
|
12650
12711
|
|
|
12651
12712
|
// ../core/dist/kernel/syscalls/schedule-syscalls.js
|
|
@@ -12659,15 +12720,17 @@ class ScheduleSyscalls {
|
|
|
12659
12720
|
this.ops = options.ops ?? CONVEX_1_0_SYSCALL_API.schedule;
|
|
12660
12721
|
}
|
|
12661
12722
|
register(router) {
|
|
12662
|
-
router.registerAsync(this.ops.schedule, (args) => this.handleSchedule(args,
|
|
12663
|
-
router.registerAsync(this.ops.scheduleFromAction, (args) => this.handleSchedule(args, true), {
|
|
12723
|
+
router.registerAsync(this.ops.schedule, (args) => this.handleSchedule(args, "mutationScheduler"), {
|
|
12664
12724
|
argsFormat: "convex"
|
|
12665
12725
|
});
|
|
12666
|
-
router.registerAsync(this.ops.
|
|
12667
|
-
|
|
12726
|
+
router.registerAsync(this.ops.scheduleFromAction, (args) => this.handleSchedule(args, "actionScheduler"), {
|
|
12727
|
+
argsFormat: "convex"
|
|
12728
|
+
});
|
|
12729
|
+
router.registerAsync(this.ops.cancelJobFromAction, (args) => this.handleCancelJob(args, "actionScheduler"));
|
|
12730
|
+
router.registerAsync(this.ops.cancelJob, (args) => this.handleCancelJob(args, "mutationScheduler"));
|
|
12668
12731
|
}
|
|
12669
|
-
async handleSchedule(args,
|
|
12670
|
-
this.requireScheduler(
|
|
12732
|
+
async handleSchedule(args, capability) {
|
|
12733
|
+
this.requireScheduler(capability);
|
|
12671
12734
|
const target = resolveFunctionTarget(args, this.context.componentPath);
|
|
12672
12735
|
const { args: fnArgs, ts } = args;
|
|
12673
12736
|
if (fnArgs === undefined || typeof ts !== "number") {
|
|
@@ -12676,8 +12739,8 @@ class ScheduleSyscalls {
|
|
|
12676
12739
|
const componentPathForJob = normalizeComponentPathValue(target.componentPath ?? this.context.componentPath);
|
|
12677
12740
|
return this.scheduler.schedule(target.udfPath, fnArgs, ts, componentPathForJob);
|
|
12678
12741
|
}
|
|
12679
|
-
async handleCancelJob(args,
|
|
12680
|
-
this.requireScheduler(
|
|
12742
|
+
async handleCancelJob(args, capability) {
|
|
12743
|
+
this.requireScheduler(capability);
|
|
12681
12744
|
const { id, state } = args;
|
|
12682
12745
|
if (typeof id !== "string") {
|
|
12683
12746
|
throw new Error("`id` argument for `cancel_job` must be a string.");
|
|
@@ -12685,8 +12748,8 @@ class ScheduleSyscalls {
|
|
|
12685
12748
|
await this.scheduler.cancel(id, state);
|
|
12686
12749
|
return {};
|
|
12687
12750
|
}
|
|
12688
|
-
requireScheduler(
|
|
12689
|
-
assertSyscallCapability(this.context.udfType,
|
|
12751
|
+
requireScheduler(capability) {
|
|
12752
|
+
assertSyscallCapability(this.context.udfType, capability, "Scheduler");
|
|
12690
12753
|
}
|
|
12691
12754
|
}
|
|
12692
12755
|
|
|
@@ -12828,7 +12891,11 @@ class KernelSyscalls {
|
|
|
12828
12891
|
context: resources.context,
|
|
12829
12892
|
udfExecutor: resources.udfExecutor
|
|
12830
12893
|
});
|
|
12831
|
-
new QuerySyscalls(
|
|
12894
|
+
new QuerySyscalls({
|
|
12895
|
+
context: resources.context,
|
|
12896
|
+
queryRuntime: resources.queryRuntime,
|
|
12897
|
+
ops: syscallApi.query
|
|
12898
|
+
}).register(this.router);
|
|
12832
12899
|
new DatabaseSyscalls({
|
|
12833
12900
|
context: resources.context,
|
|
12834
12901
|
docStore: resources.docStore,
|
|
@@ -13558,6 +13625,16 @@ function rangesToTables(ranges) {
|
|
|
13558
13625
|
}
|
|
13559
13626
|
return tables;
|
|
13560
13627
|
}
|
|
13628
|
+
function cloneSetMap(source) {
|
|
13629
|
+
const clone = new Map;
|
|
13630
|
+
copySetMap(source, clone);
|
|
13631
|
+
return clone;
|
|
13632
|
+
}
|
|
13633
|
+
function copySetMap(source, target) {
|
|
13634
|
+
for (const [key, values] of source) {
|
|
13635
|
+
target.set(key, new Set(values));
|
|
13636
|
+
}
|
|
13637
|
+
}
|
|
13561
13638
|
var TABLE_WRITE_TIMESTAMP_TTL_MS = 60 * 60 * 1000;
|
|
13562
13639
|
var RECENT_WRITE_RANGE_TTL_MS = 60 * 1000;
|
|
13563
13640
|
var TABLE_WRITE_TIMESTAMP_MAX_SIZE = 1e4;
|
|
@@ -13571,6 +13648,30 @@ class SubscriptionGraph {
|
|
|
13571
13648
|
clientQueryToId = new Map;
|
|
13572
13649
|
hashToTables = new Map;
|
|
13573
13650
|
tableToHashes = new Map;
|
|
13651
|
+
apply(change) {
|
|
13652
|
+
const snapshot = this.snapshot();
|
|
13653
|
+
try {
|
|
13654
|
+
switch (change.type) {
|
|
13655
|
+
case "subscribe":
|
|
13656
|
+
this.setClientQueryHash(change.clientQuery, change.queryId, change.queryHash);
|
|
13657
|
+
this.setQueryTables(change.queryHash, change.tables);
|
|
13658
|
+
break;
|
|
13659
|
+
case "unsubscribe":
|
|
13660
|
+
this.removeClientQuery(change.clientQuery);
|
|
13661
|
+
break;
|
|
13662
|
+
case "unsubscribeClient":
|
|
13663
|
+
this.removeClient(change.clientId);
|
|
13664
|
+
break;
|
|
13665
|
+
case "renameClient":
|
|
13666
|
+
this.renameClient(change.oldClientId, change.newClientId);
|
|
13667
|
+
break;
|
|
13668
|
+
}
|
|
13669
|
+
this.assertConsistent();
|
|
13670
|
+
} catch (error) {
|
|
13671
|
+
this.restore(snapshot);
|
|
13672
|
+
throw error;
|
|
13673
|
+
}
|
|
13674
|
+
}
|
|
13574
13675
|
getClientQueriesForHash(hash) {
|
|
13575
13676
|
return this.hashToClientQueries.get(hash) ?? new Set;
|
|
13576
13677
|
}
|
|
@@ -13623,6 +13724,11 @@ class SubscriptionGraph {
|
|
|
13623
13724
|
const hash = this.clientQueryToHash.get(oldKey);
|
|
13624
13725
|
if (!hash)
|
|
13625
13726
|
return;
|
|
13727
|
+
if (oldKey === newKey) {
|
|
13728
|
+
this.clientQueryToId.set(oldKey, newQueryId);
|
|
13729
|
+
return;
|
|
13730
|
+
}
|
|
13731
|
+
this.removeClientQuery(newKey);
|
|
13626
13732
|
this.clientQueryToHash.delete(oldKey);
|
|
13627
13733
|
this.clientQueryToId.delete(oldKey);
|
|
13628
13734
|
this.clientQueryToHash.set(newKey, hash);
|
|
@@ -13631,6 +13737,54 @@ class SubscriptionGraph {
|
|
|
13631
13737
|
cqSet.delete(oldKey);
|
|
13632
13738
|
cqSet.add(newKey);
|
|
13633
13739
|
}
|
|
13740
|
+
assertConsistent() {
|
|
13741
|
+
for (const [hash, clientQueries] of this.hashToClientQueries) {
|
|
13742
|
+
if (clientQueries.size === 0) {
|
|
13743
|
+
throw new Error(`SubscriptionGraph invariant failed: empty client query set for ${hash}`);
|
|
13744
|
+
}
|
|
13745
|
+
for (const clientQuery of clientQueries) {
|
|
13746
|
+
if (this.clientQueryToHash.get(clientQuery) !== hash) {
|
|
13747
|
+
throw new Error(`SubscriptionGraph invariant failed: stale client query ${clientQuery} for ${hash}`);
|
|
13748
|
+
}
|
|
13749
|
+
if (!this.clientQueryToId.has(clientQuery)) {
|
|
13750
|
+
throw new Error(`SubscriptionGraph invariant failed: missing query id for ${clientQuery}`);
|
|
13751
|
+
}
|
|
13752
|
+
}
|
|
13753
|
+
}
|
|
13754
|
+
for (const [clientQuery, hash] of this.clientQueryToHash) {
|
|
13755
|
+
if (!this.hashToClientQueries.get(hash)?.has(clientQuery)) {
|
|
13756
|
+
throw new Error(`SubscriptionGraph invariant failed: missing reverse hash entry for ${clientQuery}`);
|
|
13757
|
+
}
|
|
13758
|
+
if (!this.clientQueryToId.has(clientQuery)) {
|
|
13759
|
+
throw new Error(`SubscriptionGraph invariant failed: missing query id for ${clientQuery}`);
|
|
13760
|
+
}
|
|
13761
|
+
}
|
|
13762
|
+
for (const clientQuery of this.clientQueryToId.keys()) {
|
|
13763
|
+
if (!this.clientQueryToHash.has(clientQuery)) {
|
|
13764
|
+
throw new Error(`SubscriptionGraph invariant failed: orphaned query id for ${clientQuery}`);
|
|
13765
|
+
}
|
|
13766
|
+
}
|
|
13767
|
+
for (const [hash, tables] of this.hashToTables) {
|
|
13768
|
+
if (!this.hashToClientQueries.has(hash)) {
|
|
13769
|
+
throw new Error(`SubscriptionGraph invariant failed: table dependencies for orphaned hash ${hash}`);
|
|
13770
|
+
}
|
|
13771
|
+
for (const table of tables) {
|
|
13772
|
+
if (!this.tableToHashes.get(table)?.has(hash)) {
|
|
13773
|
+
throw new Error(`SubscriptionGraph invariant failed: missing reverse table entry for ${hash} on ${table}`);
|
|
13774
|
+
}
|
|
13775
|
+
}
|
|
13776
|
+
}
|
|
13777
|
+
for (const [table, hashes] of this.tableToHashes) {
|
|
13778
|
+
if (hashes.size === 0) {
|
|
13779
|
+
throw new Error(`SubscriptionGraph invariant failed: empty hash set for table ${table}`);
|
|
13780
|
+
}
|
|
13781
|
+
for (const hash of hashes) {
|
|
13782
|
+
if (!this.hashToTables.get(hash)?.has(table)) {
|
|
13783
|
+
throw new Error(`SubscriptionGraph invariant failed: stale table hash ${hash} for ${table}`);
|
|
13784
|
+
}
|
|
13785
|
+
}
|
|
13786
|
+
}
|
|
13787
|
+
}
|
|
13634
13788
|
setQueryTables(hash, tables) {
|
|
13635
13789
|
if (!this.hashToClientQueries.has(hash))
|
|
13636
13790
|
return;
|
|
@@ -13686,6 +13840,56 @@ class SubscriptionGraph {
|
|
|
13686
13840
|
*hashes() {
|
|
13687
13841
|
yield* this.hashToClientQueries.keys();
|
|
13688
13842
|
}
|
|
13843
|
+
removeClient(clientId) {
|
|
13844
|
+
const prefix = `${clientId}:`;
|
|
13845
|
+
const keysToRemove = [];
|
|
13846
|
+
for (const [key] of this.clientQueryToHash) {
|
|
13847
|
+
if (key.startsWith(prefix)) {
|
|
13848
|
+
keysToRemove.push(key);
|
|
13849
|
+
}
|
|
13850
|
+
}
|
|
13851
|
+
for (const key of keysToRemove) {
|
|
13852
|
+
this.removeClientQuery(key);
|
|
13853
|
+
}
|
|
13854
|
+
}
|
|
13855
|
+
renameClient(oldClientId, newClientId) {
|
|
13856
|
+
const prefix = `${oldClientId}:`;
|
|
13857
|
+
const updates = [];
|
|
13858
|
+
for (const [key] of this.clientQueryToHash) {
|
|
13859
|
+
if (key.startsWith(prefix)) {
|
|
13860
|
+
const queryId = this.clientQueryToId.get(key);
|
|
13861
|
+
if (queryId !== undefined) {
|
|
13862
|
+
updates.push({ oldKey: key, newKey: makeClientQueryKey(newClientId, queryId), queryId });
|
|
13863
|
+
}
|
|
13864
|
+
}
|
|
13865
|
+
}
|
|
13866
|
+
for (const { oldKey, newKey, queryId } of updates) {
|
|
13867
|
+
this.renameClientQuery(oldKey, newKey, queryId);
|
|
13868
|
+
}
|
|
13869
|
+
}
|
|
13870
|
+
snapshot() {
|
|
13871
|
+
return {
|
|
13872
|
+
hashToClientQueries: cloneSetMap(this.hashToClientQueries),
|
|
13873
|
+
clientQueryToHash: new Map(this.clientQueryToHash),
|
|
13874
|
+
clientQueryToId: new Map(this.clientQueryToId),
|
|
13875
|
+
hashToTables: cloneSetMap(this.hashToTables),
|
|
13876
|
+
tableToHashes: cloneSetMap(this.tableToHashes)
|
|
13877
|
+
};
|
|
13878
|
+
}
|
|
13879
|
+
restore(snapshot) {
|
|
13880
|
+
this.hashToClientQueries.clear();
|
|
13881
|
+
this.clientQueryToHash.clear();
|
|
13882
|
+
this.clientQueryToId.clear();
|
|
13883
|
+
this.hashToTables.clear();
|
|
13884
|
+
this.tableToHashes.clear();
|
|
13885
|
+
copySetMap(snapshot.hashToClientQueries, this.hashToClientQueries);
|
|
13886
|
+
for (const [key, value] of snapshot.clientQueryToHash)
|
|
13887
|
+
this.clientQueryToHash.set(key, value);
|
|
13888
|
+
for (const [key, value] of snapshot.clientQueryToId)
|
|
13889
|
+
this.clientQueryToId.set(key, value);
|
|
13890
|
+
copySetMap(snapshot.hashToTables, this.hashToTables);
|
|
13891
|
+
copySetMap(snapshot.tableToHashes, this.tableToHashes);
|
|
13892
|
+
}
|
|
13689
13893
|
}
|
|
13690
13894
|
|
|
13691
13895
|
class SubscriptionManager {
|
|
@@ -13696,9 +13900,14 @@ class SubscriptionManager {
|
|
|
13696
13900
|
subscribe(clientId, queryId, dependencies, queryHash, snapshotTimestamp) {
|
|
13697
13901
|
const hash = queryHash ?? makeClientQueryKey(clientId, queryId);
|
|
13698
13902
|
const clientQueryKey = makeClientQueryKey(clientId, queryId);
|
|
13699
|
-
this.graph.setClientQueryHash(clientQueryKey, queryId, hash);
|
|
13700
13903
|
const tables = rangesToTables(dependencies.ranges);
|
|
13701
|
-
this.graph.
|
|
13904
|
+
this.graph.apply({
|
|
13905
|
+
type: "subscribe",
|
|
13906
|
+
clientQuery: clientQueryKey,
|
|
13907
|
+
queryId,
|
|
13908
|
+
queryHash: hash,
|
|
13909
|
+
tables
|
|
13910
|
+
});
|
|
13702
13911
|
let needsRerun = false;
|
|
13703
13912
|
const now = Date.now();
|
|
13704
13913
|
const preciseCheckedTables = new Set;
|
|
@@ -13741,18 +13950,10 @@ class SubscriptionManager {
|
|
|
13741
13950
|
}
|
|
13742
13951
|
unsubscribe(clientId, queryId) {
|
|
13743
13952
|
const clientQueryKey = makeClientQueryKey(clientId, queryId);
|
|
13744
|
-
this.graph.
|
|
13953
|
+
this.graph.apply({ type: "unsubscribe", clientQuery: clientQueryKey });
|
|
13745
13954
|
}
|
|
13746
13955
|
unsubscribeAll(clientId) {
|
|
13747
|
-
|
|
13748
|
-
for (const [key] of this.graph.clientQueries()) {
|
|
13749
|
-
if (key.startsWith(`${clientId}:`)) {
|
|
13750
|
-
keysToRemove.push(key);
|
|
13751
|
-
}
|
|
13752
|
-
}
|
|
13753
|
-
for (const key of keysToRemove) {
|
|
13754
|
-
this.graph.removeClientQuery(key);
|
|
13755
|
-
}
|
|
13956
|
+
this.graph.apply({ type: "unsubscribeClient", clientId });
|
|
13756
13957
|
}
|
|
13757
13958
|
findAffectedQueries(writtenRanges) {
|
|
13758
13959
|
const writtenTables = rangesToTables(writtenRanges);
|
|
@@ -13863,18 +14064,7 @@ class SubscriptionManager {
|
|
|
13863
14064
|
return queries;
|
|
13864
14065
|
}
|
|
13865
14066
|
updateSessionId(oldClientId, newClientId) {
|
|
13866
|
-
|
|
13867
|
-
for (const [key] of this.graph.clientQueries()) {
|
|
13868
|
-
if (key.startsWith(`${oldClientId}:`)) {
|
|
13869
|
-
const queryId = this.graph.getOriginalQueryId(key);
|
|
13870
|
-
if (queryId !== undefined) {
|
|
13871
|
-
updates.push({ oldKey: key, newKey: makeClientQueryKey(newClientId, queryId), queryId });
|
|
13872
|
-
}
|
|
13873
|
-
}
|
|
13874
|
-
}
|
|
13875
|
-
for (const { oldKey, newKey, queryId } of updates) {
|
|
13876
|
-
this.graph.renameClientQuery(oldKey, newKey, queryId);
|
|
13877
|
-
}
|
|
14067
|
+
this.graph.apply({ type: "renameClient", oldClientId, newClientId });
|
|
13878
14068
|
}
|
|
13879
14069
|
getStats() {
|
|
13880
14070
|
const clients = new Set;
|
|
@@ -13889,7 +14079,9 @@ class SubscriptionManager {
|
|
|
13889
14079
|
totalTrackedWriteTimestamps: this.tableWriteTimestamps.size
|
|
13890
14080
|
};
|
|
13891
14081
|
}
|
|
13892
|
-
assertConsistency() {
|
|
14082
|
+
assertConsistency() {
|
|
14083
|
+
this.graph.assertConsistent();
|
|
14084
|
+
}
|
|
13893
14085
|
forceCleanupTableWriteTimestamps() {
|
|
13894
14086
|
const sizeBefore = this.tableWriteTimestamps.size;
|
|
13895
14087
|
this.lastCleanupTime = 0;
|
|
@@ -14339,13 +14531,13 @@ var udfMathRandom2 = () => {
|
|
|
14339
14531
|
const udfRuntime = UDF_ASYNC_CONTEXT.getStore();
|
|
14340
14532
|
return (udfRuntime?.mathRandom ?? OG_MATH_RANDOM)();
|
|
14341
14533
|
};
|
|
14342
|
-
var udfSetInterval = (callback, delay) => {
|
|
14534
|
+
var udfSetInterval = (callback, delay, ...args) => {
|
|
14343
14535
|
const udfRuntime = UDF_ASYNC_CONTEXT.getStore();
|
|
14344
|
-
return (udfRuntime?.setInterval ?? OG_SET_INTERVAL)(callback, delay ?? 0);
|
|
14536
|
+
return (udfRuntime?.setInterval ?? OG_SET_INTERVAL)(callback, delay ?? 0, ...args);
|
|
14345
14537
|
};
|
|
14346
|
-
var udfSetTimeout = (callback, delay) => {
|
|
14538
|
+
var udfSetTimeout = (callback, delay, ...args) => {
|
|
14347
14539
|
const udfRuntime = UDF_ASYNC_CONTEXT.getStore();
|
|
14348
|
-
return (udfRuntime?.setTimeout ?? OG_SET_TIMEOUT)(callback, delay ?? 0);
|
|
14540
|
+
return (udfRuntime?.setTimeout ?? OG_SET_TIMEOUT)(callback, delay ?? 0, ...args);
|
|
14349
14541
|
};
|
|
14350
14542
|
var udfCryptoRandomUUID2 = () => {
|
|
14351
14543
|
const udfRuntime = UDF_ASYNC_CONTEXT.getStore();
|
|
@@ -14419,15 +14611,19 @@ function resolveSeed(kind, requestId, tnow) {
|
|
|
14419
14611
|
fallbackSeedCounter += 1;
|
|
14420
14612
|
return `udf:${kind}:${tnow}:${fallbackSeedCounter}:${OG_CRYPTO_RANDOM_UUID()}`;
|
|
14421
14613
|
}
|
|
14614
|
+
function isKernelAuthContext(auth) {
|
|
14615
|
+
return !!auth && typeof auth === "object" && "tokenType" in auth && (auth.tokenType === "Admin" || auth.tokenType === "System" || auth.tokenType === "User" || auth.tokenType === "None");
|
|
14616
|
+
}
|
|
14422
14617
|
function resolveEffectiveKernelAuth(auth) {
|
|
14423
14618
|
const ambientIdentity = getAuthContext();
|
|
14424
|
-
if (auth
|
|
14619
|
+
if (isKernelAuthContext(auth)) {
|
|
14425
14620
|
return {
|
|
14426
14621
|
...auth,
|
|
14427
14622
|
userIdentity: auth.userIdentity ?? ambientIdentity
|
|
14428
14623
|
};
|
|
14429
14624
|
}
|
|
14430
|
-
|
|
14625
|
+
const userIdentity = ambientIdentity ?? auth;
|
|
14626
|
+
return userIdentity ? { tokenType: "User", userIdentity } : undefined;
|
|
14431
14627
|
}
|
|
14432
14628
|
function resolveExecutionIdGenerator(deterministicSeed, explicitIdGenerator) {
|
|
14433
14629
|
if (explicitIdGenerator) {
|
|
@@ -14436,20 +14632,12 @@ function resolveExecutionIdGenerator(deterministicSeed, explicitIdGenerator) {
|
|
|
14436
14632
|
return idGeneratorContext.getStore() ?? (deterministicSeed ? createDeterministicIdGenerator(deterministicSeed) : undefined);
|
|
14437
14633
|
}
|
|
14438
14634
|
function createExecutionKernel(options) {
|
|
14439
|
-
const capabilities = {};
|
|
14440
|
-
if (options.storage) {
|
|
14441
|
-
capabilities.blobs = { store: options.storage, consistency: "eventual" };
|
|
14442
|
-
}
|
|
14443
|
-
if (options.searchstore) {
|
|
14444
|
-
capabilities.search = options.searchstore;
|
|
14445
|
-
}
|
|
14446
|
-
if (options.vecstore) {
|
|
14447
|
-
capabilities.vector = options.vecstore;
|
|
14448
|
-
}
|
|
14449
14635
|
const convex = buildKernel({
|
|
14450
14636
|
services: {
|
|
14451
14637
|
docstore: options.docstore,
|
|
14452
|
-
|
|
14638
|
+
...options.storage ? { blobstore: options.storage } : {},
|
|
14639
|
+
...options.searchstore ? { searchstore: options.searchstore } : {},
|
|
14640
|
+
...options.vecstore ? { vecstore: options.vecstore } : {},
|
|
14453
14641
|
udfExecutor: options.udfExecutor
|
|
14454
14642
|
},
|
|
14455
14643
|
authContext: resolveEffectiveKernelAuth(options.auth),
|
|
@@ -14720,6 +14908,82 @@ async function runUdfHttpAction(docstore, fn, auth, storage2, searchstore2, vecs
|
|
|
14720
14908
|
|
|
14721
14909
|
// ../core/dist/udf/executor/inline.js
|
|
14722
14910
|
init_module_loader();
|
|
14911
|
+
|
|
14912
|
+
// ../core/dist/udf/function-resolution.js
|
|
14913
|
+
function normalizeUdfFunctionTarget(input, options = {}) {
|
|
14914
|
+
const policy = options.policy ?? {};
|
|
14915
|
+
if (input.startsWith("function://")) {
|
|
14916
|
+
if (policy.allowFunctionHandle === false) {
|
|
14917
|
+
throw new Error(`Invalid UDF path: ${input}`);
|
|
14918
|
+
}
|
|
14919
|
+
const remainder = input.slice("function://".length);
|
|
14920
|
+
const separatorIndex = remainder.indexOf(";");
|
|
14921
|
+
if (separatorIndex === -1) {
|
|
14922
|
+
throw new Error(`Invalid function handle: ${input}`);
|
|
14923
|
+
}
|
|
14924
|
+
const componentPath = normalizeComponentPath2(remainder.slice(0, separatorIndex));
|
|
14925
|
+
const udfPath = remainder.slice(separatorIndex + 1);
|
|
14926
|
+
const target = normalizePlainUdfPath(udfPath, {
|
|
14927
|
+
componentPath: componentPath ?? options.componentPath,
|
|
14928
|
+
policy
|
|
14929
|
+
});
|
|
14930
|
+
return {
|
|
14931
|
+
...target,
|
|
14932
|
+
componentPath: componentPath ?? target.componentPath,
|
|
14933
|
+
isFunctionHandle: true
|
|
14934
|
+
};
|
|
14935
|
+
}
|
|
14936
|
+
return normalizePlainUdfPath(input, options);
|
|
14937
|
+
}
|
|
14938
|
+
function classifyUdfFunction(fn) {
|
|
14939
|
+
if (fn === null || typeof fn !== "object" && typeof fn !== "function") {
|
|
14940
|
+
return null;
|
|
14941
|
+
}
|
|
14942
|
+
const types = [];
|
|
14943
|
+
if (fn.isQuery)
|
|
14944
|
+
types.push("query");
|
|
14945
|
+
if (fn.isMutation)
|
|
14946
|
+
types.push("mutation");
|
|
14947
|
+
if (fn.isAction)
|
|
14948
|
+
types.push("action");
|
|
14949
|
+
return types.length === 1 ? types[0] : null;
|
|
14950
|
+
}
|
|
14951
|
+
function normalizePlainUdfPath(input, options = {}) {
|
|
14952
|
+
const policy = options.policy ?? {};
|
|
14953
|
+
let path = input;
|
|
14954
|
+
if (policy.allowSlashPath && !path.includes(":") && path.includes("/")) {
|
|
14955
|
+
const lastSlash = path.lastIndexOf("/");
|
|
14956
|
+
path = path.substring(0, lastSlash) + ":" + path.substring(lastSlash + 1);
|
|
14957
|
+
}
|
|
14958
|
+
const parts = path.split(":");
|
|
14959
|
+
if (parts.length === 2 && parts[0].length > 0 && parts[1].length > 0) {
|
|
14960
|
+
return {
|
|
14961
|
+
path,
|
|
14962
|
+
modulePath: parts[0],
|
|
14963
|
+
exportName: parts[1],
|
|
14964
|
+
componentPath: normalizeComponentPath2(options.componentPath),
|
|
14965
|
+
isFunctionHandle: false
|
|
14966
|
+
};
|
|
14967
|
+
}
|
|
14968
|
+
if (parts.length === 1 && policy.allowDefaultExport && parts[0].length > 0) {
|
|
14969
|
+
return {
|
|
14970
|
+
path: `${parts[0]}:default`,
|
|
14971
|
+
modulePath: parts[0],
|
|
14972
|
+
exportName: "default",
|
|
14973
|
+
componentPath: normalizeComponentPath2(options.componentPath),
|
|
14974
|
+
isFunctionHandle: false
|
|
14975
|
+
};
|
|
14976
|
+
}
|
|
14977
|
+
throw new Error(`Invalid UDF path: ${input}`);
|
|
14978
|
+
}
|
|
14979
|
+
function normalizeComponentPath2(componentPath) {
|
|
14980
|
+
if (!componentPath) {
|
|
14981
|
+
return;
|
|
14982
|
+
}
|
|
14983
|
+
return componentPath.length > 0 ? componentPath : undefined;
|
|
14984
|
+
}
|
|
14985
|
+
|
|
14986
|
+
// ../core/dist/udf/executor/inline.js
|
|
14723
14987
|
init_validator2();
|
|
14724
14988
|
|
|
14725
14989
|
// ../core/dist/errors/index.js
|
|
@@ -14889,22 +15153,8 @@ class InlineUdfExecutor {
|
|
|
14889
15153
|
this.bootstrapState = options.bootstrapState ?? new InlineExecutorBootstrapState;
|
|
14890
15154
|
}
|
|
14891
15155
|
withAmbientAuth(auth, fn) {
|
|
14892
|
-
|
|
14893
|
-
|
|
14894
|
-
if (auth && typeof auth === "object" && "tokenType" in auth) {
|
|
14895
|
-
authContext2 = auth;
|
|
14896
|
-
userIdentity = authContext2.tokenType === "User" && !authContext2.userIdentity && authContext2.token ? identityFromTrustedToken(authContext2.token) : authContext2.userIdentity;
|
|
14897
|
-
if (userIdentity && authContext2.tokenType === "User") {
|
|
14898
|
-
authContext2 = {
|
|
14899
|
-
...authContext2,
|
|
14900
|
-
userIdentity
|
|
14901
|
-
};
|
|
14902
|
-
}
|
|
14903
|
-
} else {
|
|
14904
|
-
userIdentity = auth;
|
|
14905
|
-
}
|
|
14906
|
-
const principal2 = authContext2 ? legacyAuthContextToPrincipal(authContext2) : userIdentity ? legacyAuthContextToPrincipal({ tokenType: "User", userIdentity }) : legacyAuthContextToPrincipal({ tokenType: "None" });
|
|
14907
|
-
return runWithAuth(userIdentity, fn, principal2);
|
|
15156
|
+
const executionAuth = resolveExecutionAuth(auth);
|
|
15157
|
+
return runWithAuth(executionAuth.userIdentity, fn, executionAuth.authContext);
|
|
14908
15158
|
}
|
|
14909
15159
|
get docstore() {
|
|
14910
15160
|
return this.services.docstore;
|
|
@@ -14920,27 +15170,32 @@ class InlineUdfExecutor {
|
|
|
14920
15170
|
}
|
|
14921
15171
|
async execute(functionPath, args, udfType, auth, componentPath, requestId, snapshotTimestamp) {
|
|
14922
15172
|
const bootstrapTiming = await this.ensureBootstrapped();
|
|
14923
|
-
const
|
|
14924
|
-
|
|
14925
|
-
|
|
15173
|
+
const target = normalizeUdfFunctionTarget(functionPath, {
|
|
15174
|
+
componentPath,
|
|
15175
|
+
policy: { allowFunctionHandle: true }
|
|
15176
|
+
});
|
|
15177
|
+
const { modulePath: moduleName, exportName: functionName2 } = target;
|
|
15178
|
+
const finalRequestId = requestId ?? this.requestIdFactory(udfType, target.path);
|
|
15179
|
+
const executionAuth = resolveExecutionAuth(auth);
|
|
15180
|
+
const isSystemFunction = moduleName === "_system" || target.path.startsWith("_system:");
|
|
14926
15181
|
const startTime = performance.now();
|
|
14927
15182
|
const invokeUdf = async () => {
|
|
14928
|
-
const module = await withTraceSpan("udf.load_module", "runtime", () => this.loadModule(moduleName, componentPath), { moduleName, componentPath: componentPath ?? "" });
|
|
15183
|
+
const module = await withTraceSpan("udf.load_module", "runtime", () => this.loadModule(moduleName, target.componentPath), { moduleName, componentPath: target.componentPath ?? "" });
|
|
14929
15184
|
const fn = module?.[functionName2];
|
|
14930
|
-
this.assertFunctionExport(functionName2, moduleName, fn, udfType,
|
|
14931
|
-
await withTraceSpan("udf.validate_args", "runtime", () => this.validateArgs(fn, args, componentPath), {
|
|
15185
|
+
const resolvedType = this.assertFunctionExport(functionName2, moduleName, fn, udfType, executionAuth.executorAuth);
|
|
15186
|
+
await withTraceSpan("udf.validate_args", "runtime", () => this.validateArgs(fn, args, target.componentPath), {
|
|
14932
15187
|
moduleName,
|
|
14933
15188
|
functionName: functionName2,
|
|
14934
|
-
componentPath: componentPath ?? ""
|
|
15189
|
+
componentPath: target.componentPath ?? ""
|
|
14935
15190
|
});
|
|
14936
15191
|
const argsString = JSON.stringify(convexToJson([args]));
|
|
14937
|
-
if (
|
|
15192
|
+
if (resolvedType === "query") {
|
|
14938
15193
|
return withTraceSpan("udf.invoke_query", "runtime", async () => JSON.parse(await fn.invokeQuery(argsString)), { moduleName, functionName: functionName2 });
|
|
14939
15194
|
}
|
|
14940
|
-
if (
|
|
15195
|
+
if (resolvedType === "mutation") {
|
|
14941
15196
|
return withTraceSpan("udf.invoke_mutation", "runtime", async () => JSON.parse(await fn.invokeMutation(argsString)), { moduleName, functionName: functionName2 });
|
|
14942
15197
|
}
|
|
14943
|
-
if (
|
|
15198
|
+
if (resolvedType === "action") {
|
|
14944
15199
|
return withTraceSpan("udf.invoke_action", "runtime", async () => JSON.parse(await fn.invokeAction(finalRequestId, argsString)), { moduleName, functionName: functionName2 });
|
|
14945
15200
|
}
|
|
14946
15201
|
throw new Error(`Function "${functionName2}" has no valid type`);
|
|
@@ -14950,15 +15205,15 @@ class InlineUdfExecutor {
|
|
|
14950
15205
|
type: udfType,
|
|
14951
15206
|
docstore: this.docstore,
|
|
14952
15207
|
fn: invokeUdf,
|
|
14953
|
-
auth,
|
|
15208
|
+
auth: executionAuth.executorAuth,
|
|
14954
15209
|
storage: this.blobstore,
|
|
14955
15210
|
searchstore: this.searchstore,
|
|
14956
15211
|
vecstore: this.vecstore,
|
|
14957
15212
|
requestId: finalRequestId,
|
|
14958
15213
|
udfExecutor: this,
|
|
14959
|
-
componentPath,
|
|
15214
|
+
componentPath: target.componentPath,
|
|
14960
15215
|
snapshotOverride: udfType === "query" ? snapshotTimestamp : undefined,
|
|
14961
|
-
functionPath,
|
|
15216
|
+
functionPath: target.path,
|
|
14962
15217
|
tableRegistry: this.tableRegistry
|
|
14963
15218
|
});
|
|
14964
15219
|
};
|
|
@@ -14969,7 +15224,7 @@ class InlineUdfExecutor {
|
|
|
14969
15224
|
const duration = performance.now() - startTime;
|
|
14970
15225
|
const logEntry = {
|
|
14971
15226
|
timestamp: Date.now(),
|
|
14972
|
-
functionName:
|
|
15227
|
+
functionName: target.path,
|
|
14973
15228
|
functionType: udfType,
|
|
14974
15229
|
status: "success",
|
|
14975
15230
|
duration: Math.round(duration * 100) / 100,
|
|
@@ -15028,6 +15283,7 @@ class InlineUdfExecutor {
|
|
|
15028
15283
|
}
|
|
15029
15284
|
const runHttpUdf = () => resolvedRoute.handler.invokeHttpAction(request);
|
|
15030
15285
|
const finalRequestId = requestId ?? this.requestIdFactory("http", `${request.method}:${url.pathname}`);
|
|
15286
|
+
const executionAuth = resolveExecutionAuth(auth);
|
|
15031
15287
|
const functionPath = `${request.method} ${url.pathname}`;
|
|
15032
15288
|
const startTime = performance.now();
|
|
15033
15289
|
const recordHttpExecution = (status, extra) => {
|
|
@@ -15057,9 +15313,9 @@ class InlineUdfExecutor {
|
|
|
15057
15313
|
try {
|
|
15058
15314
|
const response = await this.withAmbientAuth(auth, async () => {
|
|
15059
15315
|
if (!this.moduleRegistry) {
|
|
15060
|
-
return runUdfHttpAction(this.docstore, runHttpUdf,
|
|
15316
|
+
return runUdfHttpAction(this.docstore, runHttpUdf, executionAuth.executorAuth, this.blobstore, this.searchstore, this.vecstore, finalRequestId, this, resolvedRoute.componentPath);
|
|
15061
15317
|
}
|
|
15062
|
-
return withModuleRegistry(this.moduleRegistry, () => runUdfHttpAction(this.docstore, runHttpUdf,
|
|
15318
|
+
return withModuleRegistry(this.moduleRegistry, () => runUdfHttpAction(this.docstore, runHttpUdf, executionAuth.executorAuth, this.blobstore, this.searchstore, this.vecstore, finalRequestId, this, resolvedRoute.componentPath));
|
|
15063
15319
|
});
|
|
15064
15320
|
recordHttpExecution("success", { statusCode: response.status });
|
|
15065
15321
|
return response;
|
|
@@ -15153,23 +15409,21 @@ class InlineUdfExecutor {
|
|
|
15153
15409
|
}
|
|
15154
15410
|
}
|
|
15155
15411
|
parseUdfPath(functionPath) {
|
|
15156
|
-
const
|
|
15157
|
-
|
|
15158
|
-
throw new Error(`Invalid UDF path: ${functionPath}`);
|
|
15159
|
-
}
|
|
15160
|
-
return [parts[0], parts[1]];
|
|
15412
|
+
const target = normalizeUdfFunctionTarget(functionPath);
|
|
15413
|
+
return [target.modulePath, target.exportName];
|
|
15161
15414
|
}
|
|
15162
15415
|
assertFunctionExport(functionName2, moduleName, fn, udfType, auth) {
|
|
15163
15416
|
if (typeof fn !== "function") {
|
|
15164
15417
|
throw new Error(`Function "${functionName2}" not found in module "${moduleName}"`);
|
|
15165
15418
|
}
|
|
15166
|
-
|
|
15419
|
+
const actualType = classifyUdfFunction(fn);
|
|
15420
|
+
if (udfType === "query" && actualType !== "query") {
|
|
15167
15421
|
throw new Error(`Function "${functionName2}" is not a query`);
|
|
15168
15422
|
}
|
|
15169
|
-
if (udfType === "mutation" &&
|
|
15423
|
+
if (udfType === "mutation" && actualType !== "mutation") {
|
|
15170
15424
|
throw new Error(`Function "${functionName2}" is not a mutation`);
|
|
15171
15425
|
}
|
|
15172
|
-
if (udfType === "action" &&
|
|
15426
|
+
if (udfType === "action" && actualType !== "action") {
|
|
15173
15427
|
throw new Error(`Function "${functionName2}" is not an action`);
|
|
15174
15428
|
}
|
|
15175
15429
|
if (fn.isInternal) {
|
|
@@ -15180,6 +15434,7 @@ class InlineUdfExecutor {
|
|
|
15180
15434
|
throw new InternalFunctionAccessError(functionPath);
|
|
15181
15435
|
}
|
|
15182
15436
|
}
|
|
15437
|
+
return udfType;
|
|
15183
15438
|
}
|
|
15184
15439
|
async validateArgs(fn, args, componentPath) {
|
|
15185
15440
|
const callContext2 = getCallContext();
|
|
@@ -15339,7 +15594,7 @@ init_analysis();
|
|
|
15339
15594
|
init_module_loader();
|
|
15340
15595
|
// ../core/dist/udf/execution-adapter.js
|
|
15341
15596
|
init_auth_context();
|
|
15342
|
-
|
|
15597
|
+
init_execution_auth();
|
|
15343
15598
|
// ../core/dist/http/api-router.js
|
|
15344
15599
|
init_auth();
|
|
15345
15600
|
init_auth_resolver();
|
|
@@ -15776,7 +16031,7 @@ class ScheduledFunctionExecutor {
|
|
|
15776
16031
|
return [];
|
|
15777
16032
|
}
|
|
15778
16033
|
const tables = new Set;
|
|
15779
|
-
for await (const entry of this.docstore.
|
|
16034
|
+
for await (const entry of this.docstore.loadDocuments({
|
|
15780
16035
|
min_timestamp_inclusive: sinceExclusive + 1n,
|
|
15781
16036
|
max_timestamp_exclusive: maxTimestamp + 1n
|
|
15782
16037
|
}, Order.Asc)) {
|
|
@@ -16454,10 +16709,10 @@ class BaseSqliteDocStore {
|
|
|
16454
16709
|
}
|
|
16455
16710
|
}
|
|
16456
16711
|
}
|
|
16457
|
-
async
|
|
16712
|
+
async indexScanRows(indexId, tableId, readTimestamp, interval, order, limit) {
|
|
16458
16713
|
return this.scanIndexRows(indexId, tableId, readTimestamp, interval, order, limit);
|
|
16459
16714
|
}
|
|
16460
|
-
async
|
|
16715
|
+
async indexScanRowsAfterKey(indexId, tableId, readTimestamp, interval, order, resumeAfterKey, limit) {
|
|
16461
16716
|
return this.scanIndexRows(indexId, tableId, readTimestamp, interval, order, limit, resumeAfterKey);
|
|
16462
16717
|
}
|
|
16463
16718
|
async scanIndexRows(indexId, tableId, readTimestamp, interval, order, limit, resumeAfterKey) {
|
|
@@ -16559,13 +16814,13 @@ class BaseSqliteDocStore {
|
|
|
16559
16814
|
}
|
|
16560
16815
|
return results;
|
|
16561
16816
|
}
|
|
16562
|
-
async*
|
|
16563
|
-
const rows = await this.
|
|
16817
|
+
async* indexScan(indexId, tabletId, readTimestamp, interval, order, limit) {
|
|
16818
|
+
const rows = await this.indexScanRows(indexId, tabletId, readTimestamp, interval, order, limit);
|
|
16564
16819
|
for (const row of rows) {
|
|
16565
16820
|
yield row;
|
|
16566
16821
|
}
|
|
16567
16822
|
}
|
|
16568
|
-
async*
|
|
16823
|
+
async* loadDocuments(range, order) {
|
|
16569
16824
|
const orderClause = order === Order.Asc ? "ASC" : "DESC";
|
|
16570
16825
|
const query = `
|
|
16571
16826
|
SELECT id, ts, table_id, json_value, deleted, prev_ts
|
|
@@ -16603,7 +16858,7 @@ class BaseSqliteDocStore {
|
|
|
16603
16858
|
const rows = await stmt.all(key, JSON.stringify(value));
|
|
16604
16859
|
return rows.length > 0;
|
|
16605
16860
|
}
|
|
16606
|
-
async
|
|
16861
|
+
async previousRevisions(queries) {
|
|
16607
16862
|
const results = new Map;
|
|
16608
16863
|
const stmt = this.getPreparedStatement(`
|
|
16609
16864
|
SELECT ts, json_value, deleted, prev_ts
|
|
@@ -16628,7 +16883,7 @@ class BaseSqliteDocStore {
|
|
|
16628
16883
|
}
|
|
16629
16884
|
return results;
|
|
16630
16885
|
}
|
|
16631
|
-
async
|
|
16886
|
+
async previousRevisionsOfDocuments(queries) {
|
|
16632
16887
|
const results = new Map;
|
|
16633
16888
|
const stmt = this.getPreparedStatement(`
|
|
16634
16889
|
SELECT ts, json_value, deleted, prev_ts
|
|
@@ -16685,7 +16940,7 @@ class BaseSqliteDocStore {
|
|
|
16685
16940
|
prev_ts: row.prev_ts != null ? BigInt(row.prev_ts) : null
|
|
16686
16941
|
};
|
|
16687
16942
|
}
|
|
16688
|
-
async
|
|
16943
|
+
async getMany(ids, readTimestamp) {
|
|
16689
16944
|
const results = new Map;
|
|
16690
16945
|
if (ids.length === 0) {
|
|
16691
16946
|
return results;
|