@concavejs/docstore-memory 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.
package/dist/index.js CHANGED
@@ -13,12 +13,236 @@ var __export = (target, all) => {
13
13
  });
14
14
  };
15
15
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
16
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
17
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
18
- }) : x)(function(x) {
19
- if (typeof require !== "undefined")
20
- return require.apply(this, arguments);
21
- throw Error('Dynamic require of "' + x + '" is not supported');
16
+
17
+ // ../core/dist/id-codec/base32.js
18
+ function base32Encode(data) {
19
+ if (data.length === 0)
20
+ return "";
21
+ let result = "";
22
+ let buffer = 0;
23
+ let bitsLeft = 0;
24
+ for (const byte of data) {
25
+ buffer = buffer << 8 | byte;
26
+ bitsLeft += 8;
27
+ while (bitsLeft >= 5) {
28
+ bitsLeft -= 5;
29
+ const index = buffer >> bitsLeft & 31;
30
+ result += ALPHABET[index];
31
+ }
32
+ }
33
+ if (bitsLeft > 0) {
34
+ const index = buffer << 5 - bitsLeft & 31;
35
+ result += ALPHABET[index];
36
+ }
37
+ return result;
38
+ }
39
+ function base32Decode(str) {
40
+ if (str.length === 0)
41
+ return new Uint8Array(0);
42
+ const outputLength = Math.floor(str.length * 5 / 8);
43
+ const result = new Uint8Array(outputLength);
44
+ let buffer = 0;
45
+ let bitsLeft = 0;
46
+ let outputIndex = 0;
47
+ for (const char of str) {
48
+ const value = ALPHABET_MAP.get(char);
49
+ if (value === undefined) {
50
+ throw new Error(`Invalid base32 character: ${char}`);
51
+ }
52
+ buffer = buffer << 5 | value;
53
+ bitsLeft += 5;
54
+ if (bitsLeft >= 8) {
55
+ bitsLeft -= 8;
56
+ result[outputIndex++] = buffer >> bitsLeft & 255;
57
+ }
58
+ }
59
+ return result;
60
+ }
61
+ function isValidBase32(str) {
62
+ for (const char of str) {
63
+ if (!ALPHABET_MAP.has(char)) {
64
+ return false;
65
+ }
66
+ }
67
+ return true;
68
+ }
69
+ var ALPHABET = "0123456789abcdefghjkmnpqrstvwxyz", ALPHABET_MAP;
70
+ var init_base32 = __esm(() => {
71
+ ALPHABET_MAP = new Map;
72
+ for (let i = 0;i < ALPHABET.length; i++) {
73
+ ALPHABET_MAP.set(ALPHABET[i], i);
74
+ ALPHABET_MAP.set(ALPHABET[i].toUpperCase(), i);
75
+ }
76
+ ALPHABET_MAP.set("i", 1);
77
+ ALPHABET_MAP.set("I", 1);
78
+ ALPHABET_MAP.set("l", 1);
79
+ ALPHABET_MAP.set("L", 1);
80
+ ALPHABET_MAP.set("o", 0);
81
+ ALPHABET_MAP.set("O", 0);
82
+ });
83
+
84
+ // ../core/dist/id-codec/vint.js
85
+ function vintEncode(value) {
86
+ if (value < 0) {
87
+ throw new Error("VInt cannot encode negative numbers");
88
+ }
89
+ if (value > 4294967295) {
90
+ throw new Error("VInt cannot encode values larger than 2^32-1");
91
+ }
92
+ value = value >>> 0;
93
+ if (value < 128) {
94
+ return new Uint8Array([value]);
95
+ }
96
+ if (value < 16512) {
97
+ const adjusted2 = value - 128;
98
+ return new Uint8Array([128 | adjusted2 >> 8 & 63, adjusted2 & 255]);
99
+ }
100
+ if (value < 2113664) {
101
+ const adjusted2 = value - 16512;
102
+ return new Uint8Array([192 | adjusted2 >> 16 & 31, adjusted2 >> 8 & 255, adjusted2 & 255]);
103
+ }
104
+ if (value < 270549120) {
105
+ const adjusted2 = value - 2113664;
106
+ return new Uint8Array([
107
+ 224 | adjusted2 >> 24 & 15,
108
+ adjusted2 >> 16 & 255,
109
+ adjusted2 >> 8 & 255,
110
+ adjusted2 & 255
111
+ ]);
112
+ }
113
+ const adjusted = value - 270549120;
114
+ return new Uint8Array([
115
+ 240 | adjusted >> 32 & 7,
116
+ adjusted >> 24 & 255,
117
+ adjusted >> 16 & 255,
118
+ adjusted >> 8 & 255,
119
+ adjusted & 255
120
+ ]);
121
+ }
122
+ function vintDecode(data, offset = 0) {
123
+ if (offset >= data.length) {
124
+ throw new Error("VInt decode: unexpected end of data");
125
+ }
126
+ const first = data[offset];
127
+ if ((first & 128) === 0) {
128
+ return { value: first, bytesRead: 1 };
129
+ }
130
+ if ((first & 192) === 128) {
131
+ if (offset + 1 >= data.length) {
132
+ throw new Error("VInt decode: truncated 2-byte encoding");
133
+ }
134
+ const value = 128 + ((first & 63) << 8 | data[offset + 1]);
135
+ return { value, bytesRead: 2 };
136
+ }
137
+ if ((first & 224) === 192) {
138
+ if (offset + 2 >= data.length) {
139
+ throw new Error("VInt decode: truncated 3-byte encoding");
140
+ }
141
+ const value = 16512 + ((first & 31) << 16 | data[offset + 1] << 8 | data[offset + 2]);
142
+ return { value, bytesRead: 3 };
143
+ }
144
+ if ((first & 240) === 224) {
145
+ if (offset + 3 >= data.length) {
146
+ throw new Error("VInt decode: truncated 4-byte encoding");
147
+ }
148
+ const value = 2113664 + ((first & 15) << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3]);
149
+ return { value: value >>> 0, bytesRead: 4 };
150
+ }
151
+ if ((first & 248) === 240) {
152
+ if (offset + 4 >= data.length) {
153
+ throw new Error("VInt decode: truncated 5-byte encoding");
154
+ }
155
+ const high = first & 7;
156
+ const low = (data[offset + 1] << 24 | data[offset + 2] << 16 | data[offset + 3] << 8 | data[offset + 4]) >>> 0;
157
+ const value = 270549120 + high * 4294967296 + low;
158
+ return { value: value >>> 0, bytesRead: 5 };
159
+ }
160
+ throw new Error("VInt decode: invalid prefix");
161
+ }
162
+
163
+ // ../core/dist/id-codec/fletcher16.js
164
+ function fletcher16(data) {
165
+ let sum1 = 0;
166
+ let sum2 = 0;
167
+ for (const byte of data) {
168
+ sum1 = (sum1 + byte) % 255;
169
+ sum2 = (sum2 + sum1) % 255;
170
+ }
171
+ return new Uint8Array([sum1, sum2]);
172
+ }
173
+ function verifyFletcher16(data, checksum) {
174
+ if (checksum.length !== 2)
175
+ return false;
176
+ const computed = fletcher16(data);
177
+ return computed[0] === checksum[0] && computed[1] === checksum[1];
178
+ }
179
+
180
+ // ../core/dist/utils/crypto.js
181
+ var weakRandomState;
182
+ var init_crypto = __esm(() => {
183
+ weakRandomState = (Date.now() ^ 2654435769) >>> 0;
184
+ });
185
+
186
+ // ../core/dist/id-codec/document-id.js
187
+ function encodeDocumentId(tableNumber, internalId) {
188
+ if (internalId.length !== INTERNAL_ID_LENGTH) {
189
+ throw new Error(`Internal ID must be exactly ${INTERNAL_ID_LENGTH} bytes, got ${internalId.length}`);
190
+ }
191
+ if (tableNumber < 1 || tableNumber > 4294967295) {
192
+ throw new Error(`Table number must be between 1 and 2^32-1, got ${tableNumber}`);
193
+ }
194
+ const tableBytes = vintEncode(tableNumber);
195
+ const payload = new Uint8Array(tableBytes.length + INTERNAL_ID_LENGTH);
196
+ payload.set(tableBytes, 0);
197
+ payload.set(internalId, tableBytes.length);
198
+ const checksum = fletcher16(payload);
199
+ const final = new Uint8Array(payload.length + 2);
200
+ final.set(payload, 0);
201
+ final.set(checksum, payload.length);
202
+ return base32Encode(final);
203
+ }
204
+ function decodeDocumentId(encoded) {
205
+ if (encoded.length < MIN_ENCODED_LENGTH || encoded.length > MAX_ENCODED_LENGTH) {
206
+ throw new Error(`Invalid document ID length: ${encoded.length} (expected ${MIN_ENCODED_LENGTH}-${MAX_ENCODED_LENGTH})`);
207
+ }
208
+ if (!isValidBase32(encoded)) {
209
+ throw new Error("Invalid document ID: contains invalid base32 characters");
210
+ }
211
+ const bytes = base32Decode(encoded);
212
+ if (bytes.length < 19) {
213
+ throw new Error(`Invalid document ID: decoded to ${bytes.length} bytes (minimum 19)`);
214
+ }
215
+ const checksum = bytes.slice(bytes.length - 2);
216
+ const payload = bytes.slice(0, bytes.length - 2);
217
+ if (!verifyFletcher16(payload, checksum)) {
218
+ throw new Error("Invalid document ID: checksum verification failed");
219
+ }
220
+ const { value: tableNumber, bytesRead } = vintDecode(payload, 0);
221
+ const internalId = payload.slice(bytesRead, bytesRead + INTERNAL_ID_LENGTH);
222
+ if (internalId.length !== INTERNAL_ID_LENGTH) {
223
+ throw new Error(`Invalid document ID: internal ID is ${internalId.length} bytes (expected ${INTERNAL_ID_LENGTH})`);
224
+ }
225
+ return { tableNumber, internalId };
226
+ }
227
+ function isValidDocumentId(encoded) {
228
+ try {
229
+ decodeDocumentId(encoded);
230
+ return true;
231
+ } catch {
232
+ return false;
233
+ }
234
+ }
235
+ function internalIdToHex(internalId) {
236
+ let hex = "";
237
+ for (let i = 0;i < internalId.length; i++) {
238
+ hex += internalId[i].toString(16).padStart(2, "0");
239
+ }
240
+ return hex;
241
+ }
242
+ var INTERNAL_ID_LENGTH = 16, MIN_ENCODED_LENGTH = 31, MAX_ENCODED_LENGTH = 37;
243
+ var init_document_id = __esm(() => {
244
+ init_base32();
245
+ init_crypto();
22
246
  });
23
247
 
24
248
  // ../core/dist/utils/utils.js
@@ -59,9 +283,15 @@ function deserializeDeveloperId(developerId) {
59
283
  return null;
60
284
  }
61
285
  var DOC_ID_SEPARATOR = ":", LEGACY_DOC_ID_SEPARATOR = ";";
286
+ var init_utils = __esm(() => {
287
+ init_document_id();
288
+ });
62
289
 
63
290
  // ../core/dist/tables/interface.js
64
291
  function getFullTableName(tableName, componentPath) {
292
+ if (isSystemTable(tableName)) {
293
+ return tableName;
294
+ }
65
295
  if (!componentPath || componentPath === "") {
66
296
  return tableName;
67
297
  }
@@ -78,23 +308,28 @@ function parseFullTableName(fullName) {
78
308
  };
79
309
  }
80
310
  function isSystemTable(tableName) {
81
- return tableName.startsWith("_");
311
+ return Object.hasOwn(SYSTEM_TABLE_NUMBERS, tableName);
82
312
  }
83
- var SYSTEM_TABLE_NUMBERS, FIRST_USER_TABLE_NUMBER = 100;
313
+ var SYSTEM_TABLE_NUMBERS, FIRST_USER_TABLE_NUMBER = 10001;
84
314
  var init_interface = __esm(() => {
85
315
  SYSTEM_TABLE_NUMBERS = {
86
316
  _tables: 1,
87
317
  _scheduled_functions: 2,
88
318
  _storage: 3,
89
- _crons: 4
319
+ _crons: 4,
320
+ _indexes: 5,
321
+ _schemas: 6,
322
+ _components: 7,
323
+ _component_definitions: 8,
324
+ _schema_validation_progress: 9
90
325
  };
91
326
  });
92
327
 
93
328
  // ../core/dist/kernel/context-storage.js
94
- function resolveFromRequire(req) {
329
+ function resolveFromModuleResolver(resolveModule) {
95
330
  for (const specifier of ["node:async_hooks", "async_hooks"]) {
96
331
  try {
97
- const mod = req(specifier);
332
+ const mod = resolveModule(specifier);
98
333
  if (mod?.AsyncLocalStorage) {
99
334
  return mod.AsyncLocalStorage;
100
335
  }
@@ -137,16 +372,16 @@ var resolveAsyncLocalStorage = () => {
137
372
  if (globalCtor) {
138
373
  return globalCtor;
139
374
  }
140
- const runtimeRequire = __require;
141
- if (runtimeRequire) {
142
- const ctor = resolveFromRequire(runtimeRequire);
375
+ const getBuiltinModule = globalThis?.process?.getBuiltinModule;
376
+ if (typeof getBuiltinModule === "function") {
377
+ const ctor = resolveFromModuleResolver((specifier) => getBuiltinModule(specifier));
143
378
  if (ctor) {
144
379
  return ctor;
145
380
  }
146
381
  }
147
382
  const globalRequire = globalThis?.require;
148
383
  if (typeof globalRequire === "function") {
149
- return resolveFromRequire(globalRequire);
384
+ return resolveFromModuleResolver(globalRequire);
150
385
  }
151
386
  return;
152
387
  }, AsyncLocalStorageCtor;
@@ -2217,7 +2452,7 @@ async function listSystemFunctions(options = {}) {
2217
2452
  }
2218
2453
  for (const route of httpRoutes) {
2219
2454
  const method = route.route.method;
2220
- const routePath = route.route.path;
2455
+ const routePath = mountHttpRoutePath(route.route.path, owningComponent);
2221
2456
  results.push({
2222
2457
  name: `${method} ${routePath}`,
2223
2458
  module: listing.path,
@@ -2279,6 +2514,16 @@ async function loadAndAnalyzeModule(listing, componentPath) {
2279
2514
  function makeCacheKey(componentPath, modulePath) {
2280
2515
  return `${componentPath ?? ""}::${modulePath}`;
2281
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
+ }
2282
2527
  function buildFallbackSourcePath(modulePath) {
2283
2528
  const trimmed = modulePath.replace(/\\/g, "/").replace(/^\//, "");
2284
2529
  const withConvex = trimmed.startsWith("convex/") ? trimmed : `convex/${trimmed}`;
@@ -3965,6 +4210,7 @@ var init_remote = __esm(() => {
3965
4210
  // ../../node_modules/jose/dist/webapi/index.js
3966
4211
  var init_webapi = __esm(() => {
3967
4212
  init_verify4();
4213
+ init_local();
3968
4214
  init_remote();
3969
4215
  init_errors2();
3970
4216
  });
@@ -4169,7 +4415,7 @@ function getRemoteJwks(jwksUrl, config) {
4169
4415
  if (cached) {
4170
4416
  JWKS_CACHE.delete(jwksUrl);
4171
4417
  }
4172
- const jwks = createRemoteJWKSet(new URL(jwksUrl));
4418
+ const jwks = jwksUrl.startsWith("data:") ? createLocalJWKSet(parseDataUriJson(jwksUrl)) : createRemoteJWKSet(new URL(jwksUrl));
4173
4419
  const configuredTtl = config?.jwksCacheTtlMs;
4174
4420
  const ttlMs = resolveJwksCacheTtlMs(configuredTtl);
4175
4421
  JWKS_CACHE.set(jwksUrl, {
@@ -4178,6 +4424,24 @@ function getRemoteJwks(jwksUrl, config) {
4178
4424
  });
4179
4425
  return jwks;
4180
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
+ }
4181
4445
  function resolveJwksCacheTtlMs(configuredTtl) {
4182
4446
  if (configuredTtl === undefined) {
4183
4447
  return DEFAULT_JWKS_CACHE_TTL_MS;
@@ -4212,6 +4476,7 @@ async function verifyJwt(token, config) {
4212
4476
  const options = {
4213
4477
  issuer: effectiveConfig.issuer,
4214
4478
  audience: effectiveConfig.audience,
4479
+ algorithms: effectiveConfig.algorithms,
4215
4480
  clockTolerance: effectiveConfig.clockTolerance ?? DEFAULT_CLOCK_TOLERANCE_SECONDS
4216
4481
  };
4217
4482
  let payload;
@@ -4769,47 +5034,231 @@ var init_auth = __esm(() => {
4769
5034
  init_auth_config_service();
4770
5035
  });
4771
5036
 
4772
- // ../core/dist/system/internal.js
4773
- function requireSystemCapability(capability) {
4774
- const principal2 = getPrincipal();
4775
- if (!principal2) {
4776
- throw new Error("System functions require authentication context");
4777
- }
4778
- requireAuthorization(principal2, { kind: "management_operation", capability });
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;
4779
5052
  }
4780
- function createSystemFunctions(deps) {
4781
- const { query, mutation } = deps;
5053
+ function isPublicSystemTable(name) {
5054
+ return getSystemTableDefinition(name)?.visibility === "public";
5055
+ }
5056
+ function createTableInfo(name, tableNumber, componentPath = "", options = {}) {
5057
+ const fullName = getFullTableName(name, componentPath);
4782
5058
  return {
4783
- systemListComponents: query({
4784
- args: {},
4785
- handler: async (_ctx) => {
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, timestamp) {
5171
+ return createTableMetadataEntry(table, timestamp, table.createdAt);
5172
+ }
5173
+ function createTableMetadataEntry(table, timestamp, 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(timestamp),
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: timestamp,
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({
5250
+ args: {},
5251
+ handler: async (ctx) => {
4786
5252
  requireSystemCapability("components:read");
4787
- const modules = await listRegisteredModules();
4788
- const componentPaths = new Set;
4789
- componentPaths.add("");
4790
- for (const module of modules) {
4791
- if (module.componentPath) {
4792
- componentPaths.add(module.componentPath);
4793
- }
4794
- }
4795
- const components = [];
4796
- for (const path of componentPaths) {
4797
- const componentModules = modules.filter((m) => path === "" ? !m.componentPath || m.componentPath === "" : m.componentPath === path);
4798
- const functions = await listSystemFunctions({ componentPath: path || undefined });
4799
- components.push({
4800
- path: path || "(root)",
4801
- isRoot: path === "",
4802
- 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,
4803
5258
  functionCount: functions.length
4804
- });
4805
- }
4806
- return components.sort((a, b) => {
4807
- if (a.isRoot)
4808
- return -1;
4809
- if (b.isRoot)
4810
- return 1;
4811
- return a.path.localeCompare(b.path);
4812
- });
5259
+ };
5260
+ }));
5261
+ return sortComponentRows(withFunctionCounts);
4813
5262
  }
4814
5263
  }),
4815
5264
  systemListTables: query({
@@ -4818,25 +5267,40 @@ function createSystemFunctions(deps) {
4818
5267
  requireSystemCapability("tables:read");
4819
5268
  const targetComponent = componentPath ?? "";
4820
5269
  const schema2 = await loadSchemaDefinition(targetComponent);
4821
- let tableEntries = [];
5270
+ const schemaTables = new Map;
4822
5271
  if (schema2?.tables) {
4823
- tableEntries = extractTablesFromSchema(schema2);
4824
- } else {
4825
- try {
4826
- const systemTables = await ctx.db.system.query("_tables").collect();
4827
- tableEntries = systemTables.map((table) => ({
4828
- name: table.name,
4829
- exported: {
4830
- indexes: table.indexes || [],
4831
- searchIndexes: table.searchIndexes || [],
4832
- vectorIndexes: table.vectorIndexes || [],
4833
- documentType: null
4834
- }
4835
- }));
4836
- } catch {
4837
- tableEntries = [];
5272
+ for (const table of extractTablesFromSchema(schema2)) {
5273
+ schemaTables.set(table.name, table);
4838
5274
  }
4839
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
+ }));
4840
5304
  const tableInfo = await Promise.all(tableEntries.map(async (table) => {
4841
5305
  const fullName = getFullTableName(table.name, targetComponent);
4842
5306
  const documentCount = await countDocuments(ctx, fullName);
@@ -4847,6 +5311,8 @@ function createSystemFunctions(deps) {
4847
5311
  name: table.name,
4848
5312
  fullName,
4849
5313
  componentPath: targetComponent || undefined,
5314
+ isSystem: table.isSystem,
5315
+ visibility: table.visibility,
4850
5316
  documentCount,
4851
5317
  indexes: buildIndexList(exported?.indexes),
4852
5318
  searchIndexes: searchIndexes.map((idx) => typeof idx === "string" ? idx : idx.indexDescriptor),
@@ -4880,7 +5346,7 @@ function createSystemFunctions(deps) {
4880
5346
  }
4881
5347
  try {
4882
5348
  const fullName = getFullTableName(tableName, targetComponent);
4883
- const sampleDoc = await ctx.db.query(fullName).first();
5349
+ const sampleDoc = await getTableQuery(ctx, fullName).first();
4884
5350
  const fields = sampleDoc ? Object.keys(sampleDoc).map((key) => ({
4885
5351
  name: key,
4886
5352
  type: typeof sampleDoc[key],
@@ -4915,7 +5381,7 @@ function createSystemFunctions(deps) {
4915
5381
  handler: async (ctx, args) => {
4916
5382
  requireSystemCapability("documents:read");
4917
5383
  const fullName = getFullTableName(args.tableName, args.componentPath ?? "");
4918
- let query2 = ctx.db.query(fullName);
5384
+ let query2 = getTableQuery(ctx, fullName);
4919
5385
  if (args.orderBy && args.orderBy !== "_creationTime") {
4920
5386
  const allDocs2 = await query2.collect();
4921
5387
  const sorted = allDocs2.sort((a, b) => {
@@ -4966,7 +5432,7 @@ function createSystemFunctions(deps) {
4966
5432
  handler: async (ctx, args) => {
4967
5433
  requireSystemCapability("documents:write");
4968
5434
  const fullName = getFullTableName(args.tableName, args.componentPath ?? "");
4969
- const docs = await ctx.db.query(fullName).collect();
5435
+ const docs = await getTableQuery(ctx, fullName).collect();
4970
5436
  for (const doc of docs) {
4971
5437
  await ctx.db.delete(doc._id);
4972
5438
  }
@@ -5262,6 +5728,83 @@ function resolveFunctionReference(functionPath, componentPath) {
5262
5728
  }
5263
5729
  return functionPath;
5264
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
+ }
5265
5808
  async function loadSchemaDefinition(componentPath) {
5266
5809
  try {
5267
5810
  const module = await loadConvexModule("schema", {
@@ -5295,13 +5838,26 @@ function extractTableMetadata(schema2, tableName) {
5295
5838
  }
5296
5839
  async function countDocuments(ctx, tableName) {
5297
5840
  try {
5298
- const documents = await ctx.db.query(tableName).collect();
5841
+ const documents = await getTableQuery(ctx, tableName).collect();
5299
5842
  return documents.length;
5300
5843
  } catch (error) {
5301
5844
  console.warn(`Failed to count documents for table ${tableName}:`, error);
5302
5845
  return 0;
5303
5846
  }
5304
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
+ }
5305
5861
  function buildIndexList(indexes) {
5306
5862
  const base = ["by_id", "by_creation_time"];
5307
5863
  if (!indexes || indexes.length === 0) {
@@ -5403,6 +5959,7 @@ var init_internal = __esm(() => {
5403
5959
  init_interface();
5404
5960
  init_execution_log();
5405
5961
  init_auth();
5962
+ init_system_tables();
5406
5963
  });
5407
5964
 
5408
5965
  // ../core/dist/system/system-functions-module.js
@@ -5560,8 +6117,9 @@ class ModuleRegistry {
5560
6117
  const normalized = normalizeModuleListing(listing);
5561
6118
  if (!normalized)
5562
6119
  continue;
5563
- if (!results.has(normalized.path)) {
5564
- results.set(normalized.path, {
6120
+ const resultKey = `${normalized.componentPath ?? scope ?? ""}:${normalized.path}`;
6121
+ if (!results.has(resultKey)) {
6122
+ results.set(resultKey, {
5565
6123
  ...normalized,
5566
6124
  scope: scope || undefined,
5567
6125
  componentPath: normalized.componentPath ?? (scope || undefined)
@@ -5880,8 +6438,10 @@ var init_module_loader = __esm(() => {
5880
6438
  class SchemaValidator {
5881
6439
  schemaCache = new Map;
5882
6440
  componentPath;
5883
- constructor(componentPath) {
6441
+ tableRegistry;
6442
+ constructor(componentPath, tableRegistry) {
5884
6443
  this.componentPath = componentPath;
6444
+ this.tableRegistry = tableRegistry;
5885
6445
  }
5886
6446
  async loadTableSchema(tableName) {
5887
6447
  if (this.schemaCache.has(tableName)) {
@@ -5924,8 +6484,11 @@ class SchemaValidator {
5924
6484
  return;
5925
6485
  }
5926
6486
  try {
6487
+ const tableNumberToName = this.tableRegistry ? new Map((await this.tableRegistry.listTables()).map((table) => [table.tableNumber, table.fullName])) : undefined;
5927
6488
  validateValidator(tableSchema, omit(document, ["_id", "_creationTime"]), "", {
5928
- componentPath: this.componentPath ?? ""
6489
+ componentPath: this.componentPath ?? "",
6490
+ tableRegistry: this.tableRegistry,
6491
+ tableNumberToName
5929
6492
  });
5930
6493
  } catch (error) {
5931
6494
  throw new ValidatorError(`Failed to insert or update a document in table "${tableName}" because it does not match the schema: ${error.message}`);
@@ -6023,6 +6586,16 @@ Path: ${formatPath(path)}
6023
6586
  Value: ${formatValue(value)}
6024
6587
  Validator: v.id("${validator2.tableName}")`);
6025
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
+ }
6026
6599
  const tableName = tableNameFromId(value);
6027
6600
  if (!tableName || !isMatchingValidatorTable(tableName, validator2.tableName, options.componentPath)) {
6028
6601
  throw new Error(`Value does not match validator.
@@ -6076,302 +6649,88 @@ Validator: v.object({...})`);
6076
6649
  }
6077
6650
  for (const [k, { fieldType, optional }] of Object.entries(validator2.value)) {
6078
6651
  if (value[k] === undefined) {
6079
- if (!optional) {
6080
- throw new Error(`Object is missing the required field \`${k}\`. Consider wrapping the field validator in \`v.optional(...)\` if this is expected.
6081
-
6082
- Object: ${JSON.stringify(value)}
6083
- Validator: v.object({...})`);
6084
- }
6085
- } else {
6086
- const fieldPath = path ? `${path}.${k}` : `.${k}`;
6087
- validateValidator(fieldType, value[k], fieldPath, options);
6088
- }
6089
- }
6090
- for (const k of Object.keys(value)) {
6091
- if (validator2.value[k] === undefined) {
6092
- throw new Error(`Object contains extra field \`${k}\` that is not in the validator.
6093
-
6094
- Object: ${JSON.stringify(value)}
6095
- Validator: v.object({...})`);
6096
- }
6097
- }
6098
- return;
6099
- }
6100
- }
6101
- }
6102
- function tableNameFromId(id) {
6103
- const parts = deserializeDeveloperId(id);
6104
- if (!parts) {
6105
- return null;
6106
- }
6107
- return hexToString(parts.table);
6108
- }
6109
- function isMatchingValidatorTable(idTableName, validatorTableName, componentPath) {
6110
- if (idTableName === validatorTableName) {
6111
- return true;
6112
- }
6113
- const { tableName: validatorBareName } = parseFullTableName(validatorTableName);
6114
- const { tableName: idBareName } = parseFullTableName(idTableName);
6115
- if (componentPath !== undefined) {
6116
- const expectedFullName = getFullTableName(validatorBareName, componentPath);
6117
- return idTableName === expectedFullName;
6118
- }
6119
- return idBareName === validatorBareName;
6120
- }
6121
- function isSimpleObject2(value) {
6122
- const isObject2 = typeof value === "object";
6123
- const prototype = Object.getPrototypeOf(value);
6124
- const isSimple = prototype === null || prototype === Object.prototype || prototype?.constructor?.name === "Object";
6125
- return isObject2 && isSimple;
6126
- }
6127
- var ValidatorError;
6128
- var init_validator2 = __esm(() => {
6129
- init_interface();
6130
- init_module_loader();
6131
- ValidatorError = class ValidatorError extends Error {
6132
- path;
6133
- constructor(message2, path = "") {
6134
- super(message2);
6135
- this.path = path;
6136
- this.name = "ValidatorError";
6137
- }
6138
- };
6139
- });
6140
-
6141
- // ../core/dist/id-codec/base32.js
6142
- function base32Encode(data) {
6143
- if (data.length === 0)
6144
- return "";
6145
- let result = "";
6146
- let buffer = 0;
6147
- let bitsLeft = 0;
6148
- for (const byte of data) {
6149
- buffer = buffer << 8 | byte;
6150
- bitsLeft += 8;
6151
- while (bitsLeft >= 5) {
6152
- bitsLeft -= 5;
6153
- const index = buffer >> bitsLeft & 31;
6154
- result += ALPHABET[index];
6155
- }
6156
- }
6157
- if (bitsLeft > 0) {
6158
- const index = buffer << 5 - bitsLeft & 31;
6159
- result += ALPHABET[index];
6160
- }
6161
- return result;
6162
- }
6163
- function base32Decode(str) {
6164
- if (str.length === 0)
6165
- return new Uint8Array(0);
6166
- const outputLength = Math.floor(str.length * 5 / 8);
6167
- const result = new Uint8Array(outputLength);
6168
- let buffer = 0;
6169
- let bitsLeft = 0;
6170
- let outputIndex = 0;
6171
- for (const char of str) {
6172
- const value = ALPHABET_MAP.get(char);
6173
- if (value === undefined) {
6174
- throw new Error(`Invalid base32 character: ${char}`);
6175
- }
6176
- buffer = buffer << 5 | value;
6177
- bitsLeft += 5;
6178
- if (bitsLeft >= 8) {
6179
- bitsLeft -= 8;
6180
- result[outputIndex++] = buffer >> bitsLeft & 255;
6181
- }
6182
- }
6183
- return result;
6184
- }
6185
- function isValidBase32(str) {
6186
- for (const char of str) {
6187
- if (!ALPHABET_MAP.has(char)) {
6188
- return false;
6189
- }
6190
- }
6191
- return true;
6192
- }
6193
- var ALPHABET = "0123456789abcdefghjkmnpqrstvwxyz", ALPHABET_MAP;
6194
- var init_base32 = __esm(() => {
6195
- ALPHABET_MAP = new Map;
6196
- for (let i2 = 0;i2 < ALPHABET.length; i2++) {
6197
- ALPHABET_MAP.set(ALPHABET[i2], i2);
6198
- ALPHABET_MAP.set(ALPHABET[i2].toUpperCase(), i2);
6199
- }
6200
- ALPHABET_MAP.set("i", 1);
6201
- ALPHABET_MAP.set("I", 1);
6202
- ALPHABET_MAP.set("l", 1);
6203
- ALPHABET_MAP.set("L", 1);
6204
- ALPHABET_MAP.set("o", 0);
6205
- ALPHABET_MAP.set("O", 0);
6206
- });
6207
-
6208
- // ../core/dist/id-codec/vint.js
6209
- function vintEncode(value) {
6210
- if (value < 0) {
6211
- throw new Error("VInt cannot encode negative numbers");
6212
- }
6213
- if (value > 4294967295) {
6214
- throw new Error("VInt cannot encode values larger than 2^32-1");
6215
- }
6216
- value = value >>> 0;
6217
- if (value < 128) {
6218
- return new Uint8Array([value]);
6219
- }
6220
- if (value < 16512) {
6221
- const adjusted2 = value - 128;
6222
- return new Uint8Array([128 | adjusted2 >> 8 & 63, adjusted2 & 255]);
6223
- }
6224
- if (value < 2113664) {
6225
- const adjusted2 = value - 16512;
6226
- return new Uint8Array([192 | adjusted2 >> 16 & 31, adjusted2 >> 8 & 255, adjusted2 & 255]);
6227
- }
6228
- if (value < 270549120) {
6229
- const adjusted2 = value - 2113664;
6230
- return new Uint8Array([
6231
- 224 | adjusted2 >> 24 & 15,
6232
- adjusted2 >> 16 & 255,
6233
- adjusted2 >> 8 & 255,
6234
- adjusted2 & 255
6235
- ]);
6236
- }
6237
- const adjusted = value - 270549120;
6238
- return new Uint8Array([
6239
- 240 | adjusted >> 32 & 7,
6240
- adjusted >> 24 & 255,
6241
- adjusted >> 16 & 255,
6242
- adjusted >> 8 & 255,
6243
- adjusted & 255
6244
- ]);
6245
- }
6246
- function vintDecode(data, offset = 0) {
6247
- if (offset >= data.length) {
6248
- throw new Error("VInt decode: unexpected end of data");
6249
- }
6250
- const first = data[offset];
6251
- if ((first & 128) === 0) {
6252
- return { value: first, bytesRead: 1 };
6253
- }
6254
- if ((first & 192) === 128) {
6255
- if (offset + 1 >= data.length) {
6256
- throw new Error("VInt decode: truncated 2-byte encoding");
6257
- }
6258
- const value = 128 + ((first & 63) << 8 | data[offset + 1]);
6259
- return { value, bytesRead: 2 };
6260
- }
6261
- if ((first & 224) === 192) {
6262
- if (offset + 2 >= data.length) {
6263
- throw new Error("VInt decode: truncated 3-byte encoding");
6264
- }
6265
- const value = 16512 + ((first & 31) << 16 | data[offset + 1] << 8 | data[offset + 2]);
6266
- return { value, bytesRead: 3 };
6267
- }
6268
- if ((first & 240) === 224) {
6269
- if (offset + 3 >= data.length) {
6270
- throw new Error("VInt decode: truncated 4-byte encoding");
6271
- }
6272
- const value = 2113664 + ((first & 15) << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3]);
6273
- return { value: value >>> 0, bytesRead: 4 };
6274
- }
6275
- if ((first & 248) === 240) {
6276
- if (offset + 4 >= data.length) {
6277
- throw new Error("VInt decode: truncated 5-byte encoding");
6278
- }
6279
- const high = first & 7;
6280
- const low = (data[offset + 1] << 24 | data[offset + 2] << 16 | data[offset + 3] << 8 | data[offset + 4]) >>> 0;
6281
- const value = 270549120 + high * 4294967296 + low;
6282
- return { value: value >>> 0, bytesRead: 5 };
6283
- }
6284
- throw new Error("VInt decode: invalid prefix");
6285
- }
6286
-
6287
- // ../core/dist/id-codec/fletcher16.js
6288
- function fletcher16(data) {
6289
- let sum1 = 0;
6290
- let sum2 = 0;
6291
- for (const byte of data) {
6292
- sum1 = (sum1 + byte) % 255;
6293
- sum2 = (sum2 + sum1) % 255;
6294
- }
6295
- return new Uint8Array([sum1, sum2]);
6296
- }
6297
- function verifyFletcher16(data, checksum) {
6298
- if (checksum.length !== 2)
6299
- return false;
6300
- const computed = fletcher16(data);
6301
- return computed[0] === checksum[0] && computed[1] === checksum[1];
6302
- }
6303
-
6304
- // ../core/dist/utils/crypto.js
6305
- var weakRandomState;
6306
- var init_crypto = __esm(() => {
6307
- weakRandomState = (Date.now() ^ 2654435769) >>> 0;
6308
- });
6309
-
6310
- // ../core/dist/id-codec/document-id.js
6311
- function encodeDocumentId(tableNumber, internalId) {
6312
- if (internalId.length !== INTERNAL_ID_LENGTH) {
6313
- throw new Error(`Internal ID must be exactly ${INTERNAL_ID_LENGTH} bytes, got ${internalId.length}`);
6314
- }
6315
- if (tableNumber < 1 || tableNumber > 4294967295) {
6316
- throw new Error(`Table number must be between 1 and 2^32-1, got ${tableNumber}`);
6317
- }
6318
- const tableBytes = vintEncode(tableNumber);
6319
- const payload = new Uint8Array(tableBytes.length + INTERNAL_ID_LENGTH);
6320
- payload.set(tableBytes, 0);
6321
- payload.set(internalId, tableBytes.length);
6322
- const checksum = fletcher16(payload);
6323
- const final = new Uint8Array(payload.length + 2);
6324
- final.set(payload, 0);
6325
- final.set(checksum, payload.length);
6326
- return base32Encode(final);
6327
- }
6328
- function decodeDocumentId(encoded) {
6329
- if (encoded.length < MIN_ENCODED_LENGTH || encoded.length > MAX_ENCODED_LENGTH) {
6330
- throw new Error(`Invalid document ID length: ${encoded.length} (expected ${MIN_ENCODED_LENGTH}-${MAX_ENCODED_LENGTH})`);
6331
- }
6332
- if (!isValidBase32(encoded)) {
6333
- throw new Error("Invalid document ID: contains invalid base32 characters");
6334
- }
6335
- const bytes = base32Decode(encoded);
6336
- if (bytes.length < 19) {
6337
- throw new Error(`Invalid document ID: decoded to ${bytes.length} bytes (minimum 19)`);
6338
- }
6339
- const checksum = bytes.slice(bytes.length - 2);
6340
- const payload = bytes.slice(0, bytes.length - 2);
6341
- if (!verifyFletcher16(payload, checksum)) {
6342
- throw new Error("Invalid document ID: checksum verification failed");
6652
+ if (!optional) {
6653
+ throw new Error(`Object is missing the required field \`${k}\`. Consider wrapping the field validator in \`v.optional(...)\` if this is expected.
6654
+
6655
+ Object: ${JSON.stringify(value)}
6656
+ Validator: v.object({...})`);
6657
+ }
6658
+ } else {
6659
+ const fieldPath = path ? `${path}.${k}` : `.${k}`;
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
+ }
6343
6673
  }
6344
- const { value: tableNumber, bytesRead } = vintDecode(payload, 0);
6345
- const internalId = payload.slice(bytesRead, bytesRead + INTERNAL_ID_LENGTH);
6346
- if (internalId.length !== INTERNAL_ID_LENGTH) {
6347
- 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;
6348
6679
  }
6349
- return { tableNumber, internalId };
6680
+ return hexToString(parts.table);
6350
6681
  }
6351
- function isValidDocumentId(encoded) {
6682
+ function tableNameFromConvexId(id, options) {
6352
6683
  try {
6353
- decodeDocumentId(encoded);
6354
- 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;
6355
6690
  } catch {
6356
- return false;
6691
+ return null;
6357
6692
  }
6358
6693
  }
6359
- function internalIdToHex(internalId) {
6360
- let hex = "";
6361
- for (let i2 = 0;i2 < internalId.length; i2++) {
6362
- hex += internalId[i2].toString(16).padStart(2, "0");
6694
+ function isMatchingValidatorTable(idTableName, validatorTableName, componentPath) {
6695
+ if (idTableName === validatorTableName) {
6696
+ return true;
6363
6697
  }
6364
- 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;
6365
6705
  }
6366
- var INTERNAL_ID_LENGTH = 16, MIN_ENCODED_LENGTH = 31, MAX_ENCODED_LENGTH = 37;
6367
- var init_document_id = __esm(() => {
6368
- init_base32();
6369
- 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
+ };
6370
6726
  });
6371
6727
 
6372
6728
  // ../core/dist/docstore/interface.js
6373
6729
  function documentIdKey(id) {
6374
- const tableKey = id.table && id.table.length > 0 ? id.table : id.tableNumber !== undefined && Number.isInteger(id.tableNumber) && id.tableNumber > 0 ? `#${id.tableNumber}` : id.table;
6730
+ const tableKey = id.table && id.table.length > 0 ? id.table : id.tableNumber !== undefined && Number.isInteger(id.tableNumber) && id.tableNumber > 0 ? `#${id.tableNumber}` : null;
6731
+ if (!tableKey) {
6732
+ throw new Error("Invalid document ID: missing table and tableNumber");
6733
+ }
6375
6734
  return `${tableKey}:${id.internalId}`;
6376
6735
  }
6377
6736
  var Order;
@@ -6401,6 +6760,9 @@ function extractSearchContent(docValue, searchField) {
6401
6760
  }
6402
6761
  return null;
6403
6762
  }
6763
+ // ../core/dist/queryengine/indexing/index-manager.js
6764
+ init_utils();
6765
+
6404
6766
  // ../core/dist/queryengine/indexing/index-key-codec.js
6405
6767
  var TypeTag;
6406
6768
  (function(TypeTag2) {
@@ -6450,8 +6812,9 @@ function encodeBigInt(n) {
6450
6812
  return bytes;
6451
6813
  }
6452
6814
  function encodeString(s) {
6453
- const encoder = new TextEncoder;
6454
- const raw = encoder.encode(s);
6815
+ return encodeEscapedBytes(new TextEncoder().encode(s));
6816
+ }
6817
+ function encodeEscapedBytes(raw) {
6455
6818
  let nullCount = 0;
6456
6819
  for (const byte of raw) {
6457
6820
  if (byte === 0)
@@ -6515,11 +6878,10 @@ function encodeValue(value) {
6515
6878
  }
6516
6879
  if (value instanceof ArrayBuffer || value instanceof Uint8Array) {
6517
6880
  const bytes = value instanceof Uint8Array ? value : new Uint8Array(value);
6518
- const result = new Uint8Array(1 + bytes.length + 2);
6881
+ const encoded = encodeEscapedBytes(bytes);
6882
+ const result = new Uint8Array(1 + encoded.length);
6519
6883
  result[0] = TypeTag.Bytes;
6520
- result.set(bytes, 1);
6521
- result[result.length - 2] = 0;
6522
- result[result.length - 1] = 0;
6884
+ result.set(encoded, 1);
6523
6885
  return result;
6524
6886
  }
6525
6887
  throw new Error(`Cannot encode value of type ${typeof value} in index key`);
@@ -6636,9 +6998,11 @@ class SchemaService {
6636
6998
  tableCache = new Map;
6637
6999
  schemaValidator;
6638
7000
  componentPath;
6639
- constructor(componentPath) {
7001
+ tableRegistry;
7002
+ constructor(componentPath, tableRegistry) {
6640
7003
  this.componentPath = componentPath;
6641
- this.schemaValidator = new SchemaValidator(componentPath);
7004
+ this.tableRegistry = tableRegistry;
7005
+ this.schemaValidator = new SchemaValidator(componentPath, tableRegistry);
6642
7006
  }
6643
7007
  async validate(tableName, document) {
6644
7008
  try {
@@ -6763,6 +7127,10 @@ class SchemaService {
6763
7127
  return this.cachedSchemaDefinition;
6764
7128
  }
6765
7129
  }
7130
+
7131
+ // ../core/dist/queryengine/index-query.js
7132
+ init_utils();
7133
+
6766
7134
  // ../core/dist/observability/udf-trace.js
6767
7135
  init_context_storage();
6768
7136
  var TRACE_CONTEXT = new ContextStorage;
@@ -7006,11 +7374,10 @@ function evaluateFieldPath(fieldPath, document) {
7006
7374
  }
7007
7375
  return current;
7008
7376
  }
7009
- // ../core/dist/id-codec/index.js
7010
- init_base32();
7011
- init_document_id();
7012
7377
 
7013
7378
  // ../core/dist/queryengine/developer-id.js
7379
+ init_utils();
7380
+ init_id_codec();
7014
7381
  function parseDeveloperId(developerId) {
7015
7382
  if (isValidDocumentId(developerId)) {
7016
7383
  try {
@@ -7028,6 +7395,25 @@ function parseDeveloperId(developerId) {
7028
7395
  }
7029
7396
  return { table: parts.table, internalId: parts.internalId };
7030
7397
  }
7398
+ async function parseDeveloperIdWithTableRegistry(developerId, tableRegistry) {
7399
+ if (isValidDocumentId(developerId)) {
7400
+ try {
7401
+ const decoded = decodeDocumentId(developerId);
7402
+ const tableInfo = await tableRegistry.getTableInfo(decoded.tableNumber);
7403
+ if (!tableInfo) {
7404
+ return null;
7405
+ }
7406
+ return {
7407
+ table: stringToHex(tableInfo.fullName),
7408
+ internalId: internalIdToHex(decoded.internalId),
7409
+ tableNumber: decoded.tableNumber
7410
+ };
7411
+ } catch {
7412
+ return null;
7413
+ }
7414
+ }
7415
+ return parseDeveloperId(developerId);
7416
+ }
7031
7417
  function parseStorageId(storageId) {
7032
7418
  const parsed = parseDeveloperId(storageId);
7033
7419
  if (parsed) {
@@ -7044,7 +7430,12 @@ function parseStorageId(storageId) {
7044
7430
  function isTablePlaceholder(table) {
7045
7431
  return table.startsWith("#");
7046
7432
  }
7433
+
7434
+ // ../core/dist/query/query-runtime.js
7435
+ init_utils();
7436
+
7047
7437
  // ../core/dist/utils/keyspace.js
7438
+ init_utils();
7048
7439
  var TABLE_PREFIX = "table";
7049
7440
  var INDEX_PREFIX = "index";
7050
7441
  function encodeComponent(component) {
@@ -7088,10 +7479,15 @@ function decodeIndexId(indexId) {
7088
7479
 
7089
7480
  // ../core/dist/query/planner.js
7090
7481
  init_interface();
7482
+ init_utils();
7483
+
7091
7484
  // ../core/dist/query/actions.js
7485
+ init_utils();
7092
7486
  init_interface();
7093
7487
 
7094
7488
  // ../core/dist/queryengine/indexing/read-write-set.js
7489
+ init_utils();
7490
+
7095
7491
  class RangeSet {
7096
7492
  ranges = new Map;
7097
7493
  addDocument(docId) {
@@ -7202,6 +7598,8 @@ function deserializeKeyRange(serialized) {
7202
7598
  }
7203
7599
 
7204
7600
  // ../core/dist/kernel/access-log.js
7601
+ init_utils();
7602
+
7205
7603
  class AccessLog {
7206
7604
  ranges = new RangeSet;
7207
7605
  addDocument(docId) {
@@ -7226,104 +7624,9 @@ class AccessLog {
7226
7624
  }
7227
7625
  }
7228
7626
 
7229
- // ../core/dist/tables/memory-table-registry.js
7627
+ // ../core/dist/kernel/kernel-context.js
7230
7628
  init_interface();
7231
7629
 
7232
- class MemoryTableRegistry {
7233
- tablesByName = new Map;
7234
- tablesByNumber = new Map;
7235
- nextTableNumber = FIRST_USER_TABLE_NUMBER;
7236
- constructor() {
7237
- this.registerSystemTables();
7238
- }
7239
- registerSystemTables() {
7240
- for (const [name, number] of Object.entries(SYSTEM_TABLE_NUMBERS)) {
7241
- const info = {
7242
- tableNumber: number,
7243
- name,
7244
- componentPath: "",
7245
- fullName: name,
7246
- isSystem: true,
7247
- createdAt: Date.now()
7248
- };
7249
- this.tablesByName.set(name, info);
7250
- this.tablesByNumber.set(number, info);
7251
- }
7252
- }
7253
- async getOrAllocateTableNumber(tableName, componentPath = "") {
7254
- const fullName = getFullTableName(tableName, componentPath);
7255
- const existing = this.tablesByName.get(fullName);
7256
- if (existing) {
7257
- return existing.tableNumber;
7258
- }
7259
- if (isSystemTable(tableName) && componentPath === "") {
7260
- const systemNumber = SYSTEM_TABLE_NUMBERS[tableName];
7261
- if (systemNumber !== undefined) {
7262
- return systemNumber;
7263
- }
7264
- }
7265
- const tableNumber = this.nextTableNumber++;
7266
- const info = {
7267
- tableNumber,
7268
- name: tableName,
7269
- componentPath,
7270
- fullName,
7271
- isSystem: false,
7272
- createdAt: Date.now()
7273
- };
7274
- this.tablesByName.set(fullName, info);
7275
- this.tablesByNumber.set(tableNumber, info);
7276
- return tableNumber;
7277
- }
7278
- async getTableInfo(tableNumber) {
7279
- return this.tablesByNumber.get(tableNumber) ?? null;
7280
- }
7281
- async getTableInfoByName(tableName, componentPath = "") {
7282
- const fullName = getFullTableName(tableName, componentPath);
7283
- return this.tablesByName.get(fullName) ?? null;
7284
- }
7285
- async listTables(componentPath) {
7286
- const tables = Array.from(this.tablesByNumber.values());
7287
- if (componentPath === undefined) {
7288
- return tables;
7289
- }
7290
- return tables.filter((t) => t.componentPath === componentPath);
7291
- }
7292
- async hasAccess(tableNumber, componentPath) {
7293
- const info = await this.getTableInfo(tableNumber);
7294
- if (!info) {
7295
- return false;
7296
- }
7297
- if (info.isSystem) {
7298
- return true;
7299
- }
7300
- return info.componentPath === componentPath;
7301
- }
7302
- getSystemTableNumber(systemTableName) {
7303
- return SYSTEM_TABLE_NUMBERS[systemTableName];
7304
- }
7305
- reset() {
7306
- this.tablesByName.clear();
7307
- this.tablesByNumber.clear();
7308
- this.nextTableNumber = FIRST_USER_TABLE_NUMBER;
7309
- this.registerSystemTables();
7310
- }
7311
- getState() {
7312
- return {
7313
- tableCount: this.tablesByNumber.size,
7314
- nextNumber: this.nextTableNumber
7315
- };
7316
- }
7317
- }
7318
- var globalRegistry = null;
7319
- function getGlobalTableRegistry() {
7320
- if (!globalRegistry) {
7321
- globalRegistry = new MemoryTableRegistry;
7322
- }
7323
- return globalRegistry;
7324
- }
7325
-
7326
- // ../core/dist/kernel/kernel-context.js
7327
7630
  class KernelContext {
7328
7631
  authContext;
7329
7632
  componentPath;
@@ -7340,11 +7643,14 @@ class KernelContext {
7340
7643
  this.authContext = options.authContext;
7341
7644
  this.componentPath = options.componentPath ?? "";
7342
7645
  this.mutationTransaction = options.mutationTransaction;
7343
- this.tableRegistry = options.tableRegistry ?? getGlobalTableRegistry();
7344
- this.useConvexIdFormat = options.useConvexIdFormat ?? false;
7646
+ if (!options.tableRegistry) {
7647
+ throw new Error("KernelContext requires an explicit tableRegistry");
7648
+ }
7649
+ this.tableRegistry = options.tableRegistry;
7650
+ this.useConvexIdFormat = options.useConvexIdFormat ?? true;
7345
7651
  }
7346
7652
  async getTableNumber(tableName) {
7347
- return this.tableRegistry.getOrAllocateTableNumber(tableName, this.componentPath);
7653
+ return this.tableRegistry.getOrAllocateTableNumber(tableName, isSystemTable(tableName) ? "" : this.componentPath);
7348
7654
  }
7349
7655
  nextSubrequestId(prefix, udfPath) {
7350
7656
  return `${prefix}:${udfPath}:${Date.now()}:${Math.random()}:${this.subrequestCounter++}`;
@@ -7389,7 +7695,7 @@ class KernelContext {
7389
7695
  this.writeLog.addDocument(docId);
7390
7696
  }
7391
7697
  recordLocalWrite(developerId, tableName, value, docId) {
7392
- this.localWrites.set(developerId, { table: tableName, value });
7698
+ this.localWrites.set(developerId, { table: tableName, value, docId });
7393
7699
  if (docId) {
7394
7700
  this.recordDocumentWrite(docId);
7395
7701
  return;
@@ -7431,7 +7737,13 @@ class KernelContext {
7431
7737
  }
7432
7738
  }
7433
7739
 
7740
+ // ../core/dist/kernel/udf-kernel.js
7741
+ init_id_codec();
7742
+
7434
7743
  // ../core/dist/kernel/blob-store-gateway.js
7744
+ init_id_codec();
7745
+ init_utils();
7746
+
7435
7747
  class BlobStoreGateway {
7436
7748
  context;
7437
7749
  docStore;
@@ -7480,7 +7792,7 @@ class BlobStoreGateway {
7480
7792
  if (!this.storage) {
7481
7793
  return null;
7482
7794
  }
7483
- const docId = parseStorageId(storageId);
7795
+ const docId = await parseDeveloperIdWithTableRegistry(storageId, this.context.tableRegistry) ?? parseStorageId(storageId);
7484
7796
  if (!docId) {
7485
7797
  console.debug(`[BlobStoreGateway] Failed to parse storage ID: ${storageId}`);
7486
7798
  return null;
@@ -7501,7 +7813,7 @@ class BlobStoreGateway {
7501
7813
  if (!this.storage) {
7502
7814
  return null;
7503
7815
  }
7504
- const docId = parseStorageId(storageId);
7816
+ const docId = await parseDeveloperIdWithTableRegistry(storageId, this.context.tableRegistry) ?? parseStorageId(storageId);
7505
7817
  if (!docId) {
7506
7818
  return null;
7507
7819
  }
@@ -7514,7 +7826,7 @@ class BlobStoreGateway {
7514
7826
  }
7515
7827
  async delete(storageId) {
7516
7828
  const storage2 = this.requireStorage();
7517
- const docId = parseStorageId(storageId);
7829
+ const docId = await parseDeveloperIdWithTableRegistry(storageId, this.context.tableRegistry) ?? parseStorageId(storageId);
7518
7830
  if (!docId) {
7519
7831
  return;
7520
7832
  }
@@ -7539,13 +7851,17 @@ class BlobStoreGateway {
7539
7851
 
7540
7852
  // ../core/dist/kernel/scheduler-gateway.js
7541
7853
  init_values();
7854
+ init_id_codec();
7855
+ init_utils();
7856
+
7542
7857
  // ../core/dist/kernel/syscalls/utils.js
7543
7858
  init_values();
7859
+ init_utils();
7544
7860
  async function resolveTableName(docId, tableRegistry) {
7545
7861
  if (docId.tableNumber !== undefined) {
7546
7862
  const info = await tableRegistry.getTableInfo(docId.tableNumber);
7547
7863
  if (info) {
7548
- return info.name;
7864
+ return info.fullName;
7549
7865
  }
7550
7866
  if (!isTablePlaceholder(docId.table)) {
7551
7867
  return hexToString(docId.table);
@@ -7726,7 +8042,7 @@ class SchedulerGateway {
7726
8042
  return developerId;
7727
8043
  }
7728
8044
  async cancel(id, state) {
7729
- const docId = parseDeveloperId(id);
8045
+ const docId = await parseDeveloperIdWithTableRegistry(id, this.context.tableRegistry);
7730
8046
  if (!docId) {
7731
8047
  throw new Error(`Scheduled job with id ${id} not found.`);
7732
8048
  }
@@ -7851,6 +8167,8 @@ class ActionSyscalls {
7851
8167
 
7852
8168
  // ../core/dist/kernel/syscalls/database-syscalls.js
7853
8169
  init_values();
8170
+ init_id_codec();
8171
+ init_utils();
7854
8172
  init_interface();
7855
8173
 
7856
8174
  class DatabaseSyscalls {
@@ -7887,7 +8205,8 @@ class DatabaseSyscalls {
7887
8205
  if (docId.tableNumber !== undefined) {
7888
8206
  return { id: idString };
7889
8207
  }
7890
- if (docId.table === stringToHex(tableName)) {
8208
+ const expectedFullTableName = getFullTableName(tableName, isSystemTable(tableName) ? "" : this.context.componentPath);
8209
+ if (docId.table === stringToHex(expectedFullTableName)) {
7891
8210
  return { id: idString };
7892
8211
  }
7893
8212
  return { id: null };
@@ -7946,29 +8265,28 @@ class DatabaseSyscalls {
7946
8265
  return { _id: developerId };
7947
8266
  }
7948
8267
  async handleGet(args) {
7949
- const { id } = args;
8268
+ const { id, table } = args;
7950
8269
  if (typeof id !== "string") {
7951
8270
  throw new Error("`id` argument for `get` must be a string.");
7952
8271
  }
7953
- const internalId = parseDeveloperId(id);
7954
- if (!internalId) {
8272
+ const resolved = await this.resolveDocumentTarget(id, table, "get");
8273
+ if (!resolved) {
7955
8274
  return null;
7956
8275
  }
7957
- this.context.recordDocumentRead(internalId);
7958
- const doc = await this.queryRuntime.getVisibleDocumentById(id, internalId);
8276
+ this.context.recordDocumentRead(resolved.docId);
8277
+ const doc = await this.queryRuntime.getVisibleDocumentById(id, resolved.docId);
7959
8278
  return doc ?? null;
7960
8279
  }
7961
8280
  async handleRemove(args) {
7962
- const { id } = args;
8281
+ const { id, table } = args;
7963
8282
  if (typeof id !== "string") {
7964
8283
  throw new Error("`id` argument for `remove` must be a string.");
7965
8284
  }
7966
- const docId = parseDeveloperId(id);
7967
- if (!docId) {
8285
+ const resolved = await this.resolveDocumentTarget(id, table, "remove", true);
8286
+ if (!resolved) {
7968
8287
  throw new Error(`Document with id ${id} not found.`);
7969
8288
  }
7970
- const fullTableName = await resolveTableName(docId, this.context.tableRegistry);
7971
- const { tableName: bareTableName } = parseFullTableName(fullTableName);
8289
+ const { docId, fullTableName, bareTableName } = resolved;
7972
8290
  const latest = await this.docStore.fetchLatestDocument(docId, this.context.snapshotTimestamp);
7973
8291
  if (!latest) {
7974
8292
  throw new Error(`Document with id ${id} not found.`);
@@ -7984,16 +8302,15 @@ class DatabaseSyscalls {
7984
8302
  return {};
7985
8303
  }
7986
8304
  async handleShallowMerge(args) {
7987
- const { id, value } = args;
8305
+ const { id, table, value } = args;
7988
8306
  if (typeof id !== "string") {
7989
8307
  throw new Error("`id` argument for `shallowMerge` must be a string.");
7990
8308
  }
7991
- const docId = parseDeveloperId(id);
7992
- if (!docId) {
8309
+ const resolved = await this.resolveDocumentTarget(id, table, "patch", true);
8310
+ if (!resolved) {
7993
8311
  throw new Error(`Document with id ${id} not found.`);
7994
8312
  }
7995
- const fullTableName = await resolveTableName(docId, this.context.tableRegistry);
7996
- const { tableName: bareTableName } = parseFullTableName(fullTableName);
8313
+ const { docId, fullTableName, bareTableName } = resolved;
7997
8314
  if (value && typeof value === "object") {
7998
8315
  if ("_id" in value) {
7999
8316
  throw new Error("System field `_id` cannot be modified in a patch operation.");
@@ -8044,16 +8361,15 @@ class DatabaseSyscalls {
8044
8361
  return {};
8045
8362
  }
8046
8363
  async handleReplace(args) {
8047
- const { id, value } = args;
8364
+ const { id, table, value } = args;
8048
8365
  if (typeof id !== "string") {
8049
8366
  throw new Error("`id` argument for `replace` must be a string.");
8050
8367
  }
8051
- const docId = parseDeveloperId(id);
8052
- if (!docId) {
8368
+ const resolved = await this.resolveDocumentTarget(id, table, "replace", true);
8369
+ if (!resolved) {
8053
8370
  throw new Error(`Document with id ${id} not found.`);
8054
8371
  }
8055
- const fullTableName = await resolveTableName(docId, this.context.tableRegistry);
8056
- const { tableName: bareTableName } = parseFullTableName(fullTableName);
8372
+ const { docId, fullTableName, bareTableName } = resolved;
8057
8373
  const replaceValue = jsonToConvex(value);
8058
8374
  if (typeof replaceValue !== "object" || replaceValue === null || Array.isArray(replaceValue)) {
8059
8375
  throw new Error("The replacement value for `replace` must be an object.");
@@ -8076,6 +8392,27 @@ class DatabaseSyscalls {
8076
8392
  this.context.recordLocalWrite(id, fullTableName, newValue, canonicalDocId);
8077
8393
  return {};
8078
8394
  }
8395
+ async resolveDocumentTarget(id, table, operation, throwOnMismatch = false) {
8396
+ if (table !== undefined && typeof table !== "string") {
8397
+ throw new Error(`\`table\` argument for \`${operation}\` must be a string.`);
8398
+ }
8399
+ const docId = await parseDeveloperIdWithTableRegistry(id, this.context.tableRegistry);
8400
+ if (!docId) {
8401
+ return null;
8402
+ }
8403
+ const fullTableName = await resolveTableName(docId, this.context.tableRegistry);
8404
+ if (typeof table === "string") {
8405
+ const expectedFullTableName = getFullTableName(table, isSystemTable(table) ? "" : this.context.componentPath);
8406
+ if (fullTableName !== expectedFullTableName) {
8407
+ if (throwOnMismatch) {
8408
+ throw new Error(`Document with id ${id} does not belong to table ${table}.`);
8409
+ }
8410
+ return null;
8411
+ }
8412
+ }
8413
+ const { tableName: bareTableName } = parseFullTableName(fullTableName);
8414
+ return { docId, fullTableName, bareTableName };
8415
+ }
8079
8416
  }
8080
8417
 
8081
8418
  // ../core/dist/kernel/syscalls/identity-syscalls.js
@@ -8391,11 +8728,203 @@ class KernelSyscalls {
8391
8728
  return this.jsRouter.dispatch(op, args);
8392
8729
  }
8393
8730
  }
8731
+
8732
+ // ../core/dist/tables/docstore-table-registry.js
8733
+ init_system_tables();
8734
+ init_utils();
8735
+ init_interface();
8736
+
8737
+ class DocStoreTableRegistry {
8738
+ docstore;
8739
+ tablesByNumber = new Map;
8740
+ tablesByName = new Map;
8741
+ loadPromise = null;
8742
+ cachedRegistryVersion = 0;
8743
+ constructor(docstore) {
8744
+ this.docstore = docstore;
8745
+ }
8746
+ async getOrAllocateTableNumber(tableName, componentPath = "") {
8747
+ await this.ensureLoaded();
8748
+ await this.ensureFresh();
8749
+ const normalizedComponent = isSystemTable(tableName) ? "" : componentPath;
8750
+ const fullName = getFullTableName(tableName, normalizedComponent);
8751
+ let existing = this.tablesByName.get(fullName);
8752
+ if (existing) {
8753
+ return existing.tableNumber;
8754
+ }
8755
+ await this.reloadTables();
8756
+ existing = this.tablesByName.get(fullName);
8757
+ if (existing) {
8758
+ return existing.tableNumber;
8759
+ }
8760
+ const oracle = this.docstore.timestampOracle;
8761
+ for (;; ) {
8762
+ const metadata = await readSystemMetadata(this.docstore) ?? createSystemMetadata({
8763
+ nextUserTableNumber: Math.max(FIRST_USER_TABLE_NUMBER, nextUserTableNumber(this.tablesByNumber.values()))
8764
+ });
8765
+ const candidate = Math.max(metadata.nextUserTableNumber, nextUserTableNumber(this.tablesByNumber.values()));
8766
+ const reserved = await this.docstore.writeGlobalIfAbsent(createTableNumberReservationKey(candidate), {
8767
+ fullName,
8768
+ reservedAt: Date.now()
8769
+ });
8770
+ if (!reserved) {
8771
+ await this.reloadTables();
8772
+ const raced = this.tablesByName.get(fullName);
8773
+ if (raced) {
8774
+ return raced.tableNumber;
8775
+ }
8776
+ continue;
8777
+ }
8778
+ const createdAt = Date.now();
8779
+ const info = createTableInfo(tableName, candidate, normalizedComponent, { createdAt, visibility: "public" });
8780
+ const timestamp = oracle?.allocateTimestamp?.() ?? BigInt(createdAt);
8781
+ const entry = createTableMetadataEntryForUserTable(info, timestamp);
8782
+ try {
8783
+ await this.docstore.write([entry], new Set, "Error");
8784
+ } catch {
8785
+ await this.reloadTables();
8786
+ const raced = this.tablesByName.get(fullName);
8787
+ if (raced) {
8788
+ return raced.tableNumber;
8789
+ }
8790
+ throw new Error(`Failed to allocate table number for ${fullName}`);
8791
+ }
8792
+ const registryVersion = Number(timestamp > BigInt(Number.MAX_SAFE_INTEGER) ? BigInt(Date.now()) : timestamp);
8793
+ await this.docstore.writeGlobal(SYSTEM_METADATA_GLOBAL_KEY, createSystemMetadata({
8794
+ nextUserTableNumber: candidate + 1,
8795
+ registryVersion,
8796
+ bootstrappedAt: metadata.bootstrappedAt,
8797
+ updatedAt: registryVersion
8798
+ }));
8799
+ this.cachedRegistryVersion = registryVersion;
8800
+ this.tablesByName.set(fullName, info);
8801
+ this.tablesByNumber.set(candidate, info);
8802
+ return candidate;
8803
+ }
8804
+ }
8805
+ async getTableInfo(tableNumber) {
8806
+ await this.ensureLoaded();
8807
+ await this.ensureFresh();
8808
+ const existing = this.tablesByNumber.get(tableNumber);
8809
+ if (existing) {
8810
+ return existing;
8811
+ }
8812
+ await this.reloadTables();
8813
+ return this.tablesByNumber.get(tableNumber) ?? null;
8814
+ }
8815
+ async getTableInfoByName(tableName, componentPath = "") {
8816
+ await this.ensureLoaded();
8817
+ await this.ensureFresh();
8818
+ const fullName = getFullTableName(tableName, isSystemTable(tableName) ? "" : componentPath);
8819
+ const existing = this.tablesByName.get(fullName);
8820
+ if (existing) {
8821
+ return existing;
8822
+ }
8823
+ await this.reloadTables();
8824
+ return this.tablesByName.get(fullName) ?? null;
8825
+ }
8826
+ async listTables(componentPath) {
8827
+ await this.ensureLoaded();
8828
+ await this.ensureFresh();
8829
+ const values = Array.from(this.tablesByNumber.values());
8830
+ if (componentPath === undefined) {
8831
+ return values.sort((a, b) => a.tableNumber - b.tableNumber);
8832
+ }
8833
+ return values.filter((table) => table.componentPath === componentPath).sort((a, b) => a.tableNumber - b.tableNumber);
8834
+ }
8835
+ async hasAccess(tableNumber, componentPath) {
8836
+ const info = await this.getTableInfo(tableNumber);
8837
+ if (!info) {
8838
+ return false;
8839
+ }
8840
+ if (info.isSystem) {
8841
+ return true;
8842
+ }
8843
+ return info.componentPath === componentPath;
8844
+ }
8845
+ getSystemTableNumber(systemTableName) {
8846
+ return SYSTEM_TABLE_NUMBERS[systemTableName];
8847
+ }
8848
+ async ensureLoaded() {
8849
+ if (!this.loadPromise) {
8850
+ this.loadPromise = this.loadTables();
8851
+ }
8852
+ await this.loadPromise;
8853
+ }
8854
+ async ensureFresh() {
8855
+ const metadata = await readSystemMetadata(this.docstore);
8856
+ if (!metadata) {
8857
+ if (this.cachedRegistryVersion !== 0 || this.tablesByName.size > 0 || this.tablesByNumber.size > 0) {
8858
+ await this.reloadTables();
8859
+ }
8860
+ return;
8861
+ }
8862
+ if (metadata.registryVersion > this.cachedRegistryVersion) {
8863
+ await this.reloadTables();
8864
+ }
8865
+ }
8866
+ async reloadTables() {
8867
+ this.loadPromise = this.loadTables();
8868
+ await this.loadPromise;
8869
+ }
8870
+ async loadTables() {
8871
+ await ensureSystemTablesBootstrapped(this.docstore);
8872
+ const docs = await this.docstore.scan(stringToHex("_tables"));
8873
+ this.tablesByName.clear();
8874
+ this.tablesByNumber.clear();
8875
+ for (const doc of docs) {
8876
+ const info = tableInfoFromStoredDocument(doc.value.value);
8877
+ if (!info) {
8878
+ continue;
8879
+ }
8880
+ this.tablesByName.set(info.fullName, info);
8881
+ this.tablesByNumber.set(info.tableNumber, info);
8882
+ }
8883
+ if (this.tablesByNumber.size === 0) {
8884
+ for (const [name, tableNumber] of Object.entries(SYSTEM_TABLE_NUMBERS)) {
8885
+ const info = createTableInfo(name, tableNumber, "", { isSystem: true });
8886
+ this.tablesByName.set(info.fullName, info);
8887
+ this.tablesByNumber.set(info.tableNumber, info);
8888
+ }
8889
+ }
8890
+ const metadata = await readSystemMetadata(this.docstore);
8891
+ if (!metadata) {
8892
+ const now = Date.now();
8893
+ this.cachedRegistryVersion = now;
8894
+ await this.docstore.writeGlobal(SYSTEM_METADATA_GLOBAL_KEY, createSystemMetadata({
8895
+ nextUserTableNumber: Math.max(FIRST_USER_TABLE_NUMBER, nextUserTableNumber(this.tablesByNumber.values())),
8896
+ registryVersion: now,
8897
+ bootstrappedAt: now,
8898
+ updatedAt: now
8899
+ }));
8900
+ } else {
8901
+ this.cachedRegistryVersion = metadata.registryVersion;
8902
+ }
8903
+ }
8904
+ }
8905
+
8906
+ // ../core/dist/tables/transactional-table-registry.js
8907
+ init_system_tables();
8908
+ init_utils();
8909
+ init_interface();
8394
8910
  // ../core/dist/kernel/contexts.js
8395
8911
  init_context_storage();
8396
- var snapshotContext = new ContextStorage;
8397
- var transactionContext = new ContextStorage;
8398
- var idGeneratorContext = new ContextStorage;
8912
+ var SNAPSHOT_CONTEXT_SYMBOL = Symbol.for("@concavejs/core/snapshot-context");
8913
+ var TRANSACTION_CONTEXT_SYMBOL = Symbol.for("@concavejs/core/transaction-context");
8914
+ var ID_GENERATOR_CONTEXT_SYMBOL = Symbol.for("@concavejs/core/id-generator-context");
8915
+ var globalContexts = globalThis;
8916
+ var snapshotContext = globalContexts[SNAPSHOT_CONTEXT_SYMBOL] ?? new ContextStorage;
8917
+ var transactionContext = globalContexts[TRANSACTION_CONTEXT_SYMBOL] ?? new ContextStorage;
8918
+ var idGeneratorContext = globalContexts[ID_GENERATOR_CONTEXT_SYMBOL] ?? new ContextStorage;
8919
+ if (!globalContexts[SNAPSHOT_CONTEXT_SYMBOL]) {
8920
+ globalContexts[SNAPSHOT_CONTEXT_SYMBOL] = snapshotContext;
8921
+ }
8922
+ if (!globalContexts[TRANSACTION_CONTEXT_SYMBOL]) {
8923
+ globalContexts[TRANSACTION_CONTEXT_SYMBOL] = transactionContext;
8924
+ }
8925
+ if (!globalContexts[ID_GENERATOR_CONTEXT_SYMBOL]) {
8926
+ globalContexts[ID_GENERATOR_CONTEXT_SYMBOL] = idGeneratorContext;
8927
+ }
8399
8928
  // ../core/dist/queryengine/convex-ops.js
8400
8929
  var debug = () => {};
8401
8930
  class CfConvex {
@@ -8542,6 +9071,10 @@ class TimestampOracle {
8542
9071
  this.logicalClock = ts;
8543
9072
  }
8544
9073
  }
9074
+
9075
+ // ../core/dist/utils/index.js
9076
+ init_utils();
9077
+
8545
9078
  // src/memory-docstore.ts
8546
9079
  class MemoryDocStore {
8547
9080
  timestampOracle = new TimestampOracle;
@@ -8643,6 +9176,13 @@ class MemoryDocStore {
8643
9176
  async writeGlobal(key, value) {
8644
9177
  this.globals.set(key, cloneValue(value));
8645
9178
  }
9179
+ async writeGlobalIfAbsent(key, value) {
9180
+ if (this.globals.has(key)) {
9181
+ return false;
9182
+ }
9183
+ this.globals.set(key, cloneValue(value));
9184
+ return true;
9185
+ }
8646
9186
  async previous_revisions(queries) {
8647
9187
  const results = new Map;
8648
9188
  for (const query of queries) {