@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.
- package/dist/internal/Attempt.d.ts +77 -0
- package/dist/internal/Attempt.d.ts.map +1 -0
- package/dist/internal/Attempt.js +154 -0
- package/dist/internal/Attempt.js.map +1 -0
- package/dist/internal/ConvexTest.d.ts +34 -0
- package/dist/internal/ConvexTest.d.ts.map +1 -0
- package/dist/internal/ConvexTest.js +59 -0
- package/dist/internal/ConvexTest.js.map +1 -0
- package/dist/internal/Execution.d.ts +167 -0
- package/dist/internal/Execution.d.ts.map +1 -0
- package/dist/internal/Execution.js +790 -0
- package/dist/internal/Execution.js.map +1 -0
- package/dist/internal/Globals.d.ts +11 -0
- package/dist/internal/Globals.d.ts.map +1 -0
- package/dist/internal/Globals.js +76 -0
- package/dist/internal/Globals.js.map +1 -0
- package/dist/internal/Invocation.d.ts +57 -0
- package/dist/internal/Invocation.d.ts.map +1 -0
- package/dist/internal/Invocation.js +145 -0
- package/dist/internal/Invocation.js.map +1 -0
- package/dist/internal/Kernel.d.ts +93 -0
- package/dist/internal/Kernel.d.ts.map +1 -0
- package/dist/internal/Kernel.js +91 -0
- package/dist/internal/Kernel.js.map +1 -0
- package/dist/internal/KernelQuery.d.ts +55 -0
- package/dist/internal/KernelQuery.d.ts.map +1 -0
- package/dist/internal/KernelQuery.js +205 -0
- package/dist/internal/KernelQuery.js.map +1 -0
- package/dist/internal/KernelRefusal.d.ts +77 -0
- package/dist/internal/KernelRefusal.d.ts.map +1 -0
- package/dist/internal/KernelRefusal.js +73 -0
- package/dist/internal/KernelRefusal.js.map +1 -0
- package/dist/internal/KernelValues.d.ts +136 -0
- package/dist/internal/KernelValues.d.ts.map +1 -0
- package/dist/internal/KernelValues.js +266 -0
- package/dist/internal/KernelValues.js.map +1 -0
- package/dist/internal/ReadSet.d.ts +55 -0
- package/dist/internal/ReadSet.d.ts.map +1 -0
- package/dist/internal/ReadSet.js +29 -0
- package/dist/internal/ReadSet.js.map +1 -0
- package/package.json +3 -3
- package/src/internal/Attempt.ts +185 -0
- package/src/internal/ConvexTest.ts +118 -0
- package/src/internal/Execution.ts +1430 -0
- package/src/internal/Globals.ts +93 -0
- package/src/internal/Invocation.ts +291 -0
- package/src/internal/Kernel.ts +190 -0
- package/src/internal/KernelQuery.ts +405 -0
- package/src/internal/KernelRefusal.ts +88 -0
- package/src/internal/KernelValues.ts +725 -0
- package/src/internal/ReadSet.ts +108 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { host } from "./Globals.js";
|
|
2
|
+
import { resolveCommittedValues, tableNameFromId } from "./KernelValues.js";
|
|
3
|
+
import { covers } from "./ReadSet.js";
|
|
4
|
+
//#region src/internal/Kernel.ts
|
|
5
|
+
const empty = {
|
|
6
|
+
tables: /* @__PURE__ */ new Map(),
|
|
7
|
+
version: 0,
|
|
8
|
+
commitTs: 0n,
|
|
9
|
+
log: []
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* The committed row for `id` in `componentPath`, if any.
|
|
13
|
+
*/
|
|
14
|
+
const get = (state, componentPath, id) => {
|
|
15
|
+
const tableName = tableNameFromId(id);
|
|
16
|
+
return tableName === null ? void 0 : state.tables.get(componentPath)?.get(tableName)?.get(id);
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Every committed row of one table in one component.
|
|
20
|
+
*/
|
|
21
|
+
const rows = (state, componentPath, tableName) => state.tables.get(componentPath)?.get(tableName)?.values() ?? [];
|
|
22
|
+
/**
|
|
23
|
+
* Publish one attempt's writes as a single commit at `commitTs`. Every
|
|
24
|
+
* component's writes land in the same version, so a reader sees all of them or
|
|
25
|
+
* none. A commit with no writes publishes nothing and leaves the state as it
|
|
26
|
+
* was.
|
|
27
|
+
*/
|
|
28
|
+
const apply = (state, writes, commitTs) => {
|
|
29
|
+
if (writes.length === 0) return state;
|
|
30
|
+
const version = state.version + 1;
|
|
31
|
+
const tables = new Map(Array.from(state.tables, ([path, byTable]) => [path, new Map(byTable)]));
|
|
32
|
+
const changes = writes.map(({ componentPath, id, doc }) => ({
|
|
33
|
+
componentPath,
|
|
34
|
+
id,
|
|
35
|
+
before: get(state, componentPath, id)?.doc ?? null,
|
|
36
|
+
after: doc === null ? null : resolveCommittedValues(doc, commitTs)
|
|
37
|
+
}));
|
|
38
|
+
const touched = /* @__PURE__ */ new Set();
|
|
39
|
+
for (const { componentPath, id, after } of changes) {
|
|
40
|
+
const tableName = tableNameFromId(id);
|
|
41
|
+
const byTable = tables.get(componentPath) ?? /* @__PURE__ */ new Map();
|
|
42
|
+
tables.set(componentPath, byTable);
|
|
43
|
+
const key = `${componentPath}\u0000${tableName}`;
|
|
44
|
+
const table = touched.has(key) ? byTable.get(tableName) : new Map(byTable.get(tableName) ?? []);
|
|
45
|
+
touched.add(key);
|
|
46
|
+
byTable.set(tableName, table);
|
|
47
|
+
if (after === null) table.delete(id);
|
|
48
|
+
else table.set(id, {
|
|
49
|
+
doc: after,
|
|
50
|
+
version
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
tables,
|
|
55
|
+
version,
|
|
56
|
+
commitTs,
|
|
57
|
+
log: [...state.log, {
|
|
58
|
+
version,
|
|
59
|
+
commitTs,
|
|
60
|
+
changes
|
|
61
|
+
}]
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* The first change published after version `snapshot` that invalidates one of
|
|
66
|
+
* `reads`, if any.
|
|
67
|
+
*/
|
|
68
|
+
const conflict = (state, snapshot, reads) => {
|
|
69
|
+
for (const commit of state.log.slice(snapshot)) for (const change of commit.changes) if (reads.some((read) => covers(read, change))) return change;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* The wall clock, as convex-test reads it. Each answer is the time in
|
|
73
|
+
* nanoseconds when it is asked for, bumped past the previous answer when the
|
|
74
|
+
* clock stands still.
|
|
75
|
+
*/
|
|
76
|
+
const wallClock = () => {
|
|
77
|
+
let latest = 0n;
|
|
78
|
+
const now = () => host(() => Date.now());
|
|
79
|
+
return {
|
|
80
|
+
now,
|
|
81
|
+
commitTs: () => {
|
|
82
|
+
const nanos = BigInt(now()) * 1000000n;
|
|
83
|
+
latest = nanos > latest ? nanos : latest + 1n;
|
|
84
|
+
return latest;
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
//#endregion
|
|
89
|
+
export { apply, conflict, empty, get, rows, wallClock };
|
|
90
|
+
|
|
91
|
+
//# sourceMappingURL=Kernel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Kernel.js","names":["ReadSet.covers","Globals.host"],"sources":["../../src/internal/Kernel.ts"],"sourcesContent":["import * as Globals from \"./Globals.js\";\nimport type { DocumentId, StoredDocument } from \"./KernelValues.js\";\nimport { resolveCommittedValues, tableNameFromId } from \"./KernelValues.js\";\nimport * as ReadSet from \"./ReadSet.js\";\n\n/**\n * The number of commits the kernel has published. The empty world is 0.\n */\nexport type Version = number;\n\n/**\n * A committed document and the version that wrote it.\n */\nexport interface Row {\n readonly doc: StoredDocument;\n readonly version: Version;\n}\n\n/**\n * Committed rows, keyed by component path, then table name, then document ID. A\n * published state is never changed. A commit makes a new one.\n */\nexport type Tables = ReadonlyMap<\n string,\n ReadonlyMap<string, ReadonlyMap<DocumentId, Row>>\n>;\n\n/**\n * One document's final value in a commit. `null` deletes it.\n */\nexport interface Write {\n readonly componentPath: string;\n readonly id: DocumentId;\n readonly doc: StoredDocument | null;\n}\n\n/**\n * One document a commit changed: its value before and after. `null` is absent.\n */\nexport interface Change {\n readonly componentPath: string;\n readonly id: DocumentId;\n readonly before: StoredDocument | null;\n readonly after: StoredDocument | null;\n}\n\nexport interface Commit {\n readonly version: Version;\n readonly commitTs: bigint;\n readonly changes: ReadonlyArray<Change>;\n}\n\n/**\n * The kernel's committed state: rows, the latest version and commit timestamp,\n * and the write log, oldest first.\n */\nexport interface State {\n readonly tables: Tables;\n readonly version: Version;\n readonly commitTs: bigint;\n readonly log: ReadonlyArray<Commit>;\n}\n\nexport const empty: State = {\n tables: new Map(),\n version: 0,\n commitTs: 0n,\n log: [],\n};\n\n/**\n * The committed row for `id` in `componentPath`, if any.\n */\nexport const get = (\n state: State,\n componentPath: string,\n id: DocumentId,\n): Row | undefined => {\n const tableName = tableNameFromId(id);\n return tableName === null\n ? undefined\n : state.tables.get(componentPath)?.get(tableName)?.get(id);\n};\n\n/**\n * Every committed row of one table in one component.\n */\nexport const rows = (\n state: State,\n componentPath: string,\n tableName: string,\n): Iterable<Row> =>\n state.tables.get(componentPath)?.get(tableName)?.values() ?? [];\n\n/**\n * Publish one attempt's writes as a single commit at `commitTs`. Every\n * component's writes land in the same version, so a reader sees all of them or\n * none. A commit with no writes publishes nothing and leaves the state as it\n * was.\n */\nexport const apply = (\n state: State,\n writes: ReadonlyArray<Write>,\n commitTs: bigint,\n): State => {\n if (writes.length === 0) return state;\n const version = state.version + 1;\n const tables = new Map(\n Array.from(state.tables, ([path, byTable]) => [path, new Map(byTable)]),\n );\n const changes = writes.map(({ componentPath, id, doc }): Change => ({\n componentPath,\n id,\n before: get(state, componentPath, id)?.doc ?? null,\n after: doc === null ? null : resolveCommittedValues(doc, commitTs),\n }));\n const touched = new Set<string>();\n for (const { componentPath, id, after } of changes) {\n const tableName = tableNameFromId(id)!;\n const byTable = tables.get(componentPath) ?? new Map();\n tables.set(componentPath, byTable);\n const key = `${componentPath}\\u0000${tableName}`;\n const table = touched.has(key)\n ? byTable.get(tableName)!\n : new Map(byTable.get(tableName) ?? []);\n touched.add(key);\n byTable.set(tableName, table);\n if (after === null) table.delete(id);\n else table.set(id, { doc: after, version });\n }\n return {\n tables,\n version,\n commitTs,\n log: [...state.log, { version, commitTs, changes }],\n };\n};\n\n/**\n * The first change published after version `snapshot` that invalidates one of\n * `reads`, if any.\n */\nexport const conflict = (\n state: State,\n snapshot: Version,\n reads: ReadonlyArray<ReadSet.Read>,\n): Change | undefined => {\n for (const commit of state.log.slice(snapshot)) {\n for (const change of commit.changes) {\n if (reads.some((read) => ReadSet.covers(read, change))) return change;\n }\n }\n return undefined;\n};\n\n/**\n * What the driver supplies. The kernel holds no clock of its own.\n */\nexport interface KernelRuntime {\n /**\n * The time in milliseconds, for each inserted document's creation time.\n */\n readonly now: () => number;\n /**\n * The commit timestamp of `version`, asked once as it is published. The\n * answers strictly increase. A mutation that wrote nothing publishes no\n * version and asks nothing.\n */\n readonly commitTs: (version: Version) => bigint;\n}\n\n/**\n * The wall clock, as convex-test reads it. Each answer is the time in\n * nanoseconds when it is asked for, bumped past the previous answer when the\n * clock stands still.\n */\nexport const wallClock = (): KernelRuntime => {\n let latest = 0n;\n // The host's clock, never the copy a bound handler pinned.\n // oxlint-disable-next-line effecttsgo/global-date -- The default runtime is the wall clock. A driver that replays supplies its own.\n const now = () => Globals.host(() => Date.now());\n return {\n now,\n commitTs: () => {\n const nanos = BigInt(now()) * 1_000_000n;\n latest = nanos > latest ? nanos : latest + 1n;\n return latest;\n },\n };\n};\n"],"mappings":";;;;AA+DA,MAAa,QAAe;CAC1B,wBAAQ,IAAI,IAAI;CAChB,SAAS;CACT,UAAU;CACV,KAAK,CAAC;AACR;;;;AAKA,MAAa,OACX,OACA,eACA,OACoB;CACpB,MAAM,YAAY,gBAAgB,EAAE;CACpC,OAAO,cAAc,OACjB,KAAA,IACA,MAAM,OAAO,IAAI,aAAa,CAAC,EAAE,IAAI,SAAS,CAAC,EAAE,IAAI,EAAE;AAC7D;;;;AAKA,MAAa,QACX,OACA,eACA,cAEA,MAAM,OAAO,IAAI,aAAa,CAAC,EAAE,IAAI,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;;;;;;;AAQhE,MAAa,SACX,OACA,QACA,aACU;CACV,IAAI,OAAO,WAAW,GAAG,OAAO;CAChC,MAAM,UAAU,MAAM,UAAU;CAChC,MAAM,SAAS,IAAI,IACjB,MAAM,KAAK,MAAM,SAAS,CAAC,MAAM,aAAa,CAAC,MAAM,IAAI,IAAI,OAAO,CAAC,CAAC,CACxE;CACA,MAAM,UAAU,OAAO,KAAK,EAAE,eAAe,IAAI,WAAmB;EAClE;EACA;EACA,QAAQ,IAAI,OAAO,eAAe,EAAE,CAAC,EAAE,OAAO;EAC9C,OAAO,QAAQ,OAAO,OAAO,uBAAuB,KAAK,QAAQ;CACnE,EAAE;CACF,MAAM,0BAAU,IAAI,IAAY;CAChC,KAAK,MAAM,EAAE,eAAe,IAAI,WAAW,SAAS;EAClD,MAAM,YAAY,gBAAgB,EAAE;EACpC,MAAM,UAAU,OAAO,IAAI,aAAa,qBAAK,IAAI,IAAI;EACrD,OAAO,IAAI,eAAe,OAAO;EACjC,MAAM,MAAM,GAAG,cAAc,QAAQ;EACrC,MAAM,QAAQ,QAAQ,IAAI,GAAG,IACzB,QAAQ,IAAI,SAAS,IACrB,IAAI,IAAI,QAAQ,IAAI,SAAS,KAAK,CAAC,CAAC;EACxC,QAAQ,IAAI,GAAG;EACf,QAAQ,IAAI,WAAW,KAAK;EAC5B,IAAI,UAAU,MAAM,MAAM,OAAO,EAAE;OAC9B,MAAM,IAAI,IAAI;GAAE,KAAK;GAAO;EAAQ,CAAC;CAC5C;CACA,OAAO;EACL;EACA;EACA;EACA,KAAK,CAAC,GAAG,MAAM,KAAK;GAAE;GAAS;GAAU;EAAQ,CAAC;CACpD;AACF;;;;;AAMA,MAAa,YACX,OACA,UACA,UACuB;CACvB,KAAK,MAAM,UAAU,MAAM,IAAI,MAAM,QAAQ,GAC3C,KAAK,MAAM,UAAU,OAAO,SAC1B,IAAI,MAAM,MAAM,SAASA,OAAe,MAAM,MAAM,CAAC,GAAG,OAAO;AAIrE;;;;;;AAuBA,MAAa,kBAAiC;CAC5C,IAAI,SAAS;CAGb,MAAM,YAAYC,WAAmB,KAAK,IAAI,CAAC;CAC/C,OAAO;EACL;EACA,gBAAgB;GACd,MAAM,QAAQ,OAAO,IAAI,CAAC,IAAI;GAC9B,SAAS,QAAQ,SAAS,QAAQ,SAAS;GAC3C,OAAO;EACT;CACF;AACF"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { GenericDocument, GenericSchema, SchemaDefinition } from "convex/server";
|
|
2
|
+
import * as ReadSet from "./ReadSet.js";
|
|
3
|
+
import type { Index, SerializedQuery, StoredDocument, ValidatorJSON } from "./KernelValues.js";
|
|
4
|
+
/**
|
|
5
|
+
* A component's tables as its schema declares them.
|
|
6
|
+
*/
|
|
7
|
+
export interface KernelSchema {
|
|
8
|
+
readonly schemaValidation: boolean;
|
|
9
|
+
readonly tables: ReadonlyMap<string, {
|
|
10
|
+
readonly indexes: ReadonlyArray<Index>;
|
|
11
|
+
readonly documentType: ValidatorJSON;
|
|
12
|
+
}>;
|
|
13
|
+
}
|
|
14
|
+
export declare const exportSchema: (schema: SchemaDefinition<GenericSchema, boolean> | null | undefined) => KernelSchema | null;
|
|
15
|
+
/**
|
|
16
|
+
* Check a document against its table's declared type, as the backend does
|
|
17
|
+
* before a write.
|
|
18
|
+
*/
|
|
19
|
+
export declare const validateDocument: (schema: KernelSchema | null, tableName: string, doc: Record<string, unknown>) => void;
|
|
20
|
+
/**
|
|
21
|
+
* An interval a query reads, before it says where it starts and how far it got.
|
|
22
|
+
*/
|
|
23
|
+
export type Interval = Omit<ReadSet.IntervalRead, "componentPath" | "after" | "through">;
|
|
24
|
+
/**
|
|
25
|
+
* What a query reads: one table of one component, as the running attempt sees
|
|
26
|
+
* it. `read` records an interval in the attempt's read set and returns how to
|
|
27
|
+
* advance it.
|
|
28
|
+
*/
|
|
29
|
+
export interface TableView {
|
|
30
|
+
readonly schema: KernelSchema | null;
|
|
31
|
+
readonly scan: (tableName: string) => ReadonlyArray<StoredDocument>;
|
|
32
|
+
readonly read: (interval: Interval, after: ReadSet.Key | null) => (through: ReadSet.Key | "end") => void;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* A query's documents in order. The source is read when the query starts, as a
|
|
36
|
+
* snapshot, and consumed lazily. The read set holds the prefix the stream has
|
|
37
|
+
* examined, filtered documents included, or the whole range once it ends.
|
|
38
|
+
*/
|
|
39
|
+
export declare const stream: (view: TableView, query: SerializedQuery) => Iterator<GenericDocument>;
|
|
40
|
+
export interface PageRequest {
|
|
41
|
+
readonly query: SerializedQuery;
|
|
42
|
+
readonly cursor: string | null;
|
|
43
|
+
readonly endCursor?: string | null;
|
|
44
|
+
readonly pageSize: number;
|
|
45
|
+
readonly maximumRowsRead?: number | null;
|
|
46
|
+
readonly maximumBytesRead?: number | null;
|
|
47
|
+
}
|
|
48
|
+
export declare const paginate: (view: TableView, { query, cursor, endCursor, pageSize, maximumRowsRead, maximumBytesRead, }: PageRequest) => {
|
|
49
|
+
page: GenericDocument[];
|
|
50
|
+
isDone: boolean;
|
|
51
|
+
continueCursor: string;
|
|
52
|
+
splitCursor: string | null;
|
|
53
|
+
pageStatus: "SplitRecommended" | "SplitRequired" | null;
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=KernelQuery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KernelQuery.d.ts","sourceRoot":"","sources":["../../src/internal/KernelQuery.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,eAAe,EACf,aAAa,EACb,gBAAgB,EACjB,MAAM,eAAe,CAAC;AAQvB,OAAO,KAAK,OAAO,MAAM,cAAc,CAAC;AACxC,OAAO,KAAK,EAEV,KAAK,EACL,eAAe,EAEf,cAAc,EACd,aAAa,EACd,MAAM,mBAAmB,CAAC;AAY3B;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAC1B,MAAM,EACN;QACE,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;QACvC,QAAQ,CAAC,YAAY,EAAE,aAAa,CAAC;KACtC,CACF,CAAC;CACH;AAED,eAAO,MAAM,YAAY,WACf,gBAAgB,CAAC,aAAa,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,KAClE,YAAY,GAAG,IA4BjB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,gBAAgB,WACnB,YAAY,GAAG,IAAI,aAChB,MAAM,OACZ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,SAM7B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,IAAI,CACzB,OAAO,CAAC,YAAY,EACpB,eAAe,GAAG,OAAO,GAAG,SAAS,CACtC,CAAC;AAEF;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,IAAI,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,aAAa,CAAC,cAAc,CAAC,CAAC;IACpE,QAAQ,CAAC,IAAI,EAAE,CACb,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,OAAO,CAAC,GAAG,GAAG,IAAI,KACtB,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,GAAG,KAAK,KAAK,IAAI,CAAC;CAC7C;AA4GD;;;;GAIG;AACH,eAAO,MAAM,MAAM,SACX,SAAS,SACR,eAAe,KACrB,QAAQ,CAAC,eAAe,CAe1B,CAAC;AAqCF,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3C;AAED,eAAO,MAAM,QAAQ,SACb,SAAS,8EAQZ,WAAW;;;;;;CAkGf,CAAC"}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { evaluateFieldPath, evaluateFilter, evaluateRangeFilter, isValidIdentifier, resolvePendingValues, validateFieldNames, validateIndexRangeExpression, validateValidator } from "./KernelValues.js";
|
|
2
|
+
import { keyOf } from "./ReadSet.js";
|
|
3
|
+
import { requiresBinary } from "./KernelRefusal.js";
|
|
4
|
+
import { compareValues, convexToJson, getDocumentSize, jsonToConvex } from "convex/values";
|
|
5
|
+
//#region src/internal/KernelQuery.ts
|
|
6
|
+
const exportSchema = (schema) => {
|
|
7
|
+
if (schema === null || schema === void 0) return null;
|
|
8
|
+
const exported = {
|
|
9
|
+
schemaValidation: schema.schemaValidation,
|
|
10
|
+
tables: new Map(Object.entries(schema.tables).map(([name, table]) => [name, table.export()]))
|
|
11
|
+
};
|
|
12
|
+
exported.tables.forEach((table, tableName) => {
|
|
13
|
+
if (!isValidIdentifier(tableName)) throw new Error(`Table names must be valid identifiers, got "${tableName}"`);
|
|
14
|
+
validateFieldNames(table.documentType);
|
|
15
|
+
table.indexes.forEach(({ indexDescriptor }) => {
|
|
16
|
+
if (!isValidIdentifier(indexDescriptor)) throw new Error(`Index names must be valid identifiers, got "${indexDescriptor}"`);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
return exported;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Check a document against its table's declared type, as the backend does
|
|
23
|
+
* before a write.
|
|
24
|
+
*/
|
|
25
|
+
const validateDocument = (schema, tableName, doc) => {
|
|
26
|
+
if (schema === null || !schema.schemaValidation) return;
|
|
27
|
+
const validator = schema.tables.get(tableName)?.documentType;
|
|
28
|
+
if (validator === void 0) return;
|
|
29
|
+
validateValidator(validator, resolvePendingValues(doc));
|
|
30
|
+
};
|
|
31
|
+
const resolveSource = (view, query) => {
|
|
32
|
+
const source = query.source;
|
|
33
|
+
let docs;
|
|
34
|
+
let fieldPathsToSortBy;
|
|
35
|
+
let order;
|
|
36
|
+
let table;
|
|
37
|
+
let range = [];
|
|
38
|
+
switch (source.type) {
|
|
39
|
+
case "FullTableScan":
|
|
40
|
+
table = source.tableName;
|
|
41
|
+
docs = [...view.scan(source.tableName)];
|
|
42
|
+
order = source.order ?? "asc";
|
|
43
|
+
fieldPathsToSortBy = ["_creationTime"];
|
|
44
|
+
break;
|
|
45
|
+
case "IndexRange": {
|
|
46
|
+
const [tableName, indexName] = source.indexName.split(".");
|
|
47
|
+
table = tableName;
|
|
48
|
+
range = source.range;
|
|
49
|
+
order = source.order ?? "asc";
|
|
50
|
+
let fields;
|
|
51
|
+
if (indexName === "by_creation_time") fields = ["_creationTime", "_id"];
|
|
52
|
+
else if (indexName === "by_id") fields = ["_id"];
|
|
53
|
+
else {
|
|
54
|
+
const index = view.schema?.tables.get(tableName)?.indexes.find(({ indexDescriptor }) => indexDescriptor === indexName);
|
|
55
|
+
if (index === void 0) throw new Error(`Cannot use index "${indexName}" for table "${tableName}" because it is not declared in the schema.`);
|
|
56
|
+
fields = index.fields.concat(["_creationTime", "_id"]);
|
|
57
|
+
}
|
|
58
|
+
fieldPathsToSortBy = fields;
|
|
59
|
+
validateIndexRangeExpression(source, fields);
|
|
60
|
+
docs = view.scan(tableName).filter((doc) => source.range.every((filter) => evaluateRangeFilter(doc, filter)));
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
case "Search": throw requiresBinary("textSearch");
|
|
64
|
+
}
|
|
65
|
+
const filters = query.operators.filter((operator) => "filter" in operator).map((operator) => operator.filter);
|
|
66
|
+
const limit = query.operators.find((operator) => "limit" in operator) ?? null;
|
|
67
|
+
const orderMultiplier = order === "asc" ? 1 : -1;
|
|
68
|
+
docs.sort((a, b) => {
|
|
69
|
+
for (const fp of fieldPathsToSortBy) {
|
|
70
|
+
const v = compareValues(evaluateFieldPath(fp, a), evaluateFieldPath(fp, b));
|
|
71
|
+
if (v !== 0) return v * orderMultiplier;
|
|
72
|
+
}
|
|
73
|
+
return 0;
|
|
74
|
+
});
|
|
75
|
+
return {
|
|
76
|
+
sortedDocs: docs,
|
|
77
|
+
filterFn: (doc) => filters.every((f) => evaluateFilter(doc, f)),
|
|
78
|
+
limit: limit?.limit ?? null,
|
|
79
|
+
order,
|
|
80
|
+
interval: {
|
|
81
|
+
kind: "interval",
|
|
82
|
+
table,
|
|
83
|
+
fields: fieldPathsToSortBy.includes("_id") ? fieldPathsToSortBy : [...fieldPathsToSortBy, "_id"],
|
|
84
|
+
order,
|
|
85
|
+
range
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* A query's documents in order. The source is read when the query starts, as a
|
|
91
|
+
* snapshot, and consumed lazily. The read set holds the prefix the stream has
|
|
92
|
+
* examined, filtered documents included, or the whole range once it ends.
|
|
93
|
+
*/
|
|
94
|
+
const stream = (view, query) => {
|
|
95
|
+
const { sortedDocs, filterFn, limit, interval } = resolveSource(view, query);
|
|
96
|
+
const examined = view.read(interval, null);
|
|
97
|
+
return (function* () {
|
|
98
|
+
let returned = 0;
|
|
99
|
+
for (const doc of sortedDocs) {
|
|
100
|
+
if (limit !== null && returned >= limit) return;
|
|
101
|
+
examined(keyOf(interval.fields, doc));
|
|
102
|
+
if (filterFn(doc)) {
|
|
103
|
+
returned++;
|
|
104
|
+
yield doc;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
examined("end");
|
|
108
|
+
})();
|
|
109
|
+
};
|
|
110
|
+
const encodeCursor = (doc, fieldPaths) => JSON.stringify(fieldPaths.map((fp) => {
|
|
111
|
+
const k = evaluateFieldPath(fp, doc);
|
|
112
|
+
return k === void 0 ? null : JSON.stringify(convexToJson(k));
|
|
113
|
+
}));
|
|
114
|
+
const parseCursor = (c) => c ? JSON.parse(c).map((k) => k === null ? void 0 : jsonToConvex(JSON.parse(k))) : null;
|
|
115
|
+
const compareToCursor = (doc, cursorKeys, fieldPaths, order) => {
|
|
116
|
+
const orderMultiplier = order === "asc" ? 1 : -1;
|
|
117
|
+
for (let i = 0; i < fieldPaths.length; i++) {
|
|
118
|
+
const cmp = compareValues(evaluateFieldPath(fieldPaths[i], doc), cursorKeys[i]);
|
|
119
|
+
if (cmp !== 0) return cmp * orderMultiplier;
|
|
120
|
+
}
|
|
121
|
+
return 0;
|
|
122
|
+
};
|
|
123
|
+
const paginate = (view, { query, cursor, endCursor, pageSize, maximumRowsRead, maximumBytesRead }) => {
|
|
124
|
+
const { sortedDocs, filterFn, order, interval } = resolveSource(view, query);
|
|
125
|
+
if (cursor === "_end_cursor") return {
|
|
126
|
+
page: [],
|
|
127
|
+
isDone: true,
|
|
128
|
+
continueCursor: "_end_cursor",
|
|
129
|
+
splitCursor: null,
|
|
130
|
+
pageStatus: null
|
|
131
|
+
};
|
|
132
|
+
const cursorFields = interval.fields;
|
|
133
|
+
const cursorKeys = parseCursor(cursor);
|
|
134
|
+
const hasEndBoundary = !!endCursor && endCursor !== "_end_cursor";
|
|
135
|
+
const endCursorKeys = hasEndBoundary ? parseCursor(endCursor) : null;
|
|
136
|
+
const examined = view.read(interval, cursorKeys);
|
|
137
|
+
let reachedEnd = true;
|
|
138
|
+
const page = [];
|
|
139
|
+
let isInPage = cursor === null;
|
|
140
|
+
let continueCursor = "_end_cursor";
|
|
141
|
+
let splitCursor = null;
|
|
142
|
+
let pageStatus = null;
|
|
143
|
+
let rowsRead = 0;
|
|
144
|
+
let bytesRead = 0;
|
|
145
|
+
const readDocCursors = [];
|
|
146
|
+
for (let i = 0; i < sortedDocs.length; i++) {
|
|
147
|
+
const doc = sortedDocs[i];
|
|
148
|
+
const isLastDoc = i === sortedDocs.length - 1;
|
|
149
|
+
if (!isInPage) {
|
|
150
|
+
if (cursorKeys) {
|
|
151
|
+
if (compareToCursor(doc, cursorKeys, cursorFields, order) > 0) isInPage = true;
|
|
152
|
+
else continue;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (hasEndBoundary && endCursorKeys) {
|
|
156
|
+
const cmp = compareToCursor(doc, endCursorKeys, cursorFields, order);
|
|
157
|
+
if (cmp >= 0) {
|
|
158
|
+
reachedEnd = false;
|
|
159
|
+
examined(endCursorKeys);
|
|
160
|
+
if (cmp === 0) {
|
|
161
|
+
rowsRead += 1;
|
|
162
|
+
bytesRead += getDocumentSize(doc);
|
|
163
|
+
readDocCursors.push(encodeCursor(doc, cursorFields));
|
|
164
|
+
if (filterFn(doc)) page.push(doc);
|
|
165
|
+
continueCursor = encodeCursor(doc, cursorFields);
|
|
166
|
+
}
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
rowsRead += 1;
|
|
171
|
+
bytesRead += getDocumentSize(doc);
|
|
172
|
+
readDocCursors.push(encodeCursor(doc, cursorFields));
|
|
173
|
+
examined(keyOf(cursorFields, doc));
|
|
174
|
+
const hitLimit = !!maximumRowsRead && rowsRead >= maximumRowsRead || !!maximumBytesRead && bytesRead >= maximumBytesRead;
|
|
175
|
+
if (filterFn(doc)) page.push(doc);
|
|
176
|
+
if (hitLimit) {
|
|
177
|
+
reachedEnd = false;
|
|
178
|
+
pageStatus = "SplitRequired";
|
|
179
|
+
continueCursor = encodeCursor(doc, cursorFields);
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
if (!endCursor && page.length >= pageSize) {
|
|
183
|
+
reachedEnd = isLastDoc;
|
|
184
|
+
if (!isLastDoc) continueCursor = encodeCursor(doc, cursorFields);
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (reachedEnd) examined(endCursorKeys ?? "end");
|
|
189
|
+
if (pageStatus === "SplitRequired" && readDocCursors.length >= 2) splitCursor = readDocCursors[Math.floor((readDocCursors.length - 1) / 2)];
|
|
190
|
+
else if (pageStatus === null && rowsRead > pageSize + 1 && readDocCursors.length >= 2) {
|
|
191
|
+
pageStatus = "SplitRecommended";
|
|
192
|
+
splitCursor = readDocCursors[Math.floor((readDocCursors.length - 1) / 2)];
|
|
193
|
+
}
|
|
194
|
+
return {
|
|
195
|
+
page,
|
|
196
|
+
isDone: continueCursor === "_end_cursor",
|
|
197
|
+
continueCursor,
|
|
198
|
+
splitCursor,
|
|
199
|
+
pageStatus
|
|
200
|
+
};
|
|
201
|
+
};
|
|
202
|
+
//#endregion
|
|
203
|
+
export { exportSchema, paginate, stream, validateDocument };
|
|
204
|
+
|
|
205
|
+
//# sourceMappingURL=KernelQuery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KernelQuery.js","names":["KernelRefusal.requiresBinary","ReadSet.keyOf"],"sources":["../../src/internal/KernelQuery.ts"],"sourcesContent":["// Derived from convex-test 0.0.65 (index.ts, `DatabaseFake`), Copyright Convex,\n// Inc., licensed under the Apache License, Version 2.0\n// (https://www.apache.org/licenses/LICENSE-2.0). The ordering, index range and\n// pagination rules are convex-test's. They read a table through the attempt\n// that runs the query instead of convex-test's database, and record the\n// interval each query examined.\n\nimport type {\n GenericDocument,\n GenericSchema,\n SchemaDefinition,\n} from \"convex/server\";\nimport {\n compareValues,\n convexToJson,\n getDocumentSize,\n jsonToConvex,\n} from \"convex/values\";\nimport * as KernelRefusal from \"./KernelRefusal.js\";\nimport * as ReadSet from \"./ReadSet.js\";\nimport type {\n FilterJson,\n Index,\n SerializedQuery,\n SerializedRangeExpression,\n StoredDocument,\n ValidatorJSON,\n} from \"./KernelValues.js\";\nimport {\n evaluateFieldPath,\n evaluateFilter,\n evaluateRangeFilter,\n isValidIdentifier,\n resolvePendingValues,\n validateFieldNames,\n validateIndexRangeExpression,\n validateValidator,\n} from \"./KernelValues.js\";\n\n/**\n * A component's tables as its schema declares them.\n */\nexport interface KernelSchema {\n readonly schemaValidation: boolean;\n readonly tables: ReadonlyMap<\n string,\n {\n readonly indexes: ReadonlyArray<Index>;\n readonly documentType: ValidatorJSON;\n }\n >;\n}\n\nexport const exportSchema = (\n schema: SchemaDefinition<GenericSchema, boolean> | null | undefined,\n): KernelSchema | null => {\n if (schema === null || schema === undefined) return null;\n const exported: KernelSchema = {\n schemaValidation: (schema as unknown as { schemaValidation: boolean })\n .schemaValidation,\n tables: new Map(\n Object.entries(schema.tables).map(([name, table]) => [\n name,\n (table as unknown as { export: () => any }).export(),\n ]),\n ),\n };\n exported.tables.forEach((table, tableName) => {\n if (!isValidIdentifier(tableName)) {\n throw new Error(\n `Table names must be valid identifiers, got \"${tableName}\"`,\n );\n }\n validateFieldNames(table.documentType);\n table.indexes.forEach(({ indexDescriptor }) => {\n if (!isValidIdentifier(indexDescriptor)) {\n throw new Error(\n `Index names must be valid identifiers, got \"${indexDescriptor}\"`,\n );\n }\n });\n });\n return exported;\n};\n\n/**\n * Check a document against its table's declared type, as the backend does\n * before a write.\n */\nexport const validateDocument = (\n schema: KernelSchema | null,\n tableName: string,\n doc: Record<string, unknown>,\n) => {\n if (schema === null || !schema.schemaValidation) return;\n const validator = schema.tables.get(tableName)?.documentType;\n if (validator === undefined) return;\n validateValidator(validator, resolvePendingValues(doc as GenericDocument));\n};\n\n/**\n * An interval a query reads, before it says where it starts and how far it got.\n */\nexport type Interval = Omit<\n ReadSet.IntervalRead,\n \"componentPath\" | \"after\" | \"through\"\n>;\n\n/**\n * What a query reads: one table of one component, as the running attempt sees\n * it. `read` records an interval in the attempt's read set and returns how to\n * advance it.\n */\nexport interface TableView {\n readonly schema: KernelSchema | null;\n readonly scan: (tableName: string) => ReadonlyArray<StoredDocument>;\n readonly read: (\n interval: Interval,\n after: ReadSet.Key | null,\n ) => (through: ReadSet.Key | \"end\") => void;\n}\n\ninterface ResolvedSource {\n readonly sortedDocs: ReadonlyArray<GenericDocument>;\n readonly filterFn: (doc: GenericDocument) => boolean;\n readonly limit: number | null;\n readonly order: \"asc\" | \"desc\";\n readonly interval: Interval;\n}\n\nconst resolveSource = (\n view: TableView,\n query: SerializedQuery,\n): ResolvedSource => {\n const source = query.source;\n let docs: Array<GenericDocument>;\n let fieldPathsToSortBy: Array<string>;\n let order: \"asc\" | \"desc\";\n let table: string;\n let range: ReadonlyArray<SerializedRangeExpression> = [];\n switch (source.type) {\n case \"FullTableScan\": {\n table = source.tableName;\n docs = [...view.scan(source.tableName)];\n order = source.order ?? \"asc\";\n fieldPathsToSortBy = [\"_creationTime\"];\n break;\n }\n case \"IndexRange\": {\n const [tableName, indexName] = source.indexName.split(\".\") as [\n string,\n string,\n ];\n table = tableName;\n range = source.range;\n order = source.order ?? \"asc\";\n let fields: Array<string>;\n if (indexName === \"by_creation_time\") {\n fields = [\"_creationTime\", \"_id\"];\n } else if (indexName === \"by_id\") {\n fields = [\"_id\"];\n } else {\n const index = view.schema?.tables\n .get(tableName)\n ?.indexes.find(\n ({ indexDescriptor }) => indexDescriptor === indexName,\n );\n if (index === undefined) {\n throw new Error(\n `Cannot use index \"${indexName}\" for table \"${tableName}\" because ` +\n `it is not declared in the schema.`,\n );\n }\n fields = index.fields.concat([\"_creationTime\", \"_id\"]);\n }\n fieldPathsToSortBy = fields;\n validateIndexRangeExpression(source, fields);\n docs = view\n .scan(tableName)\n .filter((doc) =>\n source.range.every((filter) => evaluateRangeFilter(doc, filter)),\n );\n break;\n }\n case \"Search\": {\n throw KernelRefusal.requiresBinary(\"textSearch\");\n }\n }\n\n const filters = query.operators\n .filter(\n (operator): operator is { filter: FilterJson } => \"filter\" in operator,\n )\n .map((operator) => operator.filter);\n const limit =\n query.operators.find(\n (operator): operator is { limit: number } => \"limit\" in operator,\n ) ?? null;\n\n const orderMultiplier = order === \"asc\" ? 1 : -1;\n docs.sort((a, b) => {\n for (const fp of fieldPathsToSortBy) {\n const v = compareValues(\n evaluateFieldPath(fp, a),\n evaluateFieldPath(fp, b),\n );\n if (v !== 0) return v * orderMultiplier;\n }\n return 0;\n });\n\n return {\n sortedDocs: docs,\n filterFn: (doc) => filters.every((f) => evaluateFilter(doc, f)),\n limit: limit?.limit ?? null,\n order,\n interval: {\n kind: \"interval\",\n table,\n fields: fieldPathsToSortBy.includes(\"_id\")\n ? fieldPathsToSortBy\n : [...fieldPathsToSortBy, \"_id\"],\n order,\n range,\n },\n };\n};\n\n/**\n * A query's documents in order. The source is read when the query starts, as a\n * snapshot, and consumed lazily. The read set holds the prefix the stream has\n * examined, filtered documents included, or the whole range once it ends.\n */\nexport const stream = (\n view: TableView,\n query: SerializedQuery,\n): Iterator<GenericDocument> => {\n const { sortedDocs, filterFn, limit, interval } = resolveSource(view, query);\n const examined = view.read(interval, null);\n return (function* () {\n let returned = 0;\n for (const doc of sortedDocs) {\n if (limit !== null && returned >= limit) return;\n examined(ReadSet.keyOf(interval.fields, doc as StoredDocument));\n if (filterFn(doc)) {\n returned++;\n yield doc;\n }\n }\n examined(\"end\");\n })();\n};\n\nconst encodeCursor = (\n doc: GenericDocument,\n fieldPaths: ReadonlyArray<string>,\n): string =>\n JSON.stringify(\n fieldPaths.map((fp) => {\n const k = evaluateFieldPath(fp, doc);\n return k === undefined ? null : JSON.stringify(convexToJson(k));\n }),\n );\n\nconst parseCursor = (c: string | null | undefined) =>\n c\n ? (JSON.parse(c) as Array<string | null>).map((k) =>\n k === null ? undefined : jsonToConvex(JSON.parse(k)),\n )\n : null;\n\nconst compareToCursor = (\n doc: GenericDocument,\n cursorKeys: ReadonlyArray<unknown>,\n fieldPaths: ReadonlyArray<string>,\n order: \"asc\" | \"desc\",\n): number => {\n const orderMultiplier = order === \"asc\" ? 1 : -1;\n for (let i = 0; i < fieldPaths.length; i++) {\n const cmp = compareValues(\n evaluateFieldPath(fieldPaths[i]!, doc),\n cursorKeys[i] as any,\n );\n if (cmp !== 0) return cmp * orderMultiplier;\n }\n return 0;\n};\n\nexport interface PageRequest {\n readonly query: SerializedQuery;\n readonly cursor: string | null;\n readonly endCursor?: string | null;\n readonly pageSize: number;\n readonly maximumRowsRead?: number | null;\n readonly maximumBytesRead?: number | null;\n}\n\nexport const paginate = (\n view: TableView,\n {\n query,\n cursor,\n endCursor,\n pageSize,\n maximumRowsRead,\n maximumBytesRead,\n }: PageRequest,\n) => {\n const { sortedDocs, filterFn, order, interval } = resolveSource(view, query);\n // A page from the terminal cursor reads the empty interval past the end, so\n // it depends on nothing.\n if (cursor === \"_end_cursor\") {\n return {\n page: [],\n isDone: true,\n continueCursor: \"_end_cursor\",\n splitCursor: null,\n pageStatus: null,\n };\n }\n const cursorFields = interval.fields;\n const cursorKeys = parseCursor(cursor);\n const hasEndBoundary = !!endCursor && endCursor !== \"_end_cursor\";\n const endCursorKeys = hasEndBoundary ? parseCursor(endCursor) : null;\n const examined = view.read(interval, cursorKeys);\n let reachedEnd = true;\n\n const page: Array<GenericDocument> = [];\n let isInPage = cursor === null;\n let continueCursor = \"_end_cursor\";\n let splitCursor: string | null = null;\n let pageStatus: \"SplitRecommended\" | \"SplitRequired\" | null = null;\n let rowsRead = 0;\n let bytesRead = 0;\n const readDocCursors: Array<string> = [];\n\n for (let i = 0; i < sortedDocs.length; i++) {\n const doc = sortedDocs[i]!;\n const isLastDoc = i === sortedDocs.length - 1;\n if (!isInPage) {\n if (cursorKeys) {\n if (compareToCursor(doc, cursorKeys, cursorFields, order) > 0) {\n isInPage = true;\n } else {\n continue;\n }\n }\n }\n if (hasEndBoundary && endCursorKeys) {\n const cmp = compareToCursor(doc, endCursorKeys, cursorFields, order);\n if (cmp >= 0) {\n reachedEnd = false;\n examined(endCursorKeys);\n if (cmp === 0) {\n rowsRead += 1;\n bytesRead += getDocumentSize(doc);\n readDocCursors.push(encodeCursor(doc, cursorFields));\n if (filterFn(doc)) page.push(doc);\n continueCursor = encodeCursor(doc, cursorFields);\n }\n break;\n }\n }\n rowsRead += 1;\n bytesRead += getDocumentSize(doc);\n readDocCursors.push(encodeCursor(doc, cursorFields));\n examined(ReadSet.keyOf(cursorFields, doc as StoredDocument));\n const hitLimit =\n (!!maximumRowsRead && rowsRead >= maximumRowsRead) ||\n (!!maximumBytesRead && bytesRead >= maximumBytesRead);\n if (filterFn(doc)) page.push(doc);\n if (hitLimit) {\n reachedEnd = false;\n pageStatus = \"SplitRequired\";\n continueCursor = encodeCursor(doc, cursorFields);\n break;\n }\n if (!endCursor && page.length >= pageSize) {\n reachedEnd = isLastDoc;\n if (!isLastDoc) continueCursor = encodeCursor(doc, cursorFields);\n break;\n }\n }\n // A page bounded by an end cursor examined the range only up to it.\n if (reachedEnd) examined(endCursorKeys ?? \"end\");\n\n if (pageStatus === \"SplitRequired\" && readDocCursors.length >= 2) {\n splitCursor = readDocCursors[Math.floor((readDocCursors.length - 1) / 2)]!;\n } else if (\n pageStatus === null &&\n rowsRead > pageSize + 1 &&\n readDocCursors.length >= 2\n ) {\n pageStatus = \"SplitRecommended\";\n splitCursor = readDocCursors[Math.floor((readDocCursors.length - 1) / 2)]!;\n }\n\n return {\n page,\n isDone: continueCursor === \"_end_cursor\",\n continueCursor,\n splitCursor,\n pageStatus,\n };\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import * as Schema from "effect/Schema";
|
|
2
|
+
declare const RequiresBinary_base: Schema.Class<RequiresBinary, Schema.TaggedStruct<"RequiresBinary", {
|
|
3
|
+
readonly operation: Schema.Literals<readonly ["textSearch", "vectorSearch"]>;
|
|
4
|
+
readonly message: Schema.String;
|
|
5
|
+
}>, import("effect/Cause").YieldableError>;
|
|
6
|
+
/**
|
|
7
|
+
* The kernel never answers this operation in process. Only the binary does.
|
|
8
|
+
*/
|
|
9
|
+
export declare class RequiresBinary extends RequiresBinary_base {
|
|
10
|
+
}
|
|
11
|
+
declare const KernelRowPending_base: Schema.Class<KernelRowPending, Schema.TaggedStruct<"KernelRowPending", {
|
|
12
|
+
readonly operation: Schema.String;
|
|
13
|
+
readonly row: Schema.Int;
|
|
14
|
+
readonly message: Schema.String;
|
|
15
|
+
}>, import("effect/Cause").YieldableError>;
|
|
16
|
+
/**
|
|
17
|
+
* A later kernel row supplies this operation. Until then the kernel refuses it
|
|
18
|
+
* rather than answer with convex-test's behaviour.
|
|
19
|
+
*/
|
|
20
|
+
export declare class KernelRowPending extends KernelRowPending_base {
|
|
21
|
+
}
|
|
22
|
+
declare const RegisteredAfterOpen_base: Schema.Class<RegisteredAfterOpen, Schema.TaggedStruct<"RegisteredAfterOpen", {
|
|
23
|
+
readonly componentPath: Schema.String;
|
|
24
|
+
readonly message: Schema.String;
|
|
25
|
+
}>, import("effect/Cause").YieldableError>;
|
|
26
|
+
/**
|
|
27
|
+
* A component was registered after the test backend opened, so its modules
|
|
28
|
+
* would load after a function had already run.
|
|
29
|
+
*/
|
|
30
|
+
export declare class RegisteredAfterOpen extends RegisteredAfterOpen_base {
|
|
31
|
+
}
|
|
32
|
+
declare const OptimisticConcurrencyControlFailure_base: Schema.Class<OptimisticConcurrencyControlFailure, Schema.TaggedStruct<"OptimisticConcurrencyControlFailure", {
|
|
33
|
+
readonly attempts: Schema.Int;
|
|
34
|
+
readonly message: Schema.String;
|
|
35
|
+
}>, import("effect/Cause").YieldableError>;
|
|
36
|
+
/**
|
|
37
|
+
* Every attempt of a mutation read data a commit changed before it could
|
|
38
|
+
* publish. The kernel gives up on attempt 5.
|
|
39
|
+
*/
|
|
40
|
+
export declare class OptimisticConcurrencyControlFailure extends OptimisticConcurrencyControlFailure_base {
|
|
41
|
+
}
|
|
42
|
+
declare const ClosedAttempt_base: Schema.Class<ClosedAttempt, Schema.TaggedStruct<"ClosedAttempt", {
|
|
43
|
+
readonly operation: Schema.String;
|
|
44
|
+
readonly message: Schema.String;
|
|
45
|
+
}>, import("effect/Cause").YieldableError>;
|
|
46
|
+
/**
|
|
47
|
+
* A syscall reached a mutation's attempt after the mutation returned and its
|
|
48
|
+
* syscalls drained, so the attempt was already held or published.
|
|
49
|
+
*/
|
|
50
|
+
export declare class ClosedAttempt extends ClosedAttempt_base {
|
|
51
|
+
}
|
|
52
|
+
declare const StaleAttempt_base: Schema.Class<StaleAttempt, Schema.TaggedStruct<"StaleAttempt", {
|
|
53
|
+
readonly id: Schema.String;
|
|
54
|
+
readonly message: Schema.String;
|
|
55
|
+
}>, import("effect/Cause").YieldableError>;
|
|
56
|
+
/**
|
|
57
|
+
* `apply` named an attempt the kernel does not hold: it was already applied, or
|
|
58
|
+
* never prepared.
|
|
59
|
+
*/
|
|
60
|
+
export declare class StaleAttempt extends StaleAttempt_base {
|
|
61
|
+
}
|
|
62
|
+
declare const CommitTsNotIncreasing_base: Schema.Class<CommitTsNotIncreasing, Schema.TaggedStruct<"CommitTsNotIncreasing", {
|
|
63
|
+
readonly version: Schema.Int;
|
|
64
|
+
readonly previous: Schema.BigInt;
|
|
65
|
+
readonly commitTs: Schema.BigInt;
|
|
66
|
+
readonly message: Schema.String;
|
|
67
|
+
}>, import("effect/Cause").YieldableError>;
|
|
68
|
+
/**
|
|
69
|
+
* The runtime answered a commit timestamp no greater than the previous
|
|
70
|
+
* commit's.
|
|
71
|
+
*/
|
|
72
|
+
export declare class CommitTsNotIncreasing extends CommitTsNotIncreasing_base {
|
|
73
|
+
}
|
|
74
|
+
export declare const requiresBinary: (operation: RequiresBinary["operation"]) => RequiresBinary;
|
|
75
|
+
export declare const rowPending: (operation: string, row: number) => KernelRowPending;
|
|
76
|
+
export {};
|
|
77
|
+
//# sourceMappingURL=KernelRefusal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KernelRefusal.d.ts","sourceRoot":"","sources":["../../src/internal/KernelRefusal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;;;;;AAExC;;GAEG;AACH,qBAAa,cAAe,SAAQ,mBAMnC;CAAG;;;;;;AAEJ;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,qBAOrC;CAAG;;;;;AAEJ;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,wBAGxC;CAAG;;;;;AAEJ;;;GAGG;AACH,qBAAa,mCAAoC,SAAQ,wCAGxD;CAAG;;;;;AAEJ;;;GAGG;AACH,qBAAa,aAAc,SAAQ,kBAGlC;CAAG;;;;;AAEJ;;;GAGG;AACH,qBAAa,YAAa,SAAQ,iBAGjC;CAAG;;;;;;;AAEJ;;;GAGG;AACH,qBAAa,qBAAsB,SAAQ,0BAQ1C;CAAG;AAEJ,eAAO,MAAM,cAAc,cAAe,cAAc,CAAC,WAAW,CAAC,mBAIjE,CAAC;AAEL,eAAO,MAAM,UAAU,cAAe,MAAM,OAAO,MAAM,qBAKrD,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import * as Schema from "effect/Schema";
|
|
2
|
+
//#region src/internal/KernelRefusal.ts
|
|
3
|
+
/**
|
|
4
|
+
* The kernel never answers this operation in process. Only the binary does.
|
|
5
|
+
*/
|
|
6
|
+
var RequiresBinary = class extends Schema.TaggedError()("RequiresBinary", {
|
|
7
|
+
operation: Schema.Literals(["textSearch", "vectorSearch"]),
|
|
8
|
+
message: Schema.String
|
|
9
|
+
}) {};
|
|
10
|
+
/**
|
|
11
|
+
* A later kernel row supplies this operation. Until then the kernel refuses it
|
|
12
|
+
* rather than answer with convex-test's behaviour.
|
|
13
|
+
*/
|
|
14
|
+
var KernelRowPending = class extends Schema.TaggedError()("KernelRowPending", {
|
|
15
|
+
operation: Schema.String,
|
|
16
|
+
row: Schema.Int,
|
|
17
|
+
message: Schema.String
|
|
18
|
+
}) {};
|
|
19
|
+
/**
|
|
20
|
+
* A component was registered after the test backend opened, so its modules
|
|
21
|
+
* would load after a function had already run.
|
|
22
|
+
*/
|
|
23
|
+
var RegisteredAfterOpen = class extends Schema.TaggedError()("RegisteredAfterOpen", {
|
|
24
|
+
componentPath: Schema.String,
|
|
25
|
+
message: Schema.String
|
|
26
|
+
}) {};
|
|
27
|
+
/**
|
|
28
|
+
* Every attempt of a mutation read data a commit changed before it could
|
|
29
|
+
* publish. The kernel gives up on attempt 5.
|
|
30
|
+
*/
|
|
31
|
+
var OptimisticConcurrencyControlFailure = class extends Schema.TaggedError()("OptimisticConcurrencyControlFailure", {
|
|
32
|
+
attempts: Schema.Int,
|
|
33
|
+
message: Schema.String
|
|
34
|
+
}) {};
|
|
35
|
+
/**
|
|
36
|
+
* A syscall reached a mutation's attempt after the mutation returned and its
|
|
37
|
+
* syscalls drained, so the attempt was already held or published.
|
|
38
|
+
*/
|
|
39
|
+
var ClosedAttempt = class extends Schema.TaggedError()("ClosedAttempt", {
|
|
40
|
+
operation: Schema.String,
|
|
41
|
+
message: Schema.String
|
|
42
|
+
}) {};
|
|
43
|
+
/**
|
|
44
|
+
* `apply` named an attempt the kernel does not hold: it was already applied, or
|
|
45
|
+
* never prepared.
|
|
46
|
+
*/
|
|
47
|
+
var StaleAttempt = class extends Schema.TaggedError()("StaleAttempt", {
|
|
48
|
+
id: Schema.String,
|
|
49
|
+
message: Schema.String
|
|
50
|
+
}) {};
|
|
51
|
+
/**
|
|
52
|
+
* The runtime answered a commit timestamp no greater than the previous
|
|
53
|
+
* commit's.
|
|
54
|
+
*/
|
|
55
|
+
var CommitTsNotIncreasing = class extends Schema.TaggedError()("CommitTsNotIncreasing", {
|
|
56
|
+
version: Schema.Int,
|
|
57
|
+
previous: Schema.BigInt,
|
|
58
|
+
commitTs: Schema.BigInt,
|
|
59
|
+
message: Schema.String
|
|
60
|
+
}) {};
|
|
61
|
+
const requiresBinary = (operation) => new RequiresBinary({
|
|
62
|
+
operation,
|
|
63
|
+
message: `The test kernel does not simulate ${operation}. Run this case against the Convex binary.`
|
|
64
|
+
});
|
|
65
|
+
const rowPending = (operation, row) => new KernelRowPending({
|
|
66
|
+
operation,
|
|
67
|
+
row,
|
|
68
|
+
message: `The test kernel supplies ${operation} in build-order row ${row}.`
|
|
69
|
+
});
|
|
70
|
+
//#endregion
|
|
71
|
+
export { ClosedAttempt, CommitTsNotIncreasing, KernelRowPending, OptimisticConcurrencyControlFailure, RegisteredAfterOpen, RequiresBinary, StaleAttempt, requiresBinary, rowPending };
|
|
72
|
+
|
|
73
|
+
//# sourceMappingURL=KernelRefusal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KernelRefusal.js","names":[],"sources":["../../src/internal/KernelRefusal.ts"],"sourcesContent":["import * as Schema from \"effect/Schema\";\n\n/**\n * The kernel never answers this operation in process. Only the binary does.\n */\nexport class RequiresBinary extends Schema.TaggedError<RequiresBinary>()(\n \"RequiresBinary\",\n {\n operation: Schema.Literals([\"textSearch\", \"vectorSearch\"]),\n message: Schema.String,\n },\n) {}\n\n/**\n * A later kernel row supplies this operation. Until then the kernel refuses it\n * rather than answer with convex-test's behaviour.\n */\nexport class KernelRowPending extends Schema.TaggedError<KernelRowPending>()(\n \"KernelRowPending\",\n {\n operation: Schema.String,\n row: Schema.Int,\n message: Schema.String,\n },\n) {}\n\n/**\n * A component was registered after the test backend opened, so its modules\n * would load after a function had already run.\n */\nexport class RegisteredAfterOpen extends Schema.TaggedError<RegisteredAfterOpen>()(\n \"RegisteredAfterOpen\",\n { componentPath: Schema.String, message: Schema.String },\n) {}\n\n/**\n * Every attempt of a mutation read data a commit changed before it could\n * publish. The kernel gives up on attempt 5.\n */\nexport class OptimisticConcurrencyControlFailure extends Schema.TaggedError<OptimisticConcurrencyControlFailure>()(\n \"OptimisticConcurrencyControlFailure\",\n { attempts: Schema.Int, message: Schema.String },\n) {}\n\n/**\n * A syscall reached a mutation's attempt after the mutation returned and its\n * syscalls drained, so the attempt was already held or published.\n */\nexport class ClosedAttempt extends Schema.TaggedError<ClosedAttempt>()(\n \"ClosedAttempt\",\n { operation: Schema.String, message: Schema.String },\n) {}\n\n/**\n * `apply` named an attempt the kernel does not hold: it was already applied, or\n * never prepared.\n */\nexport class StaleAttempt extends Schema.TaggedError<StaleAttempt>()(\n \"StaleAttempt\",\n { id: Schema.String, message: Schema.String },\n) {}\n\n/**\n * The runtime answered a commit timestamp no greater than the previous\n * commit's.\n */\nexport class CommitTsNotIncreasing extends Schema.TaggedError<CommitTsNotIncreasing>()(\n \"CommitTsNotIncreasing\",\n {\n version: Schema.Int,\n previous: Schema.BigInt,\n commitTs: Schema.BigInt,\n message: Schema.String,\n },\n) {}\n\nexport const requiresBinary = (operation: RequiresBinary[\"operation\"]) =>\n new RequiresBinary({\n operation,\n message: `The test kernel does not simulate ${operation}. Run this case against the Convex binary.`,\n });\n\nexport const rowPending = (operation: string, row: number) =>\n new KernelRowPending({\n operation,\n row,\n message: `The test kernel supplies ${operation} in build-order row ${row}.`,\n });\n"],"mappings":";;;;;AAKA,IAAa,iBAAb,cAAoC,OAAO,YAA4B,CAAC,CACtE,kBACA;CACE,WAAW,OAAO,SAAS,CAAC,cAAc,cAAc,CAAC;CACzD,SAAS,OAAO;AAClB,CACF,CAAC,CAAC,CAAC;;;;;AAMH,IAAa,mBAAb,cAAsC,OAAO,YAA8B,CAAC,CAC1E,oBACA;CACE,WAAW,OAAO;CAClB,KAAK,OAAO;CACZ,SAAS,OAAO;AAClB,CACF,CAAC,CAAC,CAAC;;;;;AAMH,IAAa,sBAAb,cAAyC,OAAO,YAAiC,CAAC,CAChF,uBACA;CAAE,eAAe,OAAO;CAAQ,SAAS,OAAO;AAAO,CACzD,CAAC,CAAC,CAAC;;;;;AAMH,IAAa,sCAAb,cAAyD,OAAO,YAAiD,CAAC,CAChH,uCACA;CAAE,UAAU,OAAO;CAAK,SAAS,OAAO;AAAO,CACjD,CAAC,CAAC,CAAC;;;;;AAMH,IAAa,gBAAb,cAAmC,OAAO,YAA2B,CAAC,CACpE,iBACA;CAAE,WAAW,OAAO;CAAQ,SAAS,OAAO;AAAO,CACrD,CAAC,CAAC,CAAC;;;;;AAMH,IAAa,eAAb,cAAkC,OAAO,YAA0B,CAAC,CAClE,gBACA;CAAE,IAAI,OAAO;CAAQ,SAAS,OAAO;AAAO,CAC9C,CAAC,CAAC,CAAC;;;;;AAMH,IAAa,wBAAb,cAA2C,OAAO,YAAmC,CAAC,CACpF,yBACA;CACE,SAAS,OAAO;CAChB,UAAU,OAAO;CACjB,UAAU,OAAO;CACjB,SAAS,OAAO;AAClB,CACF,CAAC,CAAC,CAAC;AAEH,MAAa,kBAAkB,cAC7B,IAAI,eAAe;CACjB;CACA,SAAS,qCAAqC,UAAU;AAC1D,CAAC;AAEH,MAAa,cAAc,WAAmB,QAC5C,IAAI,iBAAiB;CACnB;CACA;CACA,SAAS,4BAA4B,UAAU,sBAAsB,IAAI;AAC3E,CAAC"}
|