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