@concavejs/docstore-better-sqlite3 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 -490
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -1,4 +1,3 @@
1
- import { createRequire } from "node:module";
2
1
  var __defProp = Object.defineProperty;
3
2
  var __returnValue = (v) => v;
4
3
  function __exportSetter(name, newValue) {
@@ -14,7 +13,6 @@ var __export = (target, all) => {
14
13
  });
15
14
  };
16
15
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
17
- var __require = /* @__PURE__ */ createRequire(import.meta.url);
18
16
 
19
17
  // ../../node_modules/convex/dist/esm/values/base64.js
20
18
  function getLens(b64) {
@@ -802,6 +800,237 @@ var init_values = __esm(() => {
802
800
  init_errors();
803
801
  });
804
802
 
803
+ // ../core/dist/id-codec/base32.js
804
+ function base32Encode(data) {
805
+ if (data.length === 0)
806
+ return "";
807
+ let result = "";
808
+ let buffer = 0;
809
+ let bitsLeft = 0;
810
+ for (const byte of data) {
811
+ buffer = buffer << 8 | byte;
812
+ bitsLeft += 8;
813
+ while (bitsLeft >= 5) {
814
+ bitsLeft -= 5;
815
+ const index = buffer >> bitsLeft & 31;
816
+ result += ALPHABET[index];
817
+ }
818
+ }
819
+ if (bitsLeft > 0) {
820
+ const index = buffer << 5 - bitsLeft & 31;
821
+ result += ALPHABET[index];
822
+ }
823
+ return result;
824
+ }
825
+ function base32Decode(str) {
826
+ if (str.length === 0)
827
+ return new Uint8Array(0);
828
+ const outputLength = Math.floor(str.length * 5 / 8);
829
+ const result = new Uint8Array(outputLength);
830
+ let buffer = 0;
831
+ let bitsLeft = 0;
832
+ let outputIndex = 0;
833
+ for (const char of str) {
834
+ const value = ALPHABET_MAP.get(char);
835
+ if (value === undefined) {
836
+ throw new Error(`Invalid base32 character: ${char}`);
837
+ }
838
+ buffer = buffer << 5 | value;
839
+ bitsLeft += 5;
840
+ if (bitsLeft >= 8) {
841
+ bitsLeft -= 8;
842
+ result[outputIndex++] = buffer >> bitsLeft & 255;
843
+ }
844
+ }
845
+ return result;
846
+ }
847
+ function isValidBase32(str) {
848
+ for (const char of str) {
849
+ if (!ALPHABET_MAP.has(char)) {
850
+ return false;
851
+ }
852
+ }
853
+ return true;
854
+ }
855
+ var ALPHABET = "0123456789abcdefghjkmnpqrstvwxyz", ALPHABET_MAP;
856
+ var init_base32 = __esm(() => {
857
+ ALPHABET_MAP = new Map;
858
+ for (let i2 = 0;i2 < ALPHABET.length; i2++) {
859
+ ALPHABET_MAP.set(ALPHABET[i2], i2);
860
+ ALPHABET_MAP.set(ALPHABET[i2].toUpperCase(), i2);
861
+ }
862
+ ALPHABET_MAP.set("i", 1);
863
+ ALPHABET_MAP.set("I", 1);
864
+ ALPHABET_MAP.set("l", 1);
865
+ ALPHABET_MAP.set("L", 1);
866
+ ALPHABET_MAP.set("o", 0);
867
+ ALPHABET_MAP.set("O", 0);
868
+ });
869
+
870
+ // ../core/dist/id-codec/vint.js
871
+ function vintEncode(value) {
872
+ if (value < 0) {
873
+ throw new Error("VInt cannot encode negative numbers");
874
+ }
875
+ if (value > 4294967295) {
876
+ throw new Error("VInt cannot encode values larger than 2^32-1");
877
+ }
878
+ value = value >>> 0;
879
+ if (value < 128) {
880
+ return new Uint8Array([value]);
881
+ }
882
+ if (value < 16512) {
883
+ const adjusted2 = value - 128;
884
+ return new Uint8Array([128 | adjusted2 >> 8 & 63, adjusted2 & 255]);
885
+ }
886
+ if (value < 2113664) {
887
+ const adjusted2 = value - 16512;
888
+ return new Uint8Array([192 | adjusted2 >> 16 & 31, adjusted2 >> 8 & 255, adjusted2 & 255]);
889
+ }
890
+ if (value < 270549120) {
891
+ const adjusted2 = value - 2113664;
892
+ return new Uint8Array([
893
+ 224 | adjusted2 >> 24 & 15,
894
+ adjusted2 >> 16 & 255,
895
+ adjusted2 >> 8 & 255,
896
+ adjusted2 & 255
897
+ ]);
898
+ }
899
+ const adjusted = value - 270549120;
900
+ return new Uint8Array([
901
+ 240 | adjusted >> 32 & 7,
902
+ adjusted >> 24 & 255,
903
+ adjusted >> 16 & 255,
904
+ adjusted >> 8 & 255,
905
+ adjusted & 255
906
+ ]);
907
+ }
908
+ function vintDecode(data, offset = 0) {
909
+ if (offset >= data.length) {
910
+ throw new Error("VInt decode: unexpected end of data");
911
+ }
912
+ const first = data[offset];
913
+ if ((first & 128) === 0) {
914
+ return { value: first, bytesRead: 1 };
915
+ }
916
+ if ((first & 192) === 128) {
917
+ if (offset + 1 >= data.length) {
918
+ throw new Error("VInt decode: truncated 2-byte encoding");
919
+ }
920
+ const value = 128 + ((first & 63) << 8 | data[offset + 1]);
921
+ return { value, bytesRead: 2 };
922
+ }
923
+ if ((first & 224) === 192) {
924
+ if (offset + 2 >= data.length) {
925
+ throw new Error("VInt decode: truncated 3-byte encoding");
926
+ }
927
+ const value = 16512 + ((first & 31) << 16 | data[offset + 1] << 8 | data[offset + 2]);
928
+ return { value, bytesRead: 3 };
929
+ }
930
+ if ((first & 240) === 224) {
931
+ if (offset + 3 >= data.length) {
932
+ throw new Error("VInt decode: truncated 4-byte encoding");
933
+ }
934
+ const value = 2113664 + ((first & 15) << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3]);
935
+ return { value: value >>> 0, bytesRead: 4 };
936
+ }
937
+ if ((first & 248) === 240) {
938
+ if (offset + 4 >= data.length) {
939
+ throw new Error("VInt decode: truncated 5-byte encoding");
940
+ }
941
+ const high = first & 7;
942
+ const low = (data[offset + 1] << 24 | data[offset + 2] << 16 | data[offset + 3] << 8 | data[offset + 4]) >>> 0;
943
+ const value = 270549120 + high * 4294967296 + low;
944
+ return { value: value >>> 0, bytesRead: 5 };
945
+ }
946
+ throw new Error("VInt decode: invalid prefix");
947
+ }
948
+
949
+ // ../core/dist/id-codec/fletcher16.js
950
+ function fletcher16(data) {
951
+ let sum1 = 0;
952
+ let sum2 = 0;
953
+ for (const byte of data) {
954
+ sum1 = (sum1 + byte) % 255;
955
+ sum2 = (sum2 + sum1) % 255;
956
+ }
957
+ return new Uint8Array([sum1, sum2]);
958
+ }
959
+ function verifyFletcher16(data, checksum) {
960
+ if (checksum.length !== 2)
961
+ return false;
962
+ const computed = fletcher16(data);
963
+ return computed[0] === checksum[0] && computed[1] === checksum[1];
964
+ }
965
+
966
+ // ../core/dist/utils/crypto.js
967
+ var weakRandomState;
968
+ var init_crypto = __esm(() => {
969
+ weakRandomState = (Date.now() ^ 2654435769) >>> 0;
970
+ });
971
+
972
+ // ../core/dist/id-codec/document-id.js
973
+ function encodeDocumentId(tableNumber, internalId) {
974
+ if (internalId.length !== INTERNAL_ID_LENGTH) {
975
+ throw new Error(`Internal ID must be exactly ${INTERNAL_ID_LENGTH} bytes, got ${internalId.length}`);
976
+ }
977
+ if (tableNumber < 1 || tableNumber > 4294967295) {
978
+ throw new Error(`Table number must be between 1 and 2^32-1, got ${tableNumber}`);
979
+ }
980
+ const tableBytes = vintEncode(tableNumber);
981
+ const payload = new Uint8Array(tableBytes.length + INTERNAL_ID_LENGTH);
982
+ payload.set(tableBytes, 0);
983
+ payload.set(internalId, tableBytes.length);
984
+ const checksum = fletcher16(payload);
985
+ const final = new Uint8Array(payload.length + 2);
986
+ final.set(payload, 0);
987
+ final.set(checksum, payload.length);
988
+ return base32Encode(final);
989
+ }
990
+ function decodeDocumentId(encoded) {
991
+ if (encoded.length < MIN_ENCODED_LENGTH || encoded.length > MAX_ENCODED_LENGTH) {
992
+ throw new Error(`Invalid document ID length: ${encoded.length} (expected ${MIN_ENCODED_LENGTH}-${MAX_ENCODED_LENGTH})`);
993
+ }
994
+ if (!isValidBase32(encoded)) {
995
+ throw new Error("Invalid document ID: contains invalid base32 characters");
996
+ }
997
+ const bytes = base32Decode(encoded);
998
+ if (bytes.length < 19) {
999
+ throw new Error(`Invalid document ID: decoded to ${bytes.length} bytes (minimum 19)`);
1000
+ }
1001
+ const checksum = bytes.slice(bytes.length - 2);
1002
+ const payload = bytes.slice(0, bytes.length - 2);
1003
+ if (!verifyFletcher16(payload, checksum)) {
1004
+ throw new Error("Invalid document ID: checksum verification failed");
1005
+ }
1006
+ const { value: tableNumber, bytesRead } = vintDecode(payload, 0);
1007
+ const internalId = payload.slice(bytesRead, bytesRead + INTERNAL_ID_LENGTH);
1008
+ if (internalId.length !== INTERNAL_ID_LENGTH) {
1009
+ throw new Error(`Invalid document ID: internal ID is ${internalId.length} bytes (expected ${INTERNAL_ID_LENGTH})`);
1010
+ }
1011
+ return { tableNumber, internalId };
1012
+ }
1013
+ function isValidDocumentId(encoded) {
1014
+ try {
1015
+ decodeDocumentId(encoded);
1016
+ return true;
1017
+ } catch {
1018
+ return false;
1019
+ }
1020
+ }
1021
+ function internalIdToHex(internalId) {
1022
+ let hex = "";
1023
+ for (let i2 = 0;i2 < internalId.length; i2++) {
1024
+ hex += internalId[i2].toString(16).padStart(2, "0");
1025
+ }
1026
+ return hex;
1027
+ }
1028
+ var INTERNAL_ID_LENGTH = 16, MIN_ENCODED_LENGTH = 31, MAX_ENCODED_LENGTH = 37;
1029
+ var init_document_id = __esm(() => {
1030
+ init_base32();
1031
+ init_crypto();
1032
+ });
1033
+
805
1034
  // ../core/dist/utils/utils.js
806
1035
  function hexToArrayBuffer(hex) {
807
1036
  if (hex === "") {
@@ -840,9 +1069,15 @@ function deserializeDeveloperId(developerId) {
840
1069
  return null;
841
1070
  }
842
1071
  var DOC_ID_SEPARATOR = ":", LEGACY_DOC_ID_SEPARATOR = ";";
1072
+ var init_utils = __esm(() => {
1073
+ init_document_id();
1074
+ });
843
1075
 
844
1076
  // ../core/dist/tables/interface.js
845
1077
  function getFullTableName(tableName, componentPath) {
1078
+ if (isSystemTable(tableName)) {
1079
+ return tableName;
1080
+ }
846
1081
  if (!componentPath || componentPath === "") {
847
1082
  return tableName;
848
1083
  }
@@ -859,23 +1094,28 @@ function parseFullTableName(fullName) {
859
1094
  };
860
1095
  }
861
1096
  function isSystemTable(tableName) {
862
- return tableName.startsWith("_");
1097
+ return Object.hasOwn(SYSTEM_TABLE_NUMBERS, tableName);
863
1098
  }
864
- var SYSTEM_TABLE_NUMBERS, FIRST_USER_TABLE_NUMBER = 100;
1099
+ var SYSTEM_TABLE_NUMBERS, FIRST_USER_TABLE_NUMBER = 10001;
865
1100
  var init_interface = __esm(() => {
866
1101
  SYSTEM_TABLE_NUMBERS = {
867
1102
  _tables: 1,
868
1103
  _scheduled_functions: 2,
869
1104
  _storage: 3,
870
- _crons: 4
1105
+ _crons: 4,
1106
+ _indexes: 5,
1107
+ _schemas: 6,
1108
+ _components: 7,
1109
+ _component_definitions: 8,
1110
+ _schema_validation_progress: 9
871
1111
  };
872
1112
  });
873
1113
 
874
1114
  // ../core/dist/kernel/context-storage.js
875
- function resolveFromRequire(req) {
1115
+ function resolveFromModuleResolver(resolveModule) {
876
1116
  for (const specifier of ["node:async_hooks", "async_hooks"]) {
877
1117
  try {
878
- const mod = req(specifier);
1118
+ const mod = resolveModule(specifier);
879
1119
  if (mod?.AsyncLocalStorage) {
880
1120
  return mod.AsyncLocalStorage;
881
1121
  }
@@ -918,16 +1158,16 @@ var resolveAsyncLocalStorage = () => {
918
1158
  if (globalCtor) {
919
1159
  return globalCtor;
920
1160
  }
921
- const runtimeRequire = __require;
922
- if (runtimeRequire) {
923
- const ctor = resolveFromRequire(runtimeRequire);
1161
+ const getBuiltinModule = globalThis?.process?.getBuiltinModule;
1162
+ if (typeof getBuiltinModule === "function") {
1163
+ const ctor = resolveFromModuleResolver((specifier) => getBuiltinModule(specifier));
924
1164
  if (ctor) {
925
1165
  return ctor;
926
1166
  }
927
1167
  }
928
1168
  const globalRequire = globalThis?.require;
929
1169
  if (typeof globalRequire === "function") {
930
- return resolveFromRequire(globalRequire);
1170
+ return resolveFromModuleResolver(globalRequire);
931
1171
  }
932
1172
  return;
933
1173
  }, AsyncLocalStorageCtor;
@@ -2212,7 +2452,7 @@ async function listSystemFunctions(options = {}) {
2212
2452
  }
2213
2453
  for (const route of httpRoutes) {
2214
2454
  const method = route.route.method;
2215
- const routePath = route.route.path;
2455
+ const routePath = mountHttpRoutePath(route.route.path, owningComponent);
2216
2456
  results.push({
2217
2457
  name: `${method} ${routePath}`,
2218
2458
  module: listing.path,
@@ -2274,6 +2514,16 @@ async function loadAndAnalyzeModule(listing, componentPath) {
2274
2514
  function makeCacheKey(componentPath, modulePath) {
2275
2515
  return `${componentPath ?? ""}::${modulePath}`;
2276
2516
  }
2517
+ function mountHttpRoutePath(routePath, componentPath) {
2518
+ if (!componentPath) {
2519
+ return routePath;
2520
+ }
2521
+ const prefix = `/${componentPath}`;
2522
+ if (routePath === "/") {
2523
+ return prefix;
2524
+ }
2525
+ return `${prefix}${routePath}`;
2526
+ }
2277
2527
  function buildFallbackSourcePath(modulePath) {
2278
2528
  const trimmed = modulePath.replace(/\\/g, "/").replace(/^\//, "");
2279
2529
  const withConvex = trimmed.startsWith("convex/") ? trimmed : `convex/${trimmed}`;
@@ -3960,6 +4210,7 @@ var init_remote = __esm(() => {
3960
4210
  // ../../node_modules/jose/dist/webapi/index.js
3961
4211
  var init_webapi = __esm(() => {
3962
4212
  init_verify4();
4213
+ init_local();
3963
4214
  init_remote();
3964
4215
  init_errors2();
3965
4216
  });
@@ -4164,7 +4415,7 @@ function getRemoteJwks(jwksUrl, config) {
4164
4415
  if (cached) {
4165
4416
  JWKS_CACHE.delete(jwksUrl);
4166
4417
  }
4167
- const jwks = createRemoteJWKSet(new URL(jwksUrl));
4418
+ const jwks = jwksUrl.startsWith("data:") ? createLocalJWKSet(parseDataUriJson(jwksUrl)) : createRemoteJWKSet(new URL(jwksUrl));
4168
4419
  const configuredTtl = config?.jwksCacheTtlMs;
4169
4420
  const ttlMs = resolveJwksCacheTtlMs(configuredTtl);
4170
4421
  JWKS_CACHE.set(jwksUrl, {
@@ -4173,6 +4424,24 @@ function getRemoteJwks(jwksUrl, config) {
4173
4424
  });
4174
4425
  return jwks;
4175
4426
  }
4427
+ function parseDataUriJson(dataUri) {
4428
+ const match = /^data:([^;,]+)?(?:;charset=[^;,]+)?(;base64)?,(.*)$/i.exec(dataUri);
4429
+ if (!match) {
4430
+ throw new JWTValidationError("INVALID_TOKEN", "Invalid JWKS data URI");
4431
+ }
4432
+ const [, , isBase64, payload] = match;
4433
+ const jsonText = isBase64 ? decodeBase642(payload) : decodeURIComponent(payload);
4434
+ return JSON.parse(jsonText);
4435
+ }
4436
+ function decodeBase642(value) {
4437
+ if (typeof Buffer !== "undefined") {
4438
+ return Buffer.from(value, "base64").toString("utf8");
4439
+ }
4440
+ if (typeof atob === "function") {
4441
+ return new TextDecoder().decode(Uint8Array.from(atob(value), (char) => char.charCodeAt(0)));
4442
+ }
4443
+ throw new JWTValidationError("INVALID_TOKEN", "Base64 decoding is unavailable");
4444
+ }
4176
4445
  function resolveJwksCacheTtlMs(configuredTtl) {
4177
4446
  if (configuredTtl === undefined) {
4178
4447
  return DEFAULT_JWKS_CACHE_TTL_MS;
@@ -4207,6 +4476,7 @@ async function verifyJwt(token, config) {
4207
4476
  const options = {
4208
4477
  issuer: effectiveConfig.issuer,
4209
4478
  audience: effectiveConfig.audience,
4479
+ algorithms: effectiveConfig.algorithms,
4210
4480
  clockTolerance: effectiveConfig.clockTolerance ?? DEFAULT_CLOCK_TOLERANCE_SECONDS
4211
4481
  };
4212
4482
  let payload;
@@ -4764,47 +5034,231 @@ var init_auth = __esm(() => {
4764
5034
  init_auth_config_service();
4765
5035
  });
4766
5036
 
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({
5037
+ // ../core/dist/components/manifest.js
5038
+ var COMPONENT_MANIFEST_SYMBOL;
5039
+ var init_manifest = __esm(() => {
5040
+ COMPONENT_MANIFEST_SYMBOL = Symbol.for("concave.componentManifest");
5041
+ });
5042
+
5043
+ // ../core/dist/id-codec/index.js
5044
+ var init_id_codec = __esm(() => {
5045
+ init_base32();
5046
+ init_document_id();
5047
+ });
5048
+
5049
+ // ../core/dist/system/system-tables.js
5050
+ function getSystemTableDefinition(name) {
5051
+ return SYSTEM_TABLE_DEFINITIONS.find((definition) => definition.name === name) ?? null;
5052
+ }
5053
+ function isPublicSystemTable(name) {
5054
+ return getSystemTableDefinition(name)?.visibility === "public";
5055
+ }
5056
+ function createTableInfo(name, tableNumber, componentPath = "", options = {}) {
5057
+ const fullName = getFullTableName(name, componentPath);
5058
+ return {
5059
+ tableNumber,
5060
+ name,
5061
+ componentPath: isSystemTableName(name) ? "" : componentPath,
5062
+ fullName,
5063
+ isSystem: options.isSystem ?? isSystemTableName(name),
5064
+ visibility: options.visibility ?? (isPublicSystemTable(name) ? "public" : "private"),
5065
+ state: "active",
5066
+ createdAt: options.createdAt ?? Date.now()
5067
+ };
5068
+ }
5069
+ function getReservedSystemTables() {
5070
+ return SYSTEM_TABLE_DEFINITIONS.map((definition) => createTableInfo(definition.name, SYSTEM_TABLE_NUMBERS[definition.name], "", {
5071
+ isSystem: true,
5072
+ visibility: definition.visibility
5073
+ }));
5074
+ }
5075
+ function tableInfoFromStoredDocument(value) {
5076
+ if (!value) {
5077
+ return null;
5078
+ }
5079
+ const name = typeof value.name === "string" ? value.name : null;
5080
+ const tableNumber = typeof value.tableNumber === "number" ? value.tableNumber : null;
5081
+ if (!name || !tableNumber) {
5082
+ return null;
5083
+ }
5084
+ const componentPath = typeof value.componentPath === "string" ? value.componentPath : "";
5085
+ const fullName = typeof value.fullName === "string" ? value.fullName : getFullTableName(name, componentPath);
5086
+ return {
5087
+ tableNumber,
5088
+ name,
5089
+ componentPath,
5090
+ fullName,
5091
+ isSystem: value.isSystem === true,
5092
+ visibility: value.visibility === "private" ? "private" : "public",
5093
+ state: "active",
5094
+ createdAt: typeof value.createdAt === "number" ? value.createdAt : Date.now()
5095
+ };
5096
+ }
5097
+ function nextUserTableNumber(tables) {
5098
+ let next = FIRST_USER_TABLE_NUMBER;
5099
+ for (const table of tables) {
5100
+ if (table.tableNumber >= next) {
5101
+ next = table.tableNumber + 1;
5102
+ }
5103
+ }
5104
+ return next;
5105
+ }
5106
+ function createSystemMetadata(partial) {
5107
+ const now = partial?.updatedAt ?? Date.now();
5108
+ return {
5109
+ version: 1,
5110
+ bootstrapped: true,
5111
+ tableIdStrategy: "registry_u32",
5112
+ developerIdCodec: "convex_base32",
5113
+ nextUserTableNumber: partial?.nextUserTableNumber ?? FIRST_USER_TABLE_NUMBER,
5114
+ registryVersion: partial?.registryVersion ?? now,
5115
+ runtimeMetadataVersion: partial?.runtimeMetadataVersion,
5116
+ bootstrappedAt: partial?.bootstrappedAt ?? now,
5117
+ updatedAt: now
5118
+ };
5119
+ }
5120
+ async function readSystemMetadata(docstore) {
5121
+ const metadata = await docstore.getGlobal(SYSTEM_METADATA_GLOBAL_KEY);
5122
+ if (!metadata || metadata.bootstrapped !== true || metadata.version !== 1) {
5123
+ return null;
5124
+ }
5125
+ return createSystemMetadata({
5126
+ nextUserTableNumber: metadata.nextUserTableNumber,
5127
+ registryVersion: metadata.registryVersion ?? metadata.updatedAt,
5128
+ runtimeMetadataVersion: metadata.runtimeMetadataVersion,
5129
+ bootstrappedAt: metadata.bootstrappedAt,
5130
+ updatedAt: metadata.updatedAt
5131
+ });
5132
+ }
5133
+ function createTableNumberReservationKey(tableNumber) {
5134
+ return `${TABLE_NUMBER_RESERVATION_GLOBAL_PREFIX}${tableNumber}`;
5135
+ }
5136
+ async function ensureSystemTablesBootstrapped(docstore) {
5137
+ const existingMetadata = await readSystemMetadata(docstore);
5138
+ if (existingMetadata?.version === 1 && existingMetadata.bootstrapped) {
5139
+ return;
5140
+ }
5141
+ const now = Date.now();
5142
+ const tableInfos = getReservedSystemTables();
5143
+ const existingEntries = await docstore.scan(stringToHex("_tables"));
5144
+ const existingByName = new Map;
5145
+ for (const entry of existingEntries) {
5146
+ const info = tableInfoFromStoredDocument(entry.value.value);
5147
+ if (info) {
5148
+ existingByName.set(info.fullName, info);
5149
+ }
5150
+ }
5151
+ const docs = [];
5152
+ const oracle = docstore.timestampOracle;
5153
+ const allocateTimestamp = oracle?.allocateTimestamp?.bind(oracle) ?? (() => BigInt(Date.now()));
5154
+ for (const table of tableInfos) {
5155
+ const existing = existingByName.get(table.fullName);
5156
+ const createdAt = existing?.createdAt ?? now;
5157
+ docs.push(createTableMetadataEntry(table, allocateTimestamp(), createdAt));
5158
+ }
5159
+ if (docs.length > 0) {
5160
+ await docstore.write(docs, new Set, "Overwrite");
5161
+ }
5162
+ const metadata = createSystemMetadata({
5163
+ nextUserTableNumber: nextUserTableNumber([...tableInfos, ...existingByName.values()]),
5164
+ registryVersion: now,
5165
+ bootstrappedAt: existingMetadata?.bootstrappedAt ?? now,
5166
+ updatedAt: now
5167
+ });
5168
+ await docstore.writeGlobal(SYSTEM_METADATA_GLOBAL_KEY, metadata);
5169
+ }
5170
+ function createTableMetadataEntryForUserTable(table, timestamp2) {
5171
+ return createTableMetadataEntry(table, timestamp2, table.createdAt);
5172
+ }
5173
+ function createTableMetadataEntry(table, timestamp2, createdAt) {
5174
+ const docId = createTableMetadataDocumentId(table.fullName);
5175
+ const developerId = encodeDocumentId(SYSTEM_TABLE_NUMBERS._tables, stableMetadataInternalIdBytes(table.fullName));
5176
+ const storedTable = {
5177
+ _id: developerId,
5178
+ _creationTime: Number(timestamp2),
5179
+ name: table.name,
5180
+ componentPath: table.componentPath,
5181
+ fullName: table.fullName,
5182
+ tableNumber: table.tableNumber,
5183
+ isSystem: table.isSystem,
5184
+ visibility: table.visibility,
5185
+ state: table.state,
5186
+ createdAt
5187
+ };
5188
+ return {
5189
+ ts: timestamp2,
5190
+ id: docId,
5191
+ value: {
5192
+ id: docId,
5193
+ value: storedTable
5194
+ },
5195
+ prev_ts: null
5196
+ };
5197
+ }
5198
+ function createTableMetadataDocumentId(fullTableName) {
5199
+ const internalIdBytes = stableMetadataInternalIdBytes(fullTableName);
5200
+ return {
5201
+ table: stringToHex("_tables"),
5202
+ internalId: internalIdToHex(internalIdBytes),
5203
+ tableNumber: SYSTEM_TABLE_NUMBERS._tables
5204
+ };
5205
+ }
5206
+ function stableMetadataInternalIdBytes(fullTableName) {
5207
+ const bytes = new Uint8Array(16);
5208
+ const input = new TextEncoder().encode(`table:${fullTableName}`);
5209
+ for (let i2 = 0;i2 < input.length; i2 += 1) {
5210
+ const target = i2 % 16;
5211
+ bytes[target] = bytes[target] * 33 + input[i2] & 255;
5212
+ }
5213
+ return bytes;
5214
+ }
5215
+ function isSystemTableName(name) {
5216
+ return Object.hasOwn(SYSTEM_TABLE_NUMBERS, name);
5217
+ }
5218
+ var SYSTEM_METADATA_GLOBAL_KEY = "concave:system_metadata:v1", TABLE_NUMBER_RESERVATION_GLOBAL_PREFIX = "concave:table_number:", SYSTEM_TABLE_DEFINITIONS;
5219
+ var init_system_tables = __esm(() => {
5220
+ init_manifest();
5221
+ init_id_codec();
5222
+ init_interface();
5223
+ init_utils();
5224
+ init_module_loader();
5225
+ SYSTEM_TABLE_DEFINITIONS = [
5226
+ { name: "_tables", visibility: "public" },
5227
+ { name: "_scheduled_functions", visibility: "public" },
5228
+ { name: "_storage", visibility: "public" },
5229
+ { name: "_crons", visibility: "public" },
5230
+ { name: "_indexes", visibility: "private" },
5231
+ { name: "_schemas", visibility: "private" },
5232
+ { name: "_components", visibility: "private" },
5233
+ { name: "_component_definitions", visibility: "private" },
5234
+ { name: "_schema_validation_progress", visibility: "private" }
5235
+ ];
5236
+ });
5237
+
5238
+ // ../core/dist/system/internal.js
5239
+ function requireSystemCapability(capability) {
5240
+ const principal2 = getPrincipal();
5241
+ if (!principal2) {
5242
+ throw new Error("System functions require authentication context");
5243
+ }
5244
+ requireAuthorization(principal2, { kind: "management_operation", capability });
5245
+ }
5246
+ function createSystemFunctions(deps) {
5247
+ const { query, mutation } = deps;
5248
+ return {
5249
+ systemListComponents: query({
4779
5250
  args: {},
4780
- handler: async (_ctx) => {
5251
+ handler: async (ctx) => {
4781
5252
  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,
5253
+ const components = await loadComponentRows(ctx);
5254
+ const withFunctionCounts = await Promise.all(components.map(async (component) => {
5255
+ const functions = await listSystemFunctions({ componentPath: component.componentPath || undefined });
5256
+ return {
5257
+ ...component,
4798
5258
  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
- });
5259
+ };
5260
+ }));
5261
+ return sortComponentRows(withFunctionCounts);
4808
5262
  }
4809
5263
  }),
4810
5264
  systemListTables: query({
@@ -4813,25 +5267,40 @@ function createSystemFunctions(deps) {
4813
5267
  requireSystemCapability("tables:read");
4814
5268
  const targetComponent = componentPath ?? "";
4815
5269
  const schema2 = await loadSchemaDefinition(targetComponent);
4816
- let tableEntries = [];
5270
+ const schemaTables = new Map;
4817
5271
  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 = [];
5272
+ for (const table of extractTablesFromSchema(schema2)) {
5273
+ schemaTables.set(table.name, table);
4833
5274
  }
4834
5275
  }
5276
+ const discoveredTables = new Map;
5277
+ for (const name of schemaTables.keys()) {
5278
+ discoveredTables.set(name, {
5279
+ name,
5280
+ isSystem: isSystemTable(name),
5281
+ visibility: getDefaultSystemTableVisibility(name)
5282
+ });
5283
+ }
5284
+ try {
5285
+ const systemTables = await ctx.db.system.query("_tables").collect();
5286
+ discoveredTables.clear();
5287
+ for (const table of systemTables.filter((entry) => (entry.componentPath ?? "") === targetComponent)) {
5288
+ discoveredTables.set(table.name, {
5289
+ name: table.name,
5290
+ isSystem: table.isSystem === true || isSystemTable(table.name),
5291
+ visibility: table.visibility === "private" ? "private" : "public"
5292
+ });
5293
+ }
5294
+ } catch {}
5295
+ const tableEntries = Array.from(discoveredTables.values()).map((metadata) => ({
5296
+ ...metadata,
5297
+ exported: schemaTables.get(metadata.name)?.exported ?? {
5298
+ indexes: [],
5299
+ searchIndexes: [],
5300
+ vectorIndexes: [],
5301
+ documentType: null
5302
+ }
5303
+ }));
4835
5304
  const tableInfo = await Promise.all(tableEntries.map(async (table) => {
4836
5305
  const fullName = getFullTableName(table.name, targetComponent);
4837
5306
  const documentCount = await countDocuments(ctx, fullName);
@@ -4842,6 +5311,8 @@ function createSystemFunctions(deps) {
4842
5311
  name: table.name,
4843
5312
  fullName,
4844
5313
  componentPath: targetComponent || undefined,
5314
+ isSystem: table.isSystem,
5315
+ visibility: table.visibility,
4845
5316
  documentCount,
4846
5317
  indexes: buildIndexList(exported?.indexes),
4847
5318
  searchIndexes: searchIndexes.map((idx) => typeof idx === "string" ? idx : idx.indexDescriptor),
@@ -4875,7 +5346,7 @@ function createSystemFunctions(deps) {
4875
5346
  }
4876
5347
  try {
4877
5348
  const fullName = getFullTableName(tableName, targetComponent);
4878
- const sampleDoc = await ctx.db.query(fullName).first();
5349
+ const sampleDoc = await getTableQuery(ctx, fullName).first();
4879
5350
  const fields = sampleDoc ? Object.keys(sampleDoc).map((key) => ({
4880
5351
  name: key,
4881
5352
  type: typeof sampleDoc[key],
@@ -4910,7 +5381,7 @@ function createSystemFunctions(deps) {
4910
5381
  handler: async (ctx, args) => {
4911
5382
  requireSystemCapability("documents:read");
4912
5383
  const fullName = getFullTableName(args.tableName, args.componentPath ?? "");
4913
- let query2 = ctx.db.query(fullName);
5384
+ let query2 = getTableQuery(ctx, fullName);
4914
5385
  if (args.orderBy && args.orderBy !== "_creationTime") {
4915
5386
  const allDocs2 = await query2.collect();
4916
5387
  const sorted = allDocs2.sort((a, b) => {
@@ -4961,7 +5432,7 @@ function createSystemFunctions(deps) {
4961
5432
  handler: async (ctx, args) => {
4962
5433
  requireSystemCapability("documents:write");
4963
5434
  const fullName = getFullTableName(args.tableName, args.componentPath ?? "");
4964
- const docs = await ctx.db.query(fullName).collect();
5435
+ const docs = await getTableQuery(ctx, fullName).collect();
4965
5436
  for (const doc of docs) {
4966
5437
  await ctx.db.delete(doc._id);
4967
5438
  }
@@ -5257,6 +5728,83 @@ function resolveFunctionReference(functionPath, componentPath) {
5257
5728
  }
5258
5729
  return functionPath;
5259
5730
  }
5731
+ async function loadComponentRows(ctx) {
5732
+ try {
5733
+ const rows = await ctx.db.system.query("_components").collect();
5734
+ if (rows.length > 0) {
5735
+ return rows.map((row) => normalizeStoredComponentRow(row));
5736
+ }
5737
+ } catch {}
5738
+ const modules = await listRegisteredModules();
5739
+ const moduleCountByComponent = new Map;
5740
+ const hasHttpByComponent = new Map;
5741
+ const componentPaths = new Set([""]);
5742
+ for (const module of modules) {
5743
+ const componentPath = module.componentPath ?? "";
5744
+ componentPaths.add(componentPath);
5745
+ moduleCountByComponent.set(componentPath, (moduleCountByComponent.get(componentPath) ?? 0) + 1);
5746
+ if (module.path === "http") {
5747
+ hasHttpByComponent.set(componentPath, true);
5748
+ }
5749
+ }
5750
+ return Array.from(componentPaths).map((componentPath) => ({
5751
+ componentPath,
5752
+ path: componentPath || "(root)",
5753
+ isRoot: componentPath === "",
5754
+ parentPath: componentPath === "" ? null : componentPath.includes("/") ? componentPath.split("/").slice(0, -1).join("/") : "",
5755
+ depth: componentPath === "" ? 0 : componentPath.split("/").length,
5756
+ moduleCount: moduleCountByComponent.get(componentPath) ?? 0,
5757
+ childCount: 0,
5758
+ functionCount: 0,
5759
+ sourceType: "local",
5760
+ hasHttp: hasHttpByComponent.get(componentPath) === true
5761
+ }));
5762
+ }
5763
+ function normalizeStoredComponentRow(row) {
5764
+ const componentPath = typeof row.componentPath === "string" ? row.componentPath : "";
5765
+ return {
5766
+ componentPath,
5767
+ path: typeof row.displayPath === "string" ? row.displayPath : typeof row.path === "string" && row.path.length > 0 ? row.path : componentPath || "(root)",
5768
+ isRoot: row.isRoot === true || componentPath === "",
5769
+ parentPath: row.parentPath === null ? null : typeof row.parentPath === "string" ? row.parentPath : componentPath === "" ? null : "",
5770
+ depth: typeof row.depth === "number" ? row.depth : componentPath === "" ? 0 : componentPath.split("/").length,
5771
+ moduleCount: typeof row.moduleCount === "number" ? row.moduleCount : 0,
5772
+ childCount: typeof row.childCount === "number" ? row.childCount : 0,
5773
+ functionCount: 0,
5774
+ sourceType: row.sourceType === "npm" ? "npm" : row.sourceType === "local" ? "local" : undefined,
5775
+ sourcePath: typeof row.sourcePath === "string" ? row.sourcePath : undefined,
5776
+ packageName: typeof row.packageName === "string" ? row.packageName : undefined,
5777
+ packageVersion: typeof row.packageVersion === "string" ? row.packageVersion : undefined,
5778
+ hasHttp: row.hasHttp === true
5779
+ };
5780
+ }
5781
+ function sortComponentRows(rows) {
5782
+ const childrenByParent = new Map;
5783
+ for (const row of rows) {
5784
+ const parentKey = row.parentPath ?? null;
5785
+ const siblings = childrenByParent.get(parentKey) ?? [];
5786
+ siblings.push(row);
5787
+ childrenByParent.set(parentKey, siblings);
5788
+ }
5789
+ for (const siblings of childrenByParent.values()) {
5790
+ siblings.sort((a, b) => {
5791
+ if (a.isRoot)
5792
+ return -1;
5793
+ if (b.isRoot)
5794
+ return 1;
5795
+ return a.componentPath.localeCompare(b.componentPath);
5796
+ });
5797
+ }
5798
+ const ordered = [];
5799
+ const visit = (parentPath) => {
5800
+ for (const row of childrenByParent.get(parentPath) ?? []) {
5801
+ ordered.push(row);
5802
+ visit(row.componentPath);
5803
+ }
5804
+ };
5805
+ visit(null);
5806
+ return ordered;
5807
+ }
5260
5808
  async function loadSchemaDefinition(componentPath) {
5261
5809
  try {
5262
5810
  const module = await loadConvexModule("schema", {
@@ -5290,13 +5838,26 @@ function extractTableMetadata(schema2, tableName) {
5290
5838
  }
5291
5839
  async function countDocuments(ctx, tableName) {
5292
5840
  try {
5293
- const documents = await ctx.db.query(tableName).collect();
5841
+ const documents = await getTableQuery(ctx, tableName).collect();
5294
5842
  return documents.length;
5295
5843
  } catch (error) {
5296
5844
  console.warn(`Failed to count documents for table ${tableName}:`, error);
5297
5845
  return 0;
5298
5846
  }
5299
5847
  }
5848
+ function getTableQuery(ctx, fullTableName) {
5849
+ const { tableName } = parseFullTableName(fullTableName);
5850
+ if (isSystemTable(tableName)) {
5851
+ return ctx.db.system.query(tableName);
5852
+ }
5853
+ return ctx.db.query(fullTableName);
5854
+ }
5855
+ function getDefaultSystemTableVisibility(tableName) {
5856
+ if (!isSystemTable(tableName)) {
5857
+ return "public";
5858
+ }
5859
+ return isPublicSystemTable(tableName) ? "public" : "private";
5860
+ }
5300
5861
  function buildIndexList(indexes) {
5301
5862
  const base = ["by_id", "by_creation_time"];
5302
5863
  if (!indexes || indexes.length === 0) {
@@ -5398,6 +5959,7 @@ var init_internal = __esm(() => {
5398
5959
  init_interface();
5399
5960
  init_execution_log();
5400
5961
  init_auth();
5962
+ init_system_tables();
5401
5963
  });
5402
5964
 
5403
5965
  // ../core/dist/system/system-functions-module.js
@@ -5555,8 +6117,9 @@ class ModuleRegistry {
5555
6117
  const normalized = normalizeModuleListing(listing);
5556
6118
  if (!normalized)
5557
6119
  continue;
5558
- if (!results.has(normalized.path)) {
5559
- results.set(normalized.path, {
6120
+ const resultKey = `${normalized.componentPath ?? scope ?? ""}:${normalized.path}`;
6121
+ if (!results.has(resultKey)) {
6122
+ results.set(resultKey, {
5560
6123
  ...normalized,
5561
6124
  scope: scope || undefined,
5562
6125
  componentPath: normalized.componentPath ?? (scope || undefined)
@@ -5875,8 +6438,10 @@ var init_module_loader = __esm(() => {
5875
6438
  class SchemaValidator {
5876
6439
  schemaCache = new Map;
5877
6440
  componentPath;
5878
- constructor(componentPath) {
6441
+ tableRegistry;
6442
+ constructor(componentPath, tableRegistry) {
5879
6443
  this.componentPath = componentPath;
6444
+ this.tableRegistry = tableRegistry;
5880
6445
  }
5881
6446
  async loadTableSchema(tableName) {
5882
6447
  if (this.schemaCache.has(tableName)) {
@@ -5919,8 +6484,11 @@ class SchemaValidator {
5919
6484
  return;
5920
6485
  }
5921
6486
  try {
6487
+ const tableNumberToName = this.tableRegistry ? new Map((await this.tableRegistry.listTables()).map((table) => [table.tableNumber, table.fullName])) : undefined;
5922
6488
  validateValidator(tableSchema, omit(document, ["_id", "_creationTime"]), "", {
5923
- componentPath: this.componentPath ?? ""
6489
+ componentPath: this.componentPath ?? "",
6490
+ tableRegistry: this.tableRegistry,
6491
+ tableNumberToName
5924
6492
  });
5925
6493
  } catch (error) {
5926
6494
  throw new ValidatorError(`Failed to insert or update a document in table "${tableName}" because it does not match the schema: ${error.message}`);
@@ -6018,6 +6586,16 @@ Path: ${formatPath(path)}
6018
6586
  Value: ${formatValue(value)}
6019
6587
  Validator: v.id("${validator2.tableName}")`);
6020
6588
  }
6589
+ if (isValidDocumentId(value)) {
6590
+ const tableName2 = tableNameFromConvexId(value, options);
6591
+ if (!tableName2 || !isMatchingValidatorTable(tableName2, validator2.tableName, options.componentPath)) {
6592
+ throw new Error(`Value does not match validator.
6593
+ Path: ${formatPath(path)}
6594
+ Value: ${formatValue(value)}
6595
+ Validator: v.id("${validator2.tableName}")`);
6596
+ }
6597
+ return;
6598
+ }
6021
6599
  const tableName = tableNameFromId(value);
6022
6600
  if (!tableName || !isMatchingValidatorTable(tableName, validator2.tableName, options.componentPath)) {
6023
6601
  throw new Error(`Value does not match validator.
@@ -6079,289 +6657,72 @@ Validator: v.object({...})`);
6079
6657
  }
6080
6658
  } else {
6081
6659
  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");
6660
+ validateValidator(fieldType, value[k], fieldPath, options);
6661
+ }
6662
+ }
6663
+ for (const k of Object.keys(value)) {
6664
+ if (validator2.value[k] === undefined) {
6665
+ throw new Error(`Object contains extra field \`${k}\` that is not in the validator.
6666
+
6667
+ Object: ${JSON.stringify(value)}
6668
+ Validator: v.object({...})`);
6669
+ }
6670
+ }
6671
+ return;
6672
+ }
6338
6673
  }
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})`);
6674
+ }
6675
+ function tableNameFromId(id) {
6676
+ const parts = deserializeDeveloperId(id);
6677
+ if (!parts) {
6678
+ return null;
6343
6679
  }
6344
- return { tableNumber, internalId };
6680
+ return hexToString(parts.table);
6345
6681
  }
6346
- function isValidDocumentId(encoded) {
6682
+ function tableNameFromConvexId(id, options) {
6347
6683
  try {
6348
- decodeDocumentId(encoded);
6349
- return true;
6684
+ const decoded = decodeDocumentId(id);
6685
+ const fromMap = options.tableNumberToName?.get(decoded.tableNumber);
6686
+ if (fromMap) {
6687
+ return fromMap;
6688
+ }
6689
+ return null;
6350
6690
  } catch {
6351
- return false;
6691
+ return null;
6352
6692
  }
6353
6693
  }
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");
6694
+ function isMatchingValidatorTable(idTableName, validatorTableName, componentPath) {
6695
+ if (idTableName === validatorTableName) {
6696
+ return true;
6358
6697
  }
6359
- return hex;
6698
+ const { tableName: validatorBareName } = parseFullTableName(validatorTableName);
6699
+ const { tableName: idBareName } = parseFullTableName(idTableName);
6700
+ if (componentPath !== undefined) {
6701
+ const expectedFullName = getFullTableName(validatorBareName, componentPath);
6702
+ return idTableName === expectedFullName;
6703
+ }
6704
+ return idBareName === validatorBareName;
6360
6705
  }
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();
6706
+ function isSimpleObject2(value) {
6707
+ const isObject2 = typeof value === "object";
6708
+ const prototype = Object.getPrototypeOf(value);
6709
+ const isSimple = prototype === null || prototype === Object.prototype || prototype?.constructor?.name === "Object";
6710
+ return isObject2 && isSimple;
6711
+ }
6712
+ var ValidatorError;
6713
+ var init_validator2 = __esm(() => {
6714
+ init_utils();
6715
+ init_interface();
6716
+ init_module_loader();
6717
+ init_id_codec();
6718
+ ValidatorError = class ValidatorError extends Error {
6719
+ path;
6720
+ constructor(message2, path = "") {
6721
+ super(message2);
6722
+ this.path = path;
6723
+ this.name = "ValidatorError";
6724
+ }
6725
+ };
6365
6726
  });
6366
6727
 
6367
6728
  // src/sqlite-docstore.ts
@@ -6372,7 +6733,10 @@ init_values();
6372
6733
 
6373
6734
  // ../core/dist/docstore/interface.js
6374
6735
  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;
6736
+ const tableKey = id.table && id.table.length > 0 ? id.table : id.tableNumber !== undefined && Number.isInteger(id.tableNumber) && id.tableNumber > 0 ? `#${id.tableNumber}` : null;
6737
+ if (!tableKey) {
6738
+ throw new Error("Invalid document ID: missing table and tableNumber");
6739
+ }
6376
6740
  return `${tableKey}:${id.internalId}`;
6377
6741
  }
6378
6742
  var Order;
@@ -6579,6 +6943,7 @@ class TimestampOracle {
6579
6943
  }
6580
6944
  }
6581
6945
  // ../core/dist/utils/keyspace.js
6946
+ init_utils();
6582
6947
  var TABLE_PREFIX = "table";
6583
6948
  var INDEX_PREFIX = "index";
6584
6949
  function encodeComponent(component) {
@@ -6619,6 +6984,13 @@ function decodeIndexId(indexId) {
6619
6984
  index: decoded.slice(separatorIndex + 1)
6620
6985
  };
6621
6986
  }
6987
+
6988
+ // ../core/dist/utils/index.js
6989
+ init_utils();
6990
+
6991
+ // ../core/dist/queryengine/indexing/index-manager.js
6992
+ init_utils();
6993
+
6622
6994
  // ../core/dist/queryengine/indexing/index-key-codec.js
6623
6995
  var TypeTag;
6624
6996
  (function(TypeTag2) {
@@ -6668,8 +7040,9 @@ function encodeBigInt(n) {
6668
7040
  return bytes;
6669
7041
  }
6670
7042
  function encodeString(s) {
6671
- const encoder = new TextEncoder;
6672
- const raw = encoder.encode(s);
7043
+ return encodeEscapedBytes(new TextEncoder().encode(s));
7044
+ }
7045
+ function encodeEscapedBytes(raw) {
6673
7046
  let nullCount = 0;
6674
7047
  for (const byte of raw) {
6675
7048
  if (byte === 0)
@@ -6733,11 +7106,10 @@ function encodeValue(value) {
6733
7106
  }
6734
7107
  if (value instanceof ArrayBuffer || value instanceof Uint8Array) {
6735
7108
  const bytes = value instanceof Uint8Array ? value : new Uint8Array(value);
6736
- const result = new Uint8Array(1 + bytes.length + 2);
7109
+ const encoded = encodeEscapedBytes(bytes);
7110
+ const result = new Uint8Array(1 + encoded.length);
6737
7111
  result[0] = TypeTag.Bytes;
6738
- result.set(bytes, 1);
6739
- result[result.length - 2] = 0;
6740
- result[result.length - 1] = 0;
7112
+ result.set(encoded, 1);
6741
7113
  return result;
6742
7114
  }
6743
7115
  throw new Error(`Cannot encode value of type ${typeof value} in index key`);
@@ -6854,9 +7226,11 @@ class SchemaService {
6854
7226
  tableCache = new Map;
6855
7227
  schemaValidator;
6856
7228
  componentPath;
6857
- constructor(componentPath) {
7229
+ tableRegistry;
7230
+ constructor(componentPath, tableRegistry) {
6858
7231
  this.componentPath = componentPath;
6859
- this.schemaValidator = new SchemaValidator(componentPath);
7232
+ this.tableRegistry = tableRegistry;
7233
+ this.schemaValidator = new SchemaValidator(componentPath, tableRegistry);
6860
7234
  }
6861
7235
  async validate(tableName, document) {
6862
7236
  try {
@@ -6981,6 +7355,10 @@ class SchemaService {
6981
7355
  return this.cachedSchemaDefinition;
6982
7356
  }
6983
7357
  }
7358
+
7359
+ // ../core/dist/queryengine/index-query.js
7360
+ init_utils();
7361
+
6984
7362
  // ../core/dist/observability/udf-trace.js
6985
7363
  init_context_storage();
6986
7364
  var TRACE_CONTEXT = new ContextStorage;
@@ -7224,11 +7602,10 @@ function evaluateFieldPath(fieldPath, document) {
7224
7602
  }
7225
7603
  return current;
7226
7604
  }
7227
- // ../core/dist/id-codec/index.js
7228
- init_base32();
7229
- init_document_id();
7230
7605
 
7231
7606
  // ../core/dist/queryengine/developer-id.js
7607
+ init_utils();
7608
+ init_id_codec();
7232
7609
  function parseDeveloperId(developerId) {
7233
7610
  if (isValidDocumentId(developerId)) {
7234
7611
  try {
@@ -7246,6 +7623,25 @@ function parseDeveloperId(developerId) {
7246
7623
  }
7247
7624
  return { table: parts.table, internalId: parts.internalId };
7248
7625
  }
7626
+ async function parseDeveloperIdWithTableRegistry(developerId, tableRegistry) {
7627
+ if (isValidDocumentId(developerId)) {
7628
+ try {
7629
+ const decoded = decodeDocumentId(developerId);
7630
+ const tableInfo = await tableRegistry.getTableInfo(decoded.tableNumber);
7631
+ if (!tableInfo) {
7632
+ return null;
7633
+ }
7634
+ return {
7635
+ table: stringToHex(tableInfo.fullName),
7636
+ internalId: internalIdToHex(decoded.internalId),
7637
+ tableNumber: decoded.tableNumber
7638
+ };
7639
+ } catch {
7640
+ return null;
7641
+ }
7642
+ }
7643
+ return parseDeveloperId(developerId);
7644
+ }
7249
7645
  function parseStorageId(storageId) {
7250
7646
  const parsed = parseDeveloperId(storageId);
7251
7647
  if (parsed) {
@@ -7262,12 +7658,21 @@ function parseStorageId(storageId) {
7262
7658
  function isTablePlaceholder(table) {
7263
7659
  return table.startsWith("#");
7264
7660
  }
7661
+
7662
+ // ../core/dist/query/query-runtime.js
7663
+ init_utils();
7664
+
7265
7665
  // ../core/dist/query/planner.js
7266
7666
  init_interface();
7667
+ init_utils();
7668
+
7267
7669
  // ../core/dist/query/actions.js
7670
+ init_utils();
7268
7671
  init_interface();
7269
7672
 
7270
7673
  // ../core/dist/queryengine/indexing/read-write-set.js
7674
+ init_utils();
7675
+
7271
7676
  class RangeSet {
7272
7677
  ranges = new Map;
7273
7678
  addDocument(docId) {
@@ -7378,6 +7783,8 @@ function deserializeKeyRange(serialized) {
7378
7783
  }
7379
7784
 
7380
7785
  // ../core/dist/kernel/access-log.js
7786
+ init_utils();
7787
+
7381
7788
  class AccessLog {
7382
7789
  ranges = new RangeSet;
7383
7790
  addDocument(docId) {
@@ -7402,104 +7809,9 @@ class AccessLog {
7402
7809
  }
7403
7810
  }
7404
7811
 
7405
- // ../core/dist/tables/memory-table-registry.js
7812
+ // ../core/dist/kernel/kernel-context.js
7406
7813
  init_interface();
7407
7814
 
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
7815
  class KernelContext {
7504
7816
  authContext;
7505
7817
  componentPath;
@@ -7516,11 +7828,14 @@ class KernelContext {
7516
7828
  this.authContext = options.authContext;
7517
7829
  this.componentPath = options.componentPath ?? "";
7518
7830
  this.mutationTransaction = options.mutationTransaction;
7519
- this.tableRegistry = options.tableRegistry ?? getGlobalTableRegistry();
7520
- this.useConvexIdFormat = options.useConvexIdFormat ?? false;
7831
+ if (!options.tableRegistry) {
7832
+ throw new Error("KernelContext requires an explicit tableRegistry");
7833
+ }
7834
+ this.tableRegistry = options.tableRegistry;
7835
+ this.useConvexIdFormat = options.useConvexIdFormat ?? true;
7521
7836
  }
7522
7837
  async getTableNumber(tableName) {
7523
- return this.tableRegistry.getOrAllocateTableNumber(tableName, this.componentPath);
7838
+ return this.tableRegistry.getOrAllocateTableNumber(tableName, isSystemTable(tableName) ? "" : this.componentPath);
7524
7839
  }
7525
7840
  nextSubrequestId(prefix, udfPath) {
7526
7841
  return `${prefix}:${udfPath}:${Date.now()}:${Math.random()}:${this.subrequestCounter++}`;
@@ -7565,7 +7880,7 @@ class KernelContext {
7565
7880
  this.writeLog.addDocument(docId);
7566
7881
  }
7567
7882
  recordLocalWrite(developerId, tableName, value, docId) {
7568
- this.localWrites.set(developerId, { table: tableName, value });
7883
+ this.localWrites.set(developerId, { table: tableName, value, docId });
7569
7884
  if (docId) {
7570
7885
  this.recordDocumentWrite(docId);
7571
7886
  return;
@@ -7607,7 +7922,13 @@ class KernelContext {
7607
7922
  }
7608
7923
  }
7609
7924
 
7925
+ // ../core/dist/kernel/udf-kernel.js
7926
+ init_id_codec();
7927
+
7610
7928
  // ../core/dist/kernel/blob-store-gateway.js
7929
+ init_id_codec();
7930
+ init_utils();
7931
+
7611
7932
  class BlobStoreGateway {
7612
7933
  context;
7613
7934
  docStore;
@@ -7656,7 +7977,7 @@ class BlobStoreGateway {
7656
7977
  if (!this.storage) {
7657
7978
  return null;
7658
7979
  }
7659
- const docId = parseStorageId(storageId);
7980
+ const docId = await parseDeveloperIdWithTableRegistry(storageId, this.context.tableRegistry) ?? parseStorageId(storageId);
7660
7981
  if (!docId) {
7661
7982
  console.debug(`[BlobStoreGateway] Failed to parse storage ID: ${storageId}`);
7662
7983
  return null;
@@ -7677,7 +7998,7 @@ class BlobStoreGateway {
7677
7998
  if (!this.storage) {
7678
7999
  return null;
7679
8000
  }
7680
- const docId = parseStorageId(storageId);
8001
+ const docId = await parseDeveloperIdWithTableRegistry(storageId, this.context.tableRegistry) ?? parseStorageId(storageId);
7681
8002
  if (!docId) {
7682
8003
  return null;
7683
8004
  }
@@ -7690,7 +8011,7 @@ class BlobStoreGateway {
7690
8011
  }
7691
8012
  async delete(storageId) {
7692
8013
  const storage2 = this.requireStorage();
7693
- const docId = parseStorageId(storageId);
8014
+ const docId = await parseDeveloperIdWithTableRegistry(storageId, this.context.tableRegistry) ?? parseStorageId(storageId);
7694
8015
  if (!docId) {
7695
8016
  return;
7696
8017
  }
@@ -7715,13 +8036,17 @@ class BlobStoreGateway {
7715
8036
 
7716
8037
  // ../core/dist/kernel/scheduler-gateway.js
7717
8038
  init_values();
8039
+ init_id_codec();
8040
+ init_utils();
8041
+
7718
8042
  // ../core/dist/kernel/syscalls/utils.js
7719
8043
  init_values();
8044
+ init_utils();
7720
8045
  async function resolveTableName(docId, tableRegistry) {
7721
8046
  if (docId.tableNumber !== undefined) {
7722
8047
  const info = await tableRegistry.getTableInfo(docId.tableNumber);
7723
8048
  if (info) {
7724
- return info.name;
8049
+ return info.fullName;
7725
8050
  }
7726
8051
  if (!isTablePlaceholder(docId.table)) {
7727
8052
  return hexToString(docId.table);
@@ -7902,7 +8227,7 @@ class SchedulerGateway {
7902
8227
  return developerId;
7903
8228
  }
7904
8229
  async cancel(id, state) {
7905
- const docId = parseDeveloperId(id);
8230
+ const docId = await parseDeveloperIdWithTableRegistry(id, this.context.tableRegistry);
7906
8231
  if (!docId) {
7907
8232
  throw new Error(`Scheduled job with id ${id} not found.`);
7908
8233
  }
@@ -8027,6 +8352,8 @@ class ActionSyscalls {
8027
8352
 
8028
8353
  // ../core/dist/kernel/syscalls/database-syscalls.js
8029
8354
  init_values();
8355
+ init_id_codec();
8356
+ init_utils();
8030
8357
  init_interface();
8031
8358
 
8032
8359
  class DatabaseSyscalls {
@@ -8063,7 +8390,8 @@ class DatabaseSyscalls {
8063
8390
  if (docId.tableNumber !== undefined) {
8064
8391
  return { id: idString };
8065
8392
  }
8066
- if (docId.table === stringToHex(tableName)) {
8393
+ const expectedFullTableName = getFullTableName(tableName, isSystemTable(tableName) ? "" : this.context.componentPath);
8394
+ if (docId.table === stringToHex(expectedFullTableName)) {
8067
8395
  return { id: idString };
8068
8396
  }
8069
8397
  return { id: null };
@@ -8122,29 +8450,28 @@ class DatabaseSyscalls {
8122
8450
  return { _id: developerId };
8123
8451
  }
8124
8452
  async handleGet(args) {
8125
- const { id } = args;
8453
+ const { id, table } = args;
8126
8454
  if (typeof id !== "string") {
8127
8455
  throw new Error("`id` argument for `get` must be a string.");
8128
8456
  }
8129
- const internalId = parseDeveloperId(id);
8130
- if (!internalId) {
8457
+ const resolved = await this.resolveDocumentTarget(id, table, "get");
8458
+ if (!resolved) {
8131
8459
  return null;
8132
8460
  }
8133
- this.context.recordDocumentRead(internalId);
8134
- const doc = await this.queryRuntime.getVisibleDocumentById(id, internalId);
8461
+ this.context.recordDocumentRead(resolved.docId);
8462
+ const doc = await this.queryRuntime.getVisibleDocumentById(id, resolved.docId);
8135
8463
  return doc ?? null;
8136
8464
  }
8137
8465
  async handleRemove(args) {
8138
- const { id } = args;
8466
+ const { id, table } = args;
8139
8467
  if (typeof id !== "string") {
8140
8468
  throw new Error("`id` argument for `remove` must be a string.");
8141
8469
  }
8142
- const docId = parseDeveloperId(id);
8143
- if (!docId) {
8470
+ const resolved = await this.resolveDocumentTarget(id, table, "remove", true);
8471
+ if (!resolved) {
8144
8472
  throw new Error(`Document with id ${id} not found.`);
8145
8473
  }
8146
- const fullTableName = await resolveTableName(docId, this.context.tableRegistry);
8147
- const { tableName: bareTableName } = parseFullTableName(fullTableName);
8474
+ const { docId, fullTableName, bareTableName } = resolved;
8148
8475
  const latest = await this.docStore.fetchLatestDocument(docId, this.context.snapshotTimestamp);
8149
8476
  if (!latest) {
8150
8477
  throw new Error(`Document with id ${id} not found.`);
@@ -8160,16 +8487,15 @@ class DatabaseSyscalls {
8160
8487
  return {};
8161
8488
  }
8162
8489
  async handleShallowMerge(args) {
8163
- const { id, value } = args;
8490
+ const { id, table, value } = args;
8164
8491
  if (typeof id !== "string") {
8165
8492
  throw new Error("`id` argument for `shallowMerge` must be a string.");
8166
8493
  }
8167
- const docId = parseDeveloperId(id);
8168
- if (!docId) {
8494
+ const resolved = await this.resolveDocumentTarget(id, table, "patch", true);
8495
+ if (!resolved) {
8169
8496
  throw new Error(`Document with id ${id} not found.`);
8170
8497
  }
8171
- const fullTableName = await resolveTableName(docId, this.context.tableRegistry);
8172
- const { tableName: bareTableName } = parseFullTableName(fullTableName);
8498
+ const { docId, fullTableName, bareTableName } = resolved;
8173
8499
  if (value && typeof value === "object") {
8174
8500
  if ("_id" in value) {
8175
8501
  throw new Error("System field `_id` cannot be modified in a patch operation.");
@@ -8220,16 +8546,15 @@ class DatabaseSyscalls {
8220
8546
  return {};
8221
8547
  }
8222
8548
  async handleReplace(args) {
8223
- const { id, value } = args;
8549
+ const { id, table, value } = args;
8224
8550
  if (typeof id !== "string") {
8225
8551
  throw new Error("`id` argument for `replace` must be a string.");
8226
8552
  }
8227
- const docId = parseDeveloperId(id);
8228
- if (!docId) {
8553
+ const resolved = await this.resolveDocumentTarget(id, table, "replace", true);
8554
+ if (!resolved) {
8229
8555
  throw new Error(`Document with id ${id} not found.`);
8230
8556
  }
8231
- const fullTableName = await resolveTableName(docId, this.context.tableRegistry);
8232
- const { tableName: bareTableName } = parseFullTableName(fullTableName);
8557
+ const { docId, fullTableName, bareTableName } = resolved;
8233
8558
  const replaceValue = jsonToConvex(value);
8234
8559
  if (typeof replaceValue !== "object" || replaceValue === null || Array.isArray(replaceValue)) {
8235
8560
  throw new Error("The replacement value for `replace` must be an object.");
@@ -8252,6 +8577,27 @@ class DatabaseSyscalls {
8252
8577
  this.context.recordLocalWrite(id, fullTableName, newValue, canonicalDocId);
8253
8578
  return {};
8254
8579
  }
8580
+ async resolveDocumentTarget(id, table, operation, throwOnMismatch = false) {
8581
+ if (table !== undefined && typeof table !== "string") {
8582
+ throw new Error(`\`table\` argument for \`${operation}\` must be a string.`);
8583
+ }
8584
+ const docId = await parseDeveloperIdWithTableRegistry(id, this.context.tableRegistry);
8585
+ if (!docId) {
8586
+ return null;
8587
+ }
8588
+ const fullTableName = await resolveTableName(docId, this.context.tableRegistry);
8589
+ if (typeof table === "string") {
8590
+ const expectedFullTableName = getFullTableName(table, isSystemTable(table) ? "" : this.context.componentPath);
8591
+ if (fullTableName !== expectedFullTableName) {
8592
+ if (throwOnMismatch) {
8593
+ throw new Error(`Document with id ${id} does not belong to table ${table}.`);
8594
+ }
8595
+ return null;
8596
+ }
8597
+ }
8598
+ const { tableName: bareTableName } = parseFullTableName(fullTableName);
8599
+ return { docId, fullTableName, bareTableName };
8600
+ }
8255
8601
  }
8256
8602
 
8257
8603
  // ../core/dist/kernel/syscalls/identity-syscalls.js
@@ -8567,11 +8913,203 @@ class KernelSyscalls {
8567
8913
  return this.jsRouter.dispatch(op, args);
8568
8914
  }
8569
8915
  }
8916
+
8917
+ // ../core/dist/tables/docstore-table-registry.js
8918
+ init_system_tables();
8919
+ init_utils();
8920
+ init_interface();
8921
+
8922
+ class DocStoreTableRegistry {
8923
+ docstore;
8924
+ tablesByNumber = new Map;
8925
+ tablesByName = new Map;
8926
+ loadPromise = null;
8927
+ cachedRegistryVersion = 0;
8928
+ constructor(docstore) {
8929
+ this.docstore = docstore;
8930
+ }
8931
+ async getOrAllocateTableNumber(tableName, componentPath = "") {
8932
+ await this.ensureLoaded();
8933
+ await this.ensureFresh();
8934
+ const normalizedComponent = isSystemTable(tableName) ? "" : componentPath;
8935
+ const fullName = getFullTableName(tableName, normalizedComponent);
8936
+ let existing = this.tablesByName.get(fullName);
8937
+ if (existing) {
8938
+ return existing.tableNumber;
8939
+ }
8940
+ await this.reloadTables();
8941
+ existing = this.tablesByName.get(fullName);
8942
+ if (existing) {
8943
+ return existing.tableNumber;
8944
+ }
8945
+ const oracle = this.docstore.timestampOracle;
8946
+ for (;; ) {
8947
+ const metadata = await readSystemMetadata(this.docstore) ?? createSystemMetadata({
8948
+ nextUserTableNumber: Math.max(FIRST_USER_TABLE_NUMBER, nextUserTableNumber(this.tablesByNumber.values()))
8949
+ });
8950
+ const candidate = Math.max(metadata.nextUserTableNumber, nextUserTableNumber(this.tablesByNumber.values()));
8951
+ const reserved = await this.docstore.writeGlobalIfAbsent(createTableNumberReservationKey(candidate), {
8952
+ fullName,
8953
+ reservedAt: Date.now()
8954
+ });
8955
+ if (!reserved) {
8956
+ await this.reloadTables();
8957
+ const raced = this.tablesByName.get(fullName);
8958
+ if (raced) {
8959
+ return raced.tableNumber;
8960
+ }
8961
+ continue;
8962
+ }
8963
+ const createdAt = Date.now();
8964
+ const info = createTableInfo(tableName, candidate, normalizedComponent, { createdAt, visibility: "public" });
8965
+ const timestamp2 = oracle?.allocateTimestamp?.() ?? BigInt(createdAt);
8966
+ const entry = createTableMetadataEntryForUserTable(info, timestamp2);
8967
+ try {
8968
+ await this.docstore.write([entry], new Set, "Error");
8969
+ } catch {
8970
+ await this.reloadTables();
8971
+ const raced = this.tablesByName.get(fullName);
8972
+ if (raced) {
8973
+ return raced.tableNumber;
8974
+ }
8975
+ throw new Error(`Failed to allocate table number for ${fullName}`);
8976
+ }
8977
+ const registryVersion = Number(timestamp2 > BigInt(Number.MAX_SAFE_INTEGER) ? BigInt(Date.now()) : timestamp2);
8978
+ await this.docstore.writeGlobal(SYSTEM_METADATA_GLOBAL_KEY, createSystemMetadata({
8979
+ nextUserTableNumber: candidate + 1,
8980
+ registryVersion,
8981
+ bootstrappedAt: metadata.bootstrappedAt,
8982
+ updatedAt: registryVersion
8983
+ }));
8984
+ this.cachedRegistryVersion = registryVersion;
8985
+ this.tablesByName.set(fullName, info);
8986
+ this.tablesByNumber.set(candidate, info);
8987
+ return candidate;
8988
+ }
8989
+ }
8990
+ async getTableInfo(tableNumber) {
8991
+ await this.ensureLoaded();
8992
+ await this.ensureFresh();
8993
+ const existing = this.tablesByNumber.get(tableNumber);
8994
+ if (existing) {
8995
+ return existing;
8996
+ }
8997
+ await this.reloadTables();
8998
+ return this.tablesByNumber.get(tableNumber) ?? null;
8999
+ }
9000
+ async getTableInfoByName(tableName, componentPath = "") {
9001
+ await this.ensureLoaded();
9002
+ await this.ensureFresh();
9003
+ const fullName = getFullTableName(tableName, isSystemTable(tableName) ? "" : componentPath);
9004
+ const existing = this.tablesByName.get(fullName);
9005
+ if (existing) {
9006
+ return existing;
9007
+ }
9008
+ await this.reloadTables();
9009
+ return this.tablesByName.get(fullName) ?? null;
9010
+ }
9011
+ async listTables(componentPath) {
9012
+ await this.ensureLoaded();
9013
+ await this.ensureFresh();
9014
+ const values = Array.from(this.tablesByNumber.values());
9015
+ if (componentPath === undefined) {
9016
+ return values.sort((a, b) => a.tableNumber - b.tableNumber);
9017
+ }
9018
+ return values.filter((table) => table.componentPath === componentPath).sort((a, b) => a.tableNumber - b.tableNumber);
9019
+ }
9020
+ async hasAccess(tableNumber, componentPath) {
9021
+ const info = await this.getTableInfo(tableNumber);
9022
+ if (!info) {
9023
+ return false;
9024
+ }
9025
+ if (info.isSystem) {
9026
+ return true;
9027
+ }
9028
+ return info.componentPath === componentPath;
9029
+ }
9030
+ getSystemTableNumber(systemTableName) {
9031
+ return SYSTEM_TABLE_NUMBERS[systemTableName];
9032
+ }
9033
+ async ensureLoaded() {
9034
+ if (!this.loadPromise) {
9035
+ this.loadPromise = this.loadTables();
9036
+ }
9037
+ await this.loadPromise;
9038
+ }
9039
+ async ensureFresh() {
9040
+ const metadata = await readSystemMetadata(this.docstore);
9041
+ if (!metadata) {
9042
+ if (this.cachedRegistryVersion !== 0 || this.tablesByName.size > 0 || this.tablesByNumber.size > 0) {
9043
+ await this.reloadTables();
9044
+ }
9045
+ return;
9046
+ }
9047
+ if (metadata.registryVersion > this.cachedRegistryVersion) {
9048
+ await this.reloadTables();
9049
+ }
9050
+ }
9051
+ async reloadTables() {
9052
+ this.loadPromise = this.loadTables();
9053
+ await this.loadPromise;
9054
+ }
9055
+ async loadTables() {
9056
+ await ensureSystemTablesBootstrapped(this.docstore);
9057
+ const docs = await this.docstore.scan(stringToHex("_tables"));
9058
+ this.tablesByName.clear();
9059
+ this.tablesByNumber.clear();
9060
+ for (const doc of docs) {
9061
+ const info = tableInfoFromStoredDocument(doc.value.value);
9062
+ if (!info) {
9063
+ continue;
9064
+ }
9065
+ this.tablesByName.set(info.fullName, info);
9066
+ this.tablesByNumber.set(info.tableNumber, info);
9067
+ }
9068
+ if (this.tablesByNumber.size === 0) {
9069
+ for (const [name, tableNumber] of Object.entries(SYSTEM_TABLE_NUMBERS)) {
9070
+ const info = createTableInfo(name, tableNumber, "", { isSystem: true });
9071
+ this.tablesByName.set(info.fullName, info);
9072
+ this.tablesByNumber.set(info.tableNumber, info);
9073
+ }
9074
+ }
9075
+ const metadata = await readSystemMetadata(this.docstore);
9076
+ if (!metadata) {
9077
+ const now = Date.now();
9078
+ this.cachedRegistryVersion = now;
9079
+ await this.docstore.writeGlobal(SYSTEM_METADATA_GLOBAL_KEY, createSystemMetadata({
9080
+ nextUserTableNumber: Math.max(FIRST_USER_TABLE_NUMBER, nextUserTableNumber(this.tablesByNumber.values())),
9081
+ registryVersion: now,
9082
+ bootstrappedAt: now,
9083
+ updatedAt: now
9084
+ }));
9085
+ } else {
9086
+ this.cachedRegistryVersion = metadata.registryVersion;
9087
+ }
9088
+ }
9089
+ }
9090
+
9091
+ // ../core/dist/tables/transactional-table-registry.js
9092
+ init_system_tables();
9093
+ init_utils();
9094
+ init_interface();
8570
9095
  // ../core/dist/kernel/contexts.js
8571
9096
  init_context_storage();
8572
- var snapshotContext = new ContextStorage;
8573
- var transactionContext = new ContextStorage;
8574
- var idGeneratorContext = new ContextStorage;
9097
+ var SNAPSHOT_CONTEXT_SYMBOL = Symbol.for("@concavejs/core/snapshot-context");
9098
+ var TRANSACTION_CONTEXT_SYMBOL = Symbol.for("@concavejs/core/transaction-context");
9099
+ var ID_GENERATOR_CONTEXT_SYMBOL = Symbol.for("@concavejs/core/id-generator-context");
9100
+ var globalContexts = globalThis;
9101
+ var snapshotContext = globalContexts[SNAPSHOT_CONTEXT_SYMBOL] ?? new ContextStorage;
9102
+ var transactionContext = globalContexts[TRANSACTION_CONTEXT_SYMBOL] ?? new ContextStorage;
9103
+ var idGeneratorContext = globalContexts[ID_GENERATOR_CONTEXT_SYMBOL] ?? new ContextStorage;
9104
+ if (!globalContexts[SNAPSHOT_CONTEXT_SYMBOL]) {
9105
+ globalContexts[SNAPSHOT_CONTEXT_SYMBOL] = snapshotContext;
9106
+ }
9107
+ if (!globalContexts[TRANSACTION_CONTEXT_SYMBOL]) {
9108
+ globalContexts[TRANSACTION_CONTEXT_SYMBOL] = transactionContext;
9109
+ }
9110
+ if (!globalContexts[ID_GENERATOR_CONTEXT_SYMBOL]) {
9111
+ globalContexts[ID_GENERATOR_CONTEXT_SYMBOL] = idGeneratorContext;
9112
+ }
8575
9113
  // ../core/dist/queryengine/convex-ops.js
8576
9114
  var debug = () => {};
8577
9115
  class CfConvex {
@@ -8624,6 +9162,8 @@ class BaseSqliteDocStore {
8624
9162
  vectorIndexesByTable = new Map;
8625
9163
  fts5Available = true;
8626
9164
  statementCache = new Map;
9165
+ configuredSearchIndexes = [];
9166
+ configuredVectorIndexes = [];
8627
9167
  constructor(adapter) {
8628
9168
  this.adapter = adapter;
8629
9169
  this.timestampOracle = new TimestampOracle;
@@ -8638,6 +9178,8 @@ class BaseSqliteDocStore {
8638
9178
  return statement;
8639
9179
  }
8640
9180
  async setupSchema(options) {
9181
+ this.configuredSearchIndexes = [...options?.searchIndexes ?? []];
9182
+ this.configuredVectorIndexes = [...options?.vectorIndexes ?? []];
8641
9183
  await this.adapter.exec(DOCUMENTS_TABLE_SCHEMA);
8642
9184
  await this.adapter.exec(DOCUMENTS_BY_TABLE_INDEX);
8643
9185
  await this.adapter.exec(INDEXES_TABLE_SCHEMA);
@@ -8645,6 +9187,24 @@ class BaseSqliteDocStore {
8645
9187
  await this.setupSearchIndexes(options?.searchIndexes ?? []);
8646
9188
  await this.setupVectorIndexes(options?.vectorIndexes ?? []);
8647
9189
  }
9190
+ async resetForTesting() {
9191
+ 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();
9192
+ for (const row of rows) {
9193
+ const tableName = row?.name;
9194
+ if (typeof tableName !== "string" || tableName.length === 0) {
9195
+ continue;
9196
+ }
9197
+ await this.adapter.exec(`DROP TABLE IF EXISTS ${quoteSqlIdentifier(tableName)}`);
9198
+ }
9199
+ this.statementCache.clear();
9200
+ this.searchIndexesByTable.clear();
9201
+ this.vectorIndexesByTable.clear();
9202
+ this.fts5Available = true;
9203
+ await this.setupSchema({
9204
+ searchIndexes: this.configuredSearchIndexes,
9205
+ vectorIndexes: this.configuredVectorIndexes
9206
+ });
9207
+ }
8648
9208
  async setupSearchIndexes(searchIndexes) {
8649
9209
  try {
8650
9210
  await this.adapter.exec(SEARCH_INDEXES_FTS_SCHEMA);
@@ -8860,6 +9420,15 @@ class BaseSqliteDocStore {
8860
9420
  const stmt = this.getPreparedStatement("INSERT OR REPLACE INTO persistence_globals (key, json_value) VALUES (?, ?)");
8861
9421
  await stmt.run(key, JSON.stringify(value));
8862
9422
  }
9423
+ async writeGlobalIfAbsent(key, value) {
9424
+ const insertStmt = this.getPreparedStatement("INSERT OR IGNORE INTO persistence_globals (key, json_value) VALUES (?, ?)");
9425
+ const changesStmt = this.getPreparedStatement("SELECT changes() as changes");
9426
+ return this.adapter.transaction(async () => {
9427
+ await insertStmt.run(key, JSON.stringify(value));
9428
+ const row = await changesStmt.get();
9429
+ return Number(row?.changes ?? 0) > 0;
9430
+ });
9431
+ }
8863
9432
  async previous_revisions(queries) {
8864
9433
  const results = new Map;
8865
9434
  const stmt = this.getPreparedStatement(`
@@ -9155,6 +9724,9 @@ class BaseSqliteDocStore {
9155
9724
  return scored.slice(0, limit);
9156
9725
  }
9157
9726
  }
9727
+ function quoteSqlIdentifier(value) {
9728
+ return `"${value.replace(/"/g, '""')}"`;
9729
+ }
9158
9730
  // ../docstore-sqlite-base/dist/transaction-runner.js
9159
9731
  function createSerializedTransactionRunner(hooks) {
9160
9732
  let queue = Promise.resolve();