@gaganref/confect-test 10.3.1-fork.87 → 10.3.1-fork.89

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 (51) hide show
  1. package/dist/internal/Attempt.d.ts +77 -0
  2. package/dist/internal/Attempt.d.ts.map +1 -0
  3. package/dist/internal/Attempt.js +154 -0
  4. package/dist/internal/Attempt.js.map +1 -0
  5. package/dist/internal/ConvexTest.d.ts +34 -0
  6. package/dist/internal/ConvexTest.d.ts.map +1 -0
  7. package/dist/internal/ConvexTest.js +59 -0
  8. package/dist/internal/ConvexTest.js.map +1 -0
  9. package/dist/internal/Execution.d.ts +167 -0
  10. package/dist/internal/Execution.d.ts.map +1 -0
  11. package/dist/internal/Execution.js +790 -0
  12. package/dist/internal/Execution.js.map +1 -0
  13. package/dist/internal/Globals.d.ts +11 -0
  14. package/dist/internal/Globals.d.ts.map +1 -0
  15. package/dist/internal/Globals.js +76 -0
  16. package/dist/internal/Globals.js.map +1 -0
  17. package/dist/internal/Invocation.d.ts +57 -0
  18. package/dist/internal/Invocation.d.ts.map +1 -0
  19. package/dist/internal/Invocation.js +145 -0
  20. package/dist/internal/Invocation.js.map +1 -0
  21. package/dist/internal/Kernel.d.ts +93 -0
  22. package/dist/internal/Kernel.d.ts.map +1 -0
  23. package/dist/internal/Kernel.js +91 -0
  24. package/dist/internal/Kernel.js.map +1 -0
  25. package/dist/internal/KernelQuery.d.ts +55 -0
  26. package/dist/internal/KernelQuery.d.ts.map +1 -0
  27. package/dist/internal/KernelQuery.js +205 -0
  28. package/dist/internal/KernelQuery.js.map +1 -0
  29. package/dist/internal/KernelRefusal.d.ts +77 -0
  30. package/dist/internal/KernelRefusal.d.ts.map +1 -0
  31. package/dist/internal/KernelRefusal.js +73 -0
  32. package/dist/internal/KernelRefusal.js.map +1 -0
  33. package/dist/internal/KernelValues.d.ts +136 -0
  34. package/dist/internal/KernelValues.d.ts.map +1 -0
  35. package/dist/internal/KernelValues.js +266 -0
  36. package/dist/internal/KernelValues.js.map +1 -0
  37. package/dist/internal/ReadSet.d.ts +55 -0
  38. package/dist/internal/ReadSet.d.ts.map +1 -0
  39. package/dist/internal/ReadSet.js +29 -0
  40. package/dist/internal/ReadSet.js.map +1 -0
  41. package/package.json +3 -3
  42. package/src/internal/Attempt.ts +185 -0
  43. package/src/internal/ConvexTest.ts +118 -0
  44. package/src/internal/Execution.ts +1430 -0
  45. package/src/internal/Globals.ts +93 -0
  46. package/src/internal/Invocation.ts +291 -0
  47. package/src/internal/Kernel.ts +190 -0
  48. package/src/internal/KernelQuery.ts +405 -0
  49. package/src/internal/KernelRefusal.ts +88 -0
  50. package/src/internal/KernelValues.ts +725 -0
  51. package/src/internal/ReadSet.ts +108 -0
@@ -0,0 +1,136 @@
1
+ import type { GenericDocument } from "convex/server";
2
+ import { type GenericId, type JSONValue, type Value } from "convex/values";
3
+ /**
4
+ * A function address inside one test backend: its component and its
5
+ * `module:export` path.
6
+ */
7
+ export type FunctionPath = {
8
+ readonly componentPath: string;
9
+ readonly udfPath: string;
10
+ };
11
+ export type FilterJson = {
12
+ $eq: [FilterJson, FilterJson];
13
+ } | {
14
+ $field: string;
15
+ } | JSONValue;
16
+ export type QueryOperator = {
17
+ filter: FilterJson;
18
+ } | {
19
+ limit: number;
20
+ };
21
+ export type Source = {
22
+ type: "FullTableScan";
23
+ tableName: string;
24
+ order: "asc" | "desc" | null;
25
+ } | {
26
+ type: "IndexRange";
27
+ indexName: string;
28
+ range: ReadonlyArray<SerializedRangeExpression>;
29
+ order: "asc" | "desc" | null;
30
+ } | {
31
+ type: "Search";
32
+ indexName: string;
33
+ filters: ReadonlyArray<SerializedSearchFilter>;
34
+ };
35
+ export type SerializedQuery = {
36
+ source: Source;
37
+ operators: Array<QueryOperator>;
38
+ };
39
+ export type SerializedRangeExpression = {
40
+ type: "Eq" | "Gt" | "Gte" | "Lt" | "Lte";
41
+ fieldPath: string;
42
+ value: JSONValue;
43
+ };
44
+ export type SerializedSearchFilter = {
45
+ type: "Search";
46
+ fieldPath: string;
47
+ value: string;
48
+ } | {
49
+ type: "Eq";
50
+ fieldPath: string;
51
+ value: JSONValue;
52
+ };
53
+ export type StoredDocument = GenericDocument & {
54
+ _id: DocumentId;
55
+ _creationTime: number;
56
+ };
57
+ export type Index = {
58
+ indexDescriptor: string;
59
+ fields: string[];
60
+ };
61
+ export type TableName = string;
62
+ export type DocumentId = GenericId<TableName>;
63
+ export declare function tableNameFromId(id: string): string | null;
64
+ export declare function deserializeConvexErrorData(thrown: unknown): unknown;
65
+ export declare function isSimpleObject(value: unknown): boolean;
66
+ export declare const MAX_COMMIT_TS: bigint;
67
+ export declare function hasPendingValues(value: Value): boolean;
68
+ export declare function resolvePendingValues(value: Value): Value;
69
+ export declare function resolveCommittedValues<T extends Value>(value: T, commitTs: bigint): T;
70
+ export declare function substituteCommitTs<T extends Value>(value: T, commitTs: bigint): T;
71
+ export declare function evaluateFieldPath(fieldPath: string, document: any): Value | undefined;
72
+ export declare function evaluateFilter(document: GenericDocument, filter: any): Value | undefined;
73
+ export declare function evaluateRangeFilter(document: GenericDocument, expr: SerializedRangeExpression): boolean;
74
+ export declare function evaluateValue(value: JSONValue): Value | undefined;
75
+ export declare function evaluateQueryValue(value: JSONValue): Value | undefined;
76
+ export declare function validateIndexRangeExpression(source: Source & {
77
+ type: "IndexRange";
78
+ }, fields: string[]): void;
79
+ export declare function printIndexOperator(filter: SerializedRangeExpression): string;
80
+ export declare function validateFieldNames(validator: ValidatorJSON): void;
81
+ export declare function isValidIdentifier(name: string): boolean;
82
+ export type ObjectFieldType = {
83
+ fieldType: ValidatorJSON;
84
+ optional: boolean;
85
+ };
86
+ export type ValidatorJSON = {
87
+ type: "null";
88
+ } | {
89
+ type: "number";
90
+ } | {
91
+ type: "bigint";
92
+ } | {
93
+ type: "commitTs";
94
+ } | {
95
+ type: "boolean";
96
+ } | {
97
+ type: "string";
98
+ } | {
99
+ type: "bytes";
100
+ } | {
101
+ type: "any";
102
+ } | {
103
+ type: "literal";
104
+ value: JSONValue;
105
+ } | {
106
+ type: "id";
107
+ tableName: string;
108
+ } | {
109
+ type: "array";
110
+ value: ValidatorJSON;
111
+ } | {
112
+ type: "object";
113
+ value: Record<string, ObjectFieldType>;
114
+ } | {
115
+ type: "record";
116
+ keys: ValidatorJSON;
117
+ values: ObjectFieldType;
118
+ } | {
119
+ type: "union";
120
+ value: ValidatorJSON[];
121
+ };
122
+ export declare function validateValidator(validator: ValidatorJSON, value: any): void;
123
+ export declare const JWT_CLAIM_BY_IDENTITY_ATTRIBUTE: Record<string, string>;
124
+ export declare function base64UrlEncode(value: string): string;
125
+ export declare function base64UrlEncodeBytes(bytes: Uint8Array): string;
126
+ export declare function createTestJwt(identity: Record<string, any>): string;
127
+ export declare function parseArgs(args: Record<string, Value> | undefined): Record<string, Value>;
128
+ export declare function validateFunctionArgs(argsValidator: ValidatorJSON, args: any, functionPath: FunctionPath, allowPendingValues: boolean): void;
129
+ export declare function validateReturnValue(returnsValidator: ValidatorJSON | null, result: any, functionType: "query" | "mutation" | "action", functionPath: FunctionPath): void;
130
+ export declare function createFunctionHandle(functionPath: FunctionPath): string;
131
+ export declare function parseFunctionHandle(handle: string): {
132
+ componentPath: string;
133
+ udfPath: string;
134
+ };
135
+ export declare function simpleHash(string: string): number;
136
+ //# sourceMappingURL=KernelValues.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"KernelValues.d.ts","sourceRoot":"","sources":["../../src/internal/KernelValues.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,266 @@
1
+ import { CommitTsPlaceholder, compareValues, convexToJson, jsonToConvex } from "convex/values";
2
+ //#region src/internal/KernelValues.ts
3
+ function tableNameFromId(id) {
4
+ const match = id.match(/^[0-9]+/);
5
+ if (!match || match[0].length === id.length) return null;
6
+ return id.slice(match[0].length);
7
+ }
8
+ function deserializeConvexErrorData(thrown) {
9
+ if (typeof thrown === "object" && thrown !== null && Symbol.for("ConvexError") in thrown && typeof thrown.data === "string") try {
10
+ thrown.data = jsonToConvex(JSON.parse(thrown.data));
11
+ } catch {}
12
+ return thrown;
13
+ }
14
+ function isSimpleObject(value) {
15
+ const isObject = typeof value === "object";
16
+ const prototype = Object.getPrototypeOf(value);
17
+ const isSimple = prototype === null || prototype === Object.prototype || prototype?.constructor?.name === "Object";
18
+ return isObject && isSimple;
19
+ }
20
+ const MAX_COMMIT_TS = 2n ** 63n - 1n;
21
+ function hasPendingValues(value) {
22
+ if (value instanceof CommitTsPlaceholder) return true;
23
+ if (Array.isArray(value)) return value.some(hasPendingValues);
24
+ if (value !== null && value !== void 0 && isSimpleObject(value)) return Object.values(value).some(hasPendingValues);
25
+ return false;
26
+ }
27
+ function resolvePendingValues(value) {
28
+ return substituteCommitTs(value, MAX_COMMIT_TS);
29
+ }
30
+ function resolveCommittedValues(value, commitTs) {
31
+ return substituteCommitTs(value, commitTs);
32
+ }
33
+ function substituteCommitTs(value, commitTs) {
34
+ if (!hasPendingValues(value)) return value;
35
+ if (value instanceof CommitTsPlaceholder) return commitTs;
36
+ if (Array.isArray(value)) return value.map((v) => substituteCommitTs(v, commitTs));
37
+ return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, substituteCommitTs(v, commitTs)]));
38
+ }
39
+ function evaluateFieldPath(fieldPath, document) {
40
+ const pathParts = fieldPath.split(".");
41
+ let result = document;
42
+ for (const p of pathParts) result = result !== void 0 && result !== null && isSimpleObject(result) ? result[p] : void 0;
43
+ return result === void 0 ? void 0 : resolvePendingValues(result);
44
+ }
45
+ function evaluateFilter(document, filter) {
46
+ if (filter.$eq !== void 0) return compareValues(evaluateFilter(document, filter.$eq[0]), evaluateFilter(document, filter.$eq[1])) === 0;
47
+ if (filter.$neq !== void 0) return compareValues(evaluateFilter(document, filter.$neq[0]), evaluateFilter(document, filter.$neq[1])) !== 0;
48
+ if (filter.$and !== void 0) return filter.$and.every((child) => evaluateFilter(document, child));
49
+ if (filter.$or !== void 0) return filter.$or.some((child) => evaluateFilter(document, child));
50
+ if (filter.$not !== void 0) return !evaluateFilter(document, filter.$not);
51
+ if (filter.$gt !== void 0) return evaluateFilter(document, filter.$gt[0]) > evaluateFilter(document, filter.$gt[1]);
52
+ if (filter.$gte !== void 0) return evaluateFilter(document, filter.$gte[0]) >= evaluateFilter(document, filter.$gte[1]);
53
+ if (filter.$lt !== void 0) return evaluateFilter(document, filter.$lt[0]) < evaluateFilter(document, filter.$lt[1]);
54
+ if (filter.$lte !== void 0) return evaluateFilter(document, filter.$lte[0]) <= evaluateFilter(document, filter.$lte[1]);
55
+ if (filter.$add !== void 0) return evaluateFilter(document, filter.$add[0]) + evaluateFilter(document, filter.$add[1]);
56
+ if (filter.$sub !== void 0) return evaluateFilter(document, filter.$sub[0]) - evaluateFilter(document, filter.$sub[1]);
57
+ if (filter.$mul !== void 0) return evaluateFilter(document, filter.$mul[0]) * evaluateFilter(document, filter.$mul[1]);
58
+ if (filter.$div !== void 0) return evaluateFilter(document, filter.$div[0]) / evaluateFilter(document, filter.$div[1]);
59
+ if (filter.$mod !== void 0) return evaluateFilter(document, filter.$mod[0]) % evaluateFilter(document, filter.$mod[1]);
60
+ if (filter.$field !== void 0) return evaluateFieldPath(filter.$field, document);
61
+ if (filter.$literal !== void 0) return evaluateQueryValue(filter.$literal);
62
+ throw new Error(`not implemented: ${JSON.stringify(filter)}`);
63
+ }
64
+ function evaluateRangeFilter(document, expr) {
65
+ const result = evaluateFieldPath(expr.fieldPath, document);
66
+ const value = evaluateQueryValue(expr.value);
67
+ switch (expr.type) {
68
+ case "Eq": return compareValues(result, value) === 0;
69
+ case "Gt": return compareValues(result, value) > 0;
70
+ case "Gte": return compareValues(result, value) >= 0;
71
+ case "Lt": return compareValues(result, value) < 0;
72
+ case "Lte": return compareValues(result, value) <= 0;
73
+ }
74
+ }
75
+ function evaluateValue(value) {
76
+ if (typeof value === "object" && value !== null && "$undefined" in value) return;
77
+ return jsonToConvex(value);
78
+ }
79
+ function evaluateQueryValue(value) {
80
+ const evaluatedValue = evaluateValue(value);
81
+ return evaluatedValue === void 0 ? void 0 : resolvePendingValues(evaluatedValue);
82
+ }
83
+ function validateIndexRangeExpression(source, fields) {
84
+ let fieldIndex = 0;
85
+ let state = "eq";
86
+ for (const [filterIndex, filter] of source.range.entries()) {
87
+ if (state === "done") throw new Error(`Incorrect operator used in \`withIndex\`, cannot chain more operators after both \`.gt\` and \`.lt\` were already used, got \`${printIndexOperator(filter)}\`.`);
88
+ const filterType = filter.type == "Gt" || filter.type == "Gte" ? "gt" : filter.type == "Lt" || filter.type == "Lte" ? "lt" : "eq";
89
+ switch (`${state}|${filterType}`) {
90
+ case "eq|eq":
91
+ case "eq|gt":
92
+ case "eq|lt":
93
+ if (filter.fieldPath === fields[fieldIndex]) {
94
+ fieldIndex += 1;
95
+ state = filterType;
96
+ continue;
97
+ }
98
+ throw new Error(`Incorrect field used in \`withIndex\`, expected "${fields[fieldIndex]}", got "${filter.fieldPath}"`);
99
+ case "lt|gt":
100
+ case "gt|lt":
101
+ if (fieldIndex > 0 && filter.fieldPath === fields[fieldIndex - 1]) {
102
+ state = "done";
103
+ continue;
104
+ }
105
+ throw new Error(`Incorrect field used in \`withIndex\`, \`.gt\` and \`.lt\` must operate on the same field, expected "${fields[fieldIndex - 1]}", got "${filter.fieldPath}"`);
106
+ default: throw new Error(`Incorrect operator used in \`withIndex\`, cannot chain \`.${filter.type.toLowerCase()}()\` after \`.${source.range[filterIndex - 1].type.toLowerCase()}()\``);
107
+ }
108
+ }
109
+ }
110
+ function printIndexOperator(filter) {
111
+ return `.${filter.type.toLowerCase()}(${filter.fieldPath}, ${JSON.stringify(filter.value)})`;
112
+ }
113
+ function validateFieldNames(validator) {
114
+ if (validator.type === "object") Object.keys(validator.value).forEach((fieldName) => {
115
+ if (!isValidIdentifier(fieldName)) throw new Error(`Field names must be valid identifiers, got "${fieldName}"`);
116
+ });
117
+ if (validator.type === "union") validator.value.forEach(validateFieldNames);
118
+ }
119
+ function isValidIdentifier(name) {
120
+ return /(^_(id|creationTime)$)|^[a-zA-Z][a-zA-Z0-9_]*$/.test(name);
121
+ }
122
+ function validateValidator(validator, value) {
123
+ switch (validator.type) {
124
+ case "null":
125
+ if (value !== null) throw new Error(`Validator error: Expected \`null\`, got \`${value}\``);
126
+ return;
127
+ case "number":
128
+ if (typeof value !== "number") throw new Error(`Validator error: Expected \`number\`, got \`${value}\``);
129
+ return;
130
+ case "bigint":
131
+ if (typeof value !== "bigint") throw new Error(`Validator error: Expected \`bigint\`, got \`${value}\``);
132
+ return;
133
+ case "commitTs":
134
+ if (typeof value !== "bigint" && !(value instanceof CommitTsPlaceholder)) throw new Error(`Validator error: Expected \`v.commitTs()\`, got \`${value}\``);
135
+ return;
136
+ case "boolean":
137
+ if (typeof value !== "boolean") throw new Error(`Validator error: Expected \`boolean\`, got \`${value}\``);
138
+ return;
139
+ case "string":
140
+ if (typeof value !== "string") throw new Error(`Validator error: Expected \`string\`, got \`${value}\``);
141
+ return;
142
+ case "bytes":
143
+ if (!(value instanceof ArrayBuffer)) throw new Error(`Validator error: Expected \`ArrayBuffer\`, got \`${value}\``);
144
+ return;
145
+ case "any": return;
146
+ case "literal":
147
+ if (value !== validator.value) throw new Error(`Validator error: Expected \`${validator.value}\`, got \`${value}\``);
148
+ return;
149
+ case "id":
150
+ if (typeof value !== "string") throw new Error(`Validator error: Expected \`string\`, got \`${value}\``);
151
+ if (tableNameFromId(value) !== validator.tableName) throw new Error(`Validator error: Expected ID for table "${validator.tableName}", got \`${value}\``);
152
+ return;
153
+ case "array":
154
+ if (!Array.isArray(value)) throw new Error(`Validator error: Expected \`Array\`, got \`${value}\``);
155
+ for (const v of value) validateValidator(validator.value, v);
156
+ return;
157
+ case "union": {
158
+ let isValid = false;
159
+ for (const v of validator.value) try {
160
+ validateValidator(v, value);
161
+ isValid = true;
162
+ break;
163
+ } catch {}
164
+ if (!isValid) throw new Error(`Validator error: Expected one of ${validator.value.map((v) => v.type).join(", ")}, got \`${JSON.stringify(convexToJson(value))}\``);
165
+ return;
166
+ }
167
+ case "object":
168
+ if (typeof value !== "object") throw new Error(`Validator error: Expected \`object\`, got \`${value}\``);
169
+ if (!isSimpleObject(value)) throw new Error(`Validator error: Expected a plain old JavaScript \`object\`, got \`${value}\``);
170
+ for (const [k, { fieldType, optional }] of Object.entries(validator.value)) if (value[k] === void 0) {
171
+ if (!optional) throw new Error(`Validator error: Missing required field \`${k}\` in object`);
172
+ } else validateValidator(fieldType, value[k]);
173
+ for (const k of Object.keys(value)) if (validator.value[k] === void 0) throw new Error(`Validator error: Unexpected field \`${k}\` in object`);
174
+ return;
175
+ case "record":
176
+ if (value === null || typeof value !== "object" || !isSimpleObject(value)) throw new Error(`Validator error: Expected a plain old JavaScript \`object\` for a record, got \`${value}\``);
177
+ for (const [k, fieldValue] of Object.entries(value)) {
178
+ validateValidator(validator.keys, k);
179
+ if (fieldValue !== void 0) validateValidator(validator.values.fieldType, fieldValue);
180
+ }
181
+ return;
182
+ default: throw new Error(`The test kernel cannot check a validator of type \`${validator.type}\`.`);
183
+ }
184
+ }
185
+ const JWT_CLAIM_BY_IDENTITY_ATTRIBUTE = {
186
+ subject: "sub",
187
+ issuer: "iss",
188
+ name: "name",
189
+ givenName: "given_name",
190
+ familyName: "family_name",
191
+ nickname: "nickname",
192
+ preferredUsername: "preferred_username",
193
+ profileUrl: "profile",
194
+ pictureUrl: "picture",
195
+ email: "email",
196
+ emailVerified: "email_verified",
197
+ gender: "gender",
198
+ birthday: "birthdate",
199
+ timezone: "zoneinfo",
200
+ language: "locale",
201
+ phoneNumber: "phone_number",
202
+ phoneNumberVerified: "phone_number_verified",
203
+ address: "address",
204
+ updatedAt: "updated_at"
205
+ };
206
+ function base64UrlEncode(value) {
207
+ return base64UrlEncodeBytes(new TextEncoder().encode(value));
208
+ }
209
+ function base64UrlEncodeBytes(bytes) {
210
+ let binary = "";
211
+ for (const byte of bytes) binary += String.fromCharCode(byte);
212
+ return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
213
+ }
214
+ function createTestJwt(identity) {
215
+ const claims = Object.create(null);
216
+ for (const [attribute, value] of Object.entries(identity)) {
217
+ if (value === void 0 || attribute === "tokenIdentifier") continue;
218
+ const claimName = Object.hasOwn(JWT_CLAIM_BY_IDENTITY_ATTRIBUTE, attribute) ? JWT_CLAIM_BY_IDENTITY_ATTRIBUTE[attribute] : attribute;
219
+ claims[claimName] = value;
220
+ }
221
+ claims.iss = identity.issuer;
222
+ claims.sub = identity.subject;
223
+ return `${base64UrlEncode(JSON.stringify({
224
+ alg: "none",
225
+ typ: "JWT"
226
+ }))}.${base64UrlEncode(JSON.stringify(claims))}.`;
227
+ }
228
+ function parseArgs(args) {
229
+ if (args === void 0) return {};
230
+ if (!isSimpleObject(args)) throw new Error(`The arguments to a Convex function must be an object. Received: ${args}`);
231
+ return args;
232
+ }
233
+ function validateFunctionArgs(argsValidator, args, functionPath, allowPendingValues) {
234
+ if (!allowPendingValues && hasPendingValues(args)) throw new Error(`Invalid arguments for "${functionPath.udfPath}": an unresolved placeholder value can only be passed to a query or mutation called from a mutation`);
235
+ validateValidator(argsValidator, resolvePendingValues(args));
236
+ }
237
+ function validateReturnValue(returnsValidator, result, functionType, functionPath) {
238
+ if (returnsValidator !== null) try {
239
+ validateValidator(returnsValidator, resolvePendingValues(result));
240
+ } catch (e) {
241
+ throw new Error(`Return value validation failed for ${functionType} "${functionPath.udfPath}":\n${e.message}`, { cause: e });
242
+ }
243
+ }
244
+ function createFunctionHandle(functionPath) {
245
+ return `function://${functionPath.componentPath};${functionPath.udfPath}`;
246
+ }
247
+ function parseFunctionHandle(handle) {
248
+ const [componentPath, udfPath] = handle.split("function://")[1].split(";");
249
+ return {
250
+ componentPath,
251
+ udfPath
252
+ };
253
+ }
254
+ function simpleHash(string) {
255
+ let hash = 0;
256
+ for (let i = 0; i < string.length; i++) {
257
+ const char = string.charCodeAt(i);
258
+ hash = (hash << 5) - hash + char;
259
+ hash = hash & hash;
260
+ }
261
+ return hash;
262
+ }
263
+ //#endregion
264
+ export { JWT_CLAIM_BY_IDENTITY_ATTRIBUTE, MAX_COMMIT_TS, base64UrlEncode, base64UrlEncodeBytes, createFunctionHandle, createTestJwt, deserializeConvexErrorData, evaluateFieldPath, evaluateFilter, evaluateQueryValue, evaluateRangeFilter, evaluateValue, hasPendingValues, isSimpleObject, isValidIdentifier, parseArgs, parseFunctionHandle, printIndexOperator, resolveCommittedValues, resolvePendingValues, simpleHash, substituteCommitTs, tableNameFromId, validateFieldNames, validateFunctionArgs, validateIndexRangeExpression, validateReturnValue, validateValidator };
265
+
266
+ //# sourceMappingURL=KernelValues.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"KernelValues.js","names":["unknown"],"sources":["../../src/internal/KernelValues.ts"],"sourcesContent":["// Derived from convex-test 0.0.65 (index.ts), Copyright Convex, Inc.,\n// licensed under the Apache License, Version 2.0\n// (https://www.apache.org/licenses/LICENSE-2.0). The value, filter, range,\n// validator and argument rules are kept as convex-test states them, so the\n// kernel answers a function the way convex-test does. The storage, attempts\n// and execution around them are the kernel's own.\n\nimport type { GenericDocument } from \"convex/server\";\nimport {\n CommitTsPlaceholder,\n type GenericId,\n type JSONValue,\n type Value,\n compareValues,\n convexToJson,\n jsonToConvex,\n} from \"convex/values\";\n\n/**\n * A function address inside one test backend: its component and its\n * `module:export` path.\n */\nexport type FunctionPath = {\n readonly componentPath: string;\n readonly udfPath: string;\n};\n\nexport type FilterJson =\n | { $eq: [FilterJson, FilterJson] }\n | { $field: string }\n | JSONValue;\n\nexport type QueryOperator = { filter: FilterJson } | { limit: number };\nexport type Source =\n | { type: \"FullTableScan\"; tableName: string; order: \"asc\" | \"desc\" | null }\n | {\n type: \"IndexRange\";\n indexName: string;\n range: ReadonlyArray<SerializedRangeExpression>;\n order: \"asc\" | \"desc\" | null;\n }\n | {\n type: \"Search\";\n indexName: string;\n filters: ReadonlyArray<SerializedSearchFilter>;\n };\n\nexport type SerializedQuery = {\n source: Source;\n operators: Array<QueryOperator>;\n};\n\nexport type SerializedRangeExpression = {\n type: \"Eq\" | \"Gt\" | \"Gte\" | \"Lt\" | \"Lte\";\n fieldPath: string;\n value: JSONValue;\n};\n\nexport type SerializedSearchFilter =\n | {\n type: \"Search\";\n fieldPath: string;\n value: string;\n }\n | {\n type: \"Eq\";\n fieldPath: string;\n value: JSONValue;\n };\n\nexport type StoredDocument = GenericDocument & {\n _id: DocumentId;\n _creationTime: number;\n};\n\nexport type Index = {\n indexDescriptor: string;\n fields: string[];\n};\n\nexport type TableName = string;\n\nexport type DocumentId = GenericId<TableName>;\n\nexport function tableNameFromId(id: string) {\n const match = id.match(/^[0-9]+/);\n if (!match || match[0].length === id.length) {\n return null;\n }\n return id.slice(match[0].length);\n}\nexport function deserializeConvexErrorData(thrown: unknown) {\n if (\n typeof thrown === \"object\" &&\n thrown !== null &&\n Symbol.for(\"ConvexError\") in thrown &&\n typeof (thrown as { data: unknown }).data === \"string\"\n ) {\n try {\n (thrown as { data: unknown }).data = jsonToConvex(\n JSON.parse((thrown as { data: string }).data),\n );\n } catch {\n // Data wasn't a serialized JSON string — leave it untouched.\n }\n }\n return thrown;\n}\n\nexport function isSimpleObject(value: unknown) {\n const isObject = typeof value === \"object\";\n const prototype = Object.getPrototypeOf(value);\n const isSimple =\n prototype === null ||\n prototype === Object.prototype ||\n // Objects generated from other contexts (e.g. across Node.js `vm` modules) will not satisfy the previous\n // conditions but are still simple objects.\n prototype?.constructor?.name === \"Object\";\n return isObject && isSimple;\n}\n\n// Commit timestamp placeholders are resolved to `i64::MAX` before commit.\nexport const MAX_COMMIT_TS = 2n ** 63n - 1n;\n\nexport function hasPendingValues(value: Value): boolean {\n if (value instanceof CommitTsPlaceholder) {\n return true;\n }\n if (Array.isArray(value)) {\n return value.some(hasPendingValues);\n }\n if (value !== null && value !== undefined && isSimpleObject(value)) {\n return Object.values(value).some(hasPendingValues);\n }\n return false;\n}\n\n// The value as the transaction sees it before committing.\nexport function resolvePendingValues(value: Value): Value {\n return substituteCommitTs(value, MAX_COMMIT_TS);\n}\n\n// The value as it is committed.\nexport function resolveCommittedValues<T extends Value>(\n value: T,\n commitTs: bigint,\n): T {\n return substituteCommitTs(value, commitTs);\n}\n\nexport function substituteCommitTs<T extends Value>(\n value: T,\n commitTs: bigint,\n): T {\n if (!hasPendingValues(value)) {\n return value;\n }\n if (value instanceof CommitTsPlaceholder) {\n return commitTs as T;\n }\n if (Array.isArray(value)) {\n return value.map((v) => substituteCommitTs(v, commitTs)) as T;\n }\n return Object.fromEntries(\n Object.entries(value as object).map(([k, v]) => [\n k,\n substituteCommitTs(v, commitTs),\n ]),\n ) as T;\n}\n\nexport function evaluateFieldPath(fieldPath: string, document: any) {\n const pathParts = fieldPath.split(\".\");\n let result: Value | undefined = document;\n for (const p of pathParts) {\n result =\n result !== undefined && result !== null && isSimpleObject(result)\n ? (result as any)[p]\n : undefined;\n }\n return result === undefined ? undefined : resolvePendingValues(result);\n}\n\nexport function evaluateFilter(\n document: GenericDocument,\n filter: any,\n): Value | undefined {\n if (filter.$eq !== undefined) {\n return (\n compareValues(\n evaluateFilter(document, filter.$eq[0]),\n evaluateFilter(document, filter.$eq[1]),\n ) === 0\n );\n }\n if (filter.$neq !== undefined) {\n return (\n compareValues(\n evaluateFilter(document, filter.$neq[0]),\n evaluateFilter(document, filter.$neq[1]),\n ) !== 0\n );\n }\n if (filter.$and !== undefined) {\n return filter.$and.every((child: any) => evaluateFilter(document, child));\n }\n if (filter.$or !== undefined) {\n return filter.$or.some((child: any) => evaluateFilter(document, child));\n }\n if (filter.$not !== undefined) {\n return !evaluateFilter(document, filter.$not);\n }\n if (filter.$gt !== undefined) {\n return (\n evaluateFilter(document, filter.$gt[0])! >\n evaluateFilter(document, filter.$gt[1])!\n );\n }\n if (filter.$gte !== undefined) {\n return (\n evaluateFilter(document, filter.$gte[0])! >=\n evaluateFilter(document, filter.$gte[1])!\n );\n }\n if (filter.$lt !== undefined) {\n return (\n evaluateFilter(document, filter.$lt[0])! <\n evaluateFilter(document, filter.$lt[1])!\n );\n }\n if (filter.$lte !== undefined) {\n return (\n evaluateFilter(document, filter.$lte[0])! <=\n evaluateFilter(document, filter.$lte[1])!\n );\n }\n if (filter.$add !== undefined) {\n return (\n (evaluateFilter(document, filter.$add[0]) as number) +\n (evaluateFilter(document, filter.$add[1]) as number)\n );\n }\n if (filter.$sub !== undefined) {\n return (\n (evaluateFilter(document, filter.$sub[0]) as number) -\n (evaluateFilter(document, filter.$sub[1]) as number)\n );\n }\n if (filter.$mul !== undefined) {\n return (\n (evaluateFilter(document, filter.$mul[0]) as number) *\n (evaluateFilter(document, filter.$mul[1]) as number)\n );\n }\n if (filter.$div !== undefined) {\n return (\n (evaluateFilter(document, filter.$div[0]) as number) /\n (evaluateFilter(document, filter.$div[1]) as number)\n );\n }\n if (filter.$mod !== undefined) {\n return (\n (evaluateFilter(document, filter.$mod[0]) as number) %\n (evaluateFilter(document, filter.$mod[1]) as number)\n );\n }\n if (filter.$field !== undefined) {\n return evaluateFieldPath(filter.$field, document);\n }\n if (filter.$literal !== undefined) {\n return evaluateQueryValue(filter.$literal);\n }\n throw new Error(`not implemented: ${JSON.stringify(filter)}`);\n}\n\nexport function evaluateRangeFilter(\n document: GenericDocument,\n expr: SerializedRangeExpression,\n) {\n const result = evaluateFieldPath(expr.fieldPath, document);\n const value = evaluateQueryValue(expr.value);\n switch (expr.type) {\n case \"Eq\":\n return compareValues(result, value) === 0;\n case \"Gt\":\n return compareValues(result, value) > 0;\n case \"Gte\":\n return compareValues(result, value) >= 0;\n case \"Lt\":\n return compareValues(result, value) < 0;\n case \"Lte\":\n return compareValues(result, value) <= 0;\n }\n}\n\n// A value used as a written field.\nexport function evaluateValue(value: JSONValue) {\n if (typeof value === \"object\" && value !== null && \"$undefined\" in value) {\n return undefined;\n }\n return jsonToConvex(value);\n}\n\n// A value used as a query bound or literal.\nexport function evaluateQueryValue(value: JSONValue) {\n const evaluatedValue = evaluateValue(value);\n return evaluatedValue === undefined\n ? undefined\n : resolvePendingValues(evaluatedValue);\n}\n\n// An index range expression is always a chained list of:\n//\n// 0 or more equality expressions defined with .eq.\n// [Optionally] A lower bound expression defined with .gt or .gte.\n// [Optionally] An upper bound expression defined with .lt or .lte.\nexport function validateIndexRangeExpression(\n source: Source & { type: \"IndexRange\" },\n fields: string[],\n) {\n let fieldIndex = 0;\n let state: \"eq\" | \"gt\" | \"lt\" | \"done\" = \"eq\";\n for (const [filterIndex, filter] of source.range.entries()) {\n if (state === \"done\") {\n throw new Error(\n `Incorrect operator used in \\`withIndex\\`, cannot chain ` +\n `more operators after both \\`.gt\\` and \\`.lt\\` were already used, ` +\n `got \\`${printIndexOperator(filter)}\\`.`,\n );\n }\n\n const filterType: \"eq\" | \"gt\" | \"lt\" =\n filter.type == \"Gt\" || filter.type == \"Gte\"\n ? \"gt\"\n : filter.type == \"Lt\" || filter.type == \"Lte\"\n ? \"lt\"\n : \"eq\";\n\n switch (`${state}|${filterType}`) {\n // Allow to operate on the current indexed field\n case \"eq|eq\":\n case \"eq|gt\":\n case \"eq|lt\":\n if (filter.fieldPath === fields[fieldIndex]) {\n fieldIndex += 1;\n state = filterType;\n continue;\n }\n throw new Error(\n `Incorrect field used in \\`withIndex\\`, ` +\n `expected \"${fields[fieldIndex]}\", got \"${filter.fieldPath}\"`,\n );\n\n // Allow to operate on the previous field (gt and lt must operate on same field)\n case \"lt|gt\":\n case \"gt|lt\":\n if (fieldIndex > 0 && filter.fieldPath === fields[fieldIndex - 1]) {\n state = \"done\";\n continue;\n }\n throw new Error(\n `Incorrect field used in \\`withIndex\\`, ` +\n `\\`.gt\\` and \\`.lt\\` must operate on the same field, ` +\n `expected \"${fields[fieldIndex - 1]}\", got \"${filter.fieldPath}\"`,\n );\n\n default:\n throw new Error(\n `Incorrect operator used in \\`withIndex\\`, ` +\n `cannot chain \\`.${filter.type.toLowerCase()}()\\` ` +\n `after \\`.${source.range[filterIndex - 1].type.toLowerCase()}()\\``,\n );\n }\n }\n}\n\nexport function printIndexOperator(filter: SerializedRangeExpression) {\n return `.${filter.type.toLowerCase()}(${filter.fieldPath}, ${JSON.stringify(filter.value)})`;\n}\n\nexport function validateFieldNames(validator: ValidatorJSON) {\n if (validator.type === \"object\") {\n Object.keys(validator.value).forEach((fieldName) => {\n if (!isValidIdentifier(fieldName)) {\n throw new Error(\n `Field names must be valid identifiers, got \"${fieldName}\"`,\n );\n }\n });\n }\n\n if (validator.type === \"union\") {\n validator.value.forEach(validateFieldNames);\n }\n}\n\nexport function isValidIdentifier(name: string) {\n return /(^_(id|creationTime)$)|^[a-zA-Z][a-zA-Z0-9_]*$/.test(name);\n}\n\nexport type ObjectFieldType = { fieldType: ValidatorJSON; optional: boolean };\n\nexport type ValidatorJSON =\n | {\n type: \"null\";\n }\n | { type: \"number\" }\n | { type: \"bigint\" }\n | { type: \"commitTs\" }\n | { type: \"boolean\" }\n | { type: \"string\" }\n | { type: \"bytes\" }\n | { type: \"any\" }\n | {\n type: \"literal\";\n value: JSONValue;\n }\n | { type: \"id\"; tableName: string }\n | { type: \"array\"; value: ValidatorJSON }\n | { type: \"object\"; value: Record<string, ObjectFieldType> }\n | { type: \"record\"; keys: ValidatorJSON; values: ObjectFieldType }\n | { type: \"union\"; value: ValidatorJSON[] };\n\nexport function validateValidator(validator: ValidatorJSON, value: any) {\n switch (validator.type) {\n case \"null\": {\n if (value !== null) {\n throw new Error(`Validator error: Expected \\`null\\`, got \\`${value}\\``);\n }\n return;\n }\n case \"number\": {\n if (typeof value !== \"number\") {\n throw new Error(\n `Validator error: Expected \\`number\\`, got \\`${value}\\``,\n );\n }\n return;\n }\n case \"bigint\": {\n if (typeof value !== \"bigint\") {\n throw new Error(\n `Validator error: Expected \\`bigint\\`, got \\`${value}\\``,\n );\n }\n return;\n }\n case \"commitTs\": {\n if (\n typeof value !== \"bigint\" &&\n !(value instanceof CommitTsPlaceholder)\n ) {\n throw new Error(\n `Validator error: Expected \\`v.commitTs()\\`, got \\`${value}\\``,\n );\n }\n return;\n }\n case \"boolean\": {\n if (typeof value !== \"boolean\") {\n throw new Error(\n `Validator error: Expected \\`boolean\\`, got \\`${value}\\``,\n );\n }\n return;\n }\n case \"string\": {\n if (typeof value !== \"string\") {\n throw new Error(\n `Validator error: Expected \\`string\\`, got \\`${value}\\``,\n );\n }\n return;\n }\n case \"bytes\": {\n if (!(value instanceof ArrayBuffer)) {\n throw new Error(\n `Validator error: Expected \\`ArrayBuffer\\`, got \\`${value}\\``,\n );\n }\n return;\n }\n case \"any\": {\n return;\n }\n case \"literal\": {\n if (value !== validator.value) {\n throw new Error(\n `Validator error: Expected \\`${\n validator.value as any\n }\\`, got \\`${value}\\``,\n );\n }\n return;\n }\n case \"id\": {\n if (typeof value !== \"string\") {\n throw new Error(\n `Validator error: Expected \\`string\\`, got \\`${value}\\``,\n );\n }\n if (tableNameFromId(value) !== validator.tableName) {\n throw new Error(\n `Validator error: Expected ID for table \"${validator.tableName}\", got \\`${value}\\``,\n );\n }\n return;\n }\n case \"array\": {\n if (!Array.isArray(value)) {\n throw new Error(\n `Validator error: Expected \\`Array\\`, got \\`${value}\\``,\n );\n }\n for (const v of value) {\n validateValidator(validator.value, v);\n }\n return;\n }\n case \"union\": {\n let isValid = false;\n for (const v of validator.value) {\n try {\n validateValidator(v, value);\n isValid = true;\n break;\n } catch {\n // Ignore\n }\n }\n if (!isValid) {\n throw new Error(\n `Validator error: Expected one of ${validator.value.map((v) => v.type).join(\", \")}, got \\`${JSON.stringify(convexToJson(value))}\\``,\n );\n }\n return;\n }\n case \"object\": {\n if (typeof value !== \"object\") {\n throw new Error(\n `Validator error: Expected \\`object\\`, got \\`${value}\\``,\n );\n }\n if (!isSimpleObject(value)) {\n throw new Error(\n `Validator error: Expected a plain old JavaScript \\`object\\`, got \\`${value}\\``,\n );\n }\n for (const [k, { fieldType, optional }] of Object.entries(\n validator.value,\n )) {\n if (value[k] === undefined) {\n if (!optional) {\n throw new Error(\n `Validator error: Missing required field \\`${k}\\` in object`,\n );\n }\n } else {\n validateValidator(fieldType, value[k]);\n }\n }\n for (const k of Object.keys(value)) {\n if (validator.value[k] === undefined) {\n throw new Error(\n `Validator error: Unexpected field \\`${k}\\` in object`,\n );\n }\n }\n return;\n }\n case \"record\": {\n if (\n value === null ||\n typeof value !== \"object\" ||\n !isSimpleObject(value)\n ) {\n throw new Error(\n `Validator error: Expected a plain old JavaScript \\`object\\` for a record, got \\`${value}\\``,\n );\n }\n for (const [k, fieldValue] of Object.entries(value)) {\n validateValidator(validator.keys, k);\n if (fieldValue !== undefined) {\n validateValidator(validator.values.fieldType, fieldValue);\n }\n }\n return;\n }\n default: {\n const unknown: never = validator;\n throw new Error(\n `The test kernel cannot check a validator of type \\`${(unknown as { type: string }).type}\\`.`,\n );\n }\n }\n}\n\nexport const JWT_CLAIM_BY_IDENTITY_ATTRIBUTE: Record<string, string> = {\n subject: \"sub\",\n issuer: \"iss\",\n name: \"name\",\n givenName: \"given_name\",\n familyName: \"family_name\",\n nickname: \"nickname\",\n preferredUsername: \"preferred_username\",\n profileUrl: \"profile\",\n pictureUrl: \"picture\",\n email: \"email\",\n emailVerified: \"email_verified\",\n gender: \"gender\",\n birthday: \"birthdate\",\n timezone: \"zoneinfo\",\n language: \"locale\",\n phoneNumber: \"phone_number\",\n phoneNumberVerified: \"phone_number_verified\",\n address: \"address\",\n updatedAt: \"updated_at\",\n};\n\nexport function base64UrlEncode(value: string) {\n return base64UrlEncodeBytes(new TextEncoder().encode(value));\n}\n\nexport function base64UrlEncodeBytes(bytes: Uint8Array) {\n let binary = \"\";\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n return btoa(binary)\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=+$/, \"\");\n}\n\n// Builds the token `withIdentity` pretends the request was authenticated with.\n// Real tokens are signed by an identity provider; this one is unsecured\n// (`\"alg\": \"none\"`, empty signature).\nexport function createTestJwt(identity: Record<string, any>) {\n const claims: Record<string, any> = Object.create(null);\n for (const [attribute, value] of Object.entries(identity)) {\n if (value === undefined || attribute === \"tokenIdentifier\") {\n continue;\n }\n // Custom claims are used as is, known attributes use their claim name.\n const claimName = Object.hasOwn(JWT_CLAIM_BY_IDENTITY_ATTRIBUTE, attribute)\n ? JWT_CLAIM_BY_IDENTITY_ATTRIBUTE[attribute]\n : attribute;\n claims[claimName] = value;\n }\n // The identity provider always determines who the user is.\n claims.iss = identity.issuer;\n claims.sub = identity.subject;\n const header = base64UrlEncode(JSON.stringify({ alg: \"none\", typ: \"JWT\" }));\n const payload = base64UrlEncode(JSON.stringify(claims));\n return `${header}.${payload}.`;\n}\n\n// Limits the backend puts on tokens from `ctx.auth.signJwt`.\nexport function parseArgs(\n args: Record<string, Value> | undefined,\n): Record<string, Value> {\n if (args === undefined) {\n return {};\n }\n if (!isSimpleObject(args)) {\n throw new Error(\n `The arguments to a Convex function must be an object. Received: ${\n args as any\n }`,\n );\n }\n return args;\n}\n\nexport function validateFunctionArgs(\n argsValidator: ValidatorJSON,\n args: any,\n functionPath: FunctionPath,\n allowPendingValues: boolean,\n) {\n if (!allowPendingValues && hasPendingValues(args)) {\n throw new Error(\n `Invalid arguments for \"${functionPath.udfPath}\": an unresolved ` +\n `placeholder value can only be passed to a query or mutation ` +\n `called from a mutation`,\n );\n }\n validateValidator(argsValidator, resolvePendingValues(args));\n}\n\nexport function validateReturnValue(\n returnsValidator: ValidatorJSON | null,\n result: any,\n functionType: \"query\" | \"mutation\" | \"action\",\n functionPath: FunctionPath,\n) {\n if (returnsValidator !== null) {\n try {\n validateValidator(returnsValidator, resolvePendingValues(result));\n } catch (e) {\n throw new Error(\n `Return value validation failed for ${functionType} \"${functionPath.udfPath}\":\\n${(e as Error).message}`,\n { cause: e },\n );\n }\n }\n}\n\nexport function createFunctionHandle(functionPath: FunctionPath) {\n return `function://${functionPath.componentPath};${functionPath.udfPath}`;\n}\n\nexport function parseFunctionHandle(handle: string) {\n const [componentPath, udfPath] = handle.split(\"function://\")[1].split(\";\");\n return { componentPath, udfPath };\n}\nexport function simpleHash(string: string) {\n let hash = 0;\n for (let i = 0; i < string.length; i++) {\n const char = string.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash; // Convert to 32bit integer\n }\n return hash;\n}\n"],"mappings":";;AAoFA,SAAgB,gBAAgB,IAAY;CAC1C,MAAM,QAAQ,GAAG,MAAM,SAAS;CAChC,IAAI,CAAC,SAAS,MAAM,EAAE,CAAC,WAAW,GAAG,QACnC,OAAO;CAET,OAAO,GAAG,MAAM,MAAM,EAAE,CAAC,MAAM;AACjC;AACA,SAAgB,2BAA2B,QAAiB;CAC1D,IACE,OAAO,WAAW,YAClB,WAAW,QACX,OAAO,IAAI,aAAa,KAAK,UAC7B,OAAQ,OAA6B,SAAS,UAE9C,IAAI;EACF,OAA8B,OAAO,aACnC,KAAK,MAAO,OAA4B,IAAI,CAC9C;CACF,QAAQ,CAER;CAEF,OAAO;AACT;AAEA,SAAgB,eAAe,OAAgB;CAC7C,MAAM,WAAW,OAAO,UAAU;CAClC,MAAM,YAAY,OAAO,eAAe,KAAK;CAC7C,MAAM,WACJ,cAAc,QACd,cAAc,OAAO,aAGrB,WAAW,aAAa,SAAS;CACnC,OAAO,YAAY;AACrB;AAGA,MAAa,gBAAgB,MAAM,MAAM;AAEzC,SAAgB,iBAAiB,OAAuB;CACtD,IAAI,iBAAiB,qBACnB,OAAO;CAET,IAAI,MAAM,QAAQ,KAAK,GACrB,OAAO,MAAM,KAAK,gBAAgB;CAEpC,IAAI,UAAU,QAAQ,UAAU,KAAA,KAAa,eAAe,KAAK,GAC/D,OAAO,OAAO,OAAO,KAAK,CAAC,CAAC,KAAK,gBAAgB;CAEnD,OAAO;AACT;AAGA,SAAgB,qBAAqB,OAAqB;CACxD,OAAO,mBAAmB,OAAO,aAAa;AAChD;AAGA,SAAgB,uBACd,OACA,UACG;CACH,OAAO,mBAAmB,OAAO,QAAQ;AAC3C;AAEA,SAAgB,mBACd,OACA,UACG;CACH,IAAI,CAAC,iBAAiB,KAAK,GACzB,OAAO;CAET,IAAI,iBAAiB,qBACnB,OAAO;CAET,IAAI,MAAM,QAAQ,KAAK,GACrB,OAAO,MAAM,KAAK,MAAM,mBAAmB,GAAG,QAAQ,CAAC;CAEzD,OAAO,OAAO,YACZ,OAAO,QAAQ,KAAe,CAAC,CAAC,KAAK,CAAC,GAAG,OAAO,CAC9C,GACA,mBAAmB,GAAG,QAAQ,CAChC,CAAC,CACH;AACF;AAEA,SAAgB,kBAAkB,WAAmB,UAAe;CAClE,MAAM,YAAY,UAAU,MAAM,GAAG;CACrC,IAAI,SAA4B;CAChC,KAAK,MAAM,KAAK,WACd,SACE,WAAW,KAAA,KAAa,WAAW,QAAQ,eAAe,MAAM,IAC3D,OAAe,KAChB,KAAA;CAER,OAAO,WAAW,KAAA,IAAY,KAAA,IAAY,qBAAqB,MAAM;AACvE;AAEA,SAAgB,eACd,UACA,QACmB;CACnB,IAAI,OAAO,QAAQ,KAAA,GACjB,OACE,cACE,eAAe,UAAU,OAAO,IAAI,EAAE,GACtC,eAAe,UAAU,OAAO,IAAI,EAAE,CACxC,MAAM;CAGV,IAAI,OAAO,SAAS,KAAA,GAClB,OACE,cACE,eAAe,UAAU,OAAO,KAAK,EAAE,GACvC,eAAe,UAAU,OAAO,KAAK,EAAE,CACzC,MAAM;CAGV,IAAI,OAAO,SAAS,KAAA,GAClB,OAAO,OAAO,KAAK,OAAO,UAAe,eAAe,UAAU,KAAK,CAAC;CAE1E,IAAI,OAAO,QAAQ,KAAA,GACjB,OAAO,OAAO,IAAI,MAAM,UAAe,eAAe,UAAU,KAAK,CAAC;CAExE,IAAI,OAAO,SAAS,KAAA,GAClB,OAAO,CAAC,eAAe,UAAU,OAAO,IAAI;CAE9C,IAAI,OAAO,QAAQ,KAAA,GACjB,OACE,eAAe,UAAU,OAAO,IAAI,EAAE,IACtC,eAAe,UAAU,OAAO,IAAI,EAAE;CAG1C,IAAI,OAAO,SAAS,KAAA,GAClB,OACE,eAAe,UAAU,OAAO,KAAK,EAAE,KACvC,eAAe,UAAU,OAAO,KAAK,EAAE;CAG3C,IAAI,OAAO,QAAQ,KAAA,GACjB,OACE,eAAe,UAAU,OAAO,IAAI,EAAE,IACtC,eAAe,UAAU,OAAO,IAAI,EAAE;CAG1C,IAAI,OAAO,SAAS,KAAA,GAClB,OACE,eAAe,UAAU,OAAO,KAAK,EAAE,KACvC,eAAe,UAAU,OAAO,KAAK,EAAE;CAG3C,IAAI,OAAO,SAAS,KAAA,GAClB,OACG,eAAe,UAAU,OAAO,KAAK,EAAE,IACvC,eAAe,UAAU,OAAO,KAAK,EAAE;CAG5C,IAAI,OAAO,SAAS,KAAA,GAClB,OACG,eAAe,UAAU,OAAO,KAAK,EAAE,IACvC,eAAe,UAAU,OAAO,KAAK,EAAE;CAG5C,IAAI,OAAO,SAAS,KAAA,GAClB,OACG,eAAe,UAAU,OAAO,KAAK,EAAE,IACvC,eAAe,UAAU,OAAO,KAAK,EAAE;CAG5C,IAAI,OAAO,SAAS,KAAA,GAClB,OACG,eAAe,UAAU,OAAO,KAAK,EAAE,IACvC,eAAe,UAAU,OAAO,KAAK,EAAE;CAG5C,IAAI,OAAO,SAAS,KAAA,GAClB,OACG,eAAe,UAAU,OAAO,KAAK,EAAE,IACvC,eAAe,UAAU,OAAO,KAAK,EAAE;CAG5C,IAAI,OAAO,WAAW,KAAA,GACpB,OAAO,kBAAkB,OAAO,QAAQ,QAAQ;CAElD,IAAI,OAAO,aAAa,KAAA,GACtB,OAAO,mBAAmB,OAAO,QAAQ;CAE3C,MAAM,IAAI,MAAM,oBAAoB,KAAK,UAAU,MAAM,GAAG;AAC9D;AAEA,SAAgB,oBACd,UACA,MACA;CACA,MAAM,SAAS,kBAAkB,KAAK,WAAW,QAAQ;CACzD,MAAM,QAAQ,mBAAmB,KAAK,KAAK;CAC3C,QAAQ,KAAK,MAAb;EACE,KAAK,MACH,OAAO,cAAc,QAAQ,KAAK,MAAM;EAC1C,KAAK,MACH,OAAO,cAAc,QAAQ,KAAK,IAAI;EACxC,KAAK,OACH,OAAO,cAAc,QAAQ,KAAK,KAAK;EACzC,KAAK,MACH,OAAO,cAAc,QAAQ,KAAK,IAAI;EACxC,KAAK,OACH,OAAO,cAAc,QAAQ,KAAK,KAAK;CAC3C;AACF;AAGA,SAAgB,cAAc,OAAkB;CAC9C,IAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,gBAAgB,OACjE;CAEF,OAAO,aAAa,KAAK;AAC3B;AAGA,SAAgB,mBAAmB,OAAkB;CACnD,MAAM,iBAAiB,cAAc,KAAK;CAC1C,OAAO,mBAAmB,KAAA,IACtB,KAAA,IACA,qBAAqB,cAAc;AACzC;AAOA,SAAgB,6BACd,QACA,QACA;CACA,IAAI,aAAa;CACjB,IAAI,QAAqC;CACzC,KAAK,MAAM,CAAC,aAAa,WAAW,OAAO,MAAM,QAAQ,GAAG;EAC1D,IAAI,UAAU,QACZ,MAAM,IAAI,MACR,iIAEW,mBAAmB,MAAM,EAAE,IACxC;EAGF,MAAM,aACJ,OAAO,QAAQ,QAAQ,OAAO,QAAQ,QAClC,OACA,OAAO,QAAQ,QAAQ,OAAO,QAAQ,QACpC,OACA;EAER,QAAQ,GAAG,MAAM,GAAG,cAApB;GAEE,KAAK;GACL,KAAK;GACL,KAAK;IACH,IAAI,OAAO,cAAc,OAAO,aAAa;KAC3C,cAAc;KACd,QAAQ;KACR;IACF;IACA,MAAM,IAAI,MACR,oDACe,OAAO,YAAY,UAAU,OAAO,UAAU,EAC/D;GAGF,KAAK;GACL,KAAK;IACH,IAAI,aAAa,KAAK,OAAO,cAAc,OAAO,aAAa,IAAI;KACjE,QAAQ;KACR;IACF;IACA,MAAM,IAAI,MACR,wGAEe,OAAO,aAAa,GAAG,UAAU,OAAO,UAAU,EACnE;GAEF,SACE,MAAM,IAAI,MACR,6DACqB,OAAO,KAAK,YAAY,EAAE,gBACjC,OAAO,MAAM,cAAc,EAAE,CAAC,KAAK,YAAY,EAAE,KACjE;EACJ;CACF;AACF;AAEA,SAAgB,mBAAmB,QAAmC;CACpE,OAAO,IAAI,OAAO,KAAK,YAAY,EAAE,GAAG,OAAO,UAAU,IAAI,KAAK,UAAU,OAAO,KAAK,EAAE;AAC5F;AAEA,SAAgB,mBAAmB,WAA0B;CAC3D,IAAI,UAAU,SAAS,UACrB,OAAO,KAAK,UAAU,KAAK,CAAC,CAAC,SAAS,cAAc;EAClD,IAAI,CAAC,kBAAkB,SAAS,GAC9B,MAAM,IAAI,MACR,+CAA+C,UAAU,EAC3D;CAEJ,CAAC;CAGH,IAAI,UAAU,SAAS,SACrB,UAAU,MAAM,QAAQ,kBAAkB;AAE9C;AAEA,SAAgB,kBAAkB,MAAc;CAC9C,OAAO,iDAAiD,KAAK,IAAI;AACnE;AAyBA,SAAgB,kBAAkB,WAA0B,OAAY;CACtE,QAAQ,UAAU,MAAlB;EACE,KAAK;GACH,IAAI,UAAU,MACZ,MAAM,IAAI,MAAM,6CAA6C,MAAM,GAAG;GAExE;EAEF,KAAK;GACH,IAAI,OAAO,UAAU,UACnB,MAAM,IAAI,MACR,+CAA+C,MAAM,GACvD;GAEF;EAEF,KAAK;GACH,IAAI,OAAO,UAAU,UACnB,MAAM,IAAI,MACR,+CAA+C,MAAM,GACvD;GAEF;EAEF,KAAK;GACH,IACE,OAAO,UAAU,YACjB,EAAE,iBAAiB,sBAEnB,MAAM,IAAI,MACR,qDAAqD,MAAM,GAC7D;GAEF;EAEF,KAAK;GACH,IAAI,OAAO,UAAU,WACnB,MAAM,IAAI,MACR,gDAAgD,MAAM,GACxD;GAEF;EAEF,KAAK;GACH,IAAI,OAAO,UAAU,UACnB,MAAM,IAAI,MACR,+CAA+C,MAAM,GACvD;GAEF;EAEF,KAAK;GACH,IAAI,EAAE,iBAAiB,cACrB,MAAM,IAAI,MACR,oDAAoD,MAAM,GAC5D;GAEF;EAEF,KAAK,OACH;EAEF,KAAK;GACH,IAAI,UAAU,UAAU,OACtB,MAAM,IAAI,MACR,+BACE,UAAU,MACX,YAAY,MAAM,GACrB;GAEF;EAEF,KAAK;GACH,IAAI,OAAO,UAAU,UACnB,MAAM,IAAI,MACR,+CAA+C,MAAM,GACvD;GAEF,IAAI,gBAAgB,KAAK,MAAM,UAAU,WACvC,MAAM,IAAI,MACR,2CAA2C,UAAU,UAAU,WAAW,MAAM,GAClF;GAEF;EAEF,KAAK;GACH,IAAI,CAAC,MAAM,QAAQ,KAAK,GACtB,MAAM,IAAI,MACR,8CAA8C,MAAM,GACtD;GAEF,KAAK,MAAM,KAAK,OACd,kBAAkB,UAAU,OAAO,CAAC;GAEtC;EAEF,KAAK,SAAS;GACZ,IAAI,UAAU;GACd,KAAK,MAAM,KAAK,UAAU,OACxB,IAAI;IACF,kBAAkB,GAAG,KAAK;IAC1B,UAAU;IACV;GACF,QAAQ,CAER;GAEF,IAAI,CAAC,SACH,MAAM,IAAI,MACR,oCAAoC,UAAU,MAAM,KAAK,MAAM,EAAE,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,UAAU,KAAK,UAAU,aAAa,KAAK,CAAC,EAAE,GAClI;GAEF;EACF;EACA,KAAK;GACH,IAAI,OAAO,UAAU,UACnB,MAAM,IAAI,MACR,+CAA+C,MAAM,GACvD;GAEF,IAAI,CAAC,eAAe,KAAK,GACvB,MAAM,IAAI,MACR,sEAAsE,MAAM,GAC9E;GAEF,KAAK,MAAM,CAAC,GAAG,EAAE,WAAW,eAAe,OAAO,QAChD,UAAU,KACZ,GACE,IAAI,MAAM,OAAO,KAAA,GACX;QAAA,CAAC,UACH,MAAM,IAAI,MACR,6CAA6C,EAAE,aACjD;GAAA,OAGF,kBAAkB,WAAW,MAAM,EAAE;GAGzC,KAAK,MAAM,KAAK,OAAO,KAAK,KAAK,GAC/B,IAAI,UAAU,MAAM,OAAO,KAAA,GACzB,MAAM,IAAI,MACR,uCAAuC,EAAE,aAC3C;GAGJ;EAEF,KAAK;GACH,IACE,UAAU,QACV,OAAO,UAAU,YACjB,CAAC,eAAe,KAAK,GAErB,MAAM,IAAI,MACR,mFAAmF,MAAM,GAC3F;GAEF,KAAK,MAAM,CAAC,GAAG,eAAe,OAAO,QAAQ,KAAK,GAAG;IACnD,kBAAkB,UAAU,MAAM,CAAC;IACnC,IAAI,eAAe,KAAA,GACjB,kBAAkB,UAAU,OAAO,WAAW,UAAU;GAE5D;GACA;EAEF,SAEE,MAAM,IAAI,MACR,sDAAuDA,UAA6B,KAAK,IAC3F;CAEJ;AACF;AAEA,MAAa,kCAA0D;CACrE,SAAS;CACT,QAAQ;CACR,MAAM;CACN,WAAW;CACX,YAAY;CACZ,UAAU;CACV,mBAAmB;CACnB,YAAY;CACZ,YAAY;CACZ,OAAO;CACP,eAAe;CACf,QAAQ;CACR,UAAU;CACV,UAAU;CACV,UAAU;CACV,aAAa;CACb,qBAAqB;CACrB,SAAS;CACT,WAAW;AACb;AAEA,SAAgB,gBAAgB,OAAe;CAC7C,OAAO,qBAAqB,IAAI,YAAY,CAAC,CAAC,OAAO,KAAK,CAAC;AAC7D;AAEA,SAAgB,qBAAqB,OAAmB;CACtD,IAAI,SAAS;CACb,KAAK,MAAM,QAAQ,OACjB,UAAU,OAAO,aAAa,IAAI;CAEpC,OAAO,KAAK,MAAM,CAAC,CAChB,QAAQ,OAAO,GAAG,CAAC,CACnB,QAAQ,OAAO,GAAG,CAAC,CACnB,QAAQ,OAAO,EAAE;AACtB;AAKA,SAAgB,cAAc,UAA+B;CAC3D,MAAM,SAA8B,OAAO,OAAO,IAAI;CACtD,KAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,QAAQ,GAAG;EACzD,IAAI,UAAU,KAAA,KAAa,cAAc,mBACvC;EAGF,MAAM,YAAY,OAAO,OAAO,iCAAiC,SAAS,IACtE,gCAAgC,aAChC;EACJ,OAAO,aAAa;CACtB;CAEA,OAAO,MAAM,SAAS;CACtB,OAAO,MAAM,SAAS;CAGtB,OAAO,GAFQ,gBAAgB,KAAK,UAAU;EAAE,KAAK;EAAQ,KAAK;CAAM,CAAC,CAE1D,EAAE,GADD,gBAAgB,KAAK,UAAU,MAAM,CAC3B,EAAE;AAC9B;AAGA,SAAgB,UACd,MACuB;CACvB,IAAI,SAAS,KAAA,GACX,OAAO,CAAC;CAEV,IAAI,CAAC,eAAe,IAAI,GACtB,MAAM,IAAI,MACR,mEACE,MAEJ;CAEF,OAAO;AACT;AAEA,SAAgB,qBACd,eACA,MACA,cACA,oBACA;CACA,IAAI,CAAC,sBAAsB,iBAAiB,IAAI,GAC9C,MAAM,IAAI,MACR,0BAA0B,aAAa,QAAQ,oGAGjD;CAEF,kBAAkB,eAAe,qBAAqB,IAAI,CAAC;AAC7D;AAEA,SAAgB,oBACd,kBACA,QACA,cACA,cACA;CACA,IAAI,qBAAqB,MACvB,IAAI;EACF,kBAAkB,kBAAkB,qBAAqB,MAAM,CAAC;CAClE,SAAS,GAAG;EACV,MAAM,IAAI,MACR,sCAAsC,aAAa,IAAI,aAAa,QAAQ,MAAO,EAAY,WAC/F,EAAE,OAAO,EAAE,CACb;CACF;AAEJ;AAEA,SAAgB,qBAAqB,cAA4B;CAC/D,OAAO,cAAc,aAAa,cAAc,GAAG,aAAa;AAClE;AAEA,SAAgB,oBAAoB,QAAgB;CAClD,MAAM,CAAC,eAAe,WAAW,OAAO,MAAM,aAAa,CAAC,CAAC,EAAE,CAAC,MAAM,GAAG;CACzE,OAAO;EAAE;EAAe;CAAQ;AAClC;AACA,SAAgB,WAAW,QAAgB;CACzC,IAAI,OAAO;CACX,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;EACtC,MAAM,OAAO,OAAO,WAAW,CAAC;EAChC,QAAQ,QAAQ,KAAK,OAAO;EAC5B,OAAO,OAAO;CAChB;CACA,OAAO;AACT"}
@@ -0,0 +1,55 @@
1
+ import { type Value } from "convex/values";
2
+ import type { DocumentId, SerializedRangeExpression, StoredDocument } from "./KernelValues.js";
3
+ /**
4
+ * A row's position in an interval's order: its value at each of the interval's
5
+ * fields.
6
+ */
7
+ export type Key = ReadonlyArray<Value | undefined>;
8
+ /**
9
+ * A read of one document by ID. It records the document's absence as well as
10
+ * its presence, so a commit that creates the document invalidates it.
11
+ */
12
+ export interface DocumentRead {
13
+ readonly kind: "document";
14
+ readonly componentPath: string;
15
+ readonly id: DocumentId;
16
+ }
17
+ /**
18
+ * A read of an ordered interval of one table.
19
+ *
20
+ * `fields` is the sort key: an index's fields, then the tie-breakers
21
+ * `_creationTime` and `_id`. `range` is the index range expression, whose `Gt`
22
+ * and `Lt` bounds are exclusive and `Gte` and `Lte` inclusive. `after` is an
23
+ * exclusive start in `order`, a page's cursor. `through` is how far the query
24
+ * examined, inclusive: nothing yet, up to a key, or to the end of the range. An
25
+ * empty result reads to the end, so it still covers an insert into the range.
26
+ *
27
+ * Only the attempt that owns the read advances `through`.
28
+ */
29
+ export interface IntervalRead {
30
+ readonly kind: "interval";
31
+ readonly componentPath: string;
32
+ readonly table: string;
33
+ readonly fields: ReadonlyArray<string>;
34
+ readonly order: "asc" | "desc";
35
+ readonly range: ReadonlyArray<SerializedRangeExpression>;
36
+ readonly after: Key | null;
37
+ through: Key | "end" | null;
38
+ }
39
+ export type Read = DocumentRead | IntervalRead;
40
+ /**
41
+ * Where `doc` sorts against `key` in the interval's order.
42
+ */
43
+ export declare const compareToKey: (fields: ReadonlyArray<string>, order: "asc" | "desc", doc: StoredDocument, key: Key) => number;
44
+ export declare const keyOf: (fields: ReadonlyArray<string>, doc: StoredDocument) => Key;
45
+ /**
46
+ * Whether a commit's change to one document invalidates `read`: it wrote the
47
+ * document read by ID, or the document entered or left the interval.
48
+ */
49
+ export declare const covers: (read: Read, change: {
50
+ readonly componentPath: string;
51
+ readonly id: DocumentId;
52
+ readonly before: StoredDocument | null;
53
+ readonly after: StoredDocument | null;
54
+ }) => boolean;
55
+ //# sourceMappingURL=ReadSet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReadSet.d.ts","sourceRoot":"","sources":["../../src/internal/ReadSet.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,KAAK,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,KAAK,EACV,UAAU,EACV,yBAAyB,EACzB,cAAc,EACf,MAAM,mBAAmB,CAAC;AAO3B;;;GAGG;AACH,MAAM,MAAM,GAAG,GAAG,aAAa,CAAC,KAAK,GAAG,SAAS,CAAC,CAAC;AAEnD;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,EAAE,EAAE,UAAU,CAAC;CACzB;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACvC,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,yBAAyB,CAAC,CAAC;IACzD,QAAQ,CAAC,KAAK,EAAE,GAAG,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,GAAG,GAAG,KAAK,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,MAAM,IAAI,GAAG,YAAY,GAAG,YAAY,CAAC;AAE/C;;GAEG;AACH,eAAO,MAAM,YAAY,WACf,aAAa,CAAC,MAAM,CAAC,SACtB,KAAK,GAAG,MAAM,OAChB,cAAc,OACd,GAAG,KACP,MAUF,CAAC;AAEF,eAAO,MAAM,KAAK,WACR,aAAa,CAAC,MAAM,CAAC,OACxB,cAAc,KAClB,GAA2D,CAAC;AAU/D;;;GAGG;AACH,eAAO,MAAM,MAAM,SACX,IAAI,UACF;IACN,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,EAAE,EAAE,UAAU,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;IACvC,QAAQ,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;CACvC,KACA,OASF,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { evaluateFieldPath, evaluateRangeFilter, tableNameFromId } from "./KernelValues.js";
2
+ import { compareValues } from "convex/values";
3
+ //#region src/internal/ReadSet.ts
4
+ /**
5
+ * Where `doc` sorts against `key` in the interval's order.
6
+ */
7
+ const compareToKey = (fields, order, doc, key) => {
8
+ const direction = order === "asc" ? 1 : -1;
9
+ for (let i = 0; i < fields.length; i++) {
10
+ const cmp = compareValues(evaluateFieldPath(fields[i], doc), key[i]);
11
+ if (cmp !== 0) return cmp * direction;
12
+ }
13
+ return 0;
14
+ };
15
+ const keyOf = (fields, doc) => fields.map((field) => evaluateFieldPath(field, doc));
16
+ const inInterval = (read, doc) => read.through !== null && read.range.every((filter) => evaluateRangeFilter(doc, filter)) && (read.after === null || compareToKey(read.fields, read.order, doc, read.after) > 0) && (read.through === "end" || compareToKey(read.fields, read.order, doc, read.through) <= 0);
17
+ /**
18
+ * Whether a commit's change to one document invalidates `read`: it wrote the
19
+ * document read by ID, or the document entered or left the interval.
20
+ */
21
+ const covers = (read, change) => {
22
+ if (read.componentPath !== change.componentPath) return false;
23
+ if (read.kind === "document") return read.id === change.id;
24
+ return tableNameFromId(change.id) === read.table && [change.before, change.after].some((doc) => doc !== null && inInterval(read, doc));
25
+ };
26
+ //#endregion
27
+ export { compareToKey, covers, keyOf };
28
+
29
+ //# sourceMappingURL=ReadSet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReadSet.js","names":[],"sources":["../../src/internal/ReadSet.ts"],"sourcesContent":["import { compareValues, type Value } from \"convex/values\";\nimport type {\n DocumentId,\n SerializedRangeExpression,\n StoredDocument,\n} from \"./KernelValues.js\";\nimport {\n evaluateFieldPath,\n evaluateRangeFilter,\n tableNameFromId,\n} from \"./KernelValues.js\";\n\n/**\n * A row's position in an interval's order: its value at each of the interval's\n * fields.\n */\nexport type Key = ReadonlyArray<Value | undefined>;\n\n/**\n * A read of one document by ID. It records the document's absence as well as\n * its presence, so a commit that creates the document invalidates it.\n */\nexport interface DocumentRead {\n readonly kind: \"document\";\n readonly componentPath: string;\n readonly id: DocumentId;\n}\n\n/**\n * A read of an ordered interval of one table.\n *\n * `fields` is the sort key: an index's fields, then the tie-breakers\n * `_creationTime` and `_id`. `range` is the index range expression, whose `Gt`\n * and `Lt` bounds are exclusive and `Gte` and `Lte` inclusive. `after` is an\n * exclusive start in `order`, a page's cursor. `through` is how far the query\n * examined, inclusive: nothing yet, up to a key, or to the end of the range. An\n * empty result reads to the end, so it still covers an insert into the range.\n *\n * Only the attempt that owns the read advances `through`.\n */\nexport interface IntervalRead {\n readonly kind: \"interval\";\n readonly componentPath: string;\n readonly table: string;\n readonly fields: ReadonlyArray<string>;\n readonly order: \"asc\" | \"desc\";\n readonly range: ReadonlyArray<SerializedRangeExpression>;\n readonly after: Key | null;\n through: Key | \"end\" | null;\n}\n\nexport type Read = DocumentRead | IntervalRead;\n\n/**\n * Where `doc` sorts against `key` in the interval's order.\n */\nexport const compareToKey = (\n fields: ReadonlyArray<string>,\n order: \"asc\" | \"desc\",\n doc: StoredDocument,\n key: Key,\n): number => {\n const direction = order === \"asc\" ? 1 : -1;\n for (let i = 0; i < fields.length; i++) {\n const cmp = compareValues(\n evaluateFieldPath(fields[i]!, doc),\n key[i] as Value,\n );\n if (cmp !== 0) return cmp * direction;\n }\n return 0;\n};\n\nexport const keyOf = (\n fields: ReadonlyArray<string>,\n doc: StoredDocument,\n): Key => fields.map((field) => evaluateFieldPath(field, doc));\n\nconst inInterval = (read: IntervalRead, doc: StoredDocument): boolean =>\n read.through !== null &&\n read.range.every((filter) => evaluateRangeFilter(doc, filter)) &&\n (read.after === null ||\n compareToKey(read.fields, read.order, doc, read.after) > 0) &&\n (read.through === \"end\" ||\n compareToKey(read.fields, read.order, doc, read.through) <= 0);\n\n/**\n * Whether a commit's change to one document invalidates `read`: it wrote the\n * document read by ID, or the document entered or left the interval.\n */\nexport const covers = (\n read: Read,\n change: {\n readonly componentPath: string;\n readonly id: DocumentId;\n readonly before: StoredDocument | null;\n readonly after: StoredDocument | null;\n },\n): boolean => {\n if (read.componentPath !== change.componentPath) return false;\n if (read.kind === \"document\") return read.id === change.id;\n return (\n tableNameFromId(change.id) === read.table &&\n [change.before, change.after].some(\n (doc) => doc !== null && inInterval(read, doc),\n )\n );\n};\n"],"mappings":";;;;;;AAwDA,MAAa,gBACX,QACA,OACA,KACA,QACW;CACX,MAAM,YAAY,UAAU,QAAQ,IAAI;CACxC,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;EACtC,MAAM,MAAM,cACV,kBAAkB,OAAO,IAAK,GAAG,GACjC,IAAI,EACN;EACA,IAAI,QAAQ,GAAG,OAAO,MAAM;CAC9B;CACA,OAAO;AACT;AAEA,MAAa,SACX,QACA,QACQ,OAAO,KAAK,UAAU,kBAAkB,OAAO,GAAG,CAAC;AAE7D,MAAM,cAAc,MAAoB,QACtC,KAAK,YAAY,QACjB,KAAK,MAAM,OAAO,WAAW,oBAAoB,KAAK,MAAM,CAAC,MAC5D,KAAK,UAAU,QACd,aAAa,KAAK,QAAQ,KAAK,OAAO,KAAK,KAAK,KAAK,IAAI,OAC1D,KAAK,YAAY,SAChB,aAAa,KAAK,QAAQ,KAAK,OAAO,KAAK,KAAK,OAAO,KAAK;;;;;AAMhE,MAAa,UACX,MACA,WAMY;CACZ,IAAI,KAAK,kBAAkB,OAAO,eAAe,OAAO;CACxD,IAAI,KAAK,SAAS,YAAY,OAAO,KAAK,OAAO,OAAO;CACxD,OACE,gBAAgB,OAAO,EAAE,MAAM,KAAK,SACpC,CAAC,OAAO,QAAQ,OAAO,KAAK,CAAC,CAAC,MAC3B,QAAQ,QAAQ,QAAQ,WAAW,MAAM,GAAG,CAC/C;AAEJ"}
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@gaganref/confect-test",
3
- "version": "10.3.1-fork.87",
3
+ "version": "10.3.1-fork.89",
4
4
  "peerDependencies": {
5
- "@confect/core": "npm:@gaganref/confect-core@10.3.1-fork.87",
6
- "@confect/server": "npm:@gaganref/confect-server@10.3.1-fork.87",
5
+ "@confect/core": "npm:@gaganref/confect-core@10.3.1-fork.89",
6
+ "@confect/server": "npm:@gaganref/confect-server@10.3.1-fork.89",
7
7
  "convex": "^1.32.0",
8
8
  "convex-test": ">=0.0.65 <0.1.0",
9
9
  "effect": ">=4.0.0 <4.1.0"