@concavejs/docstore-bun-sqlite 0.0.1-alpha.10 → 0.0.1-alpha.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +1072 -490
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -14,7 +14,6 @@ var __export = (target, all) => {
14
14
  });
15
15
  };
16
16
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
17
- var __require = import.meta.require;
18
17
 
19
18
  // ../../node_modules/convex/dist/esm/values/base64.js
20
19
  function getLens(b64) {
@@ -802,6 +801,237 @@ var init_values = __esm(() => {
802
801
  init_errors();
803
802
  });
804
803
 
804
+ // ../core/dist/id-codec/base32.js
805
+ function base32Encode(data) {
806
+ if (data.length === 0)
807
+ return "";
808
+ let result = "";
809
+ let buffer = 0;
810
+ let bitsLeft = 0;
811
+ for (const byte of data) {
812
+ buffer = buffer << 8 | byte;
813
+ bitsLeft += 8;
814
+ while (bitsLeft >= 5) {
815
+ bitsLeft -= 5;
816
+ const index = buffer >> bitsLeft & 31;
817
+ result += ALPHABET[index];
818
+ }
819
+ }
820
+ if (bitsLeft > 0) {
821
+ const index = buffer << 5 - bitsLeft & 31;
822
+ result += ALPHABET[index];
823
+ }
824
+ return result;
825
+ }
826
+ function base32Decode(str) {
827
+ if (str.length === 0)
828
+ return new Uint8Array(0);
829
+ const outputLength = Math.floor(str.length * 5 / 8);
830
+ const result = new Uint8Array(outputLength);
831
+ let buffer = 0;
832
+ let bitsLeft = 0;
833
+ let outputIndex = 0;
834
+ for (const char of str) {
835
+ const value = ALPHABET_MAP.get(char);
836
+ if (value === undefined) {
837
+ throw new Error(`Invalid base32 character: ${char}`);
838
+ }
839
+ buffer = buffer << 5 | value;
840
+ bitsLeft += 5;
841
+ if (bitsLeft >= 8) {
842
+ bitsLeft -= 8;
843
+ result[outputIndex++] = buffer >> bitsLeft & 255;
844
+ }
845
+ }
846
+ return result;
847
+ }
848
+ function isValidBase32(str) {
849
+ for (const char of str) {
850
+ if (!ALPHABET_MAP.has(char)) {
851
+ return false;
852
+ }
853
+ }
854
+ return true;
855
+ }
856
+ var ALPHABET = "0123456789abcdefghjkmnpqrstvwxyz", ALPHABET_MAP;
857
+ var init_base32 = __esm(() => {
858
+ ALPHABET_MAP = new Map;
859
+ for (let i2 = 0;i2 < ALPHABET.length; i2++) {
860
+ ALPHABET_MAP.set(ALPHABET[i2], i2);
861
+ ALPHABET_MAP.set(ALPHABET[i2].toUpperCase(), i2);
862
+ }
863
+ ALPHABET_MAP.set("i", 1);
864
+ ALPHABET_MAP.set("I", 1);
865
+ ALPHABET_MAP.set("l", 1);
866
+ ALPHABET_MAP.set("L", 1);
867
+ ALPHABET_MAP.set("o", 0);
868
+ ALPHABET_MAP.set("O", 0);
869
+ });
870
+
871
+ // ../core/dist/id-codec/vint.js
872
+ function vintEncode(value) {
873
+ if (value < 0) {
874
+ throw new Error("VInt cannot encode negative numbers");
875
+ }
876
+ if (value > 4294967295) {
877
+ throw new Error("VInt cannot encode values larger than 2^32-1");
878
+ }
879
+ value = value >>> 0;
880
+ if (value < 128) {
881
+ return new Uint8Array([value]);
882
+ }
883
+ if (value < 16512) {
884
+ const adjusted2 = value - 128;
885
+ return new Uint8Array([128 | adjusted2 >> 8 & 63, adjusted2 & 255]);
886
+ }
887
+ if (value < 2113664) {
888
+ const adjusted2 = value - 16512;
889
+ return new Uint8Array([192 | adjusted2 >> 16 & 31, adjusted2 >> 8 & 255, adjusted2 & 255]);
890
+ }
891
+ if (value < 270549120) {
892
+ const adjusted2 = value - 2113664;
893
+ return new Uint8Array([
894
+ 224 | adjusted2 >> 24 & 15,
895
+ adjusted2 >> 16 & 255,
896
+ adjusted2 >> 8 & 255,
897
+ adjusted2 & 255
898
+ ]);
899
+ }
900
+ const adjusted = value - 270549120;
901
+ return new Uint8Array([
902
+ 240 | adjusted >> 32 & 7,
903
+ adjusted >> 24 & 255,
904
+ adjusted >> 16 & 255,
905
+ adjusted >> 8 & 255,
906
+ adjusted & 255
907
+ ]);
908
+ }
909
+ function vintDecode(data, offset = 0) {
910
+ if (offset >= data.length) {
911
+ throw new Error("VInt decode: unexpected end of data");
912
+ }
913
+ const first = data[offset];
914
+ if ((first & 128) === 0) {
915
+ return { value: first, bytesRead: 1 };
916
+ }
917
+ if ((first & 192) === 128) {
918
+ if (offset + 1 >= data.length) {
919
+ throw new Error("VInt decode: truncated 2-byte encoding");
920
+ }
921
+ const value = 128 + ((first & 63) << 8 | data[offset + 1]);
922
+ return { value, bytesRead: 2 };
923
+ }
924
+ if ((first & 224) === 192) {
925
+ if (offset + 2 >= data.length) {
926
+ throw new Error("VInt decode: truncated 3-byte encoding");
927
+ }
928
+ const value = 16512 + ((first & 31) << 16 | data[offset + 1] << 8 | data[offset + 2]);
929
+ return { value, bytesRead: 3 };
930
+ }
931
+ if ((first & 240) === 224) {
932
+ if (offset + 3 >= data.length) {
933
+ throw new Error("VInt decode: truncated 4-byte encoding");
934
+ }
935
+ const value = 2113664 + ((first & 15) << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3]);
936
+ return { value: value >>> 0, bytesRead: 4 };
937
+ }
938
+ if ((first & 248) === 240) {
939
+ if (offset + 4 >= data.length) {
940
+ throw new Error("VInt decode: truncated 5-byte encoding");
941
+ }
942
+ const high = first & 7;
943
+ const low = (data[offset + 1] << 24 | data[offset + 2] << 16 | data[offset + 3] << 8 | data[offset + 4]) >>> 0;
944
+ const value = 270549120 + high * 4294967296 + low;
945
+ return { value: value >>> 0, bytesRead: 5 };
946
+ }
947
+ throw new Error("VInt decode: invalid prefix");
948
+ }
949
+
950
+ // ../core/dist/id-codec/fletcher16.js
951
+ function fletcher16(data) {
952
+ let sum1 = 0;
953
+ let sum2 = 0;
954
+ for (const byte of data) {
955
+ sum1 = (sum1 + byte) % 255;
956
+ sum2 = (sum2 + sum1) % 255;
957
+ }
958
+ return new Uint8Array([sum1, sum2]);
959
+ }
960
+ function verifyFletcher16(data, checksum) {
961
+ if (checksum.length !== 2)
962
+ return false;
963
+ const computed = fletcher16(data);
964
+ return computed[0] === checksum[0] && computed[1] === checksum[1];
965
+ }
966
+
967
+ // ../core/dist/utils/crypto.js
968
+ var weakRandomState;
969
+ var init_crypto = __esm(() => {
970
+ weakRandomState = (Date.now() ^ 2654435769) >>> 0;
971
+ });
972
+
973
+ // ../core/dist/id-codec/document-id.js
974
+ function encodeDocumentId(tableNumber, internalId) {
975
+ if (internalId.length !== INTERNAL_ID_LENGTH) {
976
+ throw new Error(`Internal ID must be exactly ${INTERNAL_ID_LENGTH} bytes, got ${internalId.length}`);
977
+ }
978
+ if (tableNumber < 1 || tableNumber > 4294967295) {
979
+ throw new Error(`Table number must be between 1 and 2^32-1, got ${tableNumber}`);
980
+ }
981
+ const tableBytes = vintEncode(tableNumber);
982
+ const payload = new Uint8Array(tableBytes.length + INTERNAL_ID_LENGTH);
983
+ payload.set(tableBytes, 0);
984
+ payload.set(internalId, tableBytes.length);
985
+ const checksum = fletcher16(payload);
986
+ const final = new Uint8Array(payload.length + 2);
987
+ final.set(payload, 0);
988
+ final.set(checksum, payload.length);
989
+ return base32Encode(final);
990
+ }
991
+ function decodeDocumentId(encoded) {
992
+ if (encoded.length < MIN_ENCODED_LENGTH || encoded.length > MAX_ENCODED_LENGTH) {
993
+ throw new Error(`Invalid document ID length: ${encoded.length} (expected ${MIN_ENCODED_LENGTH}-${MAX_ENCODED_LENGTH})`);
994
+ }
995
+ if (!isValidBase32(encoded)) {
996
+ throw new Error("Invalid document ID: contains invalid base32 characters");
997
+ }
998
+ const bytes = base32Decode(encoded);
999
+ if (bytes.length < 19) {
1000
+ throw new Error(`Invalid document ID: decoded to ${bytes.length} bytes (minimum 19)`);
1001
+ }
1002
+ const checksum = bytes.slice(bytes.length - 2);
1003
+ const payload = bytes.slice(0, bytes.length - 2);
1004
+ if (!verifyFletcher16(payload, checksum)) {
1005
+ throw new Error("Invalid document ID: checksum verification failed");
1006
+ }
1007
+ const { value: tableNumber, bytesRead } = vintDecode(payload, 0);
1008
+ const internalId = payload.slice(bytesRead, bytesRead + INTERNAL_ID_LENGTH);
1009
+ if (internalId.length !== INTERNAL_ID_LENGTH) {
1010
+ throw new Error(`Invalid document ID: internal ID is ${internalId.length} bytes (expected ${INTERNAL_ID_LENGTH})`);
1011
+ }
1012
+ return { tableNumber, internalId };
1013
+ }
1014
+ function isValidDocumentId(encoded) {
1015
+ try {
1016
+ decodeDocumentId(encoded);
1017
+ return true;
1018
+ } catch {
1019
+ return false;
1020
+ }
1021
+ }
1022
+ function internalIdToHex(internalId) {
1023
+ let hex = "";
1024
+ for (let i2 = 0;i2 < internalId.length; i2++) {
1025
+ hex += internalId[i2].toString(16).padStart(2, "0");
1026
+ }
1027
+ return hex;
1028
+ }
1029
+ var INTERNAL_ID_LENGTH = 16, MIN_ENCODED_LENGTH = 31, MAX_ENCODED_LENGTH = 37;
1030
+ var init_document_id = __esm(() => {
1031
+ init_base32();
1032
+ init_crypto();
1033
+ });
1034
+
805
1035
  // ../core/dist/utils/utils.js
806
1036
  function hexToArrayBuffer(hex) {
807
1037
  if (hex === "") {
@@ -840,9 +1070,15 @@ function deserializeDeveloperId(developerId) {
840
1070
  return null;
841
1071
  }
842
1072
  var DOC_ID_SEPARATOR = ":", LEGACY_DOC_ID_SEPARATOR = ";";
1073
+ var init_utils = __esm(() => {
1074
+ init_document_id();
1075
+ });
843
1076
 
844
1077
  // ../core/dist/tables/interface.js
845
1078
  function getFullTableName(tableName, componentPath) {
1079
+ if (isSystemTable(tableName)) {
1080
+ return tableName;
1081
+ }
846
1082
  if (!componentPath || componentPath === "") {
847
1083
  return tableName;
848
1084
  }
@@ -859,23 +1095,28 @@ function parseFullTableName(fullName) {
859
1095
  };
860
1096
  }
861
1097
  function isSystemTable(tableName) {
862
- return tableName.startsWith("_");
1098
+ return Object.hasOwn(SYSTEM_TABLE_NUMBERS, tableName);
863
1099
  }
864
- var SYSTEM_TABLE_NUMBERS, FIRST_USER_TABLE_NUMBER = 100;
1100
+ var SYSTEM_TABLE_NUMBERS, FIRST_USER_TABLE_NUMBER = 10001;
865
1101
  var init_interface = __esm(() => {
866
1102
  SYSTEM_TABLE_NUMBERS = {
867
1103
  _tables: 1,
868
1104
  _scheduled_functions: 2,
869
1105
  _storage: 3,
870
- _crons: 4
1106
+ _crons: 4,
1107
+ _indexes: 5,
1108
+ _schemas: 6,
1109
+ _components: 7,
1110
+ _component_definitions: 8,
1111
+ _schema_validation_progress: 9
871
1112
  };
872
1113
  });
873
1114
 
874
1115
  // ../core/dist/kernel/context-storage.js
875
- function resolveFromRequire(req) {
1116
+ function resolveFromModuleResolver(resolveModule) {
876
1117
  for (const specifier of ["node:async_hooks", "async_hooks"]) {
877
1118
  try {
878
- const mod = req(specifier);
1119
+ const mod = resolveModule(specifier);
879
1120
  if (mod?.AsyncLocalStorage) {
880
1121
  return mod.AsyncLocalStorage;
881
1122
  }
@@ -918,16 +1159,16 @@ var resolveAsyncLocalStorage = () => {
918
1159
  if (globalCtor) {
919
1160
  return globalCtor;
920
1161
  }
921
- const runtimeRequire = __require;
922
- if (runtimeRequire) {
923
- const ctor = resolveFromRequire(runtimeRequire);
1162
+ const getBuiltinModule = globalThis?.process?.getBuiltinModule;
1163
+ if (typeof getBuiltinModule === "function") {
1164
+ const ctor = resolveFromModuleResolver((specifier) => getBuiltinModule(specifier));
924
1165
  if (ctor) {
925
1166
  return ctor;
926
1167
  }
927
1168
  }
928
1169
  const globalRequire = globalThis?.require;
929
1170
  if (typeof globalRequire === "function") {
930
- return resolveFromRequire(globalRequire);
1171
+ return resolveFromModuleResolver(globalRequire);
931
1172
  }
932
1173
  return;
933
1174
  }, AsyncLocalStorageCtor;
@@ -2212,7 +2453,7 @@ async function listSystemFunctions(options = {}) {
2212
2453
  }
2213
2454
  for (const route of httpRoutes) {
2214
2455
  const method = route.route.method;
2215
- const routePath = route.route.path;
2456
+ const routePath = mountHttpRoutePath(route.route.path, owningComponent);
2216
2457
  results.push({
2217
2458
  name: `${method} ${routePath}`,
2218
2459
  module: listing.path,
@@ -2274,6 +2515,16 @@ async function loadAndAnalyzeModule(listing, componentPath) {
2274
2515
  function makeCacheKey(componentPath, modulePath) {
2275
2516
  return `${componentPath ?? ""}::${modulePath}`;
2276
2517
  }
2518
+ function mountHttpRoutePath(routePath, componentPath) {
2519
+ if (!componentPath) {
2520
+ return routePath;
2521
+ }
2522
+ const prefix = `/${componentPath}`;
2523
+ if (routePath === "/") {
2524
+ return prefix;
2525
+ }
2526
+ return `${prefix}${routePath}`;
2527
+ }
2277
2528
  function buildFallbackSourcePath(modulePath) {
2278
2529
  const trimmed = modulePath.replace(/\\/g, "/").replace(/^\//, "");
2279
2530
  const withConvex = trimmed.startsWith("convex/") ? trimmed : `convex/${trimmed}`;
@@ -3960,6 +4211,7 @@ var init_remote = __esm(() => {
3960
4211
  // ../../node_modules/jose/dist/webapi/index.js
3961
4212
  var init_webapi = __esm(() => {
3962
4213
  init_verify4();
4214
+ init_local();
3963
4215
  init_remote();
3964
4216
  init_errors2();
3965
4217
  });
@@ -4164,7 +4416,7 @@ function getRemoteJwks(jwksUrl, config) {
4164
4416
  if (cached) {
4165
4417
  JWKS_CACHE.delete(jwksUrl);
4166
4418
  }
4167
- const jwks = createRemoteJWKSet(new URL(jwksUrl));
4419
+ const jwks = jwksUrl.startsWith("data:") ? createLocalJWKSet(parseDataUriJson(jwksUrl)) : createRemoteJWKSet(new URL(jwksUrl));
4168
4420
  const configuredTtl = config?.jwksCacheTtlMs;
4169
4421
  const ttlMs = resolveJwksCacheTtlMs(configuredTtl);
4170
4422
  JWKS_CACHE.set(jwksUrl, {
@@ -4173,6 +4425,24 @@ function getRemoteJwks(jwksUrl, config) {
4173
4425
  });
4174
4426
  return jwks;
4175
4427
  }
4428
+ function parseDataUriJson(dataUri) {
4429
+ const match = /^data:([^;,]+)?(?:;charset=[^;,]+)?(;base64)?,(.*)$/i.exec(dataUri);
4430
+ if (!match) {
4431
+ throw new JWTValidationError("INVALID_TOKEN", "Invalid JWKS data URI");
4432
+ }
4433
+ const [, , isBase64, payload] = match;
4434
+ const jsonText = isBase64 ? decodeBase642(payload) : decodeURIComponent(payload);
4435
+ return JSON.parse(jsonText);
4436
+ }
4437
+ function decodeBase642(value) {
4438
+ if (typeof Buffer !== "undefined") {
4439
+ return Buffer.from(value, "base64").toString("utf8");
4440
+ }
4441
+ if (typeof atob === "function") {
4442
+ return new TextDecoder().decode(Uint8Array.from(atob(value), (char) => char.charCodeAt(0)));
4443
+ }
4444
+ throw new JWTValidationError("INVALID_TOKEN", "Base64 decoding is unavailable");
4445
+ }
4176
4446
  function resolveJwksCacheTtlMs(configuredTtl) {
4177
4447
  if (configuredTtl === undefined) {
4178
4448
  return DEFAULT_JWKS_CACHE_TTL_MS;
@@ -4207,6 +4477,7 @@ async function verifyJwt(token, config) {
4207
4477
  const options = {
4208
4478
  issuer: effectiveConfig.issuer,
4209
4479
  audience: effectiveConfig.audience,
4480
+ algorithms: effectiveConfig.algorithms,
4210
4481
  clockTolerance: effectiveConfig.clockTolerance ?? DEFAULT_CLOCK_TOLERANCE_SECONDS
4211
4482
  };
4212
4483
  let payload;
@@ -4276,11 +4547,20 @@ var init_jwt = __esm(() => {
4276
4547
  function getPrincipal() {
4277
4548
  return principalContext.getStore();
4278
4549
  }
4279
- var authContext, principalContext;
4550
+ var AUTH_CONTEXT_SYMBOL, PRINCIPAL_CONTEXT_SYMBOL, globalAuthContext, authContext, principalContext;
4280
4551
  var init_auth_context = __esm(() => {
4281
4552
  init_context_storage();
4282
- authContext = new ContextStorage;
4283
- principalContext = new ContextStorage;
4553
+ AUTH_CONTEXT_SYMBOL = Symbol.for("@concavejs/core/auth-context");
4554
+ PRINCIPAL_CONTEXT_SYMBOL = Symbol.for("@concavejs/core/principal-context");
4555
+ globalAuthContext = globalThis;
4556
+ authContext = globalAuthContext[AUTH_CONTEXT_SYMBOL] ?? new ContextStorage;
4557
+ principalContext = globalAuthContext[PRINCIPAL_CONTEXT_SYMBOL] ?? new ContextStorage;
4558
+ if (!globalAuthContext[AUTH_CONTEXT_SYMBOL]) {
4559
+ globalAuthContext[AUTH_CONTEXT_SYMBOL] = authContext;
4560
+ }
4561
+ if (!globalAuthContext[PRINCIPAL_CONTEXT_SYMBOL]) {
4562
+ globalAuthContext[PRINCIPAL_CONTEXT_SYMBOL] = principalContext;
4563
+ }
4284
4564
  });
4285
4565
 
4286
4566
  // ../core/dist/auth/principal.js
@@ -4755,47 +5035,231 @@ var init_auth = __esm(() => {
4755
5035
  init_auth_config_service();
4756
5036
  });
4757
5037
 
4758
- // ../core/dist/system/internal.js
4759
- function requireSystemCapability(capability) {
4760
- const principal2 = getPrincipal();
4761
- if (!principal2) {
4762
- throw new Error("System functions require authentication context");
4763
- }
4764
- requireAuthorization(principal2, { kind: "management_operation", capability });
4765
- }
4766
- function createSystemFunctions(deps) {
4767
- const { query, mutation } = deps;
5038
+ // ../core/dist/components/manifest.js
5039
+ var COMPONENT_MANIFEST_SYMBOL;
5040
+ var init_manifest = __esm(() => {
5041
+ COMPONENT_MANIFEST_SYMBOL = Symbol.for("concave.componentManifest");
5042
+ });
5043
+
5044
+ // ../core/dist/id-codec/index.js
5045
+ var init_id_codec = __esm(() => {
5046
+ init_base32();
5047
+ init_document_id();
5048
+ });
5049
+
5050
+ // ../core/dist/system/system-tables.js
5051
+ function getSystemTableDefinition(name) {
5052
+ return SYSTEM_TABLE_DEFINITIONS.find((definition) => definition.name === name) ?? null;
5053
+ }
5054
+ function isPublicSystemTable(name) {
5055
+ return getSystemTableDefinition(name)?.visibility === "public";
5056
+ }
5057
+ function createTableInfo(name, tableNumber, componentPath = "", options = {}) {
5058
+ const fullName = getFullTableName(name, componentPath);
5059
+ return {
5060
+ tableNumber,
5061
+ name,
5062
+ componentPath: isSystemTableName(name) ? "" : componentPath,
5063
+ fullName,
5064
+ isSystem: options.isSystem ?? isSystemTableName(name),
5065
+ visibility: options.visibility ?? (isPublicSystemTable(name) ? "public" : "private"),
5066
+ state: "active",
5067
+ createdAt: options.createdAt ?? Date.now()
5068
+ };
5069
+ }
5070
+ function getReservedSystemTables() {
5071
+ return SYSTEM_TABLE_DEFINITIONS.map((definition) => createTableInfo(definition.name, SYSTEM_TABLE_NUMBERS[definition.name], "", {
5072
+ isSystem: true,
5073
+ visibility: definition.visibility
5074
+ }));
5075
+ }
5076
+ function tableInfoFromStoredDocument(value) {
5077
+ if (!value) {
5078
+ return null;
5079
+ }
5080
+ const name = typeof value.name === "string" ? value.name : null;
5081
+ const tableNumber = typeof value.tableNumber === "number" ? value.tableNumber : null;
5082
+ if (!name || !tableNumber) {
5083
+ return null;
5084
+ }
5085
+ const componentPath = typeof value.componentPath === "string" ? value.componentPath : "";
5086
+ const fullName = typeof value.fullName === "string" ? value.fullName : getFullTableName(name, componentPath);
5087
+ return {
5088
+ tableNumber,
5089
+ name,
5090
+ componentPath,
5091
+ fullName,
5092
+ isSystem: value.isSystem === true,
5093
+ visibility: value.visibility === "private" ? "private" : "public",
5094
+ state: "active",
5095
+ createdAt: typeof value.createdAt === "number" ? value.createdAt : Date.now()
5096
+ };
5097
+ }
5098
+ function nextUserTableNumber(tables) {
5099
+ let next = FIRST_USER_TABLE_NUMBER;
5100
+ for (const table of tables) {
5101
+ if (table.tableNumber >= next) {
5102
+ next = table.tableNumber + 1;
5103
+ }
5104
+ }
5105
+ return next;
5106
+ }
5107
+ function createSystemMetadata(partial) {
5108
+ const now = partial?.updatedAt ?? Date.now();
5109
+ return {
5110
+ version: 1,
5111
+ bootstrapped: true,
5112
+ tableIdStrategy: "registry_u32",
5113
+ developerIdCodec: "convex_base32",
5114
+ nextUserTableNumber: partial?.nextUserTableNumber ?? FIRST_USER_TABLE_NUMBER,
5115
+ registryVersion: partial?.registryVersion ?? now,
5116
+ runtimeMetadataVersion: partial?.runtimeMetadataVersion,
5117
+ bootstrappedAt: partial?.bootstrappedAt ?? now,
5118
+ updatedAt: now
5119
+ };
5120
+ }
5121
+ async function readSystemMetadata(docstore) {
5122
+ const metadata = await docstore.getGlobal(SYSTEM_METADATA_GLOBAL_KEY);
5123
+ if (!metadata || metadata.bootstrapped !== true || metadata.version !== 1) {
5124
+ return null;
5125
+ }
5126
+ return createSystemMetadata({
5127
+ nextUserTableNumber: metadata.nextUserTableNumber,
5128
+ registryVersion: metadata.registryVersion ?? metadata.updatedAt,
5129
+ runtimeMetadataVersion: metadata.runtimeMetadataVersion,
5130
+ bootstrappedAt: metadata.bootstrappedAt,
5131
+ updatedAt: metadata.updatedAt
5132
+ });
5133
+ }
5134
+ function createTableNumberReservationKey(tableNumber) {
5135
+ return `${TABLE_NUMBER_RESERVATION_GLOBAL_PREFIX}${tableNumber}`;
5136
+ }
5137
+ async function ensureSystemTablesBootstrapped(docstore) {
5138
+ const existingMetadata = await readSystemMetadata(docstore);
5139
+ if (existingMetadata?.version === 1 && existingMetadata.bootstrapped) {
5140
+ return;
5141
+ }
5142
+ const now = Date.now();
5143
+ const tableInfos = getReservedSystemTables();
5144
+ const existingEntries = await docstore.scan(stringToHex("_tables"));
5145
+ const existingByName = new Map;
5146
+ for (const entry of existingEntries) {
5147
+ const info = tableInfoFromStoredDocument(entry.value.value);
5148
+ if (info) {
5149
+ existingByName.set(info.fullName, info);
5150
+ }
5151
+ }
5152
+ const docs = [];
5153
+ const oracle = docstore.timestampOracle;
5154
+ const allocateTimestamp = oracle?.allocateTimestamp?.bind(oracle) ?? (() => BigInt(Date.now()));
5155
+ for (const table of tableInfos) {
5156
+ const existing = existingByName.get(table.fullName);
5157
+ const createdAt = existing?.createdAt ?? now;
5158
+ docs.push(createTableMetadataEntry(table, allocateTimestamp(), createdAt));
5159
+ }
5160
+ if (docs.length > 0) {
5161
+ await docstore.write(docs, new Set, "Overwrite");
5162
+ }
5163
+ const metadata = createSystemMetadata({
5164
+ nextUserTableNumber: nextUserTableNumber([...tableInfos, ...existingByName.values()]),
5165
+ registryVersion: now,
5166
+ bootstrappedAt: existingMetadata?.bootstrappedAt ?? now,
5167
+ updatedAt: now
5168
+ });
5169
+ await docstore.writeGlobal(SYSTEM_METADATA_GLOBAL_KEY, metadata);
5170
+ }
5171
+ function createTableMetadataEntryForUserTable(table, timestamp2) {
5172
+ return createTableMetadataEntry(table, timestamp2, table.createdAt);
5173
+ }
5174
+ function createTableMetadataEntry(table, timestamp2, createdAt) {
5175
+ const docId = createTableMetadataDocumentId(table.fullName);
5176
+ const developerId = encodeDocumentId(SYSTEM_TABLE_NUMBERS._tables, stableMetadataInternalIdBytes(table.fullName));
5177
+ const storedTable = {
5178
+ _id: developerId,
5179
+ _creationTime: Number(timestamp2),
5180
+ name: table.name,
5181
+ componentPath: table.componentPath,
5182
+ fullName: table.fullName,
5183
+ tableNumber: table.tableNumber,
5184
+ isSystem: table.isSystem,
5185
+ visibility: table.visibility,
5186
+ state: table.state,
5187
+ createdAt
5188
+ };
5189
+ return {
5190
+ ts: timestamp2,
5191
+ id: docId,
5192
+ value: {
5193
+ id: docId,
5194
+ value: storedTable
5195
+ },
5196
+ prev_ts: null
5197
+ };
5198
+ }
5199
+ function createTableMetadataDocumentId(fullTableName) {
5200
+ const internalIdBytes = stableMetadataInternalIdBytes(fullTableName);
5201
+ return {
5202
+ table: stringToHex("_tables"),
5203
+ internalId: internalIdToHex(internalIdBytes),
5204
+ tableNumber: SYSTEM_TABLE_NUMBERS._tables
5205
+ };
5206
+ }
5207
+ function stableMetadataInternalIdBytes(fullTableName) {
5208
+ const bytes = new Uint8Array(16);
5209
+ const input = new TextEncoder().encode(`table:${fullTableName}`);
5210
+ for (let i2 = 0;i2 < input.length; i2 += 1) {
5211
+ const target = i2 % 16;
5212
+ bytes[target] = bytes[target] * 33 + input[i2] & 255;
5213
+ }
5214
+ return bytes;
5215
+ }
5216
+ function isSystemTableName(name) {
5217
+ return Object.hasOwn(SYSTEM_TABLE_NUMBERS, name);
5218
+ }
5219
+ var SYSTEM_METADATA_GLOBAL_KEY = "concave:system_metadata:v1", TABLE_NUMBER_RESERVATION_GLOBAL_PREFIX = "concave:table_number:", SYSTEM_TABLE_DEFINITIONS;
5220
+ var init_system_tables = __esm(() => {
5221
+ init_manifest();
5222
+ init_id_codec();
5223
+ init_interface();
5224
+ init_utils();
5225
+ init_module_loader();
5226
+ SYSTEM_TABLE_DEFINITIONS = [
5227
+ { name: "_tables", visibility: "public" },
5228
+ { name: "_scheduled_functions", visibility: "public" },
5229
+ { name: "_storage", visibility: "public" },
5230
+ { name: "_crons", visibility: "public" },
5231
+ { name: "_indexes", visibility: "private" },
5232
+ { name: "_schemas", visibility: "private" },
5233
+ { name: "_components", visibility: "private" },
5234
+ { name: "_component_definitions", visibility: "private" },
5235
+ { name: "_schema_validation_progress", visibility: "private" }
5236
+ ];
5237
+ });
5238
+
5239
+ // ../core/dist/system/internal.js
5240
+ function requireSystemCapability(capability) {
5241
+ const principal2 = getPrincipal();
5242
+ if (!principal2) {
5243
+ throw new Error("System functions require authentication context");
5244
+ }
5245
+ requireAuthorization(principal2, { kind: "management_operation", capability });
5246
+ }
5247
+ function createSystemFunctions(deps) {
5248
+ const { query, mutation } = deps;
4768
5249
  return {
4769
5250
  systemListComponents: query({
4770
5251
  args: {},
4771
- handler: async (_ctx) => {
5252
+ handler: async (ctx) => {
4772
5253
  requireSystemCapability("components:read");
4773
- const modules = await listRegisteredModules();
4774
- const componentPaths = new Set;
4775
- componentPaths.add("");
4776
- for (const module of modules) {
4777
- if (module.componentPath) {
4778
- componentPaths.add(module.componentPath);
4779
- }
4780
- }
4781
- const components = [];
4782
- for (const path of componentPaths) {
4783
- const componentModules = modules.filter((m) => path === "" ? !m.componentPath || m.componentPath === "" : m.componentPath === path);
4784
- const functions = await listSystemFunctions({ componentPath: path || undefined });
4785
- components.push({
4786
- path: path || "(root)",
4787
- isRoot: path === "",
4788
- moduleCount: componentModules.length,
5254
+ const components = await loadComponentRows(ctx);
5255
+ const withFunctionCounts = await Promise.all(components.map(async (component) => {
5256
+ const functions = await listSystemFunctions({ componentPath: component.componentPath || undefined });
5257
+ return {
5258
+ ...component,
4789
5259
  functionCount: functions.length
4790
- });
4791
- }
4792
- return components.sort((a, b) => {
4793
- if (a.isRoot)
4794
- return -1;
4795
- if (b.isRoot)
4796
- return 1;
4797
- return a.path.localeCompare(b.path);
4798
- });
5260
+ };
5261
+ }));
5262
+ return sortComponentRows(withFunctionCounts);
4799
5263
  }
4800
5264
  }),
4801
5265
  systemListTables: query({
@@ -4804,25 +5268,40 @@ function createSystemFunctions(deps) {
4804
5268
  requireSystemCapability("tables:read");
4805
5269
  const targetComponent = componentPath ?? "";
4806
5270
  const schema2 = await loadSchemaDefinition(targetComponent);
4807
- let tableEntries = [];
5271
+ const schemaTables = new Map;
4808
5272
  if (schema2?.tables) {
4809
- tableEntries = extractTablesFromSchema(schema2);
4810
- } else {
4811
- try {
4812
- const systemTables = await ctx.db.system.query("_tables").collect();
4813
- tableEntries = systemTables.map((table) => ({
4814
- name: table.name,
4815
- exported: {
4816
- indexes: table.indexes || [],
4817
- searchIndexes: table.searchIndexes || [],
4818
- vectorIndexes: table.vectorIndexes || [],
4819
- documentType: null
4820
- }
4821
- }));
4822
- } catch {
4823
- tableEntries = [];
5273
+ for (const table of extractTablesFromSchema(schema2)) {
5274
+ schemaTables.set(table.name, table);
4824
5275
  }
4825
5276
  }
5277
+ const discoveredTables = new Map;
5278
+ for (const name of schemaTables.keys()) {
5279
+ discoveredTables.set(name, {
5280
+ name,
5281
+ isSystem: isSystemTable(name),
5282
+ visibility: getDefaultSystemTableVisibility(name)
5283
+ });
5284
+ }
5285
+ try {
5286
+ const systemTables = await ctx.db.system.query("_tables").collect();
5287
+ discoveredTables.clear();
5288
+ for (const table of systemTables.filter((entry) => (entry.componentPath ?? "") === targetComponent)) {
5289
+ discoveredTables.set(table.name, {
5290
+ name: table.name,
5291
+ isSystem: table.isSystem === true || isSystemTable(table.name),
5292
+ visibility: table.visibility === "private" ? "private" : "public"
5293
+ });
5294
+ }
5295
+ } catch {}
5296
+ const tableEntries = Array.from(discoveredTables.values()).map((metadata) => ({
5297
+ ...metadata,
5298
+ exported: schemaTables.get(metadata.name)?.exported ?? {
5299
+ indexes: [],
5300
+ searchIndexes: [],
5301
+ vectorIndexes: [],
5302
+ documentType: null
5303
+ }
5304
+ }));
4826
5305
  const tableInfo = await Promise.all(tableEntries.map(async (table) => {
4827
5306
  const fullName = getFullTableName(table.name, targetComponent);
4828
5307
  const documentCount = await countDocuments(ctx, fullName);
@@ -4833,6 +5312,8 @@ function createSystemFunctions(deps) {
4833
5312
  name: table.name,
4834
5313
  fullName,
4835
5314
  componentPath: targetComponent || undefined,
5315
+ isSystem: table.isSystem,
5316
+ visibility: table.visibility,
4836
5317
  documentCount,
4837
5318
  indexes: buildIndexList(exported?.indexes),
4838
5319
  searchIndexes: searchIndexes.map((idx) => typeof idx === "string" ? idx : idx.indexDescriptor),
@@ -4866,7 +5347,7 @@ function createSystemFunctions(deps) {
4866
5347
  }
4867
5348
  try {
4868
5349
  const fullName = getFullTableName(tableName, targetComponent);
4869
- const sampleDoc = await ctx.db.query(fullName).first();
5350
+ const sampleDoc = await getTableQuery(ctx, fullName).first();
4870
5351
  const fields = sampleDoc ? Object.keys(sampleDoc).map((key) => ({
4871
5352
  name: key,
4872
5353
  type: typeof sampleDoc[key],
@@ -4901,7 +5382,7 @@ function createSystemFunctions(deps) {
4901
5382
  handler: async (ctx, args) => {
4902
5383
  requireSystemCapability("documents:read");
4903
5384
  const fullName = getFullTableName(args.tableName, args.componentPath ?? "");
4904
- let query2 = ctx.db.query(fullName);
5385
+ let query2 = getTableQuery(ctx, fullName);
4905
5386
  if (args.orderBy && args.orderBy !== "_creationTime") {
4906
5387
  const allDocs2 = await query2.collect();
4907
5388
  const sorted = allDocs2.sort((a, b) => {
@@ -4952,7 +5433,7 @@ function createSystemFunctions(deps) {
4952
5433
  handler: async (ctx, args) => {
4953
5434
  requireSystemCapability("documents:write");
4954
5435
  const fullName = getFullTableName(args.tableName, args.componentPath ?? "");
4955
- const docs = await ctx.db.query(fullName).collect();
5436
+ const docs = await getTableQuery(ctx, fullName).collect();
4956
5437
  for (const doc of docs) {
4957
5438
  await ctx.db.delete(doc._id);
4958
5439
  }
@@ -5248,6 +5729,83 @@ function resolveFunctionReference(functionPath, componentPath) {
5248
5729
  }
5249
5730
  return functionPath;
5250
5731
  }
5732
+ async function loadComponentRows(ctx) {
5733
+ try {
5734
+ const rows = await ctx.db.system.query("_components").collect();
5735
+ if (rows.length > 0) {
5736
+ return rows.map((row) => normalizeStoredComponentRow(row));
5737
+ }
5738
+ } catch {}
5739
+ const modules = await listRegisteredModules();
5740
+ const moduleCountByComponent = new Map;
5741
+ const hasHttpByComponent = new Map;
5742
+ const componentPaths = new Set([""]);
5743
+ for (const module of modules) {
5744
+ const componentPath = module.componentPath ?? "";
5745
+ componentPaths.add(componentPath);
5746
+ moduleCountByComponent.set(componentPath, (moduleCountByComponent.get(componentPath) ?? 0) + 1);
5747
+ if (module.path === "http") {
5748
+ hasHttpByComponent.set(componentPath, true);
5749
+ }
5750
+ }
5751
+ return Array.from(componentPaths).map((componentPath) => ({
5752
+ componentPath,
5753
+ path: componentPath || "(root)",
5754
+ isRoot: componentPath === "",
5755
+ parentPath: componentPath === "" ? null : componentPath.includes("/") ? componentPath.split("/").slice(0, -1).join("/") : "",
5756
+ depth: componentPath === "" ? 0 : componentPath.split("/").length,
5757
+ moduleCount: moduleCountByComponent.get(componentPath) ?? 0,
5758
+ childCount: 0,
5759
+ functionCount: 0,
5760
+ sourceType: "local",
5761
+ hasHttp: hasHttpByComponent.get(componentPath) === true
5762
+ }));
5763
+ }
5764
+ function normalizeStoredComponentRow(row) {
5765
+ const componentPath = typeof row.componentPath === "string" ? row.componentPath : "";
5766
+ return {
5767
+ componentPath,
5768
+ path: typeof row.displayPath === "string" ? row.displayPath : typeof row.path === "string" && row.path.length > 0 ? row.path : componentPath || "(root)",
5769
+ isRoot: row.isRoot === true || componentPath === "",
5770
+ parentPath: row.parentPath === null ? null : typeof row.parentPath === "string" ? row.parentPath : componentPath === "" ? null : "",
5771
+ depth: typeof row.depth === "number" ? row.depth : componentPath === "" ? 0 : componentPath.split("/").length,
5772
+ moduleCount: typeof row.moduleCount === "number" ? row.moduleCount : 0,
5773
+ childCount: typeof row.childCount === "number" ? row.childCount : 0,
5774
+ functionCount: 0,
5775
+ sourceType: row.sourceType === "npm" ? "npm" : row.sourceType === "local" ? "local" : undefined,
5776
+ sourcePath: typeof row.sourcePath === "string" ? row.sourcePath : undefined,
5777
+ packageName: typeof row.packageName === "string" ? row.packageName : undefined,
5778
+ packageVersion: typeof row.packageVersion === "string" ? row.packageVersion : undefined,
5779
+ hasHttp: row.hasHttp === true
5780
+ };
5781
+ }
5782
+ function sortComponentRows(rows) {
5783
+ const childrenByParent = new Map;
5784
+ for (const row of rows) {
5785
+ const parentKey = row.parentPath ?? null;
5786
+ const siblings = childrenByParent.get(parentKey) ?? [];
5787
+ siblings.push(row);
5788
+ childrenByParent.set(parentKey, siblings);
5789
+ }
5790
+ for (const siblings of childrenByParent.values()) {
5791
+ siblings.sort((a, b) => {
5792
+ if (a.isRoot)
5793
+ return -1;
5794
+ if (b.isRoot)
5795
+ return 1;
5796
+ return a.componentPath.localeCompare(b.componentPath);
5797
+ });
5798
+ }
5799
+ const ordered = [];
5800
+ const visit = (parentPath) => {
5801
+ for (const row of childrenByParent.get(parentPath) ?? []) {
5802
+ ordered.push(row);
5803
+ visit(row.componentPath);
5804
+ }
5805
+ };
5806
+ visit(null);
5807
+ return ordered;
5808
+ }
5251
5809
  async function loadSchemaDefinition(componentPath) {
5252
5810
  try {
5253
5811
  const module = await loadConvexModule("schema", {
@@ -5281,13 +5839,26 @@ function extractTableMetadata(schema2, tableName) {
5281
5839
  }
5282
5840
  async function countDocuments(ctx, tableName) {
5283
5841
  try {
5284
- const documents = await ctx.db.query(tableName).collect();
5842
+ const documents = await getTableQuery(ctx, tableName).collect();
5285
5843
  return documents.length;
5286
5844
  } catch (error) {
5287
5845
  console.warn(`Failed to count documents for table ${tableName}:`, error);
5288
5846
  return 0;
5289
5847
  }
5290
5848
  }
5849
+ function getTableQuery(ctx, fullTableName) {
5850
+ const { tableName } = parseFullTableName(fullTableName);
5851
+ if (isSystemTable(tableName)) {
5852
+ return ctx.db.system.query(tableName);
5853
+ }
5854
+ return ctx.db.query(fullTableName);
5855
+ }
5856
+ function getDefaultSystemTableVisibility(tableName) {
5857
+ if (!isSystemTable(tableName)) {
5858
+ return "public";
5859
+ }
5860
+ return isPublicSystemTable(tableName) ? "public" : "private";
5861
+ }
5291
5862
  function buildIndexList(indexes) {
5292
5863
  const base = ["by_id", "by_creation_time"];
5293
5864
  if (!indexes || indexes.length === 0) {
@@ -5389,6 +5960,7 @@ var init_internal = __esm(() => {
5389
5960
  init_interface();
5390
5961
  init_execution_log();
5391
5962
  init_auth();
5963
+ init_system_tables();
5392
5964
  });
5393
5965
 
5394
5966
  // ../core/dist/system/system-functions-module.js
@@ -5546,8 +6118,9 @@ class ModuleRegistry {
5546
6118
  const normalized = normalizeModuleListing(listing);
5547
6119
  if (!normalized)
5548
6120
  continue;
5549
- if (!results.has(normalized.path)) {
5550
- results.set(normalized.path, {
6121
+ const resultKey = `${normalized.componentPath ?? scope ?? ""}:${normalized.path}`;
6122
+ if (!results.has(resultKey)) {
6123
+ results.set(resultKey, {
5551
6124
  ...normalized,
5552
6125
  scope: scope || undefined,
5553
6126
  componentPath: normalized.componentPath ?? (scope || undefined)
@@ -5866,8 +6439,10 @@ var init_module_loader = __esm(() => {
5866
6439
  class SchemaValidator {
5867
6440
  schemaCache = new Map;
5868
6441
  componentPath;
5869
- constructor(componentPath) {
6442
+ tableRegistry;
6443
+ constructor(componentPath, tableRegistry) {
5870
6444
  this.componentPath = componentPath;
6445
+ this.tableRegistry = tableRegistry;
5871
6446
  }
5872
6447
  async loadTableSchema(tableName) {
5873
6448
  if (this.schemaCache.has(tableName)) {
@@ -5910,8 +6485,11 @@ class SchemaValidator {
5910
6485
  return;
5911
6486
  }
5912
6487
  try {
6488
+ const tableNumberToName = this.tableRegistry ? new Map((await this.tableRegistry.listTables()).map((table) => [table.tableNumber, table.fullName])) : undefined;
5913
6489
  validateValidator(tableSchema, omit(document, ["_id", "_creationTime"]), "", {
5914
- componentPath: this.componentPath ?? ""
6490
+ componentPath: this.componentPath ?? "",
6491
+ tableRegistry: this.tableRegistry,
6492
+ tableNumberToName
5915
6493
  });
5916
6494
  } catch (error) {
5917
6495
  throw new ValidatorError(`Failed to insert or update a document in table "${tableName}" because it does not match the schema: ${error.message}`);
@@ -6009,6 +6587,16 @@ Path: ${formatPath(path)}
6009
6587
  Value: ${formatValue(value)}
6010
6588
  Validator: v.id("${validator2.tableName}")`);
6011
6589
  }
6590
+ if (isValidDocumentId(value)) {
6591
+ const tableName2 = tableNameFromConvexId(value, options);
6592
+ if (!tableName2 || !isMatchingValidatorTable(tableName2, validator2.tableName, options.componentPath)) {
6593
+ throw new Error(`Value does not match validator.
6594
+ Path: ${formatPath(path)}
6595
+ Value: ${formatValue(value)}
6596
+ Validator: v.id("${validator2.tableName}")`);
6597
+ }
6598
+ return;
6599
+ }
6012
6600
  const tableName = tableNameFromId(value);
6013
6601
  if (!tableName || !isMatchingValidatorTable(tableName, validator2.tableName, options.componentPath)) {
6014
6602
  throw new Error(`Value does not match validator.
@@ -6070,289 +6658,72 @@ Validator: v.object({...})`);
6070
6658
  }
6071
6659
  } else {
6072
6660
  const fieldPath = path ? `${path}.${k}` : `.${k}`;
6073
- validateValidator(fieldType, value[k], fieldPath, options);
6074
- }
6075
- }
6076
- for (const k of Object.keys(value)) {
6077
- if (validator2.value[k] === undefined) {
6078
- throw new Error(`Object contains extra field \`${k}\` that is not in the validator.
6079
-
6080
- Object: ${JSON.stringify(value)}
6081
- Validator: v.object({...})`);
6082
- }
6083
- }
6084
- return;
6085
- }
6086
- }
6087
- }
6088
- function tableNameFromId(id) {
6089
- const parts = deserializeDeveloperId(id);
6090
- if (!parts) {
6091
- return null;
6092
- }
6093
- return hexToString(parts.table);
6094
- }
6095
- function isMatchingValidatorTable(idTableName, validatorTableName, componentPath) {
6096
- if (idTableName === validatorTableName) {
6097
- return true;
6098
- }
6099
- const { tableName: validatorBareName } = parseFullTableName(validatorTableName);
6100
- const { tableName: idBareName } = parseFullTableName(idTableName);
6101
- if (componentPath !== undefined) {
6102
- const expectedFullName = getFullTableName(validatorBareName, componentPath);
6103
- return idTableName === expectedFullName;
6104
- }
6105
- return idBareName === validatorBareName;
6106
- }
6107
- function isSimpleObject2(value) {
6108
- const isObject2 = typeof value === "object";
6109
- const prototype = Object.getPrototypeOf(value);
6110
- const isSimple = prototype === null || prototype === Object.prototype || prototype?.constructor?.name === "Object";
6111
- return isObject2 && isSimple;
6112
- }
6113
- var ValidatorError;
6114
- var init_validator2 = __esm(() => {
6115
- init_interface();
6116
- init_module_loader();
6117
- ValidatorError = class ValidatorError extends Error {
6118
- path;
6119
- constructor(message2, path = "") {
6120
- super(message2);
6121
- this.path = path;
6122
- this.name = "ValidatorError";
6123
- }
6124
- };
6125
- });
6126
-
6127
- // ../core/dist/id-codec/base32.js
6128
- function base32Encode(data) {
6129
- if (data.length === 0)
6130
- return "";
6131
- let result = "";
6132
- let buffer = 0;
6133
- let bitsLeft = 0;
6134
- for (const byte of data) {
6135
- buffer = buffer << 8 | byte;
6136
- bitsLeft += 8;
6137
- while (bitsLeft >= 5) {
6138
- bitsLeft -= 5;
6139
- const index = buffer >> bitsLeft & 31;
6140
- result += ALPHABET[index];
6141
- }
6142
- }
6143
- if (bitsLeft > 0) {
6144
- const index = buffer << 5 - bitsLeft & 31;
6145
- result += ALPHABET[index];
6146
- }
6147
- return result;
6148
- }
6149
- function base32Decode(str) {
6150
- if (str.length === 0)
6151
- return new Uint8Array(0);
6152
- const outputLength = Math.floor(str.length * 5 / 8);
6153
- const result = new Uint8Array(outputLength);
6154
- let buffer = 0;
6155
- let bitsLeft = 0;
6156
- let outputIndex = 0;
6157
- for (const char of str) {
6158
- const value = ALPHABET_MAP.get(char);
6159
- if (value === undefined) {
6160
- throw new Error(`Invalid base32 character: ${char}`);
6161
- }
6162
- buffer = buffer << 5 | value;
6163
- bitsLeft += 5;
6164
- if (bitsLeft >= 8) {
6165
- bitsLeft -= 8;
6166
- result[outputIndex++] = buffer >> bitsLeft & 255;
6167
- }
6168
- }
6169
- return result;
6170
- }
6171
- function isValidBase32(str) {
6172
- for (const char of str) {
6173
- if (!ALPHABET_MAP.has(char)) {
6174
- return false;
6175
- }
6176
- }
6177
- return true;
6178
- }
6179
- var ALPHABET = "0123456789abcdefghjkmnpqrstvwxyz", ALPHABET_MAP;
6180
- var init_base32 = __esm(() => {
6181
- ALPHABET_MAP = new Map;
6182
- for (let i2 = 0;i2 < ALPHABET.length; i2++) {
6183
- ALPHABET_MAP.set(ALPHABET[i2], i2);
6184
- ALPHABET_MAP.set(ALPHABET[i2].toUpperCase(), i2);
6185
- }
6186
- ALPHABET_MAP.set("i", 1);
6187
- ALPHABET_MAP.set("I", 1);
6188
- ALPHABET_MAP.set("l", 1);
6189
- ALPHABET_MAP.set("L", 1);
6190
- ALPHABET_MAP.set("o", 0);
6191
- ALPHABET_MAP.set("O", 0);
6192
- });
6193
-
6194
- // ../core/dist/id-codec/vint.js
6195
- function vintEncode(value) {
6196
- if (value < 0) {
6197
- throw new Error("VInt cannot encode negative numbers");
6198
- }
6199
- if (value > 4294967295) {
6200
- throw new Error("VInt cannot encode values larger than 2^32-1");
6201
- }
6202
- value = value >>> 0;
6203
- if (value < 128) {
6204
- return new Uint8Array([value]);
6205
- }
6206
- if (value < 16512) {
6207
- const adjusted2 = value - 128;
6208
- return new Uint8Array([128 | adjusted2 >> 8 & 63, adjusted2 & 255]);
6209
- }
6210
- if (value < 2113664) {
6211
- const adjusted2 = value - 16512;
6212
- return new Uint8Array([192 | adjusted2 >> 16 & 31, adjusted2 >> 8 & 255, adjusted2 & 255]);
6213
- }
6214
- if (value < 270549120) {
6215
- const adjusted2 = value - 2113664;
6216
- return new Uint8Array([
6217
- 224 | adjusted2 >> 24 & 15,
6218
- adjusted2 >> 16 & 255,
6219
- adjusted2 >> 8 & 255,
6220
- adjusted2 & 255
6221
- ]);
6222
- }
6223
- const adjusted = value - 270549120;
6224
- return new Uint8Array([
6225
- 240 | adjusted >> 32 & 7,
6226
- adjusted >> 24 & 255,
6227
- adjusted >> 16 & 255,
6228
- adjusted >> 8 & 255,
6229
- adjusted & 255
6230
- ]);
6231
- }
6232
- function vintDecode(data, offset = 0) {
6233
- if (offset >= data.length) {
6234
- throw new Error("VInt decode: unexpected end of data");
6235
- }
6236
- const first = data[offset];
6237
- if ((first & 128) === 0) {
6238
- return { value: first, bytesRead: 1 };
6239
- }
6240
- if ((first & 192) === 128) {
6241
- if (offset + 1 >= data.length) {
6242
- throw new Error("VInt decode: truncated 2-byte encoding");
6243
- }
6244
- const value = 128 + ((first & 63) << 8 | data[offset + 1]);
6245
- return { value, bytesRead: 2 };
6246
- }
6247
- if ((first & 224) === 192) {
6248
- if (offset + 2 >= data.length) {
6249
- throw new Error("VInt decode: truncated 3-byte encoding");
6250
- }
6251
- const value = 16512 + ((first & 31) << 16 | data[offset + 1] << 8 | data[offset + 2]);
6252
- return { value, bytesRead: 3 };
6253
- }
6254
- if ((first & 240) === 224) {
6255
- if (offset + 3 >= data.length) {
6256
- throw new Error("VInt decode: truncated 4-byte encoding");
6257
- }
6258
- const value = 2113664 + ((first & 15) << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3]);
6259
- return { value: value >>> 0, bytesRead: 4 };
6260
- }
6261
- if ((first & 248) === 240) {
6262
- if (offset + 4 >= data.length) {
6263
- throw new Error("VInt decode: truncated 5-byte encoding");
6264
- }
6265
- const high = first & 7;
6266
- const low = (data[offset + 1] << 24 | data[offset + 2] << 16 | data[offset + 3] << 8 | data[offset + 4]) >>> 0;
6267
- const value = 270549120 + high * 4294967296 + low;
6268
- return { value: value >>> 0, bytesRead: 5 };
6269
- }
6270
- throw new Error("VInt decode: invalid prefix");
6271
- }
6272
-
6273
- // ../core/dist/id-codec/fletcher16.js
6274
- function fletcher16(data) {
6275
- let sum1 = 0;
6276
- let sum2 = 0;
6277
- for (const byte of data) {
6278
- sum1 = (sum1 + byte) % 255;
6279
- sum2 = (sum2 + sum1) % 255;
6280
- }
6281
- return new Uint8Array([sum1, sum2]);
6282
- }
6283
- function verifyFletcher16(data, checksum) {
6284
- if (checksum.length !== 2)
6285
- return false;
6286
- const computed = fletcher16(data);
6287
- return computed[0] === checksum[0] && computed[1] === checksum[1];
6288
- }
6289
-
6290
- // ../core/dist/utils/crypto.js
6291
- var weakRandomState;
6292
- var init_crypto = __esm(() => {
6293
- weakRandomState = (Date.now() ^ 2654435769) >>> 0;
6294
- });
6295
-
6296
- // ../core/dist/id-codec/document-id.js
6297
- function encodeDocumentId(tableNumber, internalId) {
6298
- if (internalId.length !== INTERNAL_ID_LENGTH) {
6299
- throw new Error(`Internal ID must be exactly ${INTERNAL_ID_LENGTH} bytes, got ${internalId.length}`);
6300
- }
6301
- if (tableNumber < 1 || tableNumber > 4294967295) {
6302
- throw new Error(`Table number must be between 1 and 2^32-1, got ${tableNumber}`);
6303
- }
6304
- const tableBytes = vintEncode(tableNumber);
6305
- const payload = new Uint8Array(tableBytes.length + INTERNAL_ID_LENGTH);
6306
- payload.set(tableBytes, 0);
6307
- payload.set(internalId, tableBytes.length);
6308
- const checksum = fletcher16(payload);
6309
- const final = new Uint8Array(payload.length + 2);
6310
- final.set(payload, 0);
6311
- final.set(checksum, payload.length);
6312
- return base32Encode(final);
6313
- }
6314
- function decodeDocumentId(encoded) {
6315
- if (encoded.length < MIN_ENCODED_LENGTH || encoded.length > MAX_ENCODED_LENGTH) {
6316
- throw new Error(`Invalid document ID length: ${encoded.length} (expected ${MIN_ENCODED_LENGTH}-${MAX_ENCODED_LENGTH})`);
6317
- }
6318
- if (!isValidBase32(encoded)) {
6319
- throw new Error("Invalid document ID: contains invalid base32 characters");
6320
- }
6321
- const bytes = base32Decode(encoded);
6322
- if (bytes.length < 19) {
6323
- throw new Error(`Invalid document ID: decoded to ${bytes.length} bytes (minimum 19)`);
6324
- }
6325
- const checksum = bytes.slice(bytes.length - 2);
6326
- const payload = bytes.slice(0, bytes.length - 2);
6327
- if (!verifyFletcher16(payload, checksum)) {
6328
- throw new Error("Invalid document ID: checksum verification failed");
6661
+ validateValidator(fieldType, value[k], fieldPath, options);
6662
+ }
6663
+ }
6664
+ for (const k of Object.keys(value)) {
6665
+ if (validator2.value[k] === undefined) {
6666
+ throw new Error(`Object contains extra field \`${k}\` that is not in the validator.
6667
+
6668
+ Object: ${JSON.stringify(value)}
6669
+ Validator: v.object({...})`);
6670
+ }
6671
+ }
6672
+ return;
6673
+ }
6329
6674
  }
6330
- const { value: tableNumber, bytesRead } = vintDecode(payload, 0);
6331
- const internalId = payload.slice(bytesRead, bytesRead + INTERNAL_ID_LENGTH);
6332
- if (internalId.length !== INTERNAL_ID_LENGTH) {
6333
- throw new Error(`Invalid document ID: internal ID is ${internalId.length} bytes (expected ${INTERNAL_ID_LENGTH})`);
6675
+ }
6676
+ function tableNameFromId(id) {
6677
+ const parts = deserializeDeveloperId(id);
6678
+ if (!parts) {
6679
+ return null;
6334
6680
  }
6335
- return { tableNumber, internalId };
6681
+ return hexToString(parts.table);
6336
6682
  }
6337
- function isValidDocumentId(encoded) {
6683
+ function tableNameFromConvexId(id, options) {
6338
6684
  try {
6339
- decodeDocumentId(encoded);
6340
- return true;
6685
+ const decoded = decodeDocumentId(id);
6686
+ const fromMap = options.tableNumberToName?.get(decoded.tableNumber);
6687
+ if (fromMap) {
6688
+ return fromMap;
6689
+ }
6690
+ return null;
6341
6691
  } catch {
6342
- return false;
6692
+ return null;
6343
6693
  }
6344
6694
  }
6345
- function internalIdToHex(internalId) {
6346
- let hex = "";
6347
- for (let i2 = 0;i2 < internalId.length; i2++) {
6348
- hex += internalId[i2].toString(16).padStart(2, "0");
6695
+ function isMatchingValidatorTable(idTableName, validatorTableName, componentPath) {
6696
+ if (idTableName === validatorTableName) {
6697
+ return true;
6349
6698
  }
6350
- return hex;
6699
+ const { tableName: validatorBareName } = parseFullTableName(validatorTableName);
6700
+ const { tableName: idBareName } = parseFullTableName(idTableName);
6701
+ if (componentPath !== undefined) {
6702
+ const expectedFullName = getFullTableName(validatorBareName, componentPath);
6703
+ return idTableName === expectedFullName;
6704
+ }
6705
+ return idBareName === validatorBareName;
6351
6706
  }
6352
- var INTERNAL_ID_LENGTH = 16, MIN_ENCODED_LENGTH = 31, MAX_ENCODED_LENGTH = 37;
6353
- var init_document_id = __esm(() => {
6354
- init_base32();
6355
- init_crypto();
6707
+ function isSimpleObject2(value) {
6708
+ const isObject2 = typeof value === "object";
6709
+ const prototype = Object.getPrototypeOf(value);
6710
+ const isSimple = prototype === null || prototype === Object.prototype || prototype?.constructor?.name === "Object";
6711
+ return isObject2 && isSimple;
6712
+ }
6713
+ var ValidatorError;
6714
+ var init_validator2 = __esm(() => {
6715
+ init_utils();
6716
+ init_interface();
6717
+ init_module_loader();
6718
+ init_id_codec();
6719
+ ValidatorError = class ValidatorError extends Error {
6720
+ path;
6721
+ constructor(message2, path = "") {
6722
+ super(message2);
6723
+ this.path = path;
6724
+ this.name = "ValidatorError";
6725
+ }
6726
+ };
6356
6727
  });
6357
6728
 
6358
6729
  // src/sqlite-docstore.ts
@@ -6363,7 +6734,10 @@ init_values();
6363
6734
 
6364
6735
  // ../core/dist/docstore/interface.js
6365
6736
  function documentIdKey(id) {
6366
- const tableKey = id.table && id.table.length > 0 ? id.table : id.tableNumber !== undefined && Number.isInteger(id.tableNumber) && id.tableNumber > 0 ? `#${id.tableNumber}` : id.table;
6737
+ const tableKey = id.table && id.table.length > 0 ? id.table : id.tableNumber !== undefined && Number.isInteger(id.tableNumber) && id.tableNumber > 0 ? `#${id.tableNumber}` : null;
6738
+ if (!tableKey) {
6739
+ throw new Error("Invalid document ID: missing table and tableNumber");
6740
+ }
6367
6741
  return `${tableKey}:${id.internalId}`;
6368
6742
  }
6369
6743
  var Order;
@@ -6570,6 +6944,7 @@ class TimestampOracle {
6570
6944
  }
6571
6945
  }
6572
6946
  // ../core/dist/utils/keyspace.js
6947
+ init_utils();
6573
6948
  var TABLE_PREFIX = "table";
6574
6949
  var INDEX_PREFIX = "index";
6575
6950
  function encodeComponent(component) {
@@ -6610,6 +6985,13 @@ function decodeIndexId(indexId) {
6610
6985
  index: decoded.slice(separatorIndex + 1)
6611
6986
  };
6612
6987
  }
6988
+
6989
+ // ../core/dist/utils/index.js
6990
+ init_utils();
6991
+
6992
+ // ../core/dist/queryengine/indexing/index-manager.js
6993
+ init_utils();
6994
+
6613
6995
  // ../core/dist/queryengine/indexing/index-key-codec.js
6614
6996
  var TypeTag;
6615
6997
  (function(TypeTag2) {
@@ -6659,8 +7041,9 @@ function encodeBigInt(n) {
6659
7041
  return bytes;
6660
7042
  }
6661
7043
  function encodeString(s) {
6662
- const encoder = new TextEncoder;
6663
- const raw = encoder.encode(s);
7044
+ return encodeEscapedBytes(new TextEncoder().encode(s));
7045
+ }
7046
+ function encodeEscapedBytes(raw) {
6664
7047
  let nullCount = 0;
6665
7048
  for (const byte of raw) {
6666
7049
  if (byte === 0)
@@ -6724,11 +7107,10 @@ function encodeValue(value) {
6724
7107
  }
6725
7108
  if (value instanceof ArrayBuffer || value instanceof Uint8Array) {
6726
7109
  const bytes = value instanceof Uint8Array ? value : new Uint8Array(value);
6727
- const result = new Uint8Array(1 + bytes.length + 2);
7110
+ const encoded = encodeEscapedBytes(bytes);
7111
+ const result = new Uint8Array(1 + encoded.length);
6728
7112
  result[0] = TypeTag.Bytes;
6729
- result.set(bytes, 1);
6730
- result[result.length - 2] = 0;
6731
- result[result.length - 1] = 0;
7113
+ result.set(encoded, 1);
6732
7114
  return result;
6733
7115
  }
6734
7116
  throw new Error(`Cannot encode value of type ${typeof value} in index key`);
@@ -6845,9 +7227,11 @@ class SchemaService {
6845
7227
  tableCache = new Map;
6846
7228
  schemaValidator;
6847
7229
  componentPath;
6848
- constructor(componentPath) {
7230
+ tableRegistry;
7231
+ constructor(componentPath, tableRegistry) {
6849
7232
  this.componentPath = componentPath;
6850
- this.schemaValidator = new SchemaValidator(componentPath);
7233
+ this.tableRegistry = tableRegistry;
7234
+ this.schemaValidator = new SchemaValidator(componentPath, tableRegistry);
6851
7235
  }
6852
7236
  async validate(tableName, document) {
6853
7237
  try {
@@ -6972,6 +7356,10 @@ class SchemaService {
6972
7356
  return this.cachedSchemaDefinition;
6973
7357
  }
6974
7358
  }
7359
+
7360
+ // ../core/dist/queryengine/index-query.js
7361
+ init_utils();
7362
+
6975
7363
  // ../core/dist/observability/udf-trace.js
6976
7364
  init_context_storage();
6977
7365
  var TRACE_CONTEXT = new ContextStorage;
@@ -7215,11 +7603,10 @@ function evaluateFieldPath(fieldPath, document) {
7215
7603
  }
7216
7604
  return current;
7217
7605
  }
7218
- // ../core/dist/id-codec/index.js
7219
- init_base32();
7220
- init_document_id();
7221
7606
 
7222
7607
  // ../core/dist/queryengine/developer-id.js
7608
+ init_utils();
7609
+ init_id_codec();
7223
7610
  function parseDeveloperId(developerId) {
7224
7611
  if (isValidDocumentId(developerId)) {
7225
7612
  try {
@@ -7237,6 +7624,25 @@ function parseDeveloperId(developerId) {
7237
7624
  }
7238
7625
  return { table: parts.table, internalId: parts.internalId };
7239
7626
  }
7627
+ async function parseDeveloperIdWithTableRegistry(developerId, tableRegistry) {
7628
+ if (isValidDocumentId(developerId)) {
7629
+ try {
7630
+ const decoded = decodeDocumentId(developerId);
7631
+ const tableInfo = await tableRegistry.getTableInfo(decoded.tableNumber);
7632
+ if (!tableInfo) {
7633
+ return null;
7634
+ }
7635
+ return {
7636
+ table: stringToHex(tableInfo.fullName),
7637
+ internalId: internalIdToHex(decoded.internalId),
7638
+ tableNumber: decoded.tableNumber
7639
+ };
7640
+ } catch {
7641
+ return null;
7642
+ }
7643
+ }
7644
+ return parseDeveloperId(developerId);
7645
+ }
7240
7646
  function parseStorageId(storageId) {
7241
7647
  const parsed = parseDeveloperId(storageId);
7242
7648
  if (parsed) {
@@ -7253,12 +7659,21 @@ function parseStorageId(storageId) {
7253
7659
  function isTablePlaceholder(table) {
7254
7660
  return table.startsWith("#");
7255
7661
  }
7662
+
7663
+ // ../core/dist/query/query-runtime.js
7664
+ init_utils();
7665
+
7256
7666
  // ../core/dist/query/planner.js
7257
7667
  init_interface();
7668
+ init_utils();
7669
+
7258
7670
  // ../core/dist/query/actions.js
7671
+ init_utils();
7259
7672
  init_interface();
7260
7673
 
7261
7674
  // ../core/dist/queryengine/indexing/read-write-set.js
7675
+ init_utils();
7676
+
7262
7677
  class RangeSet {
7263
7678
  ranges = new Map;
7264
7679
  addDocument(docId) {
@@ -7369,6 +7784,8 @@ function deserializeKeyRange(serialized) {
7369
7784
  }
7370
7785
 
7371
7786
  // ../core/dist/kernel/access-log.js
7787
+ init_utils();
7788
+
7372
7789
  class AccessLog {
7373
7790
  ranges = new RangeSet;
7374
7791
  addDocument(docId) {
@@ -7393,104 +7810,9 @@ class AccessLog {
7393
7810
  }
7394
7811
  }
7395
7812
 
7396
- // ../core/dist/tables/memory-table-registry.js
7813
+ // ../core/dist/kernel/kernel-context.js
7397
7814
  init_interface();
7398
7815
 
7399
- class MemoryTableRegistry {
7400
- tablesByName = new Map;
7401
- tablesByNumber = new Map;
7402
- nextTableNumber = FIRST_USER_TABLE_NUMBER;
7403
- constructor() {
7404
- this.registerSystemTables();
7405
- }
7406
- registerSystemTables() {
7407
- for (const [name, number] of Object.entries(SYSTEM_TABLE_NUMBERS)) {
7408
- const info = {
7409
- tableNumber: number,
7410
- name,
7411
- componentPath: "",
7412
- fullName: name,
7413
- isSystem: true,
7414
- createdAt: Date.now()
7415
- };
7416
- this.tablesByName.set(name, info);
7417
- this.tablesByNumber.set(number, info);
7418
- }
7419
- }
7420
- async getOrAllocateTableNumber(tableName, componentPath = "") {
7421
- const fullName = getFullTableName(tableName, componentPath);
7422
- const existing = this.tablesByName.get(fullName);
7423
- if (existing) {
7424
- return existing.tableNumber;
7425
- }
7426
- if (isSystemTable(tableName) && componentPath === "") {
7427
- const systemNumber = SYSTEM_TABLE_NUMBERS[tableName];
7428
- if (systemNumber !== undefined) {
7429
- return systemNumber;
7430
- }
7431
- }
7432
- const tableNumber = this.nextTableNumber++;
7433
- const info = {
7434
- tableNumber,
7435
- name: tableName,
7436
- componentPath,
7437
- fullName,
7438
- isSystem: false,
7439
- createdAt: Date.now()
7440
- };
7441
- this.tablesByName.set(fullName, info);
7442
- this.tablesByNumber.set(tableNumber, info);
7443
- return tableNumber;
7444
- }
7445
- async getTableInfo(tableNumber) {
7446
- return this.tablesByNumber.get(tableNumber) ?? null;
7447
- }
7448
- async getTableInfoByName(tableName, componentPath = "") {
7449
- const fullName = getFullTableName(tableName, componentPath);
7450
- return this.tablesByName.get(fullName) ?? null;
7451
- }
7452
- async listTables(componentPath) {
7453
- const tables = Array.from(this.tablesByNumber.values());
7454
- if (componentPath === undefined) {
7455
- return tables;
7456
- }
7457
- return tables.filter((t) => t.componentPath === componentPath);
7458
- }
7459
- async hasAccess(tableNumber, componentPath) {
7460
- const info = await this.getTableInfo(tableNumber);
7461
- if (!info) {
7462
- return false;
7463
- }
7464
- if (info.isSystem) {
7465
- return true;
7466
- }
7467
- return info.componentPath === componentPath;
7468
- }
7469
- getSystemTableNumber(systemTableName) {
7470
- return SYSTEM_TABLE_NUMBERS[systemTableName];
7471
- }
7472
- reset() {
7473
- this.tablesByName.clear();
7474
- this.tablesByNumber.clear();
7475
- this.nextTableNumber = FIRST_USER_TABLE_NUMBER;
7476
- this.registerSystemTables();
7477
- }
7478
- getState() {
7479
- return {
7480
- tableCount: this.tablesByNumber.size,
7481
- nextNumber: this.nextTableNumber
7482
- };
7483
- }
7484
- }
7485
- var globalRegistry = null;
7486
- function getGlobalTableRegistry() {
7487
- if (!globalRegistry) {
7488
- globalRegistry = new MemoryTableRegistry;
7489
- }
7490
- return globalRegistry;
7491
- }
7492
-
7493
- // ../core/dist/kernel/kernel-context.js
7494
7816
  class KernelContext {
7495
7817
  authContext;
7496
7818
  componentPath;
@@ -7507,11 +7829,14 @@ class KernelContext {
7507
7829
  this.authContext = options.authContext;
7508
7830
  this.componentPath = options.componentPath ?? "";
7509
7831
  this.mutationTransaction = options.mutationTransaction;
7510
- this.tableRegistry = options.tableRegistry ?? getGlobalTableRegistry();
7511
- this.useConvexIdFormat = options.useConvexIdFormat ?? false;
7832
+ if (!options.tableRegistry) {
7833
+ throw new Error("KernelContext requires an explicit tableRegistry");
7834
+ }
7835
+ this.tableRegistry = options.tableRegistry;
7836
+ this.useConvexIdFormat = options.useConvexIdFormat ?? true;
7512
7837
  }
7513
7838
  async getTableNumber(tableName) {
7514
- return this.tableRegistry.getOrAllocateTableNumber(tableName, this.componentPath);
7839
+ return this.tableRegistry.getOrAllocateTableNumber(tableName, isSystemTable(tableName) ? "" : this.componentPath);
7515
7840
  }
7516
7841
  nextSubrequestId(prefix, udfPath) {
7517
7842
  return `${prefix}:${udfPath}:${Date.now()}:${Math.random()}:${this.subrequestCounter++}`;
@@ -7556,7 +7881,7 @@ class KernelContext {
7556
7881
  this.writeLog.addDocument(docId);
7557
7882
  }
7558
7883
  recordLocalWrite(developerId, tableName, value, docId) {
7559
- this.localWrites.set(developerId, { table: tableName, value });
7884
+ this.localWrites.set(developerId, { table: tableName, value, docId });
7560
7885
  if (docId) {
7561
7886
  this.recordDocumentWrite(docId);
7562
7887
  return;
@@ -7598,7 +7923,13 @@ class KernelContext {
7598
7923
  }
7599
7924
  }
7600
7925
 
7926
+ // ../core/dist/kernel/udf-kernel.js
7927
+ init_id_codec();
7928
+
7601
7929
  // ../core/dist/kernel/blob-store-gateway.js
7930
+ init_id_codec();
7931
+ init_utils();
7932
+
7602
7933
  class BlobStoreGateway {
7603
7934
  context;
7604
7935
  docStore;
@@ -7647,7 +7978,7 @@ class BlobStoreGateway {
7647
7978
  if (!this.storage) {
7648
7979
  return null;
7649
7980
  }
7650
- const docId = parseStorageId(storageId);
7981
+ const docId = await parseDeveloperIdWithTableRegistry(storageId, this.context.tableRegistry) ?? parseStorageId(storageId);
7651
7982
  if (!docId) {
7652
7983
  console.debug(`[BlobStoreGateway] Failed to parse storage ID: ${storageId}`);
7653
7984
  return null;
@@ -7668,7 +7999,7 @@ class BlobStoreGateway {
7668
7999
  if (!this.storage) {
7669
8000
  return null;
7670
8001
  }
7671
- const docId = parseStorageId(storageId);
8002
+ const docId = await parseDeveloperIdWithTableRegistry(storageId, this.context.tableRegistry) ?? parseStorageId(storageId);
7672
8003
  if (!docId) {
7673
8004
  return null;
7674
8005
  }
@@ -7681,7 +8012,7 @@ class BlobStoreGateway {
7681
8012
  }
7682
8013
  async delete(storageId) {
7683
8014
  const storage2 = this.requireStorage();
7684
- const docId = parseStorageId(storageId);
8015
+ const docId = await parseDeveloperIdWithTableRegistry(storageId, this.context.tableRegistry) ?? parseStorageId(storageId);
7685
8016
  if (!docId) {
7686
8017
  return;
7687
8018
  }
@@ -7706,13 +8037,17 @@ class BlobStoreGateway {
7706
8037
 
7707
8038
  // ../core/dist/kernel/scheduler-gateway.js
7708
8039
  init_values();
8040
+ init_id_codec();
8041
+ init_utils();
8042
+
7709
8043
  // ../core/dist/kernel/syscalls/utils.js
7710
8044
  init_values();
8045
+ init_utils();
7711
8046
  async function resolveTableName(docId, tableRegistry) {
7712
8047
  if (docId.tableNumber !== undefined) {
7713
8048
  const info = await tableRegistry.getTableInfo(docId.tableNumber);
7714
8049
  if (info) {
7715
- return info.name;
8050
+ return info.fullName;
7716
8051
  }
7717
8052
  if (!isTablePlaceholder(docId.table)) {
7718
8053
  return hexToString(docId.table);
@@ -7893,7 +8228,7 @@ class SchedulerGateway {
7893
8228
  return developerId;
7894
8229
  }
7895
8230
  async cancel(id, state) {
7896
- const docId = parseDeveloperId(id);
8231
+ const docId = await parseDeveloperIdWithTableRegistry(id, this.context.tableRegistry);
7897
8232
  if (!docId) {
7898
8233
  throw new Error(`Scheduled job with id ${id} not found.`);
7899
8234
  }
@@ -8018,6 +8353,8 @@ class ActionSyscalls {
8018
8353
 
8019
8354
  // ../core/dist/kernel/syscalls/database-syscalls.js
8020
8355
  init_values();
8356
+ init_id_codec();
8357
+ init_utils();
8021
8358
  init_interface();
8022
8359
 
8023
8360
  class DatabaseSyscalls {
@@ -8054,7 +8391,8 @@ class DatabaseSyscalls {
8054
8391
  if (docId.tableNumber !== undefined) {
8055
8392
  return { id: idString };
8056
8393
  }
8057
- if (docId.table === stringToHex(tableName)) {
8394
+ const expectedFullTableName = getFullTableName(tableName, isSystemTable(tableName) ? "" : this.context.componentPath);
8395
+ if (docId.table === stringToHex(expectedFullTableName)) {
8058
8396
  return { id: idString };
8059
8397
  }
8060
8398
  return { id: null };
@@ -8113,29 +8451,28 @@ class DatabaseSyscalls {
8113
8451
  return { _id: developerId };
8114
8452
  }
8115
8453
  async handleGet(args) {
8116
- const { id } = args;
8454
+ const { id, table } = args;
8117
8455
  if (typeof id !== "string") {
8118
8456
  throw new Error("`id` argument for `get` must be a string.");
8119
8457
  }
8120
- const internalId = parseDeveloperId(id);
8121
- if (!internalId) {
8458
+ const resolved = await this.resolveDocumentTarget(id, table, "get");
8459
+ if (!resolved) {
8122
8460
  return null;
8123
8461
  }
8124
- this.context.recordDocumentRead(internalId);
8125
- const doc = await this.queryRuntime.getVisibleDocumentById(id, internalId);
8462
+ this.context.recordDocumentRead(resolved.docId);
8463
+ const doc = await this.queryRuntime.getVisibleDocumentById(id, resolved.docId);
8126
8464
  return doc ?? null;
8127
8465
  }
8128
8466
  async handleRemove(args) {
8129
- const { id } = args;
8467
+ const { id, table } = args;
8130
8468
  if (typeof id !== "string") {
8131
8469
  throw new Error("`id` argument for `remove` must be a string.");
8132
8470
  }
8133
- const docId = parseDeveloperId(id);
8134
- if (!docId) {
8471
+ const resolved = await this.resolveDocumentTarget(id, table, "remove", true);
8472
+ if (!resolved) {
8135
8473
  throw new Error(`Document with id ${id} not found.`);
8136
8474
  }
8137
- const fullTableName = await resolveTableName(docId, this.context.tableRegistry);
8138
- const { tableName: bareTableName } = parseFullTableName(fullTableName);
8475
+ const { docId, fullTableName, bareTableName } = resolved;
8139
8476
  const latest = await this.docStore.fetchLatestDocument(docId, this.context.snapshotTimestamp);
8140
8477
  if (!latest) {
8141
8478
  throw new Error(`Document with id ${id} not found.`);
@@ -8151,16 +8488,15 @@ class DatabaseSyscalls {
8151
8488
  return {};
8152
8489
  }
8153
8490
  async handleShallowMerge(args) {
8154
- const { id, value } = args;
8491
+ const { id, table, value } = args;
8155
8492
  if (typeof id !== "string") {
8156
8493
  throw new Error("`id` argument for `shallowMerge` must be a string.");
8157
8494
  }
8158
- const docId = parseDeveloperId(id);
8159
- if (!docId) {
8495
+ const resolved = await this.resolveDocumentTarget(id, table, "patch", true);
8496
+ if (!resolved) {
8160
8497
  throw new Error(`Document with id ${id} not found.`);
8161
8498
  }
8162
- const fullTableName = await resolveTableName(docId, this.context.tableRegistry);
8163
- const { tableName: bareTableName } = parseFullTableName(fullTableName);
8499
+ const { docId, fullTableName, bareTableName } = resolved;
8164
8500
  if (value && typeof value === "object") {
8165
8501
  if ("_id" in value) {
8166
8502
  throw new Error("System field `_id` cannot be modified in a patch operation.");
@@ -8211,16 +8547,15 @@ class DatabaseSyscalls {
8211
8547
  return {};
8212
8548
  }
8213
8549
  async handleReplace(args) {
8214
- const { id, value } = args;
8550
+ const { id, table, value } = args;
8215
8551
  if (typeof id !== "string") {
8216
8552
  throw new Error("`id` argument for `replace` must be a string.");
8217
8553
  }
8218
- const docId = parseDeveloperId(id);
8219
- if (!docId) {
8554
+ const resolved = await this.resolveDocumentTarget(id, table, "replace", true);
8555
+ if (!resolved) {
8220
8556
  throw new Error(`Document with id ${id} not found.`);
8221
8557
  }
8222
- const fullTableName = await resolveTableName(docId, this.context.tableRegistry);
8223
- const { tableName: bareTableName } = parseFullTableName(fullTableName);
8558
+ const { docId, fullTableName, bareTableName } = resolved;
8224
8559
  const replaceValue = jsonToConvex(value);
8225
8560
  if (typeof replaceValue !== "object" || replaceValue === null || Array.isArray(replaceValue)) {
8226
8561
  throw new Error("The replacement value for `replace` must be an object.");
@@ -8243,6 +8578,27 @@ class DatabaseSyscalls {
8243
8578
  this.context.recordLocalWrite(id, fullTableName, newValue, canonicalDocId);
8244
8579
  return {};
8245
8580
  }
8581
+ async resolveDocumentTarget(id, table, operation, throwOnMismatch = false) {
8582
+ if (table !== undefined && typeof table !== "string") {
8583
+ throw new Error(`\`table\` argument for \`${operation}\` must be a string.`);
8584
+ }
8585
+ const docId = await parseDeveloperIdWithTableRegistry(id, this.context.tableRegistry);
8586
+ if (!docId) {
8587
+ return null;
8588
+ }
8589
+ const fullTableName = await resolveTableName(docId, this.context.tableRegistry);
8590
+ if (typeof table === "string") {
8591
+ const expectedFullTableName = getFullTableName(table, isSystemTable(table) ? "" : this.context.componentPath);
8592
+ if (fullTableName !== expectedFullTableName) {
8593
+ if (throwOnMismatch) {
8594
+ throw new Error(`Document with id ${id} does not belong to table ${table}.`);
8595
+ }
8596
+ return null;
8597
+ }
8598
+ }
8599
+ const { tableName: bareTableName } = parseFullTableName(fullTableName);
8600
+ return { docId, fullTableName, bareTableName };
8601
+ }
8246
8602
  }
8247
8603
 
8248
8604
  // ../core/dist/kernel/syscalls/identity-syscalls.js
@@ -8558,11 +8914,203 @@ class KernelSyscalls {
8558
8914
  return this.jsRouter.dispatch(op, args);
8559
8915
  }
8560
8916
  }
8917
+
8918
+ // ../core/dist/tables/docstore-table-registry.js
8919
+ init_system_tables();
8920
+ init_utils();
8921
+ init_interface();
8922
+
8923
+ class DocStoreTableRegistry {
8924
+ docstore;
8925
+ tablesByNumber = new Map;
8926
+ tablesByName = new Map;
8927
+ loadPromise = null;
8928
+ cachedRegistryVersion = 0;
8929
+ constructor(docstore) {
8930
+ this.docstore = docstore;
8931
+ }
8932
+ async getOrAllocateTableNumber(tableName, componentPath = "") {
8933
+ await this.ensureLoaded();
8934
+ await this.ensureFresh();
8935
+ const normalizedComponent = isSystemTable(tableName) ? "" : componentPath;
8936
+ const fullName = getFullTableName(tableName, normalizedComponent);
8937
+ let existing = this.tablesByName.get(fullName);
8938
+ if (existing) {
8939
+ return existing.tableNumber;
8940
+ }
8941
+ await this.reloadTables();
8942
+ existing = this.tablesByName.get(fullName);
8943
+ if (existing) {
8944
+ return existing.tableNumber;
8945
+ }
8946
+ const oracle = this.docstore.timestampOracle;
8947
+ for (;; ) {
8948
+ const metadata = await readSystemMetadata(this.docstore) ?? createSystemMetadata({
8949
+ nextUserTableNumber: Math.max(FIRST_USER_TABLE_NUMBER, nextUserTableNumber(this.tablesByNumber.values()))
8950
+ });
8951
+ const candidate = Math.max(metadata.nextUserTableNumber, nextUserTableNumber(this.tablesByNumber.values()));
8952
+ const reserved = await this.docstore.writeGlobalIfAbsent(createTableNumberReservationKey(candidate), {
8953
+ fullName,
8954
+ reservedAt: Date.now()
8955
+ });
8956
+ if (!reserved) {
8957
+ await this.reloadTables();
8958
+ const raced = this.tablesByName.get(fullName);
8959
+ if (raced) {
8960
+ return raced.tableNumber;
8961
+ }
8962
+ continue;
8963
+ }
8964
+ const createdAt = Date.now();
8965
+ const info = createTableInfo(tableName, candidate, normalizedComponent, { createdAt, visibility: "public" });
8966
+ const timestamp2 = oracle?.allocateTimestamp?.() ?? BigInt(createdAt);
8967
+ const entry = createTableMetadataEntryForUserTable(info, timestamp2);
8968
+ try {
8969
+ await this.docstore.write([entry], new Set, "Error");
8970
+ } catch {
8971
+ await this.reloadTables();
8972
+ const raced = this.tablesByName.get(fullName);
8973
+ if (raced) {
8974
+ return raced.tableNumber;
8975
+ }
8976
+ throw new Error(`Failed to allocate table number for ${fullName}`);
8977
+ }
8978
+ const registryVersion = Number(timestamp2 > BigInt(Number.MAX_SAFE_INTEGER) ? BigInt(Date.now()) : timestamp2);
8979
+ await this.docstore.writeGlobal(SYSTEM_METADATA_GLOBAL_KEY, createSystemMetadata({
8980
+ nextUserTableNumber: candidate + 1,
8981
+ registryVersion,
8982
+ bootstrappedAt: metadata.bootstrappedAt,
8983
+ updatedAt: registryVersion
8984
+ }));
8985
+ this.cachedRegistryVersion = registryVersion;
8986
+ this.tablesByName.set(fullName, info);
8987
+ this.tablesByNumber.set(candidate, info);
8988
+ return candidate;
8989
+ }
8990
+ }
8991
+ async getTableInfo(tableNumber) {
8992
+ await this.ensureLoaded();
8993
+ await this.ensureFresh();
8994
+ const existing = this.tablesByNumber.get(tableNumber);
8995
+ if (existing) {
8996
+ return existing;
8997
+ }
8998
+ await this.reloadTables();
8999
+ return this.tablesByNumber.get(tableNumber) ?? null;
9000
+ }
9001
+ async getTableInfoByName(tableName, componentPath = "") {
9002
+ await this.ensureLoaded();
9003
+ await this.ensureFresh();
9004
+ const fullName = getFullTableName(tableName, isSystemTable(tableName) ? "" : componentPath);
9005
+ const existing = this.tablesByName.get(fullName);
9006
+ if (existing) {
9007
+ return existing;
9008
+ }
9009
+ await this.reloadTables();
9010
+ return this.tablesByName.get(fullName) ?? null;
9011
+ }
9012
+ async listTables(componentPath) {
9013
+ await this.ensureLoaded();
9014
+ await this.ensureFresh();
9015
+ const values = Array.from(this.tablesByNumber.values());
9016
+ if (componentPath === undefined) {
9017
+ return values.sort((a, b) => a.tableNumber - b.tableNumber);
9018
+ }
9019
+ return values.filter((table) => table.componentPath === componentPath).sort((a, b) => a.tableNumber - b.tableNumber);
9020
+ }
9021
+ async hasAccess(tableNumber, componentPath) {
9022
+ const info = await this.getTableInfo(tableNumber);
9023
+ if (!info) {
9024
+ return false;
9025
+ }
9026
+ if (info.isSystem) {
9027
+ return true;
9028
+ }
9029
+ return info.componentPath === componentPath;
9030
+ }
9031
+ getSystemTableNumber(systemTableName) {
9032
+ return SYSTEM_TABLE_NUMBERS[systemTableName];
9033
+ }
9034
+ async ensureLoaded() {
9035
+ if (!this.loadPromise) {
9036
+ this.loadPromise = this.loadTables();
9037
+ }
9038
+ await this.loadPromise;
9039
+ }
9040
+ async ensureFresh() {
9041
+ const metadata = await readSystemMetadata(this.docstore);
9042
+ if (!metadata) {
9043
+ if (this.cachedRegistryVersion !== 0 || this.tablesByName.size > 0 || this.tablesByNumber.size > 0) {
9044
+ await this.reloadTables();
9045
+ }
9046
+ return;
9047
+ }
9048
+ if (metadata.registryVersion > this.cachedRegistryVersion) {
9049
+ await this.reloadTables();
9050
+ }
9051
+ }
9052
+ async reloadTables() {
9053
+ this.loadPromise = this.loadTables();
9054
+ await this.loadPromise;
9055
+ }
9056
+ async loadTables() {
9057
+ await ensureSystemTablesBootstrapped(this.docstore);
9058
+ const docs = await this.docstore.scan(stringToHex("_tables"));
9059
+ this.tablesByName.clear();
9060
+ this.tablesByNumber.clear();
9061
+ for (const doc of docs) {
9062
+ const info = tableInfoFromStoredDocument(doc.value.value);
9063
+ if (!info) {
9064
+ continue;
9065
+ }
9066
+ this.tablesByName.set(info.fullName, info);
9067
+ this.tablesByNumber.set(info.tableNumber, info);
9068
+ }
9069
+ if (this.tablesByNumber.size === 0) {
9070
+ for (const [name, tableNumber] of Object.entries(SYSTEM_TABLE_NUMBERS)) {
9071
+ const info = createTableInfo(name, tableNumber, "", { isSystem: true });
9072
+ this.tablesByName.set(info.fullName, info);
9073
+ this.tablesByNumber.set(info.tableNumber, info);
9074
+ }
9075
+ }
9076
+ const metadata = await readSystemMetadata(this.docstore);
9077
+ if (!metadata) {
9078
+ const now = Date.now();
9079
+ this.cachedRegistryVersion = now;
9080
+ await this.docstore.writeGlobal(SYSTEM_METADATA_GLOBAL_KEY, createSystemMetadata({
9081
+ nextUserTableNumber: Math.max(FIRST_USER_TABLE_NUMBER, nextUserTableNumber(this.tablesByNumber.values())),
9082
+ registryVersion: now,
9083
+ bootstrappedAt: now,
9084
+ updatedAt: now
9085
+ }));
9086
+ } else {
9087
+ this.cachedRegistryVersion = metadata.registryVersion;
9088
+ }
9089
+ }
9090
+ }
9091
+
9092
+ // ../core/dist/tables/transactional-table-registry.js
9093
+ init_system_tables();
9094
+ init_utils();
9095
+ init_interface();
8561
9096
  // ../core/dist/kernel/contexts.js
8562
9097
  init_context_storage();
8563
- var snapshotContext = new ContextStorage;
8564
- var transactionContext = new ContextStorage;
8565
- var idGeneratorContext = new ContextStorage;
9098
+ var SNAPSHOT_CONTEXT_SYMBOL = Symbol.for("@concavejs/core/snapshot-context");
9099
+ var TRANSACTION_CONTEXT_SYMBOL = Symbol.for("@concavejs/core/transaction-context");
9100
+ var ID_GENERATOR_CONTEXT_SYMBOL = Symbol.for("@concavejs/core/id-generator-context");
9101
+ var globalContexts = globalThis;
9102
+ var snapshotContext = globalContexts[SNAPSHOT_CONTEXT_SYMBOL] ?? new ContextStorage;
9103
+ var transactionContext = globalContexts[TRANSACTION_CONTEXT_SYMBOL] ?? new ContextStorage;
9104
+ var idGeneratorContext = globalContexts[ID_GENERATOR_CONTEXT_SYMBOL] ?? new ContextStorage;
9105
+ if (!globalContexts[SNAPSHOT_CONTEXT_SYMBOL]) {
9106
+ globalContexts[SNAPSHOT_CONTEXT_SYMBOL] = snapshotContext;
9107
+ }
9108
+ if (!globalContexts[TRANSACTION_CONTEXT_SYMBOL]) {
9109
+ globalContexts[TRANSACTION_CONTEXT_SYMBOL] = transactionContext;
9110
+ }
9111
+ if (!globalContexts[ID_GENERATOR_CONTEXT_SYMBOL]) {
9112
+ globalContexts[ID_GENERATOR_CONTEXT_SYMBOL] = idGeneratorContext;
9113
+ }
8566
9114
  // ../core/dist/queryengine/convex-ops.js
8567
9115
  var debug = () => {};
8568
9116
  class CfConvex {
@@ -8615,6 +9163,8 @@ class BaseSqliteDocStore {
8615
9163
  vectorIndexesByTable = new Map;
8616
9164
  fts5Available = true;
8617
9165
  statementCache = new Map;
9166
+ configuredSearchIndexes = [];
9167
+ configuredVectorIndexes = [];
8618
9168
  constructor(adapter) {
8619
9169
  this.adapter = adapter;
8620
9170
  this.timestampOracle = new TimestampOracle;
@@ -8629,6 +9179,8 @@ class BaseSqliteDocStore {
8629
9179
  return statement;
8630
9180
  }
8631
9181
  async setupSchema(options) {
9182
+ this.configuredSearchIndexes = [...options?.searchIndexes ?? []];
9183
+ this.configuredVectorIndexes = [...options?.vectorIndexes ?? []];
8632
9184
  await this.adapter.exec(DOCUMENTS_TABLE_SCHEMA);
8633
9185
  await this.adapter.exec(DOCUMENTS_BY_TABLE_INDEX);
8634
9186
  await this.adapter.exec(INDEXES_TABLE_SCHEMA);
@@ -8636,6 +9188,24 @@ class BaseSqliteDocStore {
8636
9188
  await this.setupSearchIndexes(options?.searchIndexes ?? []);
8637
9189
  await this.setupVectorIndexes(options?.vectorIndexes ?? []);
8638
9190
  }
9191
+ async resetForTesting() {
9192
+ const rows = await this.adapter.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%' AND sql IS NOT NULL").all();
9193
+ for (const row of rows) {
9194
+ const tableName = row?.name;
9195
+ if (typeof tableName !== "string" || tableName.length === 0) {
9196
+ continue;
9197
+ }
9198
+ await this.adapter.exec(`DROP TABLE IF EXISTS ${quoteSqlIdentifier(tableName)}`);
9199
+ }
9200
+ this.statementCache.clear();
9201
+ this.searchIndexesByTable.clear();
9202
+ this.vectorIndexesByTable.clear();
9203
+ this.fts5Available = true;
9204
+ await this.setupSchema({
9205
+ searchIndexes: this.configuredSearchIndexes,
9206
+ vectorIndexes: this.configuredVectorIndexes
9207
+ });
9208
+ }
8639
9209
  async setupSearchIndexes(searchIndexes) {
8640
9210
  try {
8641
9211
  await this.adapter.exec(SEARCH_INDEXES_FTS_SCHEMA);
@@ -8851,6 +9421,15 @@ class BaseSqliteDocStore {
8851
9421
  const stmt = this.getPreparedStatement("INSERT OR REPLACE INTO persistence_globals (key, json_value) VALUES (?, ?)");
8852
9422
  await stmt.run(key, JSON.stringify(value));
8853
9423
  }
9424
+ async writeGlobalIfAbsent(key, value) {
9425
+ const insertStmt = this.getPreparedStatement("INSERT OR IGNORE INTO persistence_globals (key, json_value) VALUES (?, ?)");
9426
+ const changesStmt = this.getPreparedStatement("SELECT changes() as changes");
9427
+ return this.adapter.transaction(async () => {
9428
+ await insertStmt.run(key, JSON.stringify(value));
9429
+ const row = await changesStmt.get();
9430
+ return Number(row?.changes ?? 0) > 0;
9431
+ });
9432
+ }
8854
9433
  async previous_revisions(queries) {
8855
9434
  const results = new Map;
8856
9435
  const stmt = this.getPreparedStatement(`
@@ -9146,6 +9725,9 @@ class BaseSqliteDocStore {
9146
9725
  return scored.slice(0, limit);
9147
9726
  }
9148
9727
  }
9728
+ function quoteSqlIdentifier(value) {
9729
+ return `"${value.replace(/"/g, '""')}"`;
9730
+ }
9149
9731
  // ../docstore-sqlite-base/dist/transaction-runner.js
9150
9732
  function createSerializedTransactionRunner(hooks) {
9151
9733
  let queue = Promise.resolve();