@concavejs/docstore-bun-sqlite 0.0.1-alpha.11 → 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 +1062 -489
  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;
@@ -4764,47 +5035,231 @@ var init_auth = __esm(() => {
4764
5035
  init_auth_config_service();
4765
5036
  });
4766
5037
 
4767
- // ../core/dist/system/internal.js
4768
- function requireSystemCapability(capability) {
4769
- const principal2 = getPrincipal();
4770
- if (!principal2) {
4771
- throw new Error("System functions require authentication context");
4772
- }
4773
- requireAuthorization(principal2, { kind: "management_operation", capability });
4774
- }
4775
- function createSystemFunctions(deps) {
4776
- const { query, mutation } = deps;
4777
- return {
4778
- systemListComponents: query({
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;
5249
+ return {
5250
+ systemListComponents: query({
4779
5251
  args: {},
4780
- handler: async (_ctx) => {
5252
+ handler: async (ctx) => {
4781
5253
  requireSystemCapability("components:read");
4782
- const modules = await listRegisteredModules();
4783
- const componentPaths = new Set;
4784
- componentPaths.add("");
4785
- for (const module of modules) {
4786
- if (module.componentPath) {
4787
- componentPaths.add(module.componentPath);
4788
- }
4789
- }
4790
- const components = [];
4791
- for (const path of componentPaths) {
4792
- const componentModules = modules.filter((m) => path === "" ? !m.componentPath || m.componentPath === "" : m.componentPath === path);
4793
- const functions = await listSystemFunctions({ componentPath: path || undefined });
4794
- components.push({
4795
- path: path || "(root)",
4796
- isRoot: path === "",
4797
- 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,
4798
5259
  functionCount: functions.length
4799
- });
4800
- }
4801
- return components.sort((a, b) => {
4802
- if (a.isRoot)
4803
- return -1;
4804
- if (b.isRoot)
4805
- return 1;
4806
- return a.path.localeCompare(b.path);
4807
- });
5260
+ };
5261
+ }));
5262
+ return sortComponentRows(withFunctionCounts);
4808
5263
  }
4809
5264
  }),
4810
5265
  systemListTables: query({
@@ -4813,25 +5268,40 @@ function createSystemFunctions(deps) {
4813
5268
  requireSystemCapability("tables:read");
4814
5269
  const targetComponent = componentPath ?? "";
4815
5270
  const schema2 = await loadSchemaDefinition(targetComponent);
4816
- let tableEntries = [];
5271
+ const schemaTables = new Map;
4817
5272
  if (schema2?.tables) {
4818
- tableEntries = extractTablesFromSchema(schema2);
4819
- } else {
4820
- try {
4821
- const systemTables = await ctx.db.system.query("_tables").collect();
4822
- tableEntries = systemTables.map((table) => ({
4823
- name: table.name,
4824
- exported: {
4825
- indexes: table.indexes || [],
4826
- searchIndexes: table.searchIndexes || [],
4827
- vectorIndexes: table.vectorIndexes || [],
4828
- documentType: null
4829
- }
4830
- }));
4831
- } catch {
4832
- tableEntries = [];
5273
+ for (const table of extractTablesFromSchema(schema2)) {
5274
+ schemaTables.set(table.name, table);
4833
5275
  }
4834
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
+ }));
4835
5305
  const tableInfo = await Promise.all(tableEntries.map(async (table) => {
4836
5306
  const fullName = getFullTableName(table.name, targetComponent);
4837
5307
  const documentCount = await countDocuments(ctx, fullName);
@@ -4842,6 +5312,8 @@ function createSystemFunctions(deps) {
4842
5312
  name: table.name,
4843
5313
  fullName,
4844
5314
  componentPath: targetComponent || undefined,
5315
+ isSystem: table.isSystem,
5316
+ visibility: table.visibility,
4845
5317
  documentCount,
4846
5318
  indexes: buildIndexList(exported?.indexes),
4847
5319
  searchIndexes: searchIndexes.map((idx) => typeof idx === "string" ? idx : idx.indexDescriptor),
@@ -4875,7 +5347,7 @@ function createSystemFunctions(deps) {
4875
5347
  }
4876
5348
  try {
4877
5349
  const fullName = getFullTableName(tableName, targetComponent);
4878
- const sampleDoc = await ctx.db.query(fullName).first();
5350
+ const sampleDoc = await getTableQuery(ctx, fullName).first();
4879
5351
  const fields = sampleDoc ? Object.keys(sampleDoc).map((key) => ({
4880
5352
  name: key,
4881
5353
  type: typeof sampleDoc[key],
@@ -4910,7 +5382,7 @@ function createSystemFunctions(deps) {
4910
5382
  handler: async (ctx, args) => {
4911
5383
  requireSystemCapability("documents:read");
4912
5384
  const fullName = getFullTableName(args.tableName, args.componentPath ?? "");
4913
- let query2 = ctx.db.query(fullName);
5385
+ let query2 = getTableQuery(ctx, fullName);
4914
5386
  if (args.orderBy && args.orderBy !== "_creationTime") {
4915
5387
  const allDocs2 = await query2.collect();
4916
5388
  const sorted = allDocs2.sort((a, b) => {
@@ -4961,7 +5433,7 @@ function createSystemFunctions(deps) {
4961
5433
  handler: async (ctx, args) => {
4962
5434
  requireSystemCapability("documents:write");
4963
5435
  const fullName = getFullTableName(args.tableName, args.componentPath ?? "");
4964
- const docs = await ctx.db.query(fullName).collect();
5436
+ const docs = await getTableQuery(ctx, fullName).collect();
4965
5437
  for (const doc of docs) {
4966
5438
  await ctx.db.delete(doc._id);
4967
5439
  }
@@ -5257,6 +5729,83 @@ function resolveFunctionReference(functionPath, componentPath) {
5257
5729
  }
5258
5730
  return functionPath;
5259
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
+ }
5260
5809
  async function loadSchemaDefinition(componentPath) {
5261
5810
  try {
5262
5811
  const module = await loadConvexModule("schema", {
@@ -5290,13 +5839,26 @@ function extractTableMetadata(schema2, tableName) {
5290
5839
  }
5291
5840
  async function countDocuments(ctx, tableName) {
5292
5841
  try {
5293
- const documents = await ctx.db.query(tableName).collect();
5842
+ const documents = await getTableQuery(ctx, tableName).collect();
5294
5843
  return documents.length;
5295
5844
  } catch (error) {
5296
5845
  console.warn(`Failed to count documents for table ${tableName}:`, error);
5297
5846
  return 0;
5298
5847
  }
5299
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
+ }
5300
5862
  function buildIndexList(indexes) {
5301
5863
  const base = ["by_id", "by_creation_time"];
5302
5864
  if (!indexes || indexes.length === 0) {
@@ -5398,6 +5960,7 @@ var init_internal = __esm(() => {
5398
5960
  init_interface();
5399
5961
  init_execution_log();
5400
5962
  init_auth();
5963
+ init_system_tables();
5401
5964
  });
5402
5965
 
5403
5966
  // ../core/dist/system/system-functions-module.js
@@ -5555,8 +6118,9 @@ class ModuleRegistry {
5555
6118
  const normalized = normalizeModuleListing(listing);
5556
6119
  if (!normalized)
5557
6120
  continue;
5558
- if (!results.has(normalized.path)) {
5559
- results.set(normalized.path, {
6121
+ const resultKey = `${normalized.componentPath ?? scope ?? ""}:${normalized.path}`;
6122
+ if (!results.has(resultKey)) {
6123
+ results.set(resultKey, {
5560
6124
  ...normalized,
5561
6125
  scope: scope || undefined,
5562
6126
  componentPath: normalized.componentPath ?? (scope || undefined)
@@ -5875,8 +6439,10 @@ var init_module_loader = __esm(() => {
5875
6439
  class SchemaValidator {
5876
6440
  schemaCache = new Map;
5877
6441
  componentPath;
5878
- constructor(componentPath) {
6442
+ tableRegistry;
6443
+ constructor(componentPath, tableRegistry) {
5879
6444
  this.componentPath = componentPath;
6445
+ this.tableRegistry = tableRegistry;
5880
6446
  }
5881
6447
  async loadTableSchema(tableName) {
5882
6448
  if (this.schemaCache.has(tableName)) {
@@ -5919,8 +6485,11 @@ class SchemaValidator {
5919
6485
  return;
5920
6486
  }
5921
6487
  try {
6488
+ const tableNumberToName = this.tableRegistry ? new Map((await this.tableRegistry.listTables()).map((table) => [table.tableNumber, table.fullName])) : undefined;
5922
6489
  validateValidator(tableSchema, omit(document, ["_id", "_creationTime"]), "", {
5923
- componentPath: this.componentPath ?? ""
6490
+ componentPath: this.componentPath ?? "",
6491
+ tableRegistry: this.tableRegistry,
6492
+ tableNumberToName
5924
6493
  });
5925
6494
  } catch (error) {
5926
6495
  throw new ValidatorError(`Failed to insert or update a document in table "${tableName}" because it does not match the schema: ${error.message}`);
@@ -6018,6 +6587,16 @@ Path: ${formatPath(path)}
6018
6587
  Value: ${formatValue(value)}
6019
6588
  Validator: v.id("${validator2.tableName}")`);
6020
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
+ }
6021
6600
  const tableName = tableNameFromId(value);
6022
6601
  if (!tableName || !isMatchingValidatorTable(tableName, validator2.tableName, options.componentPath)) {
6023
6602
  throw new Error(`Value does not match validator.
@@ -6079,289 +6658,72 @@ Validator: v.object({...})`);
6079
6658
  }
6080
6659
  } else {
6081
6660
  const fieldPath = path ? `${path}.${k}` : `.${k}`;
6082
- validateValidator(fieldType, value[k], fieldPath, options);
6083
- }
6084
- }
6085
- for (const k of Object.keys(value)) {
6086
- if (validator2.value[k] === undefined) {
6087
- throw new Error(`Object contains extra field \`${k}\` that is not in the validator.
6088
-
6089
- Object: ${JSON.stringify(value)}
6090
- Validator: v.object({...})`);
6091
- }
6092
- }
6093
- return;
6094
- }
6095
- }
6096
- }
6097
- function tableNameFromId(id) {
6098
- const parts = deserializeDeveloperId(id);
6099
- if (!parts) {
6100
- return null;
6101
- }
6102
- return hexToString(parts.table);
6103
- }
6104
- function isMatchingValidatorTable(idTableName, validatorTableName, componentPath) {
6105
- if (idTableName === validatorTableName) {
6106
- return true;
6107
- }
6108
- const { tableName: validatorBareName } = parseFullTableName(validatorTableName);
6109
- const { tableName: idBareName } = parseFullTableName(idTableName);
6110
- if (componentPath !== undefined) {
6111
- const expectedFullName = getFullTableName(validatorBareName, componentPath);
6112
- return idTableName === expectedFullName;
6113
- }
6114
- return idBareName === validatorBareName;
6115
- }
6116
- function isSimpleObject2(value) {
6117
- const isObject2 = typeof value === "object";
6118
- const prototype = Object.getPrototypeOf(value);
6119
- const isSimple = prototype === null || prototype === Object.prototype || prototype?.constructor?.name === "Object";
6120
- return isObject2 && isSimple;
6121
- }
6122
- var ValidatorError;
6123
- var init_validator2 = __esm(() => {
6124
- init_interface();
6125
- init_module_loader();
6126
- ValidatorError = class ValidatorError extends Error {
6127
- path;
6128
- constructor(message2, path = "") {
6129
- super(message2);
6130
- this.path = path;
6131
- this.name = "ValidatorError";
6132
- }
6133
- };
6134
- });
6135
-
6136
- // ../core/dist/id-codec/base32.js
6137
- function base32Encode(data) {
6138
- if (data.length === 0)
6139
- return "";
6140
- let result = "";
6141
- let buffer = 0;
6142
- let bitsLeft = 0;
6143
- for (const byte of data) {
6144
- buffer = buffer << 8 | byte;
6145
- bitsLeft += 8;
6146
- while (bitsLeft >= 5) {
6147
- bitsLeft -= 5;
6148
- const index = buffer >> bitsLeft & 31;
6149
- result += ALPHABET[index];
6150
- }
6151
- }
6152
- if (bitsLeft > 0) {
6153
- const index = buffer << 5 - bitsLeft & 31;
6154
- result += ALPHABET[index];
6155
- }
6156
- return result;
6157
- }
6158
- function base32Decode(str) {
6159
- if (str.length === 0)
6160
- return new Uint8Array(0);
6161
- const outputLength = Math.floor(str.length * 5 / 8);
6162
- const result = new Uint8Array(outputLength);
6163
- let buffer = 0;
6164
- let bitsLeft = 0;
6165
- let outputIndex = 0;
6166
- for (const char of str) {
6167
- const value = ALPHABET_MAP.get(char);
6168
- if (value === undefined) {
6169
- throw new Error(`Invalid base32 character: ${char}`);
6170
- }
6171
- buffer = buffer << 5 | value;
6172
- bitsLeft += 5;
6173
- if (bitsLeft >= 8) {
6174
- bitsLeft -= 8;
6175
- result[outputIndex++] = buffer >> bitsLeft & 255;
6176
- }
6177
- }
6178
- return result;
6179
- }
6180
- function isValidBase32(str) {
6181
- for (const char of str) {
6182
- if (!ALPHABET_MAP.has(char)) {
6183
- return false;
6184
- }
6185
- }
6186
- return true;
6187
- }
6188
- var ALPHABET = "0123456789abcdefghjkmnpqrstvwxyz", ALPHABET_MAP;
6189
- var init_base32 = __esm(() => {
6190
- ALPHABET_MAP = new Map;
6191
- for (let i2 = 0;i2 < ALPHABET.length; i2++) {
6192
- ALPHABET_MAP.set(ALPHABET[i2], i2);
6193
- ALPHABET_MAP.set(ALPHABET[i2].toUpperCase(), i2);
6194
- }
6195
- ALPHABET_MAP.set("i", 1);
6196
- ALPHABET_MAP.set("I", 1);
6197
- ALPHABET_MAP.set("l", 1);
6198
- ALPHABET_MAP.set("L", 1);
6199
- ALPHABET_MAP.set("o", 0);
6200
- ALPHABET_MAP.set("O", 0);
6201
- });
6202
-
6203
- // ../core/dist/id-codec/vint.js
6204
- function vintEncode(value) {
6205
- if (value < 0) {
6206
- throw new Error("VInt cannot encode negative numbers");
6207
- }
6208
- if (value > 4294967295) {
6209
- throw new Error("VInt cannot encode values larger than 2^32-1");
6210
- }
6211
- value = value >>> 0;
6212
- if (value < 128) {
6213
- return new Uint8Array([value]);
6214
- }
6215
- if (value < 16512) {
6216
- const adjusted2 = value - 128;
6217
- return new Uint8Array([128 | adjusted2 >> 8 & 63, adjusted2 & 255]);
6218
- }
6219
- if (value < 2113664) {
6220
- const adjusted2 = value - 16512;
6221
- return new Uint8Array([192 | adjusted2 >> 16 & 31, adjusted2 >> 8 & 255, adjusted2 & 255]);
6222
- }
6223
- if (value < 270549120) {
6224
- const adjusted2 = value - 2113664;
6225
- return new Uint8Array([
6226
- 224 | adjusted2 >> 24 & 15,
6227
- adjusted2 >> 16 & 255,
6228
- adjusted2 >> 8 & 255,
6229
- adjusted2 & 255
6230
- ]);
6231
- }
6232
- const adjusted = value - 270549120;
6233
- return new Uint8Array([
6234
- 240 | adjusted >> 32 & 7,
6235
- adjusted >> 24 & 255,
6236
- adjusted >> 16 & 255,
6237
- adjusted >> 8 & 255,
6238
- adjusted & 255
6239
- ]);
6240
- }
6241
- function vintDecode(data, offset = 0) {
6242
- if (offset >= data.length) {
6243
- throw new Error("VInt decode: unexpected end of data");
6244
- }
6245
- const first = data[offset];
6246
- if ((first & 128) === 0) {
6247
- return { value: first, bytesRead: 1 };
6248
- }
6249
- if ((first & 192) === 128) {
6250
- if (offset + 1 >= data.length) {
6251
- throw new Error("VInt decode: truncated 2-byte encoding");
6252
- }
6253
- const value = 128 + ((first & 63) << 8 | data[offset + 1]);
6254
- return { value, bytesRead: 2 };
6255
- }
6256
- if ((first & 224) === 192) {
6257
- if (offset + 2 >= data.length) {
6258
- throw new Error("VInt decode: truncated 3-byte encoding");
6259
- }
6260
- const value = 16512 + ((first & 31) << 16 | data[offset + 1] << 8 | data[offset + 2]);
6261
- return { value, bytesRead: 3 };
6262
- }
6263
- if ((first & 240) === 224) {
6264
- if (offset + 3 >= data.length) {
6265
- throw new Error("VInt decode: truncated 4-byte encoding");
6266
- }
6267
- const value = 2113664 + ((first & 15) << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3]);
6268
- return { value: value >>> 0, bytesRead: 4 };
6269
- }
6270
- if ((first & 248) === 240) {
6271
- if (offset + 4 >= data.length) {
6272
- throw new Error("VInt decode: truncated 5-byte encoding");
6273
- }
6274
- const high = first & 7;
6275
- const low = (data[offset + 1] << 24 | data[offset + 2] << 16 | data[offset + 3] << 8 | data[offset + 4]) >>> 0;
6276
- const value = 270549120 + high * 4294967296 + low;
6277
- return { value: value >>> 0, bytesRead: 5 };
6278
- }
6279
- throw new Error("VInt decode: invalid prefix");
6280
- }
6281
-
6282
- // ../core/dist/id-codec/fletcher16.js
6283
- function fletcher16(data) {
6284
- let sum1 = 0;
6285
- let sum2 = 0;
6286
- for (const byte of data) {
6287
- sum1 = (sum1 + byte) % 255;
6288
- sum2 = (sum2 + sum1) % 255;
6289
- }
6290
- return new Uint8Array([sum1, sum2]);
6291
- }
6292
- function verifyFletcher16(data, checksum) {
6293
- if (checksum.length !== 2)
6294
- return false;
6295
- const computed = fletcher16(data);
6296
- return computed[0] === checksum[0] && computed[1] === checksum[1];
6297
- }
6298
-
6299
- // ../core/dist/utils/crypto.js
6300
- var weakRandomState;
6301
- var init_crypto = __esm(() => {
6302
- weakRandomState = (Date.now() ^ 2654435769) >>> 0;
6303
- });
6304
-
6305
- // ../core/dist/id-codec/document-id.js
6306
- function encodeDocumentId(tableNumber, internalId) {
6307
- if (internalId.length !== INTERNAL_ID_LENGTH) {
6308
- throw new Error(`Internal ID must be exactly ${INTERNAL_ID_LENGTH} bytes, got ${internalId.length}`);
6309
- }
6310
- if (tableNumber < 1 || tableNumber > 4294967295) {
6311
- throw new Error(`Table number must be between 1 and 2^32-1, got ${tableNumber}`);
6312
- }
6313
- const tableBytes = vintEncode(tableNumber);
6314
- const payload = new Uint8Array(tableBytes.length + INTERNAL_ID_LENGTH);
6315
- payload.set(tableBytes, 0);
6316
- payload.set(internalId, tableBytes.length);
6317
- const checksum = fletcher16(payload);
6318
- const final = new Uint8Array(payload.length + 2);
6319
- final.set(payload, 0);
6320
- final.set(checksum, payload.length);
6321
- return base32Encode(final);
6322
- }
6323
- function decodeDocumentId(encoded) {
6324
- if (encoded.length < MIN_ENCODED_LENGTH || encoded.length > MAX_ENCODED_LENGTH) {
6325
- throw new Error(`Invalid document ID length: ${encoded.length} (expected ${MIN_ENCODED_LENGTH}-${MAX_ENCODED_LENGTH})`);
6326
- }
6327
- if (!isValidBase32(encoded)) {
6328
- throw new Error("Invalid document ID: contains invalid base32 characters");
6329
- }
6330
- const bytes = base32Decode(encoded);
6331
- if (bytes.length < 19) {
6332
- throw new Error(`Invalid document ID: decoded to ${bytes.length} bytes (minimum 19)`);
6333
- }
6334
- const checksum = bytes.slice(bytes.length - 2);
6335
- const payload = bytes.slice(0, bytes.length - 2);
6336
- if (!verifyFletcher16(payload, checksum)) {
6337
- 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
+ }
6338
6674
  }
6339
- const { value: tableNumber, bytesRead } = vintDecode(payload, 0);
6340
- const internalId = payload.slice(bytesRead, bytesRead + INTERNAL_ID_LENGTH);
6341
- if (internalId.length !== INTERNAL_ID_LENGTH) {
6342
- 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;
6343
6680
  }
6344
- return { tableNumber, internalId };
6681
+ return hexToString(parts.table);
6345
6682
  }
6346
- function isValidDocumentId(encoded) {
6683
+ function tableNameFromConvexId(id, options) {
6347
6684
  try {
6348
- decodeDocumentId(encoded);
6349
- 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;
6350
6691
  } catch {
6351
- return false;
6692
+ return null;
6352
6693
  }
6353
6694
  }
6354
- function internalIdToHex(internalId) {
6355
- let hex = "";
6356
- for (let i2 = 0;i2 < internalId.length; i2++) {
6357
- hex += internalId[i2].toString(16).padStart(2, "0");
6695
+ function isMatchingValidatorTable(idTableName, validatorTableName, componentPath) {
6696
+ if (idTableName === validatorTableName) {
6697
+ return true;
6358
6698
  }
6359
- 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;
6360
6706
  }
6361
- var INTERNAL_ID_LENGTH = 16, MIN_ENCODED_LENGTH = 31, MAX_ENCODED_LENGTH = 37;
6362
- var init_document_id = __esm(() => {
6363
- init_base32();
6364
- 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
+ };
6365
6727
  });
6366
6728
 
6367
6729
  // src/sqlite-docstore.ts
@@ -6372,7 +6734,10 @@ init_values();
6372
6734
 
6373
6735
  // ../core/dist/docstore/interface.js
6374
6736
  function documentIdKey(id) {
6375
- 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
+ }
6376
6741
  return `${tableKey}:${id.internalId}`;
6377
6742
  }
6378
6743
  var Order;
@@ -6579,6 +6944,7 @@ class TimestampOracle {
6579
6944
  }
6580
6945
  }
6581
6946
  // ../core/dist/utils/keyspace.js
6947
+ init_utils();
6582
6948
  var TABLE_PREFIX = "table";
6583
6949
  var INDEX_PREFIX = "index";
6584
6950
  function encodeComponent(component) {
@@ -6619,6 +6985,13 @@ function decodeIndexId(indexId) {
6619
6985
  index: decoded.slice(separatorIndex + 1)
6620
6986
  };
6621
6987
  }
6988
+
6989
+ // ../core/dist/utils/index.js
6990
+ init_utils();
6991
+
6992
+ // ../core/dist/queryengine/indexing/index-manager.js
6993
+ init_utils();
6994
+
6622
6995
  // ../core/dist/queryengine/indexing/index-key-codec.js
6623
6996
  var TypeTag;
6624
6997
  (function(TypeTag2) {
@@ -6668,8 +7041,9 @@ function encodeBigInt(n) {
6668
7041
  return bytes;
6669
7042
  }
6670
7043
  function encodeString(s) {
6671
- const encoder = new TextEncoder;
6672
- const raw = encoder.encode(s);
7044
+ return encodeEscapedBytes(new TextEncoder().encode(s));
7045
+ }
7046
+ function encodeEscapedBytes(raw) {
6673
7047
  let nullCount = 0;
6674
7048
  for (const byte of raw) {
6675
7049
  if (byte === 0)
@@ -6733,11 +7107,10 @@ function encodeValue(value) {
6733
7107
  }
6734
7108
  if (value instanceof ArrayBuffer || value instanceof Uint8Array) {
6735
7109
  const bytes = value instanceof Uint8Array ? value : new Uint8Array(value);
6736
- const result = new Uint8Array(1 + bytes.length + 2);
7110
+ const encoded = encodeEscapedBytes(bytes);
7111
+ const result = new Uint8Array(1 + encoded.length);
6737
7112
  result[0] = TypeTag.Bytes;
6738
- result.set(bytes, 1);
6739
- result[result.length - 2] = 0;
6740
- result[result.length - 1] = 0;
7113
+ result.set(encoded, 1);
6741
7114
  return result;
6742
7115
  }
6743
7116
  throw new Error(`Cannot encode value of type ${typeof value} in index key`);
@@ -6854,9 +7227,11 @@ class SchemaService {
6854
7227
  tableCache = new Map;
6855
7228
  schemaValidator;
6856
7229
  componentPath;
6857
- constructor(componentPath) {
7230
+ tableRegistry;
7231
+ constructor(componentPath, tableRegistry) {
6858
7232
  this.componentPath = componentPath;
6859
- this.schemaValidator = new SchemaValidator(componentPath);
7233
+ this.tableRegistry = tableRegistry;
7234
+ this.schemaValidator = new SchemaValidator(componentPath, tableRegistry);
6860
7235
  }
6861
7236
  async validate(tableName, document) {
6862
7237
  try {
@@ -6981,6 +7356,10 @@ class SchemaService {
6981
7356
  return this.cachedSchemaDefinition;
6982
7357
  }
6983
7358
  }
7359
+
7360
+ // ../core/dist/queryengine/index-query.js
7361
+ init_utils();
7362
+
6984
7363
  // ../core/dist/observability/udf-trace.js
6985
7364
  init_context_storage();
6986
7365
  var TRACE_CONTEXT = new ContextStorage;
@@ -7224,11 +7603,10 @@ function evaluateFieldPath(fieldPath, document) {
7224
7603
  }
7225
7604
  return current;
7226
7605
  }
7227
- // ../core/dist/id-codec/index.js
7228
- init_base32();
7229
- init_document_id();
7230
7606
 
7231
7607
  // ../core/dist/queryengine/developer-id.js
7608
+ init_utils();
7609
+ init_id_codec();
7232
7610
  function parseDeveloperId(developerId) {
7233
7611
  if (isValidDocumentId(developerId)) {
7234
7612
  try {
@@ -7246,6 +7624,25 @@ function parseDeveloperId(developerId) {
7246
7624
  }
7247
7625
  return { table: parts.table, internalId: parts.internalId };
7248
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
+ }
7249
7646
  function parseStorageId(storageId) {
7250
7647
  const parsed = parseDeveloperId(storageId);
7251
7648
  if (parsed) {
@@ -7262,12 +7659,21 @@ function parseStorageId(storageId) {
7262
7659
  function isTablePlaceholder(table) {
7263
7660
  return table.startsWith("#");
7264
7661
  }
7662
+
7663
+ // ../core/dist/query/query-runtime.js
7664
+ init_utils();
7665
+
7265
7666
  // ../core/dist/query/planner.js
7266
7667
  init_interface();
7668
+ init_utils();
7669
+
7267
7670
  // ../core/dist/query/actions.js
7671
+ init_utils();
7268
7672
  init_interface();
7269
7673
 
7270
7674
  // ../core/dist/queryengine/indexing/read-write-set.js
7675
+ init_utils();
7676
+
7271
7677
  class RangeSet {
7272
7678
  ranges = new Map;
7273
7679
  addDocument(docId) {
@@ -7378,6 +7784,8 @@ function deserializeKeyRange(serialized) {
7378
7784
  }
7379
7785
 
7380
7786
  // ../core/dist/kernel/access-log.js
7787
+ init_utils();
7788
+
7381
7789
  class AccessLog {
7382
7790
  ranges = new RangeSet;
7383
7791
  addDocument(docId) {
@@ -7402,104 +7810,9 @@ class AccessLog {
7402
7810
  }
7403
7811
  }
7404
7812
 
7405
- // ../core/dist/tables/memory-table-registry.js
7813
+ // ../core/dist/kernel/kernel-context.js
7406
7814
  init_interface();
7407
7815
 
7408
- class MemoryTableRegistry {
7409
- tablesByName = new Map;
7410
- tablesByNumber = new Map;
7411
- nextTableNumber = FIRST_USER_TABLE_NUMBER;
7412
- constructor() {
7413
- this.registerSystemTables();
7414
- }
7415
- registerSystemTables() {
7416
- for (const [name, number] of Object.entries(SYSTEM_TABLE_NUMBERS)) {
7417
- const info = {
7418
- tableNumber: number,
7419
- name,
7420
- componentPath: "",
7421
- fullName: name,
7422
- isSystem: true,
7423
- createdAt: Date.now()
7424
- };
7425
- this.tablesByName.set(name, info);
7426
- this.tablesByNumber.set(number, info);
7427
- }
7428
- }
7429
- async getOrAllocateTableNumber(tableName, componentPath = "") {
7430
- const fullName = getFullTableName(tableName, componentPath);
7431
- const existing = this.tablesByName.get(fullName);
7432
- if (existing) {
7433
- return existing.tableNumber;
7434
- }
7435
- if (isSystemTable(tableName) && componentPath === "") {
7436
- const systemNumber = SYSTEM_TABLE_NUMBERS[tableName];
7437
- if (systemNumber !== undefined) {
7438
- return systemNumber;
7439
- }
7440
- }
7441
- const tableNumber = this.nextTableNumber++;
7442
- const info = {
7443
- tableNumber,
7444
- name: tableName,
7445
- componentPath,
7446
- fullName,
7447
- isSystem: false,
7448
- createdAt: Date.now()
7449
- };
7450
- this.tablesByName.set(fullName, info);
7451
- this.tablesByNumber.set(tableNumber, info);
7452
- return tableNumber;
7453
- }
7454
- async getTableInfo(tableNumber) {
7455
- return this.tablesByNumber.get(tableNumber) ?? null;
7456
- }
7457
- async getTableInfoByName(tableName, componentPath = "") {
7458
- const fullName = getFullTableName(tableName, componentPath);
7459
- return this.tablesByName.get(fullName) ?? null;
7460
- }
7461
- async listTables(componentPath) {
7462
- const tables = Array.from(this.tablesByNumber.values());
7463
- if (componentPath === undefined) {
7464
- return tables;
7465
- }
7466
- return tables.filter((t) => t.componentPath === componentPath);
7467
- }
7468
- async hasAccess(tableNumber, componentPath) {
7469
- const info = await this.getTableInfo(tableNumber);
7470
- if (!info) {
7471
- return false;
7472
- }
7473
- if (info.isSystem) {
7474
- return true;
7475
- }
7476
- return info.componentPath === componentPath;
7477
- }
7478
- getSystemTableNumber(systemTableName) {
7479
- return SYSTEM_TABLE_NUMBERS[systemTableName];
7480
- }
7481
- reset() {
7482
- this.tablesByName.clear();
7483
- this.tablesByNumber.clear();
7484
- this.nextTableNumber = FIRST_USER_TABLE_NUMBER;
7485
- this.registerSystemTables();
7486
- }
7487
- getState() {
7488
- return {
7489
- tableCount: this.tablesByNumber.size,
7490
- nextNumber: this.nextTableNumber
7491
- };
7492
- }
7493
- }
7494
- var globalRegistry = null;
7495
- function getGlobalTableRegistry() {
7496
- if (!globalRegistry) {
7497
- globalRegistry = new MemoryTableRegistry;
7498
- }
7499
- return globalRegistry;
7500
- }
7501
-
7502
- // ../core/dist/kernel/kernel-context.js
7503
7816
  class KernelContext {
7504
7817
  authContext;
7505
7818
  componentPath;
@@ -7516,11 +7829,14 @@ class KernelContext {
7516
7829
  this.authContext = options.authContext;
7517
7830
  this.componentPath = options.componentPath ?? "";
7518
7831
  this.mutationTransaction = options.mutationTransaction;
7519
- this.tableRegistry = options.tableRegistry ?? getGlobalTableRegistry();
7520
- 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;
7521
7837
  }
7522
7838
  async getTableNumber(tableName) {
7523
- return this.tableRegistry.getOrAllocateTableNumber(tableName, this.componentPath);
7839
+ return this.tableRegistry.getOrAllocateTableNumber(tableName, isSystemTable(tableName) ? "" : this.componentPath);
7524
7840
  }
7525
7841
  nextSubrequestId(prefix, udfPath) {
7526
7842
  return `${prefix}:${udfPath}:${Date.now()}:${Math.random()}:${this.subrequestCounter++}`;
@@ -7565,7 +7881,7 @@ class KernelContext {
7565
7881
  this.writeLog.addDocument(docId);
7566
7882
  }
7567
7883
  recordLocalWrite(developerId, tableName, value, docId) {
7568
- this.localWrites.set(developerId, { table: tableName, value });
7884
+ this.localWrites.set(developerId, { table: tableName, value, docId });
7569
7885
  if (docId) {
7570
7886
  this.recordDocumentWrite(docId);
7571
7887
  return;
@@ -7607,7 +7923,13 @@ class KernelContext {
7607
7923
  }
7608
7924
  }
7609
7925
 
7926
+ // ../core/dist/kernel/udf-kernel.js
7927
+ init_id_codec();
7928
+
7610
7929
  // ../core/dist/kernel/blob-store-gateway.js
7930
+ init_id_codec();
7931
+ init_utils();
7932
+
7611
7933
  class BlobStoreGateway {
7612
7934
  context;
7613
7935
  docStore;
@@ -7656,7 +7978,7 @@ class BlobStoreGateway {
7656
7978
  if (!this.storage) {
7657
7979
  return null;
7658
7980
  }
7659
- const docId = parseStorageId(storageId);
7981
+ const docId = await parseDeveloperIdWithTableRegistry(storageId, this.context.tableRegistry) ?? parseStorageId(storageId);
7660
7982
  if (!docId) {
7661
7983
  console.debug(`[BlobStoreGateway] Failed to parse storage ID: ${storageId}`);
7662
7984
  return null;
@@ -7677,7 +7999,7 @@ class BlobStoreGateway {
7677
7999
  if (!this.storage) {
7678
8000
  return null;
7679
8001
  }
7680
- const docId = parseStorageId(storageId);
8002
+ const docId = await parseDeveloperIdWithTableRegistry(storageId, this.context.tableRegistry) ?? parseStorageId(storageId);
7681
8003
  if (!docId) {
7682
8004
  return null;
7683
8005
  }
@@ -7690,7 +8012,7 @@ class BlobStoreGateway {
7690
8012
  }
7691
8013
  async delete(storageId) {
7692
8014
  const storage2 = this.requireStorage();
7693
- const docId = parseStorageId(storageId);
8015
+ const docId = await parseDeveloperIdWithTableRegistry(storageId, this.context.tableRegistry) ?? parseStorageId(storageId);
7694
8016
  if (!docId) {
7695
8017
  return;
7696
8018
  }
@@ -7715,13 +8037,17 @@ class BlobStoreGateway {
7715
8037
 
7716
8038
  // ../core/dist/kernel/scheduler-gateway.js
7717
8039
  init_values();
8040
+ init_id_codec();
8041
+ init_utils();
8042
+
7718
8043
  // ../core/dist/kernel/syscalls/utils.js
7719
8044
  init_values();
8045
+ init_utils();
7720
8046
  async function resolveTableName(docId, tableRegistry) {
7721
8047
  if (docId.tableNumber !== undefined) {
7722
8048
  const info = await tableRegistry.getTableInfo(docId.tableNumber);
7723
8049
  if (info) {
7724
- return info.name;
8050
+ return info.fullName;
7725
8051
  }
7726
8052
  if (!isTablePlaceholder(docId.table)) {
7727
8053
  return hexToString(docId.table);
@@ -7902,7 +8228,7 @@ class SchedulerGateway {
7902
8228
  return developerId;
7903
8229
  }
7904
8230
  async cancel(id, state) {
7905
- const docId = parseDeveloperId(id);
8231
+ const docId = await parseDeveloperIdWithTableRegistry(id, this.context.tableRegistry);
7906
8232
  if (!docId) {
7907
8233
  throw new Error(`Scheduled job with id ${id} not found.`);
7908
8234
  }
@@ -8027,6 +8353,8 @@ class ActionSyscalls {
8027
8353
 
8028
8354
  // ../core/dist/kernel/syscalls/database-syscalls.js
8029
8355
  init_values();
8356
+ init_id_codec();
8357
+ init_utils();
8030
8358
  init_interface();
8031
8359
 
8032
8360
  class DatabaseSyscalls {
@@ -8063,7 +8391,8 @@ class DatabaseSyscalls {
8063
8391
  if (docId.tableNumber !== undefined) {
8064
8392
  return { id: idString };
8065
8393
  }
8066
- if (docId.table === stringToHex(tableName)) {
8394
+ const expectedFullTableName = getFullTableName(tableName, isSystemTable(tableName) ? "" : this.context.componentPath);
8395
+ if (docId.table === stringToHex(expectedFullTableName)) {
8067
8396
  return { id: idString };
8068
8397
  }
8069
8398
  return { id: null };
@@ -8122,29 +8451,28 @@ class DatabaseSyscalls {
8122
8451
  return { _id: developerId };
8123
8452
  }
8124
8453
  async handleGet(args) {
8125
- const { id } = args;
8454
+ const { id, table } = args;
8126
8455
  if (typeof id !== "string") {
8127
8456
  throw new Error("`id` argument for `get` must be a string.");
8128
8457
  }
8129
- const internalId = parseDeveloperId(id);
8130
- if (!internalId) {
8458
+ const resolved = await this.resolveDocumentTarget(id, table, "get");
8459
+ if (!resolved) {
8131
8460
  return null;
8132
8461
  }
8133
- this.context.recordDocumentRead(internalId);
8134
- const doc = await this.queryRuntime.getVisibleDocumentById(id, internalId);
8462
+ this.context.recordDocumentRead(resolved.docId);
8463
+ const doc = await this.queryRuntime.getVisibleDocumentById(id, resolved.docId);
8135
8464
  return doc ?? null;
8136
8465
  }
8137
8466
  async handleRemove(args) {
8138
- const { id } = args;
8467
+ const { id, table } = args;
8139
8468
  if (typeof id !== "string") {
8140
8469
  throw new Error("`id` argument for `remove` must be a string.");
8141
8470
  }
8142
- const docId = parseDeveloperId(id);
8143
- if (!docId) {
8471
+ const resolved = await this.resolveDocumentTarget(id, table, "remove", true);
8472
+ if (!resolved) {
8144
8473
  throw new Error(`Document with id ${id} not found.`);
8145
8474
  }
8146
- const fullTableName = await resolveTableName(docId, this.context.tableRegistry);
8147
- const { tableName: bareTableName } = parseFullTableName(fullTableName);
8475
+ const { docId, fullTableName, bareTableName } = resolved;
8148
8476
  const latest = await this.docStore.fetchLatestDocument(docId, this.context.snapshotTimestamp);
8149
8477
  if (!latest) {
8150
8478
  throw new Error(`Document with id ${id} not found.`);
@@ -8160,16 +8488,15 @@ class DatabaseSyscalls {
8160
8488
  return {};
8161
8489
  }
8162
8490
  async handleShallowMerge(args) {
8163
- const { id, value } = args;
8491
+ const { id, table, value } = args;
8164
8492
  if (typeof id !== "string") {
8165
8493
  throw new Error("`id` argument for `shallowMerge` must be a string.");
8166
8494
  }
8167
- const docId = parseDeveloperId(id);
8168
- if (!docId) {
8495
+ const resolved = await this.resolveDocumentTarget(id, table, "patch", true);
8496
+ if (!resolved) {
8169
8497
  throw new Error(`Document with id ${id} not found.`);
8170
8498
  }
8171
- const fullTableName = await resolveTableName(docId, this.context.tableRegistry);
8172
- const { tableName: bareTableName } = parseFullTableName(fullTableName);
8499
+ const { docId, fullTableName, bareTableName } = resolved;
8173
8500
  if (value && typeof value === "object") {
8174
8501
  if ("_id" in value) {
8175
8502
  throw new Error("System field `_id` cannot be modified in a patch operation.");
@@ -8220,16 +8547,15 @@ class DatabaseSyscalls {
8220
8547
  return {};
8221
8548
  }
8222
8549
  async handleReplace(args) {
8223
- const { id, value } = args;
8550
+ const { id, table, value } = args;
8224
8551
  if (typeof id !== "string") {
8225
8552
  throw new Error("`id` argument for `replace` must be a string.");
8226
8553
  }
8227
- const docId = parseDeveloperId(id);
8228
- if (!docId) {
8554
+ const resolved = await this.resolveDocumentTarget(id, table, "replace", true);
8555
+ if (!resolved) {
8229
8556
  throw new Error(`Document with id ${id} not found.`);
8230
8557
  }
8231
- const fullTableName = await resolveTableName(docId, this.context.tableRegistry);
8232
- const { tableName: bareTableName } = parseFullTableName(fullTableName);
8558
+ const { docId, fullTableName, bareTableName } = resolved;
8233
8559
  const replaceValue = jsonToConvex(value);
8234
8560
  if (typeof replaceValue !== "object" || replaceValue === null || Array.isArray(replaceValue)) {
8235
8561
  throw new Error("The replacement value for `replace` must be an object.");
@@ -8252,6 +8578,27 @@ class DatabaseSyscalls {
8252
8578
  this.context.recordLocalWrite(id, fullTableName, newValue, canonicalDocId);
8253
8579
  return {};
8254
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
+ }
8255
8602
  }
8256
8603
 
8257
8604
  // ../core/dist/kernel/syscalls/identity-syscalls.js
@@ -8567,11 +8914,203 @@ class KernelSyscalls {
8567
8914
  return this.jsRouter.dispatch(op, args);
8568
8915
  }
8569
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();
8570
9096
  // ../core/dist/kernel/contexts.js
8571
9097
  init_context_storage();
8572
- var snapshotContext = new ContextStorage;
8573
- var transactionContext = new ContextStorage;
8574
- 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
+ }
8575
9114
  // ../core/dist/queryengine/convex-ops.js
8576
9115
  var debug = () => {};
8577
9116
  class CfConvex {
@@ -8624,6 +9163,8 @@ class BaseSqliteDocStore {
8624
9163
  vectorIndexesByTable = new Map;
8625
9164
  fts5Available = true;
8626
9165
  statementCache = new Map;
9166
+ configuredSearchIndexes = [];
9167
+ configuredVectorIndexes = [];
8627
9168
  constructor(adapter) {
8628
9169
  this.adapter = adapter;
8629
9170
  this.timestampOracle = new TimestampOracle;
@@ -8638,6 +9179,8 @@ class BaseSqliteDocStore {
8638
9179
  return statement;
8639
9180
  }
8640
9181
  async setupSchema(options) {
9182
+ this.configuredSearchIndexes = [...options?.searchIndexes ?? []];
9183
+ this.configuredVectorIndexes = [...options?.vectorIndexes ?? []];
8641
9184
  await this.adapter.exec(DOCUMENTS_TABLE_SCHEMA);
8642
9185
  await this.adapter.exec(DOCUMENTS_BY_TABLE_INDEX);
8643
9186
  await this.adapter.exec(INDEXES_TABLE_SCHEMA);
@@ -8645,6 +9188,24 @@ class BaseSqliteDocStore {
8645
9188
  await this.setupSearchIndexes(options?.searchIndexes ?? []);
8646
9189
  await this.setupVectorIndexes(options?.vectorIndexes ?? []);
8647
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
+ }
8648
9209
  async setupSearchIndexes(searchIndexes) {
8649
9210
  try {
8650
9211
  await this.adapter.exec(SEARCH_INDEXES_FTS_SCHEMA);
@@ -8860,6 +9421,15 @@ class BaseSqliteDocStore {
8860
9421
  const stmt = this.getPreparedStatement("INSERT OR REPLACE INTO persistence_globals (key, json_value) VALUES (?, ?)");
8861
9422
  await stmt.run(key, JSON.stringify(value));
8862
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
+ }
8863
9433
  async previous_revisions(queries) {
8864
9434
  const results = new Map;
8865
9435
  const stmt = this.getPreparedStatement(`
@@ -9155,6 +9725,9 @@ class BaseSqliteDocStore {
9155
9725
  return scored.slice(0, limit);
9156
9726
  }
9157
9727
  }
9728
+ function quoteSqlIdentifier(value) {
9729
+ return `"${value.replace(/"/g, '""')}"`;
9730
+ }
9158
9731
  // ../docstore-sqlite-base/dist/transaction-runner.js
9159
9732
  function createSerializedTransactionRunner(hooks) {
9160
9733
  let queue = Promise.resolve();