@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 @@
1
+ {"version":3,"file":"Execution.js","names":["Globals.own","KernelQuery.exportSchema","Kernel.empty","Kernel.wallClock","KernelRefusal.RegisteredAfterOpen","Invocation.current","KernelRefusal.StaleAttempt","Invocation.bind","Kernel.conflict","KernelRefusal.OptimisticConcurrencyControlFailure","KernelRefusal.CommitTsNotIncreasing","Kernel.apply","KernelQuery.stream","KernelQuery.paginate","KernelRefusal.rowPending","KernelRefusal.requiresBinary","KernelRefusal.ClosedAttempt"],"sources":["../../src/internal/Execution.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\nimport {\n actionGeneric,\n getFunctionAddress,\n mutationGeneric,\n queryGeneric,\n type FunctionReference,\n type GenericSchema,\n type SchemaDefinition,\n type UserIdentity,\n} from \"convex/server\";\nimport { convexToJson, jsonToConvex, type Value } from \"convex/values\";\nimport { KernelAttempt } from \"./Attempt.js\";\nimport * as Globals from \"./Globals.js\";\nimport * as Invocation from \"./Invocation.js\";\nimport * as Kernel from \"./Kernel.js\";\nimport * as KernelQuery from \"./KernelQuery.js\";\nimport * as KernelRefusal from \"./KernelRefusal.js\";\nimport type * as ReadSet from \"./ReadSet.js\";\nimport type {\n DocumentId,\n FunctionPath,\n StoredDocument,\n ValidatorJSON,\n} from \"./KernelValues.js\";\nimport {\n createFunctionHandle,\n createTestJwt,\n deserializeConvexErrorData,\n evaluateValue,\n hasPendingValues,\n parseArgs,\n parseFunctionHandle,\n resolveCommittedValues,\n simpleHash,\n tableNameFromId,\n validateFunctionArgs,\n validateReturnValue,\n} from \"./KernelValues.js\";\n\nconst ROOT = \"\";\nconst TYPICAL_CONVEX_ID_LENGTH = 32;\n\ntype Modules = Record<string, () => Promise<any>>;\n\n/**\n * One registered component: its schema and its function modules, each loaded\n * once when the world opens.\n */\ninterface Component {\n readonly path: string;\n readonly schema: KernelQuery.KernelSchema | null;\n readonly loaders: ReadonlyMap<string, () => Promise<any>>;\n readonly loaded: Map<string, any>;\n}\n\n/**\n * Who is calling: the identity and the request attributes a test accessor set.\n */\nexport interface Caller {\n readonly identity: UserIdentity | null;\n readonly token: string | null;\n readonly ip: string | null;\n readonly userAgent: string | null;\n}\n\nexport const anonymous: Caller = {\n identity: null,\n token: null,\n ip: null,\n userAgent: null,\n};\n\nexport const withIdentity = (\n caller: Caller,\n identity: Partial<UserIdentity>,\n): Caller => {\n const subject = identity.subject ?? \"\" + simpleHash(JSON.stringify(identity));\n const issuer = identity.issuer ?? \"https://convex.test\";\n const tokenIdentifier = identity.tokenIdentifier ?? `${issuer}|${subject}`;\n const full = { ...identity, subject, issuer, tokenIdentifier };\n return { ...caller, identity: full, token: createTestJwt(full) };\n};\n\ninterface Request {\n readonly ip: string | null;\n readonly userAgent: string | null;\n readonly requestId: string;\n readonly scheduledFunctionId: string | null;\n readonly authToken: string | null;\n}\n\ntype UdfType = \"query\" | \"mutation\" | \"action\";\n\n/**\n * How a prepared attempt's function ended.\n */\nexport type Outcome =\n | { readonly _tag: \"returned\"; readonly value: Value }\n | { readonly _tag: \"failed\"; readonly error: unknown };\n\n/**\n * A mutation attempt run to its commit point and held until `apply`.\n */\nexport interface HeldAttempt {\n readonly id: string;\n readonly request: string;\n readonly number: Invocation.Attempt;\n readonly snapshot: Kernel.Version;\n readonly reads: ReadonlyArray<ReadSet.Read>;\n readonly outcome: Outcome;\n}\n\n/**\n * What `apply` did with a held attempt. A conflict discards the attempt and\n * holds exactly one next attempt, run against the latest commit. Nothing is\n * retried until that one is applied in turn.\n */\nexport type KernelApply =\n | {\n readonly kind: \"applied\";\n readonly version: Kernel.Version;\n readonly commitTs: bigint;\n readonly result: Value;\n }\n | { readonly kind: \"conflict\"; readonly next: HeldAttempt }\n | {\n readonly kind: \"exhausted\";\n readonly error: KernelRefusal.OptimisticConcurrencyControlFailure;\n }\n | { readonly kind: \"refused\"; readonly tag: string; readonly error: unknown };\n\ninterface Held {\n readonly view: HeldAttempt;\n readonly attempt: KernelAttempt;\n readonly again: (number: Invocation.Attempt) => Promise<Held>;\n}\n\nconst lastAttempt: Invocation.Attempt = 5;\n\nconst tagOf = (error: unknown): string => {\n const tagged = (value: unknown): value is { readonly _tag: string } =>\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { _tag?: unknown })._tag === \"string\";\n const data = (error as { data?: unknown } | null)?.data;\n if (tagged(data)) return data._tag;\n if (tagged(error)) return error._tag;\n return error instanceof Error ? error.name : \"Error\";\n};\n\n/**\n * One running function. Queries and mutations read and write through their\n * attempt. Every async syscall of a query or a mutation, nested calls included,\n * takes its turn on `turn` in the order the function made it.\n */\ninterface Execution {\n readonly world: World;\n readonly componentPath: string;\n readonly udfPath: string;\n readonly udfType: UdfType;\n readonly attempt: KernelAttempt | undefined;\n readonly identity: UserIdentity | null;\n readonly request: Request;\n readonly pagination: { calls: number } | undefined;\n readonly turn: Turn;\n}\n\n/**\n * A queue that runs one task at a time, in the order they were taken.\n */\nclass Turn {\n private tail: Promise<unknown> = Promise.resolve();\n\n take<A>(task: () => A | Promise<A>): Promise<A> {\n const result = this.tail.then(task);\n this.tail = result.then(\n () => undefined,\n () => undefined,\n );\n return result;\n }\n\n /**\n * Resolves once every task taken so far has settled, including the tasks\n * taken while waiting.\n */\n idle(): Promise<void> {\n const tail = this.tail;\n return tail.then(() => (this.tail === tail ? undefined : this.idle()));\n }\n}\n\n/**\n * A function's invocation finishes once its handler returned and every syscall\n * it started has run. On the binary a query or mutation keeps running the\n * syscalls in its queue after its promise resolves, then returns (`run_inner`\n * in `crates/isolate/src/environment/udf/mod.rs`, 1.49), so an unawaited write\n * still lands in its own transaction.\n */\nconst settled = <A>(execution: Execution, result: A): Promise<A> =>\n execution.turn.idle().then(() => result);\n\nconst executions = new AsyncLocalStorage<Execution>();\n\n/**\n * Run a function's code as `execution`, with its own copy of the globals a test\n * invocation pins.\n */\nconst enter = <A>(execution: Execution, run: () => A): A =>\n Globals.own(() => executions.run(execution, run));\nconst kernelBrand = Symbol.for(\"@confect/test/Kernel\");\n\nconst current = (): Execution => {\n const execution = executions.getStore();\n if (execution === undefined) {\n throw new Error(\n \"A Convex syscall ran outside any function the test kernel started.\",\n );\n }\n return execution;\n};\n\nlet nextRequestId = 0;\nconst newRequest = (caller: Caller): Request => ({\n ip: caller.ip,\n userAgent: caller.userAgent,\n requestId: `kernel-request-${nextRequestId++}`,\n scheduledFunctionId: null,\n authToken: caller.token,\n});\n\nconst findModulesRoot = (paths: ReadonlyArray<string>): string => {\n const generated = paths.find((path) => path.includes(\"_generated\"));\n if (generated === undefined) {\n throw new Error(\n 'Could not find the \"_generated\" directory, make sure to run ' +\n \"`npx convex dev` or `npx convex codegen`. Make sure your \" +\n '`import.meta.glob` includes the files in the \"_generated\" directory',\n );\n }\n return generated.split(\"_generated\", 2)[0]!;\n};\n\nconst makeComponent = (\n path: string,\n schema: SchemaDefinition<GenericSchema, boolean> | null | undefined,\n modules: Modules,\n): Component => {\n const root = findModulesRoot(Object.keys(modules));\n const relative = Object.entries(modules)\n .filter(([key]) => key.startsWith(root))\n .map(([key, load]) => [key.slice(root.length), load] as const);\n const nested = relative\n .map(([file]) => file)\n .filter((file) => file.endsWith(\"/convex.config.ts\"))\n .map((file) => file.slice(0, -\"convex.config.ts\".length));\n return {\n path,\n schema: KernelQuery.exportSchema(schema),\n loaders: new Map(\n relative\n .filter(\n ([file]) =>\n isFunctionModule(file) &&\n !nested.some((dir) => file.startsWith(dir)),\n )\n .map(([file, load]) => [file.replace(/\\.[^.]+$/, \"\"), load]),\n ),\n loaded: new Map(),\n };\n};\n\nconst entryExtensions = [\n \".js\",\n \".mjs\",\n \".cjs\",\n \".ts\",\n \".tsx\",\n \".mts\",\n \".cts\",\n \".jsx\",\n];\n\n/**\n * Whether Convex's bundler deploys this file as a function module, by the rule\n * `entryPoints` applies in `convex/src/bundler/index.ts` (1.49). A test file, a\n * schema, a config and `_generated` never reach the binary, so the kernel\n * neither loads them nor resolves a function in them.\n */\nconst isFunctionModule = (file: string): boolean => {\n const base = file.split(\"/\").pop()!;\n return (\n entryExtensions.some((extension) => file.endsWith(extension)) &&\n !file.startsWith(\"_generated/\") &&\n !base.startsWith(\".\") &&\n !base.startsWith(\"#\") &&\n base !== \"schema.ts\" &&\n base !== \"schema.js\" &&\n (base.match(/\\./g) ?? []).length <= 1 &&\n !file.includes(\" \")\n );\n};\n\nconst unregistered = (world: World, componentPath: string) => {\n const registered = [...world.components.keys()].filter((p) => p !== ROOT);\n return new Error(\n `Component \"${componentPath}\" is not registered on this test backend. ` +\n (registered.length === 0\n ? \"No components have been registered.\"\n : `Registered components: ${registered.map((p) => `\"${p}\"`).join(\", \")}.`),\n );\n};\n\ntype FunctionAddress = {\n readonly name?: string | undefined;\n readonly reference?: string | undefined;\n readonly functionHandle?: string | undefined;\n};\n\n/**\n * Where an address points, read from the calling component.\n */\nconst functionPathOf = (\n address: FunctionAddress,\n from: string,\n): FunctionPath => {\n if (address.functionHandle !== undefined) {\n return parseFunctionHandle(address.functionHandle) as FunctionPath;\n }\n if (address.name !== undefined) {\n return { udfPath: address.name, componentPath: from };\n }\n if (address.reference !== undefined) {\n // \"_reference/childComponent/<child>/path/to/file/fn\"\n const parts = address.reference.split(\"/\");\n const child = parts[2]!;\n const rest = parts.slice(3);\n return {\n componentPath: from.length > 0 ? `${from}/${child}` : child,\n udfPath: `${rest.slice(0, -1).join(\"/\")}:${rest[rest.length - 1]}`,\n };\n }\n throw new Error(\"Function address not supported\");\n};\n\nconst pathOfReference = (\n reference: FunctionReference<any, any, any, any> | string,\n from: string,\n) =>\n functionPathOf(getFunctionAddress(reference as any) as FunctionAddress, from);\n\ninterface Resolved {\n readonly func: any;\n readonly handler: (ctx: any, args: any) => any;\n readonly args: ValidatorJSON;\n readonly returns: ValidatorJSON | null;\n}\n\nconst kindCheck = {\n query: \"isQuery\",\n mutation: \"isMutation\",\n action: \"isAction\",\n} as const;\n\n/**\n * A test backend: its registered components and the kernel state they share.\n */\nexport class World {\n readonly components = new Map<string, Component>();\n state: Kernel.State = Kernel.empty;\n private opened: Promise<void> | undefined;\n private nextDocId = 10000;\n private lastCreationTime = 0;\n private nextQueryId = 1;\n private readonly queries = new Map<number, Iterator<any>>();\n private readonly holding = new Map<string, Held>();\n private nextAttemptId = 1;\n\n constructor(\n schema: SchemaDefinition<GenericSchema, boolean> | null | undefined,\n modules: Modules,\n private readonly runtime: Kernel.KernelRuntime = Kernel.wallClock(),\n ) {\n installConvexGlobal();\n this.components.set(ROOT, makeComponent(ROOT, schema, modules));\n }\n\n register(\n componentPath: string,\n schema: SchemaDefinition<GenericSchema, boolean>,\n modules: Modules,\n ) {\n if (this.opened !== undefined) {\n throw new KernelRefusal.RegisteredAfterOpen({\n componentPath,\n message: `Component \"${componentPath}\" was registered after the test backend opened. Register every component before the first call.`,\n });\n }\n this.components.set(\n componentPath,\n makeComponent(componentPath, schema, modules),\n );\n }\n\n /**\n * Load every registered module of every component, once, before any function\n * runs.\n */\n open(): Promise<void> {\n this.opened ??= Promise.all(\n Array.from(this.components.values(), (component) =>\n Promise.all(\n Array.from(component.loaders, ([path, load]) =>\n load().then((module) => component.loaded.set(path, module)),\n ),\n ),\n ),\n ).then(() => undefined);\n return this.opened;\n }\n\n private component(componentPath: string): Component {\n const component = this.components.get(componentPath);\n if (component === undefined) throw unregistered(this, componentPath);\n return component;\n }\n\n private resolve(functionPath: FunctionPath, kind: UdfType | \"any\"): Resolved {\n const [modulePath, maybeExport] = functionPath.udfPath.split(\":\") as [\n string,\n string | undefined,\n ];\n const exportName = maybeExport ?? \"default\";\n const component = this.component(functionPath.componentPath);\n const module = component.loaded.get(modulePath);\n if (module === undefined) {\n throw new Error(`Could not find module for: \"${modulePath}\"`);\n }\n const func = module[exportName];\n if (func === undefined) {\n throw new Error(\n `Expected a Convex function exported from module \"${modulePath}\" as \\`${exportName}\\`, but there is no such export.`,\n );\n }\n const handler = \"_handler\" in func ? func._handler : func;\n if (typeof handler !== \"function\") {\n throw new Error(\n `Expected a Convex function exported from module \"${modulePath}\" as \\`${exportName}\\`, but got: ${func}`,\n );\n }\n if (kind !== \"any\" && !func[kindCheck[kind]]) {\n throw new Error(\n `Expected a ${kind} function, but the function exported from module \"${modulePath}\" as \\`${exportName}\\` is not a ${kind}.`,\n );\n }\n const args = JSON.parse(func.exportArgs()) as ValidatorJSON;\n if (args.type !== \"object\" && args.type !== \"any\") {\n throw new Error(\n `Invalid JSON returned from ${modulePath}.js:${exportName}.exportArgs(): ` +\n `Args validator must be an object or any`,\n );\n }\n return { func, handler, args, returns: JSON.parse(func.exportReturns()) };\n }\n\n // Calls from the test.\n\n query(caller: Caller, reference: any, args: any): Promise<any> {\n return this.open().then(() => {\n const from = { caller, request: newRequest(caller) };\n return typeof reference === \"function\"\n ? this.runQuery(\n { componentPath: ROOT, udfPath: \"inline\" },\n { handler: reference, args: { type: \"any\" }, returns: null },\n args ?? {},\n from,\n )\n : this.queryAt(pathOfReference(reference, ROOT), args, from);\n });\n }\n\n mutation(caller: Caller, reference: any, args: any): Promise<any> {\n return this.open().then(() => {\n const from = { caller, request: newRequest(caller) };\n return typeof reference === \"function\"\n ? this.runMutation(\n { componentPath: ROOT, udfPath: \"inline\" },\n { handler: reference, args: { type: \"any\" }, returns: null },\n args ?? {},\n from,\n )\n : this.mutationAt(pathOfReference(reference, ROOT), args, from);\n });\n }\n\n action(caller: Caller, reference: any, args: any): Promise<any> {\n return this.open().then(() => {\n const from = { caller, request: newRequest(caller) };\n return typeof reference === \"function\"\n ? this.runAction(\n { componentPath: ROOT, udfPath: \"inline\" },\n { handler: reference, args: { type: \"any\" }, returns: null },\n args ?? {},\n from,\n )\n : this.actionAt(pathOfReference(reference, ROOT), args, from);\n });\n }\n\n run(\n caller: Caller,\n componentPath: string,\n handler: (ctx: any) => any,\n ): Promise<any> {\n return this.open().then(() => {\n this.component(componentPath);\n return this.runMutation(\n { componentPath, udfPath: \"custom\" },\n { handler, args: { type: \"any\" }, returns: null },\n {},\n { caller, request: newRequest(caller) },\n );\n });\n }\n\n // Held attempts.\n\n /**\n * Run a mutation to its commit point and hold it as attempt 1.\n */\n prepare(caller: Caller, reference: any, args: any): Promise<HeldAttempt> {\n return this.open().then(() => {\n const functionPath = pathOfReference(reference, ROOT);\n const resolved = this.resolve(functionPath, \"mutation\");\n validateFunctionArgs(resolved.args, args ?? {}, functionPath, false);\n return this.prepareMutation(\n functionPath,\n resolved,\n args,\n { caller, request: newRequest(caller) },\n 1,\n Invocation.current(),\n ).then((held) => held.view);\n });\n }\n\n apply(id: string): Promise<KernelApply> {\n const held = this.holding.get(id);\n return held === undefined\n ? Promise.reject(\n new KernelRefusal.StaleAttempt({\n id,\n message: `The test kernel holds no attempt \"${id}\". It was already applied, or never prepared.`,\n }),\n )\n : this.applyHeld(held);\n }\n\n /**\n * The held attempts, oldest first.\n */\n held(): ReadonlyArray<HeldAttempt> {\n return Array.from(this.holding.values(), (held) => held.view);\n }\n\n // Calls by address, from the test or from a running function.\n\n private queryAt(\n functionPath: FunctionPath,\n args: any,\n from: From,\n snapshotOnly = false,\n ) {\n const resolved = this.resolve(functionPath, \"query\");\n validateFunctionArgs(\n resolved.args,\n args ?? {},\n functionPath,\n from.parent?.attempt !== undefined,\n );\n return this.runQuery(functionPath, resolved, args, from, snapshotOnly);\n }\n\n private mutationAt(functionPath: FunctionPath, args: any, from: From) {\n const resolved = this.resolve(functionPath, \"mutation\");\n validateFunctionArgs(\n resolved.args,\n args ?? {},\n functionPath,\n from.parent?.attempt !== undefined,\n );\n return this.runMutation(functionPath, resolved, args, from);\n }\n\n private actionAt(functionPath: FunctionPath, args: any, from: From) {\n const resolved = this.resolve(functionPath, \"action\");\n validateFunctionArgs(resolved.args, args ?? {}, functionPath, false);\n return this.runAction(functionPath, resolved, args, from);\n }\n\n // Runners.\n\n private execution(\n functionPath: FunctionPath,\n udfType: UdfType,\n attempt: KernelAttempt | undefined,\n from: From,\n pagination: { calls: number } | undefined,\n ): Execution {\n // A function in a component runs with no identity, whoever called it, as\n // Convex gives a component no `ctx.auth` of the caller's. A nested call in\n // the host takes its parent's identity, even when that is none.\n const identity =\n functionPath.componentPath !== ROOT\n ? null\n : from.parent !== undefined\n ? from.parent.identity\n : from.caller.identity;\n return {\n world: this,\n componentPath: functionPath.componentPath,\n udfPath: functionPath.udfPath,\n udfType,\n attempt,\n identity,\n request: from.request,\n pagination,\n turn: new Turn(),\n };\n }\n\n private runQuery(\n functionPath: FunctionPath,\n resolved: Pick<Resolved, \"handler\" | \"args\" | \"returns\">,\n args: any,\n from: From,\n snapshotOnly = false,\n ): Promise<any> {\n const parentAttempt = from.parent?.attempt;\n const isNested = parentAttempt !== undefined;\n const attempt =\n parentAttempt === undefined\n ? new KernelAttempt(this.state)\n : snapshotOnly\n ? new KernelAttempt(parentAttempt.snapshot)\n : parentAttempt;\n const execution = this.execution(\n functionPath,\n \"query\",\n attempt,\n from,\n (isNested && from.parent?.pagination) || { calls: 0 },\n );\n const q = queryGeneric({\n handler: (ctx: any, a: any) =>\n resolved.handler({ ...ctx, auth: queryAuth(execution) }, a),\n }) as unknown as { invokeQuery: (args: string) => Promise<string> };\n return enter(execution, () =>\n q.invokeQuery(JSON.stringify(convexToJson([parseArgs(args)]))),\n )\n .then((raw) => settled(execution, raw))\n .then((raw) => {\n const result = jsonToConvex(JSON.parse(raw));\n if (!isNested && hasPendingValues(result)) {\n throw new Error(\n `Function ${functionPath.udfPath} return value invalid: queries ` +\n `cannot return an unresolved placeholder value.`,\n );\n }\n validateReturnValue(resolved.returns, result, \"query\", functionPath);\n return result;\n })\n .catch((error: unknown) => {\n throw deserializeConvexErrorData(error);\n });\n }\n\n private invokeMutation(\n execution: Execution,\n resolved: Pick<Resolved, \"handler\" | \"returns\">,\n args: any,\n ): Promise<Value> {\n const m = mutationGeneric({\n handler: (ctx: any, a: any) =>\n resolved.handler({ ...ctx, auth: mutationAuth(execution) }, a),\n }) as unknown as { invokeMutation: (args: string) => Promise<string> };\n return enter(execution, () =>\n m.invokeMutation(JSON.stringify(convexToJson([parseArgs(args)]))),\n )\n .then((raw) => settled(execution, raw))\n .then((raw) => {\n const result = jsonToConvex(JSON.parse(raw));\n validateReturnValue(resolved.returns, result, \"mutation\", {\n componentPath: execution.componentPath,\n udfPath: execution.udfPath,\n });\n return result;\n });\n }\n\n private runMutation(\n functionPath: FunctionPath,\n resolved: Pick<Resolved, \"handler\" | \"args\" | \"returns\">,\n args: any,\n from: From,\n ): Promise<any> {\n const parentAttempt = from.parent?.attempt;\n if (parentAttempt !== undefined) {\n const frame = parentAttempt.child();\n const execution = this.execution(\n functionPath,\n \"mutation\",\n frame,\n from,\n undefined,\n );\n // As at the top level, a nested mutation ends once its function has\n // returned and every syscall it started has settled. Convex runs a\n // nested function's syscall queue to the end before it commits its\n // subtransaction, so a detached fiber's late write lands in this frame\n // and merges with it. A failed one ends at once and rolls back.\n return this.invokeMutation(execution, resolved, args).then(\n (result) =>\n frame.drained().then(() => {\n frame.close();\n frame.merge();\n return result;\n }),\n (error: unknown) => {\n frame.close();\n throw deserializeConvexErrorData(error);\n },\n );\n }\n return this.prepareMutation(\n functionPath,\n resolved,\n args,\n from,\n 1,\n Invocation.current(),\n ).then((held) => this.publish(held));\n }\n\n /**\n * Run one attempt of a top-level mutation against the latest commit, then\n * hold it. The commit point is once the function has returned and every\n * syscall it started has settled. A test invocation bound when the mutation\n * was first called reaches each attempt's handler with that attempt's\n * number.\n */\n private prepareMutation(\n functionPath: FunctionPath,\n resolved: Pick<Resolved, \"handler\" | \"returns\">,\n args: any,\n from: From,\n number: Invocation.Attempt,\n bound: Invocation.Invocation | undefined,\n ): Promise<Held> {\n const attempt = new KernelAttempt(this.state, number);\n const execution = this.execution(\n functionPath,\n \"mutation\",\n attempt,\n from,\n undefined,\n );\n const run = () => this.invokeMutation(execution, resolved, args);\n const started =\n bound === undefined\n ? run()\n : Invocation.bind({ ...bound, attempt: number }, run);\n return started\n .then(\n (value) =>\n attempt.drained().then((): Outcome => ({ _tag: \"returned\", value })),\n (error: unknown): Outcome => ({\n _tag: \"failed\",\n error: deserializeConvexErrorData(error),\n }),\n )\n .then((outcome) => {\n attempt.close();\n const held: Held = {\n view: {\n id: `attempt-${this.nextAttemptId++}`,\n request: from.request.requestId,\n number,\n snapshot: attempt.snapshot.version,\n reads: attempt.reads,\n outcome,\n },\n attempt,\n again: (next) =>\n this.prepareMutation(\n functionPath,\n resolved,\n args,\n from,\n next,\n bound,\n ),\n };\n this.holding.set(held.view.id, held);\n return held;\n });\n }\n\n /**\n * Validate a held attempt's reads against every commit since its snapshot,\n * then publish its writes or prepare its next attempt. An attempt that wrote\n * nothing publishes nothing and has nothing to validate. It answers its\n * snapshot's version and commit timestamp.\n */\n private applyHeld({ view, attempt, again }: Held): Promise<KernelApply> {\n this.holding.delete(view.id);\n const { outcome } = view;\n if (outcome._tag === \"failed\") {\n return Promise.resolve({\n kind: \"refused\",\n tag: tagOf(outcome.error),\n error: outcome.error,\n });\n }\n const writes = attempt.writes();\n if (writes.length === 0) {\n // As on the binary, a mutation that wrote nothing is serialized at its\n // snapshot and allocates no timestamp for a later commit.\n const { version, commitTs } = attempt.snapshot;\n return Promise.resolve({\n kind: \"applied\",\n version,\n commitTs,\n result: resolveCommittedValues(outcome.value, commitTs),\n });\n }\n if (\n Kernel.conflict(this.state, view.snapshot, attempt.reads) !== undefined\n ) {\n if (view.number === lastAttempt) {\n return Promise.resolve({\n kind: \"exhausted\",\n error: new KernelRefusal.OptimisticConcurrencyControlFailure({\n attempts: lastAttempt,\n message: `Documents read by the mutation changed before each of its ${lastAttempt} attempts could commit.`,\n }),\n });\n }\n return again((view.number + 1) as Invocation.Attempt).then(\n (next): KernelApply => ({ kind: \"conflict\", next: next.view }),\n );\n }\n const commitTs = this.runtime.commitTs(this.state.version + 1);\n if (commitTs <= this.state.commitTs) {\n return Promise.reject(\n new KernelRefusal.CommitTsNotIncreasing({\n version: this.state.version + 1,\n previous: this.state.commitTs,\n commitTs,\n message: `The runtime answered commit timestamp ${commitTs} for version ${this.state.version + 1}, which is not greater than the previous commit's ${this.state.commitTs}.`,\n }),\n );\n }\n this.state = Kernel.apply(this.state, writes, commitTs);\n return Promise.resolve({\n kind: \"applied\",\n version: this.state.version,\n commitTs,\n result: resolveCommittedValues(outcome.value, commitTs),\n });\n }\n\n /**\n * Apply until the mutation publishes, is refused or is exhausted, as the\n * binary retries a mutation that conflicts.\n */\n private publish(held: Held): Promise<Value> {\n return this.applyHeld(held).then((applied) => {\n if (applied.kind === \"applied\") return applied.result;\n if (applied.kind === \"conflict\") {\n return this.publish(this.holding.get(applied.next.id)!);\n }\n throw applied.error;\n });\n }\n\n private runAction(\n functionPath: FunctionPath,\n resolved: Pick<Resolved, \"handler\" | \"args\" | \"returns\">,\n args: any,\n from: From,\n ): Promise<any> {\n const execution = this.execution(\n functionPath,\n \"action\",\n undefined,\n from,\n undefined,\n );\n const inner: From = { request: from.request, parent: execution };\n const a = actionGeneric({\n handler: (ctx: any, innerArgs: any) =>\n resolved.handler(\n {\n ...ctx,\n runQuery: (reference: any, queryArgs: any) =>\n this.queryAt(\n pathOfReference(reference, functionPath.componentPath),\n queryArgs,\n inner,\n ),\n runMutation: (reference: any, mutationArgs: any) =>\n this.mutationAt(\n pathOfReference(reference, functionPath.componentPath),\n mutationArgs,\n inner,\n ),\n runAction: (reference: any, actionArgs: any) =>\n this.actionAt(\n pathOfReference(reference, functionPath.componentPath),\n actionArgs,\n inner,\n ),\n auth: queryAuth(execution),\n },\n innerArgs,\n ),\n }) as unknown as {\n invokeAction: (requestId: string, args: string) => Promise<string>;\n };\n const run = () =>\n enter(execution, () =>\n a.invokeAction(\n from.request.requestId,\n JSON.stringify(convexToJson([parseArgs(args)])),\n ),\n );\n // An action another function calls is an invocation of its own, with its\n // world's services, a start time read from its world's clock and its\n // world's random stream, as a scheduled job is.\n const bound = from.parent === undefined ? undefined : Invocation.current();\n const { ip, userAgent, requestId, scheduledFunctionId } = from.request;\n const started =\n bound === undefined\n ? run()\n : Invocation.bind(\n {\n world: bound.world,\n componentPath: functionPath.componentPath,\n attempt: 1,\n request: { ip, userAgent, requestId, scheduledFunctionId },\n services: bound.world.services,\n startedAt: bound.world.clock(),\n random: bound.world.random,\n },\n run,\n );\n return started\n .then((raw) => {\n const result = jsonToConvex(JSON.parse(raw));\n validateReturnValue(resolved.returns, result, \"action\", functionPath);\n return result;\n })\n .catch((error: unknown) => {\n throw deserializeConvexErrorData(error);\n });\n }\n\n // Syscalls.\n\n private schema(componentPath: string) {\n return this.component(componentPath).schema;\n }\n\n private view(execution: Execution): KernelQuery.TableView {\n const attempt = transaction(execution);\n return {\n schema: this.schema(execution.componentPath),\n scan: (tableName) => attempt.scan(execution.componentPath, tableName),\n read: (interval, after) =>\n attempt.readInterval({\n ...interval,\n componentPath: execution.componentPath,\n after,\n }),\n };\n }\n\n private generateId(table: string): DocumentId {\n const counter = String(this.nextDocId++).padStart(\n TYPICAL_CONVEX_ID_LENGTH - table.length,\n \"0\",\n );\n return (counter + table) as DocumentId;\n }\n\n syscall(op: string, jsonArgs: string): string {\n const args = JSON.parse(jsonArgs);\n const execution = current();\n if (execution.attempt?.closed === true) throw closed(execution, op);\n switch (op) {\n case \"1.0/getSnapshotTs\":\n return JSON.stringify(\n convexToJson(transaction(execution).snapshot.commitTs),\n );\n case \"1.0/queryStream\": {\n // The binary reads a query at each `1.0/queryStreamNext`, which waits\n // its turn in the queue, so the stream opens at its first read and sees\n // every write made before it.\n const queryId = this.nextQueryId++;\n const view = this.view(execution);\n let results: Iterator<any> | undefined;\n this.queries.set(queryId, {\n next: () => (results ??= KernelQuery.stream(view, args.query)).next(),\n });\n return JSON.stringify({ queryId });\n }\n case \"1.0/queryCleanup\":\n this.queries.delete(args.queryId);\n return JSON.stringify({});\n case \"1.0/db/normalizeId\": {\n const tableName = tableNameFromId(args.idString);\n return JSON.stringify({\n id: tableName === args.table ? args.idString : null,\n });\n }\n default:\n throw new Error(`The test kernel does not support syscall: \"${op}\"`);\n }\n }\n\n /**\n * The binary queues a query's or mutation's async syscalls and runs them one\n * at a time, oldest first (`start_async_syscall` and `run_inner` in\n * `crates/isolate/src/environment/udf/mod.rs`, 1.49). A write and a nested\n * call never share a batch (`AsyncSyscallBatch::can_push` in\n * `async_syscall.rs`), and a nested call holds the queue until it has\n * committed or rolled back its subtransaction (`run_udf` in\n * `async_syscall.rs`). So a caller's write made after its nested call runs\n * after that call, and a nested mutation sees every write made before it. An\n * action's calls run side by side.\n */\n asyncSyscall(op: string, jsonArgs: string): Promise<string> {\n const execution = current();\n const attempt = execution.attempt;\n if (attempt === undefined) {\n return Promise.resolve().then(() =>\n this.dispatchAsync(op, JSON.parse(jsonArgs), execution),\n );\n }\n if (attempt.closed) return Promise.reject(closed(execution, op));\n // A syscall counts toward its frame's lifetime from the moment it is\n // queued, so a frame never closes with a write still waiting its turn.\n const end = attempt.begin();\n return execution.turn\n .take(() => this.dispatchAsync(op, JSON.parse(jsonArgs), execution))\n .finally(end);\n }\n\n private dispatchAsync(\n op: string,\n args: any,\n execution: Execution,\n ): string | Promise<string> {\n switch (op) {\n case \"1.0/get\": {\n const { table, id } = args;\n return JSON.stringify(convexToJson(this.get(execution, table, id)));\n }\n case \"1.0/queryStreamNext\": {\n const results = this.queries.get(args.queryId);\n if (results === undefined) throw new Error(\"Bad queryId\");\n const { value, done } = results.next();\n return JSON.stringify(\n convexToJson(\n done ? { value: null, done: true } : { value, done: false },\n ),\n );\n }\n case \"1.0/queryPage\": {\n const pagination = execution.pagination;\n if (pagination) {\n pagination.calls += 1;\n if (pagination.calls > 1) {\n throw new Error(\n \"Only a single paginated query (`.paginate()`) is allowed per \" +\n \"query, including nested query calls and component calls. \" +\n \"This is a Convex limit: https://docs.convex.dev/database/pagination\",\n );\n }\n }\n return JSON.stringify(\n convexToJson(KernelQuery.paginate(this.view(execution), args) as any),\n );\n }\n case \"1.0/insert\":\n return JSON.stringify({\n _id: this.insert(execution, args.table, jsonToConvex(args.value)),\n });\n case \"1.0/shallowMerge\":\n this.patch(execution, args.table, args.id, args.value);\n return JSON.stringify({});\n case \"1.0/replace\":\n this.replace(execution, args.table, args.id, args.value);\n return JSON.stringify({});\n case \"1.0/remove\":\n this.remove(execution, args.table, args.id);\n return JSON.stringify({});\n case \"1.0/count\": {\n const attempt = transaction(execution);\n attempt.readInterval({\n kind: \"interval\",\n componentPath: execution.componentPath,\n table: args.table,\n fields: [\"_creationTime\", \"_id\"],\n order: \"asc\",\n range: [],\n after: null,\n })(\"end\");\n return JSON.stringify(\n attempt.scan(execution.componentPath, args.table).length,\n );\n }\n case \"1.0/getFunctionMetadata\":\n return JSON.stringify(\n convexToJson({\n name: execution.udfPath,\n componentPath: execution.componentPath,\n }),\n );\n case \"1.0/getRequestMetadata\":\n if (execution.udfType === \"query\") {\n throw new Error(\n \"getRequestMetadata() can only be called from a mutation, action \" +\n \"or HTTP action. It is not available in queries.\",\n );\n }\n return JSON.stringify(convexToJson(execution.request as any));\n case \"1.0/getDeploymentMetadata\":\n return JSON.stringify(\n convexToJson({ name: \"test\", region: null, class: \"s16\" }),\n );\n case \"1.0/actions/query\":\n case \"1.0/actions/mutation\":\n case \"1.0/actions/action\": {\n const from: From = { request: execution.request, parent: execution };\n const functionPath = functionPathOf(args, execution.componentPath);\n const run =\n op === \"1.0/actions/query\"\n ? this.queryAt(functionPath, args.args, from)\n : op === \"1.0/actions/mutation\"\n ? this.mutationAt(functionPath, args.args, from)\n : this.actionAt(functionPath, args.args, from);\n return run.then((value) => JSON.stringify(convexToJson(value)));\n }\n case \"1.0/runUdf\": {\n const { udfType, args: udfArgs } = args;\n const from: From = { request: execution.request, parent: execution };\n const functionPath = functionPathOf(args, execution.componentPath);\n const value = jsonToConvex(udfArgs);\n const run =\n udfType === \"query\"\n ? this.queryAt(functionPath, value, from)\n : udfType === \"snapshotQuery\"\n ? this.queryAt(functionPath, value, from, true)\n : udfType === \"mutation\"\n ? this.mutationAt(functionPath, value, from)\n : Promise.reject(\n new Error(\n `The test kernel does not support udf type: \"${udfType}\"`,\n ),\n );\n return run.then((result) => JSON.stringify(convexToJson(result)));\n }\n case \"1.0/createFunctionHandle\": {\n const functionPath = functionPathOf(args, execution.componentPath);\n this.component(functionPath.componentPath);\n return JSON.stringify(createFunctionHandle(functionPath));\n }\n case \"1.0/auditLog\":\n return JSON.stringify(null);\n case \"1.0/schedule\":\n case \"1.0/actions/schedule\":\n case \"1.0/cancel_job\":\n case \"1.0/actions/cancel_job\":\n throw KernelRefusal.rowPending(\"the scheduler\", 5);\n case \"1.0/storageDelete\":\n case \"1.0/storageGetUrl\":\n case \"1.0/storageGenerateUploadUrl\":\n throw KernelRefusal.rowPending(\"storage\", 6);\n case \"1.0/getTransactionMetrics\":\n throw KernelRefusal.rowPending(\"transaction limits\", 6);\n case \"1.0/actions/vectorSearch\":\n throw KernelRefusal.requiresBinary(\"vectorSearch\");\n default:\n throw new Error(\n `The test kernel does not support async syscall: \"${op}\"`,\n );\n }\n }\n\n jsSyscall(op: string): Promise<never> {\n return Promise.reject(\n op.startsWith(\"storage/\")\n ? KernelRefusal.rowPending(\"storage\", 6)\n : new Error(`The test kernel does not support js syscall: \"${op}\"`),\n );\n }\n\n // Documents. The checks and messages are convex-test's.\n\n private get(execution: Execution, tableName: unknown, id: unknown) {\n validateId(tableName, id);\n const attempt = transaction(execution);\n attempt.readDocument(execution.componentPath, id);\n return attempt.get(execution.componentPath, id);\n }\n\n private insert(execution: Execution, table: string, value: any): DocumentId {\n const attempt = transaction(execution);\n KernelQuery.validateDocument(\n this.schema(execution.componentPath),\n table,\n value,\n );\n const _id = this.generateId(table);\n const now = this.runtime.now();\n const _creationTime =\n now <= this.lastCreationTime ? this.lastCreationTime + 0.001 : now;\n this.lastCreationTime = _creationTime;\n attempt.write(execution.componentPath, _id, {\n ...value,\n _id,\n _creationTime,\n });\n return _id;\n }\n\n private existing(\n execution: Execution,\n tableName: unknown,\n id: unknown,\n write: string,\n value: unknown,\n ): StoredDocument {\n validateId(tableName, id);\n if (value !== undefined && typeof value !== \"object\") {\n throw new Error(\n `Invalid argument \\`value\\` in \\`db.${write}\\`, expected object but got '${typeof value}': ${value as any}`,\n );\n }\n const attempt = transaction(execution);\n attempt.readDocument(execution.componentPath, id);\n const document = attempt.get(execution.componentPath, id);\n if (document === null) {\n throw new Error(\n write === \"delete\"\n ? \"Delete on non-existent doc\"\n : `${write === \"patch\" ? \"Patch\" : \"Replace\"} on non-existent document with ID \"${id}\"`,\n );\n }\n return document;\n }\n\n private fields(document: StoredDocument, value: Record<string, any>) {\n if (value._id !== undefined && value._id !== document._id) {\n throw new Error(\n `Provided \\`_id\\` field value \"${value._id}\" ` +\n `does not match the document ID \"${document._id}\"`,\n );\n }\n if (\n value._creationTime !== undefined &&\n value._creationTime !== document._creationTime\n ) {\n throw new Error(\n `Provided \\`_creationTime\\` field value ${value._creationTime} ` +\n `does not match the document's creation time ${document._creationTime}`,\n );\n }\n const convexValue: Record<string, Value | undefined> = {};\n for (const [key, v] of Object.entries(value)) {\n if (key !== \"_id\" && key !== \"_creationTime\") {\n convexValue[key] = evaluateValue(v);\n }\n }\n return convexValue;\n }\n\n private patch(\n execution: Execution,\n tableName: unknown,\n id: unknown,\n value: Record<string, any>,\n ) {\n const document = this.existing(execution, tableName, id, \"patch\", value);\n const { _id, _creationTime, ...fields } = document;\n const merged = { ...fields, ...this.fields(document, value) };\n KernelQuery.validateDocument(\n this.schema(execution.componentPath),\n tableNameFromId(_id)!,\n merged,\n );\n transaction(execution).write(execution.componentPath, _id, {\n _id,\n _creationTime,\n ...merged,\n } as StoredDocument);\n }\n\n private replace(\n execution: Execution,\n tableName: unknown,\n id: unknown,\n value: Record<string, any>,\n ) {\n const document = this.existing(execution, tableName, id, \"replace\", value);\n const fields = this.fields(document, value);\n KernelQuery.validateDocument(\n this.schema(execution.componentPath),\n tableNameFromId(document._id)!,\n fields,\n );\n transaction(execution).write(execution.componentPath, document._id, {\n ...fields,\n _id: document._id,\n _creationTime: document._creationTime,\n } as StoredDocument);\n }\n\n private remove(execution: Execution, tableName: unknown, id: unknown) {\n const document = this.existing(\n execution,\n tableName,\n id,\n \"delete\",\n undefined,\n );\n transaction(execution).write(execution.componentPath, document._id, null);\n }\n}\n\n/**\n * Where a call comes from. A call from the test carries its accessor's caller.\n * A nested call carries its parent execution and takes its identity from it.\n */\ntype From =\n | {\n readonly caller: Caller;\n readonly request: Request;\n readonly parent?: undefined;\n }\n | { readonly parent: Execution; readonly request: Request };\n\nconst closed = (execution: Execution, operation: string) =>\n new KernelRefusal.ClosedAttempt({\n operation,\n message: `\"${operation}\" reached mutation ${execution.udfPath} after it returned and its syscalls settled. Await every read and write inside the handler.`,\n });\n\nconst transaction = (execution: Execution): KernelAttempt => {\n if (execution.attempt === undefined) {\n throw new Error(\n \"The database is only available in queries and mutations. An action reads and writes through `ctx.runQuery` and `ctx.runMutation`.\",\n );\n }\n return execution.attempt;\n};\n\nconst queryAuth = (execution: Execution) => ({\n getUserIdentity: () => Promise.resolve(execution.identity),\n});\n\nconst mutationAuth = (execution: Execution) => ({\n ...queryAuth(execution),\n signJwt: () => Promise.reject(KernelRefusal.rowPending(\"JWT signing\", 6)),\n});\n\nfunction validateId(\n expectedTableName: unknown,\n id: unknown,\n): asserts id is DocumentId {\n if (typeof id !== \"string\") {\n throw new Error(\n `Invalid argument \\`id\\`, expected string but got '${typeof id}': ${id as any}`,\n );\n }\n if (expectedTableName === undefined) return;\n if (typeof expectedTableName !== \"string\") {\n throw new Error(\n `Invalid argument \\`tableName\\`, expected string but got '${typeof expectedTableName}': ${expectedTableName as any}`,\n );\n }\n const actualTableName = tableNameFromId(id);\n if (actualTableName === null) {\n throw new Error(\n `Invalid argument \\`id\\`, expected ID value but got '${id}'`,\n );\n }\n if (actualTableName !== expectedTableName) {\n throw new Error(\n `Invalid argument \\`id\\`, expected ID in table '${expectedTableName}' but got ID in table '${actualTableName}'`,\n );\n }\n}\n\n/**\n * Convex's server library reaches the backend through `globalThis.Convex`. The\n * kernel answers each syscall for the function that made it.\n */\nconst installConvexGlobal = () => {\n const global = globalThis as { Convex?: { [kernelBrand]?: true } };\n if (global.Convex?.[kernelBrand] === true) return;\n global.Convex = {\n [kernelBrand]: true,\n syscall: (op: string, args: string) => current().world.syscall(op, args),\n asyncSyscall: (op: string, args: string) =>\n current().world.asyncSyscall(op, args),\n jsSyscall: (op: string) => current().world.jsSyscall(op),\n } as any;\n};\n\n/**\n * Whether `globalThis.Convex` is the kernel's, so no other backend answered.\n */\nexport const ownsConvexGlobal = (): boolean =>\n (globalThis as { Convex?: { [kernelBrand]?: true } }).Convex?.[\n kernelBrand\n ] === true;\n"],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Run `call` with a fresh copy of the globals. It starts from the test
3
+ * environment's, whatever the caller assigned in its own copy.
4
+ */
5
+ export declare const own: <A>(call: () => A) => A;
6
+ /**
7
+ * Read `read` against the test environment's globals, never a function call's
8
+ * copy, as the kernel's own clock must.
9
+ */
10
+ export declare const host: <A>(read: () => A) => A;
11
+ //# sourceMappingURL=Globals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Globals.d.ts","sourceRoot":"","sources":["../../src/internal/Globals.ts"],"names":[],"mappings":"AA8EA;;;GAGG;AACH,eAAO,MAAM,GAAG,GAAI,CAAC,QAAQ,MAAM,CAAC,KAAG,CAItC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,IAAI,GAAI,CAAC,QAAQ,MAAM,CAAC,KAAG,CAA8B,CAAC"}
@@ -0,0 +1,76 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ //#region src/internal/Globals.ts
3
+ /**
4
+ * Convex gives every function execution its own globals. The kernel gives each
5
+ * function call it starts its own copy of the globals a test invocation pins,
6
+ * as convex-test 0.0.65 does for every handler (its `dist/index.js:1744`,
7
+ * `:1883-1905` and `:1927-1930`). An assignment inside the call lands in its
8
+ * copy only, so the invocation bridge's pins stay with the handler that made
9
+ * them, and overlapping or nested calls keep their own.
10
+ */
11
+ const names = [
12
+ "Date",
13
+ "Math",
14
+ "crypto"
15
+ ];
16
+ const key = Symbol.for("@confect/test/Globals");
17
+ const state = () => globalThis[key] ??= {
18
+ copies: new AsyncLocalStorage(),
19
+ getters: /* @__PURE__ */ new WeakSet()
20
+ };
21
+ /**
22
+ * Point each global at the calling function's copy, falling back to the
23
+ * global's own value outside one. A test that redefines a global, as
24
+ * `vi.stubGlobal` does, removes the accessor, so every call installs it again
25
+ * over what the test left.
26
+ */
27
+ const install = ({ copies, getters }) => {
28
+ const global = globalThis;
29
+ for (const name of names) {
30
+ const own = Object.getOwnPropertyDescriptor(global, name);
31
+ if (own?.get !== void 0 && getters.has(own.get)) continue;
32
+ const base = own ?? {
33
+ value: void 0,
34
+ writable: true
35
+ };
36
+ const get = () => {
37
+ const copy = copies.getStore();
38
+ if (copy !== void 0 && name in copy) return copy[name];
39
+ return "value" in base ? base.value : base.get?.call(global);
40
+ };
41
+ const set = (value) => {
42
+ const copy = copies.getStore();
43
+ if (copy !== void 0) copy[name] = value;
44
+ else if ("value" in base && base.writable === true) base.value = value;
45
+ else if (base.set !== void 0) base.set.call(global, value);
46
+ else throw new TypeError(`Cannot assign to read only global '${name}'`);
47
+ };
48
+ try {
49
+ Object.defineProperty(global, name, {
50
+ get,
51
+ set,
52
+ configurable: true,
53
+ enumerable: own?.enumerable ?? false
54
+ });
55
+ getters.add(get);
56
+ } catch {}
57
+ }
58
+ };
59
+ /**
60
+ * Run `call` with a fresh copy of the globals. It starts from the test
61
+ * environment's, whatever the caller assigned in its own copy.
62
+ */
63
+ const own = (call) => {
64
+ const current = state();
65
+ install(current);
66
+ return current.copies.run({}, call);
67
+ };
68
+ /**
69
+ * Read `read` against the test environment's globals, never a function call's
70
+ * copy, as the kernel's own clock must.
71
+ */
72
+ const host = (read) => state().copies.exit(read);
73
+ //#endregion
74
+ export { host, own };
75
+
76
+ //# sourceMappingURL=Globals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Globals.js","names":[],"sources":["../../src/internal/Globals.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\n\n/**\n * Convex gives every function execution its own globals. The kernel gives each\n * function call it starts its own copy of the globals a test invocation pins,\n * as convex-test 0.0.65 does for every handler (its `dist/index.js:1744`,\n * `:1883-1905` and `:1927-1930`). An assignment inside the call lands in its\n * copy only, so the invocation bridge's pins stay with the handler that made\n * them, and overlapping or nested calls keep their own.\n */\n\nconst names = [\"Date\", \"Math\", \"crypto\"] as const;\n\ntype Name = (typeof names)[number];\n\ntype Copies = { [name in Name]?: unknown };\n\ninterface State {\n readonly copies: AsyncLocalStorage<Copies>;\n /**\n * The getters this module installed, so a later install skips them.\n */\n readonly getters: WeakSet<() => unknown>;\n}\n\nconst key = Symbol.for(\"@confect/test/Globals\");\n\n// One store per test runtime, so every copy of this module reads the same\n// copies.\nconst state = (): State =>\n ((globalThis as { [key]?: State })[key] ??= {\n copies: new AsyncLocalStorage(),\n getters: new WeakSet(),\n });\n\n/**\n * Point each global at the calling function's copy, falling back to the\n * global's own value outside one. A test that redefines a global, as\n * `vi.stubGlobal` does, removes the accessor, so every call installs it again\n * over what the test left.\n */\nconst install = ({ copies, getters }: State) => {\n const global = globalThis as unknown as Record<Name, unknown>;\n for (const name of names) {\n const own = Object.getOwnPropertyDescriptor(global, name);\n // oxlint-disable-next-line typescript/unbound-method -- Compared by identity, never called.\n if (own?.get !== undefined && getters.has(own.get)) continue;\n const base: PropertyDescriptor = own ?? {\n value: undefined,\n writable: true,\n };\n const get = () => {\n const copy = copies.getStore();\n if (copy !== undefined && name in copy) return copy[name];\n return \"value\" in base ? base.value : base.get?.call(global);\n };\n const set = (value: unknown) => {\n const copy = copies.getStore();\n if (copy !== undefined) copy[name] = value;\n else if (\"value\" in base && base.writable === true) base.value = value;\n else if (base.set !== undefined) base.set.call(global, value);\n else throw new TypeError(`Cannot assign to read only global '${name}'`);\n };\n try {\n Object.defineProperty(global, name, {\n get,\n set,\n configurable: true,\n enumerable: own?.enumerable ?? false,\n });\n getters.add(get);\n } catch {\n // A global that cannot be redefined keeps no copy, and the bridge\n // refuses to pin it.\n }\n }\n};\n\n/**\n * Run `call` with a fresh copy of the globals. It starts from the test\n * environment's, whatever the caller assigned in its own copy.\n */\nexport const own = <A>(call: () => A): A => {\n const current = state();\n install(current);\n return current.copies.run({}, call);\n};\n\n/**\n * Read `read` against the test environment's globals, never a function call's\n * copy, as the kernel's own clock must.\n */\nexport const host = <A>(read: () => A): A => state().copies.exit(read);\n"],"mappings":";;;;;;;;;;AAWA,MAAM,QAAQ;CAAC;CAAQ;CAAQ;AAAQ;AAcvC,MAAM,MAAM,OAAO,IAAI,uBAAuB;AAI9C,MAAM,cACH,WAAkC,SAAS;CAC1C,QAAQ,IAAI,kBAAkB;CAC9B,yBAAS,IAAI,QAAQ;AACvB;;;;;;;AAQF,MAAM,WAAW,EAAE,QAAQ,cAAqB;CAC9C,MAAM,SAAS;CACf,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,MAAM,OAAO,yBAAyB,QAAQ,IAAI;EAExD,IAAI,KAAK,QAAQ,KAAA,KAAa,QAAQ,IAAI,IAAI,GAAG,GAAG;EACpD,MAAM,OAA2B,OAAO;GACtC,OAAO,KAAA;GACP,UAAU;EACZ;EACA,MAAM,YAAY;GAChB,MAAM,OAAO,OAAO,SAAS;GAC7B,IAAI,SAAS,KAAA,KAAa,QAAQ,MAAM,OAAO,KAAK;GACpD,OAAO,WAAW,OAAO,KAAK,QAAQ,KAAK,KAAK,KAAK,MAAM;EAC7D;EACA,MAAM,OAAO,UAAmB;GAC9B,MAAM,OAAO,OAAO,SAAS;GAC7B,IAAI,SAAS,KAAA,GAAW,KAAK,QAAQ;QAChC,IAAI,WAAW,QAAQ,KAAK,aAAa,MAAM,KAAK,QAAQ;QAC5D,IAAI,KAAK,QAAQ,KAAA,GAAW,KAAK,IAAI,KAAK,QAAQ,KAAK;QACvD,MAAM,IAAI,UAAU,sCAAsC,KAAK,EAAE;EACxE;EACA,IAAI;GACF,OAAO,eAAe,QAAQ,MAAM;IAClC;IACA;IACA,cAAc;IACd,YAAY,KAAK,cAAc;GACjC,CAAC;GACD,QAAQ,IAAI,GAAG;EACjB,QAAQ,CAGR;CACF;AACF;;;;;AAMA,MAAa,OAAU,SAAqB;CAC1C,MAAM,UAAU,MAAM;CACtB,QAAQ,OAAO;CACf,OAAO,QAAQ,OAAO,IAAI,CAAC,GAAG,IAAI;AACpC;;;;;AAMA,MAAa,QAAW,SAAqB,MAAM,CAAC,CAAC,OAAO,KAAK,IAAI"}
@@ -0,0 +1,57 @@
1
+ import type { RequestMetadata } from "convex/server";
2
+ import type * as Context from "effect/Context";
3
+ /**
4
+ * Four re-executions after the first try. A conflict on attempt 5 exhausts.
5
+ */
6
+ export type Attempt = 1 | 2 | 3 | 4 | 5;
7
+ /**
8
+ * One test backend. Its `services`, `clock` and `random` reach every invocation
9
+ * it starts on its own, such as a scheduled job.
10
+ */
11
+ export interface World {
12
+ readonly name: string;
13
+ readonly services: Context.Context<never>;
14
+ /**
15
+ * The world's controlled clock in epoch milliseconds. An invocation the world
16
+ * starts on its own pins its start time from one reading. A bound action's
17
+ * `Date` reads it live.
18
+ */
19
+ readonly clock: () => number;
20
+ /**
21
+ * The random stream, uniform on [0, 1), that an invocation the world starts
22
+ * on its own draws from.
23
+ */
24
+ readonly random: () => number;
25
+ }
26
+ export interface Invocation {
27
+ readonly world: World;
28
+ readonly componentPath: string;
29
+ readonly attempt: Attempt;
30
+ readonly request: Omit<RequestMetadata, "authToken">;
31
+ readonly services: Context.Context<never>;
32
+ /**
33
+ * The start time in epoch milliseconds. Every query or mutation of the
34
+ * invocation reads it from `Date.now()` and `new Date()`, so Effect's default
35
+ * `Clock` reads it too. An action reads its world's clock instead, as it
36
+ * runs, and a query or mutation an action calls starts at the action's time
37
+ * then.
38
+ */
39
+ readonly startedAt: number;
40
+ /**
41
+ * The random stream, uniform on [0, 1). Every handler of the invocation draws
42
+ * from it through `Math.random` and `crypto.getRandomValues`, so Effect's
43
+ * default `Random` draws from it too.
44
+ */
45
+ readonly random: () => number;
46
+ }
47
+ /**
48
+ * Run `start` with `invocation` bound. Every registered handler it reaches
49
+ * through convex-test runs with the invocation's services, clock and random
50
+ * stream.
51
+ */
52
+ export declare const bind: <A>(invocation: Invocation, start: () => Promise<A>) => Promise<A>;
53
+ /**
54
+ * The invocation the calling handler runs under, if one is bound.
55
+ */
56
+ export declare const current: () => Invocation | undefined;
57
+ //# sourceMappingURL=Invocation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Invocation.d.ts","sourceRoot":"","sources":["../../src/internal/Invocation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAoB,eAAe,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,KAAK,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAE/C;;GAEG;AACH,MAAM,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAExC;;;GAGG;AACH,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC1C;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,MAAM,CAAC;IAC7B;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,WAAW,CAAC,CAAC;IACrD,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC1C;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,MAAM,CAAC;CAC/B;AA+ND;;;;GAIG;AACH,eAAO,MAAM,IAAI,GAAI,CAAC,cACR,UAAU,SACf,MAAM,OAAO,CAAC,CAAC,CAAC,KACtB,OAAO,CAAC,CAAC,CAIT,CAAC;AAEJ;;GAEG;AACH,eAAO,MAAM,OAAO,QAAO,UAAU,GAAG,SACQ,CAAC"}
@@ -0,0 +1,145 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ //#region src/internal/Invocation.ts
3
+ const key = Symbol.for("@confect/test/Invocation");
4
+ /**
5
+ * The invocation a function of `functionType` called from `running` joins. A
6
+ * query or mutation an action calls is a transaction of its own, so it starts
7
+ * at the world's time when it begins. Any other call shares its caller's
8
+ * start.
9
+ */
10
+ const caller = (running, functionType) => running.functionType === "action" && functionType !== "action" ? {
11
+ ...running.invocation,
12
+ startedAt: running.invocation.world.clock()
13
+ } : running.invocation;
14
+ /**
15
+ * The invocation a handler runs under. A call nested in the bound request joins
16
+ * it at the callee's component path. A job Convex started from a timer set
17
+ * inside the bound request is a request of its own: its scheduled function ID
18
+ * differs, so it gets a fresh record with the world's services, clock and
19
+ * random stream.
20
+ */
21
+ const resolve = (bound, componentPath, request) => {
22
+ if (request !== void 0 && request.scheduledFunctionId !== bound.request.scheduledFunctionId) {
23
+ const { ip, userAgent, requestId, scheduledFunctionId } = request;
24
+ return {
25
+ world: bound.world,
26
+ componentPath,
27
+ attempt: 1,
28
+ request: {
29
+ ip,
30
+ userAgent,
31
+ requestId,
32
+ scheduledFunctionId
33
+ },
34
+ services: bound.world.services,
35
+ startedAt: bound.world.clock(),
36
+ random: bound.world.random
37
+ };
38
+ }
39
+ return componentPath === bound.componentPath ? bound : {
40
+ ...bound,
41
+ componentPath
42
+ };
43
+ };
44
+ /**
45
+ * What `Date` answers for a function of `functionType` under `invocation`: a
46
+ * query's or mutation's start, or the world's clock as it runs in an action.
47
+ */
48
+ const clockOf = (invocation, functionType) => functionType === "action" ? invocation.world.clock : () => invocation.startedAt;
49
+ const pinnedDate = (base, now) => new Proxy(base, {
50
+ get: (target, property, receiver) => property === "now" ? now : Reflect.get(target, property, receiver),
51
+ construct: (target, args, newTarget) => Reflect.construct(target, args.length === 0 ? [now()] : args, newTarget),
52
+ apply: () => new base(now()).toString()
53
+ });
54
+ const drawingMath = (base, random) => new Proxy(base, { get: (target, property, receiver) => property === "random" ? random : Reflect.get(target, property, receiver) });
55
+ const drawingCrypto = (base, random) => {
56
+ function getRandomValues(array) {
57
+ Reflect.apply(base.getRandomValues, this === drawing ? base : this, [array]);
58
+ if (array === null) return array;
59
+ const bytes = new Uint8Array(array.buffer, array.byteOffset, array.byteLength);
60
+ for (let index = 0; index < bytes.length; index++) bytes[index] = Math.floor(random() * 256);
61
+ return array;
62
+ }
63
+ const drawing = new Proxy(base, { get: (target, property) => {
64
+ if (property === "getRandomValues") return getRandomValues;
65
+ const value = Reflect.get(target, property, target);
66
+ return typeof value === "function" ? value.bind(target) : value;
67
+ } });
68
+ return drawing;
69
+ };
70
+ /**
71
+ * Point the calling handler's `Date`, `Math` and `crypto` at `invocation`, its
72
+ * `Date` through {@link clockOf}. convex-test gives each handler call its own
73
+ * copy of these globals, and an assignment inside a handler lands in that copy
74
+ * only, so overlapping handlers and the handler's own nested calls keep
75
+ * theirs.
76
+ *
77
+ * `outside` reads in the test's own async context. Where the handler has no
78
+ * copy, an assignment either throws or reaches test code, so `pin` puts back
79
+ * each global that reached it and throws.
80
+ */
81
+ const pin = (invocation, functionType, outside) => {
82
+ const host = globalThis;
83
+ const previous = {
84
+ Date: host.Date,
85
+ Math: host.Math,
86
+ crypto: host.crypto
87
+ };
88
+ const pinned = {
89
+ Date: pinnedDate(previous.Date, clockOf(invocation, functionType)),
90
+ Math: drawingMath(previous.Math, invocation.random),
91
+ crypto: drawingCrypto(previous.crypto, invocation.random)
92
+ };
93
+ try {
94
+ host.Date = pinned.Date;
95
+ host.Math = pinned.Math;
96
+ host.crypto = pinned.crypto;
97
+ } catch {}
98
+ const reached = outside(() => ({
99
+ Date: host.Date === pinned.Date,
100
+ Math: host.Math === pinned.Math,
101
+ crypto: host.crypto === pinned.crypto
102
+ }));
103
+ if (host.Date === pinned.Date && host.Math === pinned.Math && host.crypto === pinned.crypto && !reached.Date && !reached.Math && !reached.crypto) return;
104
+ if (reached.Date) host.Date = previous.Date;
105
+ if (reached.Math) host.Math = previous.Math;
106
+ if (reached.crypto) host.crypto = previous.crypto;
107
+ throw new Error("@confect/test cannot pin this handler's Date, Math and crypto: it runs without convex-test's per-handler globals, so pinning would change them for every caller");
108
+ };
109
+ const make = () => {
110
+ const storage = new AsyncLocalStorage();
111
+ const outside = AsyncLocalStorage.snapshot();
112
+ return {
113
+ storage,
114
+ start: (meta, run, functionType) => {
115
+ const running = storage.getStore();
116
+ if (running === void 0) return void 0;
117
+ return Promise.all([meta.getFunctionMetadata(), meta.getRequestMetadata?.()]).then(([{ componentPath }, request]) => {
118
+ const invocation = resolve(caller(running, functionType), componentPath, request);
119
+ pin(invocation, functionType, outside);
120
+ return storage.run({
121
+ invocation,
122
+ functionType
123
+ }, () => run(invocation.services));
124
+ });
125
+ }
126
+ };
127
+ };
128
+ const installed = globalThis;
129
+ /**
130
+ * Run `start` with `invocation` bound. Every registered handler it reaches
131
+ * through convex-test runs with the invocation's services, clock and random
132
+ * stream.
133
+ */
134
+ const bind = (invocation, start) => (installed[key] ??= make()).storage.run({
135
+ invocation,
136
+ functionType: void 0
137
+ }, start);
138
+ /**
139
+ * The invocation the calling handler runs under, if one is bound.
140
+ */
141
+ const current = () => installed[key]?.storage.getStore()?.invocation;
142
+ //#endregion
143
+ export { bind, current };
144
+
145
+ //# sourceMappingURL=Invocation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Invocation.js","names":[],"sources":["../../src/internal/Invocation.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\nimport type { FunctionMetadata, RequestMetadata } from \"convex/server\";\nimport type * as Context from \"effect/Context\";\n\n/**\n * Four re-executions after the first try. A conflict on attempt 5 exhausts.\n */\nexport type Attempt = 1 | 2 | 3 | 4 | 5;\n\n/**\n * One test backend. Its `services`, `clock` and `random` reach every invocation\n * it starts on its own, such as a scheduled job.\n */\nexport interface World {\n readonly name: string;\n readonly services: Context.Context<never>;\n /**\n * The world's controlled clock in epoch milliseconds. An invocation the world\n * starts on its own pins its start time from one reading. A bound action's\n * `Date` reads it live.\n */\n readonly clock: () => number;\n /**\n * The random stream, uniform on [0, 1), that an invocation the world starts\n * on its own draws from.\n */\n readonly random: () => number;\n}\n\nexport interface Invocation {\n readonly world: World;\n readonly componentPath: string;\n readonly attempt: Attempt;\n readonly request: Omit<RequestMetadata, \"authToken\">;\n readonly services: Context.Context<never>;\n /**\n * The start time in epoch milliseconds. Every query or mutation of the\n * invocation reads it from `Date.now()` and `new Date()`, so Effect's default\n * `Clock` reads it too. An action reads its world's clock instead, as it\n * runs, and a query or mutation an action calls starts at the action's time\n * then.\n */\n readonly startedAt: number;\n /**\n * The random stream, uniform on [0, 1). Every handler of the invocation draws\n * from it through `Math.random` and `crypto.getRandomValues`, so Effect's\n * default `Random` draws from it too.\n */\n readonly random: () => number;\n}\n\ntype FunctionType = \"query\" | \"mutation\" | \"action\";\n\n/**\n * The invocation a handler runs under, and the type of the function it runs.\n * Test code that binds an invocation runs no function, so it has no type.\n */\ninterface Running {\n readonly invocation: Invocation;\n readonly functionType: FunctionType | undefined;\n}\n\n/**\n * What `runHandlerPromise` in `@confect/server` reads from `globalThis` under\n * the same key. `start` answers `undefined` when no invocation is bound.\n */\ninterface Bridge {\n readonly storage: AsyncLocalStorage<Running>;\n readonly start: <A>(\n meta: {\n readonly getFunctionMetadata: () => Promise<FunctionMetadata>;\n readonly getRequestMetadata?: () => Promise<RequestMetadata>;\n },\n run: (services: Context.Context<never>) => Promise<A>,\n functionType: FunctionType,\n ) => Promise<A> | undefined;\n}\n\nconst key = Symbol.for(\"@confect/test/Invocation\");\n\n/**\n * The invocation a function of `functionType` called from `running` joins. A\n * query or mutation an action calls is a transaction of its own, so it starts\n * at the world's time when it begins. Any other call shares its caller's\n * start.\n */\nconst caller = (running: Running, functionType: FunctionType): Invocation =>\n running.functionType === \"action\" && functionType !== \"action\"\n ? { ...running.invocation, startedAt: running.invocation.world.clock() }\n : running.invocation;\n\n/**\n * The invocation a handler runs under. A call nested in the bound request joins\n * it at the callee's component path. A job Convex started from a timer set\n * inside the bound request is a request of its own: its scheduled function ID\n * differs, so it gets a fresh record with the world's services, clock and\n * random stream.\n */\nconst resolve = (\n bound: Invocation,\n componentPath: string,\n request: RequestMetadata | undefined,\n): Invocation => {\n if (\n request !== undefined &&\n request.scheduledFunctionId !== bound.request.scheduledFunctionId\n ) {\n const { ip, userAgent, requestId, scheduledFunctionId } = request;\n return {\n world: bound.world,\n componentPath,\n attempt: 1,\n request: { ip, userAgent, requestId, scheduledFunctionId },\n services: bound.world.services,\n startedAt: bound.world.clock(),\n random: bound.world.random,\n };\n }\n return componentPath === bound.componentPath\n ? bound\n : { ...bound, componentPath };\n};\n\n/**\n * What `Date` answers for a function of `functionType` under `invocation`: a\n * query's or mutation's start, or the world's clock as it runs in an action.\n */\nconst clockOf = (\n invocation: Invocation,\n functionType: FunctionType,\n): (() => number) =>\n functionType === \"action\"\n ? invocation.world.clock\n : () => invocation.startedAt;\n\nconst pinnedDate = (\n base: DateConstructor,\n now: () => number,\n): DateConstructor =>\n new Proxy(base, {\n get: (target, property, receiver) =>\n property === \"now\" ? now : Reflect.get(target, property, receiver),\n construct: (target, args, newTarget) =>\n Reflect.construct(target, args.length === 0 ? [now()] : args, newTarget),\n apply: () => new base(now()).toString(),\n });\n\nconst drawingMath = (base: Math, random: () => number): Math =>\n new Proxy(base, {\n get: (target, property, receiver) =>\n property === \"random\" ? random : Reflect.get(target, property, receiver),\n });\n\nconst drawingCrypto = (base: Crypto, random: () => number): Crypto => {\n function getRandomValues<T extends Parameters<Crypto[\"getRandomValues\"]>[0]>(\n this: unknown,\n array: T,\n ): T {\n // The host call checks the receiver and the argument and throws the host's\n // errors, so a detached call fails as it does in production.\n // oxlint-disable-next-line typescript/unbound-method -- Applied with the caller's receiver.\n Reflect.apply(base.getRandomValues, this === drawing ? base : this, [\n array,\n ]);\n if (array === null) return array;\n const bytes = new Uint8Array(\n array.buffer,\n array.byteOffset,\n array.byteLength,\n );\n for (let index = 0; index < bytes.length; index++) {\n bytes[index] = Math.floor(random() * 256);\n }\n return array;\n }\n const drawing: Crypto = new Proxy(base, {\n get: (target, property) => {\n if (property === \"getRandomValues\") return getRandomValues;\n // Crypto's methods and getters need the host object as `this`.\n const value: unknown = Reflect.get(target, property, target);\n return typeof value === \"function\" ? value.bind(target) : value;\n },\n });\n return drawing;\n};\n\n/**\n * Point the calling handler's `Date`, `Math` and `crypto` at `invocation`, its\n * `Date` through {@link clockOf}. convex-test gives each handler call its own\n * copy of these globals, and an assignment inside a handler lands in that copy\n * only, so overlapping handlers and the handler's own nested calls keep\n * theirs.\n *\n * `outside` reads in the test's own async context. Where the handler has no\n * copy, an assignment either throws or reaches test code, so `pin` puts back\n * each global that reached it and throws.\n */\nconst pin = (\n invocation: Invocation,\n functionType: FunctionType,\n outside: <R>(read: () => R) => R,\n): void => {\n const host = globalThis;\n const previous = { Date: host.Date, Math: host.Math, crypto: host.crypto };\n const pinned = {\n Date: pinnedDate(previous.Date, clockOf(invocation, functionType)),\n Math: drawingMath(previous.Math, invocation.random),\n crypto: drawingCrypto(previous.crypto, invocation.random),\n };\n try {\n host.Date = pinned.Date;\n host.Math = pinned.Math;\n host.crypto = pinned.crypto;\n } catch {\n // A global without a per-handler copy can be read-only. The check below\n // refuses the handler.\n }\n const reached = outside(() => ({\n Date: host.Date === pinned.Date,\n Math: host.Math === pinned.Math,\n crypto: host.crypto === pinned.crypto,\n }));\n if (\n host.Date === pinned.Date &&\n host.Math === pinned.Math &&\n host.crypto === pinned.crypto &&\n !reached.Date &&\n !reached.Math &&\n !reached.crypto\n ) {\n return;\n }\n if (reached.Date) host.Date = previous.Date;\n if (reached.Math) host.Math = previous.Math;\n if (reached.crypto) host.crypto = previous.crypto;\n throw new Error(\n \"@confect/test cannot pin this handler's Date, Math and crypto: it runs without convex-test's per-handler globals, so pinning would change them for every caller\",\n );\n};\n\nconst make = (): Bridge => {\n const storage = new AsyncLocalStorage<Running>();\n // Taken at the first `bind`, which test code calls outside any handler, so\n // it reads the test environment's globals.\n const outside = AsyncLocalStorage.snapshot();\n return {\n storage,\n start: (meta, run, functionType) => {\n const running = storage.getStore();\n if (running === undefined) return undefined;\n return Promise.all([\n meta.getFunctionMetadata(),\n meta.getRequestMetadata?.(),\n ]).then(([{ componentPath }, request]) => {\n const invocation = resolve(\n caller(running, functionType),\n componentPath,\n request,\n );\n pin(invocation, functionType, outside);\n return storage.run({ invocation, functionType }, () =>\n run(invocation.services),\n );\n });\n },\n };\n};\n\n// One bridge per test runtime, so every copy of this module that a test loads\n// binds through the store `runHandlerPromise` reads.\nconst installed = globalThis as { [key]?: Bridge };\n\n/**\n * Run `start` with `invocation` bound. Every registered handler it reaches\n * through convex-test runs with the invocation's services, clock and random\n * stream.\n */\nexport const bind = <A>(\n invocation: Invocation,\n start: () => Promise<A>,\n): Promise<A> =>\n (installed[key] ??= make()).storage.run(\n { invocation, functionType: undefined },\n start,\n );\n\n/**\n * The invocation the calling handler runs under, if one is bound.\n */\nexport const current = (): Invocation | undefined =>\n installed[key]?.storage.getStore()?.invocation;\n"],"mappings":"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"}
@@ -0,0 +1,93 @@
1
+ import type { DocumentId, StoredDocument } from "./KernelValues.js";
2
+ import * as ReadSet from "./ReadSet.js";
3
+ /**
4
+ * The number of commits the kernel has published. The empty world is 0.
5
+ */
6
+ export type Version = number;
7
+ /**
8
+ * A committed document and the version that wrote it.
9
+ */
10
+ export interface Row {
11
+ readonly doc: StoredDocument;
12
+ readonly version: Version;
13
+ }
14
+ /**
15
+ * Committed rows, keyed by component path, then table name, then document ID. A
16
+ * published state is never changed. A commit makes a new one.
17
+ */
18
+ export type Tables = ReadonlyMap<string, ReadonlyMap<string, ReadonlyMap<DocumentId, Row>>>;
19
+ /**
20
+ * One document's final value in a commit. `null` deletes it.
21
+ */
22
+ export interface Write {
23
+ readonly componentPath: string;
24
+ readonly id: DocumentId;
25
+ readonly doc: StoredDocument | null;
26
+ }
27
+ /**
28
+ * One document a commit changed: its value before and after. `null` is absent.
29
+ */
30
+ export interface Change {
31
+ readonly componentPath: string;
32
+ readonly id: DocumentId;
33
+ readonly before: StoredDocument | null;
34
+ readonly after: StoredDocument | null;
35
+ }
36
+ export interface Commit {
37
+ readonly version: Version;
38
+ readonly commitTs: bigint;
39
+ readonly changes: ReadonlyArray<Change>;
40
+ }
41
+ /**
42
+ * The kernel's committed state: rows, the latest version and commit timestamp,
43
+ * and the write log, oldest first.
44
+ */
45
+ export interface State {
46
+ readonly tables: Tables;
47
+ readonly version: Version;
48
+ readonly commitTs: bigint;
49
+ readonly log: ReadonlyArray<Commit>;
50
+ }
51
+ export declare const empty: State;
52
+ /**
53
+ * The committed row for `id` in `componentPath`, if any.
54
+ */
55
+ export declare const get: (state: State, componentPath: string, id: DocumentId) => Row | undefined;
56
+ /**
57
+ * Every committed row of one table in one component.
58
+ */
59
+ export declare const rows: (state: State, componentPath: string, tableName: string) => Iterable<Row>;
60
+ /**
61
+ * Publish one attempt's writes as a single commit at `commitTs`. Every
62
+ * component's writes land in the same version, so a reader sees all of them or
63
+ * none. A commit with no writes publishes nothing and leaves the state as it
64
+ * was.
65
+ */
66
+ export declare const apply: (state: State, writes: ReadonlyArray<Write>, commitTs: bigint) => State;
67
+ /**
68
+ * The first change published after version `snapshot` that invalidates one of
69
+ * `reads`, if any.
70
+ */
71
+ export declare const conflict: (state: State, snapshot: Version, reads: ReadonlyArray<ReadSet.Read>) => Change | undefined;
72
+ /**
73
+ * What the driver supplies. The kernel holds no clock of its own.
74
+ */
75
+ export interface KernelRuntime {
76
+ /**
77
+ * The time in milliseconds, for each inserted document's creation time.
78
+ */
79
+ readonly now: () => number;
80
+ /**
81
+ * The commit timestamp of `version`, asked once as it is published. The
82
+ * answers strictly increase. A mutation that wrote nothing publishes no
83
+ * version and asks nothing.
84
+ */
85
+ readonly commitTs: (version: Version) => bigint;
86
+ }
87
+ /**
88
+ * The wall clock, as convex-test reads it. Each answer is the time in
89
+ * nanoseconds when it is asked for, bumped past the previous answer when the
90
+ * clock stands still.
91
+ */
92
+ export declare const wallClock: () => KernelRuntime;
93
+ //# sourceMappingURL=Kernel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Kernel.d.ts","sourceRoot":"","sources":["../../src/internal/Kernel.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEpE,OAAO,KAAK,OAAO,MAAM,cAAc,CAAC;AAExC;;GAEG;AACH,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC;AAE7B;;GAEG;AACH,MAAM,WAAW,GAAG;IAClB,QAAQ,CAAC,GAAG,EAAE,cAAc,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED;;;GAGG;AACH,MAAM,MAAM,MAAM,GAAG,WAAW,CAC9B,MAAM,EACN,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAClD,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,EAAE,EAAE,UAAU,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI,CAAC;CACrC;AAED;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,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;AAED,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACzC;AAED;;;GAGG;AACH,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,GAAG,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACrC;AAED,eAAO,MAAM,KAAK,EAAE,KAKnB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,GAAG,UACP,KAAK,iBACG,MAAM,MACjB,UAAU,KACb,GAAG,GAAG,SAKR,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,IAAI,UACR,KAAK,iBACG,MAAM,aACV,MAAM,KAChB,QAAQ,CAAC,GAAG,CACkD,CAAC;AAElE;;;;;GAKG;AACH,eAAO,MAAM,KAAK,UACT,KAAK,UACJ,aAAa,CAAC,KAAK,CAAC,YAClB,MAAM,KACf,KAgCF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,QAAQ,UACZ,KAAK,YACF,OAAO,SACV,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,KACjC,MAAM,GAAG,SAOX,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,MAAM,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,MAAM,CAAC;CACjD;AAED;;;;GAIG;AACH,eAAO,MAAM,SAAS,QAAO,aAa5B,CAAC"}