@gaganref/confect-test 10.3.1-fork.91 → 10.3.1-fork.93
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/TestConfect.d.ts +26 -0
- package/dist/TestConfect.d.ts.map +1 -1
- package/dist/TestConfect.js +9 -1
- package/dist/TestConfect.js.map +1 -1
- package/dist/internal/Attempt.d.ts +14 -1
- package/dist/internal/Attempt.d.ts.map +1 -1
- package/dist/internal/Attempt.js +18 -1
- package/dist/internal/Attempt.js.map +1 -1
- package/dist/internal/ConvexTest.d.ts +26 -1
- package/dist/internal/ConvexTest.d.ts.map +1 -1
- package/dist/internal/ConvexTest.js +55 -27
- package/dist/internal/ConvexTest.js.map +1 -1
- package/dist/internal/Execution.d.ts +151 -1
- package/dist/internal/Execution.d.ts.map +1 -1
- package/dist/internal/Execution.js +731 -214
- package/dist/internal/Execution.js.map +1 -1
- package/dist/internal/KernelQuery.d.ts +8 -3
- package/dist/internal/KernelQuery.d.ts.map +1 -1
- package/dist/internal/KernelQuery.js +10 -3
- package/dist/internal/KernelQuery.js.map +1 -1
- package/dist/internal/KernelRefusal.d.ts +134 -0
- package/dist/internal/KernelRefusal.d.ts.map +1 -1
- package/dist/internal/KernelRefusal.js +134 -1
- package/dist/internal/KernelRefusal.js.map +1 -1
- package/dist/internal/Metering.d.ts +186 -0
- package/dist/internal/Metering.d.ts.map +1 -0
- package/dist/internal/Metering.js +401 -0
- package/dist/internal/Metering.js.map +1 -0
- package/dist/internal/Redaction.d.ts +142 -0
- package/dist/internal/Redaction.d.ts.map +1 -0
- package/dist/internal/Redaction.js +448 -0
- package/dist/internal/Redaction.js.map +1 -0
- package/dist/internal/Snapshot.d.ts +298 -0
- package/dist/internal/Snapshot.d.ts.map +1 -0
- package/dist/internal/Snapshot.js +532 -0
- package/dist/internal/Snapshot.js.map +1 -0
- package/dist/internal/Subscriptions.d.ts +13 -0
- package/dist/internal/Subscriptions.d.ts.map +1 -1
- package/dist/internal/Subscriptions.js +27 -3
- package/dist/internal/Subscriptions.js.map +1 -1
- package/package.json +3 -3
- package/src/TestConfect.ts +63 -4
- package/src/internal/Attempt.ts +24 -0
- package/src/internal/ConvexTest.ts +135 -38
- package/src/internal/Execution.ts +1141 -324
- package/src/internal/KernelQuery.ts +17 -6
- package/src/internal/KernelRefusal.ts +160 -0
- package/src/internal/Metering.ts +520 -0
- package/src/internal/Redaction.ts +730 -0
- package/src/internal/Snapshot.ts +945 -0
- package/src/internal/Subscriptions.ts +34 -4
package/dist/TestConfect.d.ts
CHANGED
|
@@ -43,6 +43,23 @@ export type TargetOptions = {
|
|
|
43
43
|
*/
|
|
44
44
|
readonly target?: Target;
|
|
45
45
|
};
|
|
46
|
+
/**
|
|
47
|
+
* Which values a kernel-target layer treats as secret, by component path, then
|
|
48
|
+
* table name or `module:export`: each entry a thunk of the Confect schema whose
|
|
49
|
+
* `Schema.Redacted` nodes mark the secrets. A value under one reaches the
|
|
50
|
+
* kernel's artifacts (snapshots, failure reports, diffs) only as a marker. The
|
|
51
|
+
* layer derives the app's own tables from its database schema, so this adds
|
|
52
|
+
* function arguments and returns and component tables. Codegen fills it from
|
|
53
|
+
* the Confect specs as `secrets` in the generated registry, which replaces a
|
|
54
|
+
* hand-written one.
|
|
55
|
+
*/
|
|
56
|
+
export type SecretPolicy = {
|
|
57
|
+
readonly tables?: Readonly<Record<string, Readonly<Record<string, () => Schema.Top>>>>;
|
|
58
|
+
readonly functions?: Readonly<Record<string, Readonly<Record<string, {
|
|
59
|
+
readonly args?: () => Schema.Top;
|
|
60
|
+
readonly returns?: () => Schema.Top;
|
|
61
|
+
}>>>>;
|
|
62
|
+
};
|
|
46
63
|
export type LayerOptions = TargetOptions & {
|
|
47
64
|
/**
|
|
48
65
|
* Register component kits synchronously before the test service is available.
|
|
@@ -52,6 +69,10 @@ export type LayerOptions = TargetOptions & {
|
|
|
52
69
|
* Explicit HTTP mounts. The test layer does not evaluate convex.config.ts.
|
|
53
70
|
*/
|
|
54
71
|
readonly httpMounts?: ReadonlyArray<HttpMount>;
|
|
72
|
+
/**
|
|
73
|
+
* The secret policy, read by the kernel target only.
|
|
74
|
+
*/
|
|
75
|
+
readonly secrets?: SecretPolicy;
|
|
55
76
|
};
|
|
56
77
|
export type TestConfectWithoutIdentity<ConfectSchema extends DatabaseSchema.AnyWithProps> = {
|
|
57
78
|
query: <QueryRef extends Ref.AnyQuery>(queryRef: QueryRef, ...args: Ref.OptionalArgs<QueryRef>) => Effect.Effect<Ref.Returns<QueryRef>, Ref.Error<QueryRef> | Schema.SchemaError>;
|
|
@@ -91,6 +112,11 @@ export type Registry<DatabaseSchema_ extends DatabaseSchema.AnyWithProps> = {
|
|
|
91
112
|
readonly convexSchema: SchemaDefinition<GenericSchema, true>;
|
|
92
113
|
readonly modules: Record<string, () => Promise<any>>;
|
|
93
114
|
readonly components: Readonly<Record<string, ComponentKit>>;
|
|
115
|
+
/**
|
|
116
|
+
* The secret policy codegen derives from the Confect specs, read by the
|
|
117
|
+
* kernel target only.
|
|
118
|
+
*/
|
|
119
|
+
readonly secrets?: SecretPolicy;
|
|
94
120
|
};
|
|
95
121
|
/**
|
|
96
122
|
* The declared app's generated, test-only representation.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TestConfect.d.ts","sourceRoot":"","sources":["../src/TestConfect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,KAAK,KAAK,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAa,MAAM,iBAAiB,CAAC;AACjE,OAAO,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAM3D,OAAO,KAAK,EAEV,aAAa,EACb,gBAAgB,EAChB,YAAY,EACb,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"TestConfect.d.ts","sourceRoot":"","sources":["../src/TestConfect.ts"],"names":[],"mappings":"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"}
|
package/dist/TestConfect.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { __exportAll } from "./_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { merge, policy, tablesOf } from "./internal/Redaction.js";
|
|
2
3
|
import { convexTest as convexTest$1 } from "./internal/ConvexTest.js";
|
|
3
4
|
import { make } from "./internal/MountedHttp.js";
|
|
4
5
|
import { App, Ref } from "@confect/core";
|
|
@@ -73,6 +74,7 @@ function layer(appOrSchema, second, third, options = {}) {
|
|
|
73
74
|
const mounts = App.mounts(appOrSchema);
|
|
74
75
|
return schemaLayer(registry.schema, registry.convexSchema, registry.modules, {
|
|
75
76
|
...targetOf(third),
|
|
77
|
+
...secretsOf(registry),
|
|
76
78
|
httpMounts: mounts.flatMap(({ name, httpPrefix }) => httpPrefix === void 0 ? [] : [{
|
|
77
79
|
componentPath: name,
|
|
78
80
|
httpPrefix
|
|
@@ -86,6 +88,7 @@ function layer(appOrSchema, second, third, options = {}) {
|
|
|
86
88
|
const app = appOrSchema;
|
|
87
89
|
return schemaLayer(app.schema, app.convexSchema, app.modules, {
|
|
88
90
|
...targetOf(second),
|
|
91
|
+
...secretsOf(app),
|
|
89
92
|
httpMounts: app.httpMounts,
|
|
90
93
|
register: (registerComponent) => {
|
|
91
94
|
for (const [name, component] of Object.entries(app.components)) registerKit(registerComponent, name, component);
|
|
@@ -95,10 +98,15 @@ function layer(appOrSchema, second, third, options = {}) {
|
|
|
95
98
|
return schemaLayer(appOrSchema, second, third, options);
|
|
96
99
|
}
|
|
97
100
|
const targetOf = (options) => options?.target === void 0 ? {} : { target: options.target };
|
|
101
|
+
const secretsOf = (registry) => registry.secrets === void 0 ? {} : { secrets: registry.secrets };
|
|
98
102
|
const schemaLayer = (databaseSchema, convexSchemaDefinition, modules, options = {}) => Layer.sync(TestConfect(), () => {
|
|
99
103
|
process.env.CONVEX_CLOUD_URL ??= "https://some-deployment.convex.cloud";
|
|
100
104
|
process.env.CONVEX_SITE_URL ??= "https://some.convex.site";
|
|
101
|
-
const testConvex =
|
|
105
|
+
const testConvex = options.target === "kernel" ? convexTest$1({
|
|
106
|
+
schema: convexSchemaDefinition,
|
|
107
|
+
modules,
|
|
108
|
+
redaction: policy(merge({ tables: { "": tablesOf(databaseSchema) } }, options.secrets ?? {}))
|
|
109
|
+
}) : convexTest(convexSchemaDefinition, modules);
|
|
102
110
|
const registerComponent = testConvex.registerComponent;
|
|
103
111
|
const mountedHttp = make(options.httpMounts ?? [], (...args) => registerComponent(...args));
|
|
104
112
|
options.register?.(mountedHttp.register);
|
package/dist/TestConfect.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TestConfect.js","names":["kernelTest","MountedHttp.make"],"sources":["../src/TestConfect.ts"],"sourcesContent":["import { App, type Mount, Ref } from \"@confect/core\";\nimport type { DatabaseSchema, DataModel } from \"@confect/server\";\nimport { RegisteredConvexFunction } from \"@confect/server\";\nimport type {\n TestConvexForDataModel,\n TestConvexForDataModelAndIdentity,\n} from \"convex-test\";\nimport { convexTest } from \"convex-test\";\nimport type {\n GenericMutationCtx,\n GenericSchema,\n SchemaDefinition,\n UserIdentity,\n} from \"convex/server\";\nimport type { Value } from \"convex/values\";\nimport * as Context from \"effect/Context\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as Schema from \"effect/Schema\";\nimport { convexTest as kernelTest } from \"./internal/ConvexTest.js\";\nimport * as MountedHttp from \"./internal/MountedHttp.js\";\n\ndeclare const process: { env: Record<string, string | undefined> };\n\n/**\n * How a kit registers a component beyond its schema and modules.\n */\nexport type RegisterOptions = {\n /**\n * The component's functions, as `module:export`, that schedule their own next\n * run, such as the crons component's `public:rescheduler`. The test kernel\n * never treats a job that runs one, or that one schedules, as work\n * `finishAllScheduledFunctions` must finish. convex-test ignores it.\n */\n readonly standing?: ReadonlyArray<string>;\n};\n\n/**\n * Register a component's Convex schema and modules at its installation path.\n */\nexport type RegisterComponent = (\n componentPath: string,\n schema: SchemaDefinition<GenericSchema, boolean>,\n modules: Record<string, () => Promise<any>>,\n options?: RegisterOptions,\n) => void;\n\n/**\n * An installed component path and the HTTP prefix exposed by its host.\n */\nexport type HttpMount = {\n readonly componentPath: string;\n readonly httpPrefix: string;\n};\n\n/**\n * The in-process backend a test layer runs on.\n */\nexport type Target = \"convex-test\" | \"kernel\";\n\nexport type TargetOptions = {\n /**\n * `\"kernel\"` runs every function and component the layer registers on\n * Confect's test kernel, which runs scheduled functions on its own clock and\n * reads `registerComponent`'s `standing`. Defaults to `\"convex-test\"`. The\n * option goes once the kernel replaces convex-test.\n */\n readonly target?: Target;\n};\n\nexport type LayerOptions = TargetOptions & {\n /**\n * Register component kits synchronously before the test service is available.\n */\n readonly register?: (registerComponent: RegisterComponent) => void;\n /**\n * Explicit HTTP mounts. The test layer does not evaluate convex.config.ts.\n */\n readonly httpMounts?: ReadonlyArray<HttpMount>;\n};\n\nexport type TestConfectWithoutIdentity<\n ConfectSchema extends DatabaseSchema.AnyWithProps,\n> = {\n query: <QueryRef extends Ref.AnyQuery>(\n queryRef: QueryRef,\n ...args: Ref.OptionalArgs<QueryRef>\n ) => Effect.Effect<\n Ref.Returns<QueryRef>,\n Ref.Error<QueryRef> | Schema.SchemaError\n >;\n mutation: <MutationRef extends Ref.AnyMutation>(\n mutationRef: MutationRef,\n ...args: Ref.OptionalArgs<MutationRef>\n ) => Effect.Effect<\n Ref.Returns<MutationRef>,\n Ref.Error<MutationRef> | Schema.SchemaError\n >;\n action: <ActionRef extends Ref.AnyAction>(\n actionRef: ActionRef,\n ...args: Ref.OptionalArgs<ActionRef>\n ) => Effect.Effect<\n Ref.Returns<ActionRef>,\n Ref.Error<ActionRef> | Schema.SchemaError\n >;\n run: {\n <E>(\n handler: Effect.Effect<\n void,\n E,\n RegisteredConvexFunction.MutationServices<ConfectSchema>\n >,\n ): Effect.Effect<void>;\n <A, B extends Value, E>(\n handler: Effect.Effect<\n A,\n E,\n RegisteredConvexFunction.MutationServices<ConfectSchema>\n >,\n returns: Schema.Codec<A, B>,\n ): Effect.Effect<A, Schema.SchemaError>;\n };\n fetch: (\n pathQueryFragment: string,\n init?: RequestInit,\n ) => Effect.Effect<Response>;\n finishInProgressScheduledFunctions: () => Effect.Effect<void>;\n finishAllScheduledFunctions: (\n advanceTimers: () => void,\n ) => Effect.Effect<void>;\n};\n\nexport type TestConfect<ConfectSchema extends DatabaseSchema.AnyWithProps> = {\n registerComponent: (\n componentPath: string,\n schema: SchemaDefinition<GenericSchema, boolean>,\n modules: Record<string, () => Promise<any>>,\n options?: RegisterOptions,\n ) => Effect.Effect<void>;\n withIdentity: (\n userIdentity: Partial<UserIdentity>,\n ) => TestConfectWithoutIdentity<ConfectSchema>;\n} & TestConfectWithoutIdentity<ConfectSchema>;\n\nexport const TestConfect = <\n ConfectSchema extends DatabaseSchema.AnyWithProps,\n>() => Context.Service<TestConfect<ConfectSchema>>(\"@confect/test/TestConfect\");\n\nclass TestConfectImplWithoutIdentity<\n ConfectSchema extends DatabaseSchema.AnyWithProps,\n> implements TestConfectWithoutIdentity<ConfectSchema> {\n constructor(\n private confectSchema: ConfectSchema,\n private testConvex: TestConvexForDataModel<\n DataModel.ToConvex<DataModel.FromSchema<ConfectSchema>>\n >,\n private mountedHttp: ReturnType<typeof MountedHttp.make>,\n ) {}\n\n readonly query = <QueryRef extends Ref.AnyQuery>(\n queryRef: QueryRef,\n ...args: Ref.OptionalArgs<QueryRef>\n ): Effect.Effect<\n Ref.Returns<QueryRef>,\n Ref.Error<QueryRef> | Schema.SchemaError\n > =>\n Ref.runWithCodec(\n queryRef,\n (args[0] ?? {}) as Ref.Args<QueryRef>,\n (functionReference, encodedArgs) =>\n this.testConvex.query(functionReference as any, encodedArgs),\n );\n\n readonly mutation = <MutationRef extends Ref.AnyMutation>(\n mutationRef: MutationRef,\n ...args: Ref.OptionalArgs<MutationRef>\n ): Effect.Effect<\n Ref.Returns<MutationRef>,\n Ref.Error<MutationRef> | Schema.SchemaError\n > =>\n Ref.runWithCodec(\n mutationRef,\n (args[0] ?? {}) as Ref.Args<MutationRef>,\n (functionReference, encodedArgs) =>\n this.testConvex.mutation(functionReference as any, encodedArgs),\n );\n\n readonly action = <ActionRef extends Ref.AnyAction>(\n actionRef: ActionRef,\n ...args: Ref.OptionalArgs<ActionRef>\n ): Effect.Effect<\n Ref.Returns<ActionRef>,\n Ref.Error<ActionRef> | Schema.SchemaError\n > =>\n Ref.runWithCodec(\n actionRef,\n (args[0] ?? {}) as Ref.Args<ActionRef>,\n (functionReference, encodedArgs) =>\n this.testConvex.action(functionReference as any, encodedArgs),\n );\n\n readonly run: TestConfectWithoutIdentity<ConfectSchema>[\"run\"] = (<\n A,\n B extends Value,\n E,\n >(\n handler: Effect.Effect<\n A,\n E,\n RegisteredConvexFunction.MutationServices<ConfectSchema>\n >,\n returns?: Schema.Codec<A, B>,\n ): Effect.Effect<void> | Effect.Effect<A, Schema.SchemaError> => {\n const makeMutationLayer = (\n mutationCtx: GenericMutationCtx<\n DataModel.ToConvex<DataModel.FromSchema<ConfectSchema>>\n >,\n ): Layer.Layer<RegisteredConvexFunction.MutationServices<ConfectSchema>> =>\n RegisteredConvexFunction.mutationLayer(\n this.confectSchema,\n mutationCtx,\n ) as Layer.Layer<\n RegisteredConvexFunction.MutationServices<ConfectSchema>\n >;\n\n return returns === undefined\n ? Effect.promise(() =>\n this.testConvex.run((mutationCtx) =>\n Effect.runPromise(\n handler.pipe(\n Effect.asVoid,\n Effect.provide(makeMutationLayer(mutationCtx)),\n ),\n ),\n ),\n )\n : Effect.promise(() =>\n this.testConvex.run((mutationCtx) =>\n Effect.runPromise(\n handler.pipe(\n Effect.andThen(Schema.encodeEffect(returns)),\n Effect.provide(makeMutationLayer(mutationCtx)),\n ),\n ),\n ),\n ).pipe(Effect.andThen(Schema.decodeEffect(returns)));\n }) as TestConfectWithoutIdentity<ConfectSchema>[\"run\"];\n\n readonly fetch = <PathQueryFragment extends string>(\n pathQueryFragment: PathQueryFragment,\n init?: RequestInit,\n ) =>\n Effect.promise(() =>\n this.mountedHttp.fetch(this.testConvex, pathQueryFragment, init),\n );\n\n readonly finishInProgressScheduledFunctions = () =>\n Effect.promise(() => this.testConvex.finishInProgressScheduledFunctions());\n\n readonly finishAllScheduledFunctions = (advanceTimers: () => void) =>\n Effect.promise(() =>\n this.testConvex.finishAllScheduledFunctions(advanceTimers),\n );\n}\n\nclass TestConfectImpl<\n ConfectSchema extends DatabaseSchema.AnyWithProps,\n> implements TestConfect<ConfectSchema> {\n private readonly testConfectImplWithoutIdentity: TestConfectImplWithoutIdentity<ConfectSchema>;\n\n constructor(\n private confectSchema: ConfectSchema,\n private testConvex: TestConvexForDataModelAndIdentity<\n DataModel.ToConvex<DataModel.FromSchema<ConfectSchema>>\n >,\n private mountedHttp: ReturnType<typeof MountedHttp.make>,\n ) {\n this.testConfectImplWithoutIdentity = new TestConfectImplWithoutIdentity(\n confectSchema,\n testConvex,\n mountedHttp,\n );\n }\n\n readonly withIdentity = (userIdentity: Partial<UserIdentity>) =>\n new TestConfectImplWithoutIdentity(\n this.confectSchema,\n this.testConvex.withIdentity(userIdentity),\n this.mountedHttp,\n );\n\n readonly registerComponent: TestConfect<ConfectSchema>[\"registerComponent\"] =\n Effect.fn(\"TestConfect.registerComponent\")(\n (componentPath, schema, modules, options) =>\n Effect.sync(() =>\n this.mountedHttp.register(componentPath, schema, modules, options),\n ),\n );\n\n readonly query = <QueryRef extends Ref.AnyQuery>(\n queryRef: QueryRef,\n ...args: Ref.OptionalArgs<QueryRef>\n ) => this.testConfectImplWithoutIdentity.query(queryRef, ...args);\n\n readonly mutation = <MutationRef extends Ref.AnyMutation>(\n mutationRef: MutationRef,\n ...args: Ref.OptionalArgs<MutationRef>\n ) => this.testConfectImplWithoutIdentity.mutation(mutationRef, ...args);\n\n readonly action = <ActionRef extends Ref.AnyAction>(\n actionRef: ActionRef,\n ...args: Ref.OptionalArgs<ActionRef>\n ) => this.testConfectImplWithoutIdentity.action(actionRef, ...args);\n\n readonly run: TestConfect<ConfectSchema>[\"run\"] = ((\n handler: any,\n returns?: any,\n ) =>\n this.testConfectImplWithoutIdentity.run(\n handler,\n returns,\n )) as TestConfect<ConfectSchema>[\"run\"];\n\n readonly fetch = <PathQueryFragment extends string>(\n pathQueryFragment: PathQueryFragment,\n init?: RequestInit,\n ) => this.testConfectImplWithoutIdentity.fetch(pathQueryFragment, init);\n\n readonly finishInProgressScheduledFunctions = () =>\n this.testConfectImplWithoutIdentity.finishInProgressScheduledFunctions();\n\n readonly finishAllScheduledFunctions = (advanceTimers: () => void) =>\n this.testConfectImplWithoutIdentity.finishAllScheduledFunctions(\n advanceTimers,\n );\n}\n\n/**\n * How a test registers one installed component: its own schema and modules, or\n * the `register(t, name)` a component package exports from `<package>/testing`\n * or `<package>/test`, which also registers the package's own children.\n */\nexport type ComponentKit =\n | {\n readonly schema: SchemaDefinition<GenericSchema, boolean>;\n readonly modules: Record<string, () => Promise<any>>;\n }\n | {\n register(\n t: { readonly registerComponent: RegisterComponent },\n name: string,\n ): unknown;\n };\n\nclass InvalidComponentKit extends Schema.TaggedError<InvalidComponentKit>()(\n \"InvalidComponentKit\",\n { componentPath: Schema.String, message: Schema.String },\n) {}\n\nconst registerKit = (\n registerComponent: RegisterComponent,\n name: string,\n kit: ComponentKit,\n) => {\n if (\"register\" in kit) {\n kit.register({ registerComponent }, name);\n } else if (\"schema\" in kit && \"modules\" in kit) {\n registerComponent(name, kit.schema, kit.modules);\n } else {\n // Codegen accepts a kit whose exports it cannot list, such as CommonJS.\n throw new InvalidComponentKit({\n componentPath: name,\n message: `The test kit for ${JSON.stringify(name)} must export register(t, name), or schema and modules.`,\n });\n }\n};\n\n/**\n * Codegen's test-only schema and module registry.\n */\nexport type Registry<DatabaseSchema_ extends DatabaseSchema.AnyWithProps> = {\n readonly schema: DatabaseSchema_;\n readonly convexSchema: SchemaDefinition<GenericSchema, true>;\n readonly modules: Record<string, () => Promise<any>>;\n readonly components: Readonly<Record<string, ComponentKit>>;\n};\n\n/**\n * The declared app's generated, test-only representation.\n */\nexport type DeclaredApp<DatabaseSchema_ extends DatabaseSchema.AnyWithProps> =\n Registry<DatabaseSchema_> & {\n readonly httpMounts: ReadonlyArray<HttpMount>;\n };\n\n/**\n * Build a fresh test backend from a declaration and its generated\n * `confect/_generated/testing` registry, without restating component mounts.\n * Pass `{ target: \"kernel\" }` to run it on Confect's test kernel instead of\n * convex-test.\n */\nexport function layer<DatabaseSchema_ extends DatabaseSchema.AnyWithProps>(\n app: DeclaredApp<DatabaseSchema_>,\n options?: TargetOptions,\n): Layer.Layer<TestConfect<DatabaseSchema_>>;\nexport function layer<\n A extends App.Any,\n DatabaseSchema_ extends DatabaseSchema.AnyWithProps,\n>(\n app: A,\n registry: Registry<DatabaseSchema_> & {\n readonly components: Readonly<\n Record<\n Mount.NameOf<NoInfer<A>[\"mounts\"][number]>,\n Registry<DatabaseSchema_>[\"components\"][string]\n >\n >;\n },\n options?: TargetOptions,\n): Layer.Layer<TestConfect<DatabaseSchema_>>;\nexport function layer<DatabaseSchema_ extends DatabaseSchema.AnyWithProps>(\n databaseSchema: DatabaseSchema_,\n convexSchemaDefinition: SchemaDefinition<GenericSchema, true>,\n modules: Record<string, () => Promise<any>>,\n options?: LayerOptions,\n): Layer.Layer<TestConfect<DatabaseSchema_>>;\nexport function layer<DatabaseSchema_ extends DatabaseSchema.AnyWithProps>(\n appOrSchema: App.Any | DeclaredApp<DatabaseSchema_> | DatabaseSchema_,\n second?:\n | Registry<DatabaseSchema_>\n | SchemaDefinition<GenericSchema, true>\n | TargetOptions,\n third?: Record<string, () => Promise<any>> | TargetOptions,\n options: LayerOptions = {},\n): Layer.Layer<TestConfect<DatabaseSchema_>> {\n if (App.isApp(appOrSchema)) {\n const registry = second as Registry<DatabaseSchema_>;\n const mounts = App.mounts(appOrSchema);\n return schemaLayer(\n registry.schema,\n registry.convexSchema,\n registry.modules,\n {\n ...targetOf(third as TargetOptions | undefined),\n httpMounts: mounts.flatMap(({ name, httpPrefix }) =>\n httpPrefix === undefined ? [] : [{ componentPath: name, httpPrefix }],\n ),\n register: (registerComponent) => {\n for (const [name, component] of Object.entries(registry.components)) {\n if (\n mounts.some(\n (mount) =>\n name === mount.name || name.startsWith(`${mount.name}/`),\n )\n ) {\n registerKit(registerComponent, name, component);\n }\n }\n },\n },\n );\n }\n if (\"httpMounts\" in appOrSchema) {\n const app = appOrSchema as DeclaredApp<DatabaseSchema_>;\n return schemaLayer(app.schema, app.convexSchema, app.modules, {\n ...targetOf(second as TargetOptions | undefined),\n httpMounts: app.httpMounts,\n register: (registerComponent) => {\n for (const [name, component] of Object.entries(app.components)) {\n registerKit(registerComponent, name, component);\n }\n },\n });\n }\n return schemaLayer(\n appOrSchema as DatabaseSchema_,\n second as SchemaDefinition<GenericSchema, true>,\n third as Record<string, () => Promise<any>>,\n options,\n );\n}\n\nconst targetOf = (options: TargetOptions | undefined): TargetOptions =>\n options?.target === undefined ? {} : { target: options.target };\n\nconst schemaLayer = <DatabaseSchema_ extends DatabaseSchema.AnyWithProps>(\n databaseSchema: DatabaseSchema_,\n convexSchemaDefinition: SchemaDefinition<GenericSchema, true>,\n modules: Record<string, () => Promise<any>>,\n options: LayerOptions = {},\n): Layer.Layer<TestConfect<DatabaseSchema_>> =>\n Layer.sync(TestConfect<DatabaseSchema_>(), () => {\n process.env.CONVEX_CLOUD_URL ??= \"https://some-deployment.convex.cloud\";\n process.env.CONVEX_SITE_URL ??= \"https://some.convex.site\";\n const testConvex = (options.target === \"kernel\" ? kernelTest : convexTest)(\n convexSchemaDefinition,\n modules,\n );\n // convex-test takes three arguments and ignores the options. The kernel\n // reads `standing`.\n const registerComponent =\n testConvex.registerComponent as unknown as RegisterComponent;\n const mountedHttp = MountedHttp.make(options.httpMounts ?? [], (...args) =>\n registerComponent(...args),\n );\n options.register?.(mountedHttp.register);\n return new TestConfectImpl(databaseSchema, testConvex as any, mountedHttp);\n });\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TestConfect.js","names":["kernelTest","Redaction.policy","Redaction.merge","Redaction.tablesOf","MountedHttp.make"],"sources":["../src/TestConfect.ts"],"sourcesContent":["import { App, type Mount, Ref } from \"@confect/core\";\nimport type { DatabaseSchema, DataModel } from \"@confect/server\";\nimport { RegisteredConvexFunction } from \"@confect/server\";\nimport type {\n TestConvexForDataModel,\n TestConvexForDataModelAndIdentity,\n} from \"convex-test\";\nimport { convexTest } from \"convex-test\";\nimport type {\n GenericMutationCtx,\n GenericSchema,\n SchemaDefinition,\n UserIdentity,\n} from \"convex/server\";\nimport type { Value } from \"convex/values\";\nimport * as Context from \"effect/Context\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as Schema from \"effect/Schema\";\nimport { convexTest as kernelTest } from \"./internal/ConvexTest.js\";\nimport * as MountedHttp from \"./internal/MountedHttp.js\";\nimport * as Redaction from \"./internal/Redaction.js\";\n\ndeclare const process: { env: Record<string, string | undefined> };\n\n/**\n * How a kit registers a component beyond its schema and modules.\n */\nexport type RegisterOptions = {\n /**\n * The component's functions, as `module:export`, that schedule their own next\n * run, such as the crons component's `public:rescheduler`. The test kernel\n * never treats a job that runs one, or that one schedules, as work\n * `finishAllScheduledFunctions` must finish. convex-test ignores it.\n */\n readonly standing?: ReadonlyArray<string>;\n};\n\n/**\n * Register a component's Convex schema and modules at its installation path.\n */\nexport type RegisterComponent = (\n componentPath: string,\n schema: SchemaDefinition<GenericSchema, boolean>,\n modules: Record<string, () => Promise<any>>,\n options?: RegisterOptions,\n) => void;\n\n/**\n * An installed component path and the HTTP prefix exposed by its host.\n */\nexport type HttpMount = {\n readonly componentPath: string;\n readonly httpPrefix: string;\n};\n\n/**\n * The in-process backend a test layer runs on.\n */\nexport type Target = \"convex-test\" | \"kernel\";\n\nexport type TargetOptions = {\n /**\n * `\"kernel\"` runs every function and component the layer registers on\n * Confect's test kernel, which runs scheduled functions on its own clock and\n * reads `registerComponent`'s `standing`. Defaults to `\"convex-test\"`. The\n * option goes once the kernel replaces convex-test.\n */\n readonly target?: Target;\n};\n\n/**\n * Which values a kernel-target layer treats as secret, by component path, then\n * table name or `module:export`: each entry a thunk of the Confect schema whose\n * `Schema.Redacted` nodes mark the secrets. A value under one reaches the\n * kernel's artifacts (snapshots, failure reports, diffs) only as a marker. The\n * layer derives the app's own tables from its database schema, so this adds\n * function arguments and returns and component tables. Codegen fills it from\n * the Confect specs as `secrets` in the generated registry, which replaces a\n * hand-written one.\n */\nexport type SecretPolicy = {\n readonly tables?: Readonly<\n Record<string, Readonly<Record<string, () => Schema.Top>>>\n >;\n readonly functions?: Readonly<\n Record<\n string,\n Readonly<\n Record<\n string,\n {\n readonly args?: () => Schema.Top;\n readonly returns?: () => Schema.Top;\n }\n >\n >\n >\n >;\n};\n\nexport type LayerOptions = TargetOptions & {\n /**\n * Register component kits synchronously before the test service is available.\n */\n readonly register?: (registerComponent: RegisterComponent) => void;\n /**\n * Explicit HTTP mounts. The test layer does not evaluate convex.config.ts.\n */\n readonly httpMounts?: ReadonlyArray<HttpMount>;\n /**\n * The secret policy, read by the kernel target only.\n */\n readonly secrets?: SecretPolicy;\n};\n\nexport type TestConfectWithoutIdentity<\n ConfectSchema extends DatabaseSchema.AnyWithProps,\n> = {\n query: <QueryRef extends Ref.AnyQuery>(\n queryRef: QueryRef,\n ...args: Ref.OptionalArgs<QueryRef>\n ) => Effect.Effect<\n Ref.Returns<QueryRef>,\n Ref.Error<QueryRef> | Schema.SchemaError\n >;\n mutation: <MutationRef extends Ref.AnyMutation>(\n mutationRef: MutationRef,\n ...args: Ref.OptionalArgs<MutationRef>\n ) => Effect.Effect<\n Ref.Returns<MutationRef>,\n Ref.Error<MutationRef> | Schema.SchemaError\n >;\n action: <ActionRef extends Ref.AnyAction>(\n actionRef: ActionRef,\n ...args: Ref.OptionalArgs<ActionRef>\n ) => Effect.Effect<\n Ref.Returns<ActionRef>,\n Ref.Error<ActionRef> | Schema.SchemaError\n >;\n run: {\n <E>(\n handler: Effect.Effect<\n void,\n E,\n RegisteredConvexFunction.MutationServices<ConfectSchema>\n >,\n ): Effect.Effect<void>;\n <A, B extends Value, E>(\n handler: Effect.Effect<\n A,\n E,\n RegisteredConvexFunction.MutationServices<ConfectSchema>\n >,\n returns: Schema.Codec<A, B>,\n ): Effect.Effect<A, Schema.SchemaError>;\n };\n fetch: (\n pathQueryFragment: string,\n init?: RequestInit,\n ) => Effect.Effect<Response>;\n finishInProgressScheduledFunctions: () => Effect.Effect<void>;\n finishAllScheduledFunctions: (\n advanceTimers: () => void,\n ) => Effect.Effect<void>;\n};\n\nexport type TestConfect<ConfectSchema extends DatabaseSchema.AnyWithProps> = {\n registerComponent: (\n componentPath: string,\n schema: SchemaDefinition<GenericSchema, boolean>,\n modules: Record<string, () => Promise<any>>,\n options?: RegisterOptions,\n ) => Effect.Effect<void>;\n withIdentity: (\n userIdentity: Partial<UserIdentity>,\n ) => TestConfectWithoutIdentity<ConfectSchema>;\n} & TestConfectWithoutIdentity<ConfectSchema>;\n\nexport const TestConfect = <\n ConfectSchema extends DatabaseSchema.AnyWithProps,\n>() => Context.Service<TestConfect<ConfectSchema>>(\"@confect/test/TestConfect\");\n\nclass TestConfectImplWithoutIdentity<\n ConfectSchema extends DatabaseSchema.AnyWithProps,\n> implements TestConfectWithoutIdentity<ConfectSchema> {\n constructor(\n private confectSchema: ConfectSchema,\n private testConvex: TestConvexForDataModel<\n DataModel.ToConvex<DataModel.FromSchema<ConfectSchema>>\n >,\n private mountedHttp: ReturnType<typeof MountedHttp.make>,\n ) {}\n\n readonly query = <QueryRef extends Ref.AnyQuery>(\n queryRef: QueryRef,\n ...args: Ref.OptionalArgs<QueryRef>\n ): Effect.Effect<\n Ref.Returns<QueryRef>,\n Ref.Error<QueryRef> | Schema.SchemaError\n > =>\n Ref.runWithCodec(\n queryRef,\n (args[0] ?? {}) as Ref.Args<QueryRef>,\n (functionReference, encodedArgs) =>\n this.testConvex.query(functionReference as any, encodedArgs),\n );\n\n readonly mutation = <MutationRef extends Ref.AnyMutation>(\n mutationRef: MutationRef,\n ...args: Ref.OptionalArgs<MutationRef>\n ): Effect.Effect<\n Ref.Returns<MutationRef>,\n Ref.Error<MutationRef> | Schema.SchemaError\n > =>\n Ref.runWithCodec(\n mutationRef,\n (args[0] ?? {}) as Ref.Args<MutationRef>,\n (functionReference, encodedArgs) =>\n this.testConvex.mutation(functionReference as any, encodedArgs),\n );\n\n readonly action = <ActionRef extends Ref.AnyAction>(\n actionRef: ActionRef,\n ...args: Ref.OptionalArgs<ActionRef>\n ): Effect.Effect<\n Ref.Returns<ActionRef>,\n Ref.Error<ActionRef> | Schema.SchemaError\n > =>\n Ref.runWithCodec(\n actionRef,\n (args[0] ?? {}) as Ref.Args<ActionRef>,\n (functionReference, encodedArgs) =>\n this.testConvex.action(functionReference as any, encodedArgs),\n );\n\n readonly run: TestConfectWithoutIdentity<ConfectSchema>[\"run\"] = (<\n A,\n B extends Value,\n E,\n >(\n handler: Effect.Effect<\n A,\n E,\n RegisteredConvexFunction.MutationServices<ConfectSchema>\n >,\n returns?: Schema.Codec<A, B>,\n ): Effect.Effect<void> | Effect.Effect<A, Schema.SchemaError> => {\n const makeMutationLayer = (\n mutationCtx: GenericMutationCtx<\n DataModel.ToConvex<DataModel.FromSchema<ConfectSchema>>\n >,\n ): Layer.Layer<RegisteredConvexFunction.MutationServices<ConfectSchema>> =>\n RegisteredConvexFunction.mutationLayer(\n this.confectSchema,\n mutationCtx,\n ) as Layer.Layer<\n RegisteredConvexFunction.MutationServices<ConfectSchema>\n >;\n\n return returns === undefined\n ? Effect.promise(() =>\n this.testConvex.run((mutationCtx) =>\n Effect.runPromise(\n handler.pipe(\n Effect.asVoid,\n Effect.provide(makeMutationLayer(mutationCtx)),\n ),\n ),\n ),\n )\n : Effect.promise(() =>\n this.testConvex.run((mutationCtx) =>\n Effect.runPromise(\n handler.pipe(\n Effect.andThen(Schema.encodeEffect(returns)),\n Effect.provide(makeMutationLayer(mutationCtx)),\n ),\n ),\n ),\n ).pipe(Effect.andThen(Schema.decodeEffect(returns)));\n }) as TestConfectWithoutIdentity<ConfectSchema>[\"run\"];\n\n readonly fetch = <PathQueryFragment extends string>(\n pathQueryFragment: PathQueryFragment,\n init?: RequestInit,\n ) =>\n Effect.promise(() =>\n this.mountedHttp.fetch(this.testConvex, pathQueryFragment, init),\n );\n\n readonly finishInProgressScheduledFunctions = () =>\n Effect.promise(() => this.testConvex.finishInProgressScheduledFunctions());\n\n readonly finishAllScheduledFunctions = (advanceTimers: () => void) =>\n Effect.promise(() =>\n this.testConvex.finishAllScheduledFunctions(advanceTimers),\n );\n}\n\nclass TestConfectImpl<\n ConfectSchema extends DatabaseSchema.AnyWithProps,\n> implements TestConfect<ConfectSchema> {\n private readonly testConfectImplWithoutIdentity: TestConfectImplWithoutIdentity<ConfectSchema>;\n\n constructor(\n private confectSchema: ConfectSchema,\n private testConvex: TestConvexForDataModelAndIdentity<\n DataModel.ToConvex<DataModel.FromSchema<ConfectSchema>>\n >,\n private mountedHttp: ReturnType<typeof MountedHttp.make>,\n ) {\n this.testConfectImplWithoutIdentity = new TestConfectImplWithoutIdentity(\n confectSchema,\n testConvex,\n mountedHttp,\n );\n }\n\n readonly withIdentity = (userIdentity: Partial<UserIdentity>) =>\n new TestConfectImplWithoutIdentity(\n this.confectSchema,\n this.testConvex.withIdentity(userIdentity),\n this.mountedHttp,\n );\n\n readonly registerComponent: TestConfect<ConfectSchema>[\"registerComponent\"] =\n Effect.fn(\"TestConfect.registerComponent\")(\n (componentPath, schema, modules, options) =>\n Effect.sync(() =>\n this.mountedHttp.register(componentPath, schema, modules, options),\n ),\n );\n\n readonly query = <QueryRef extends Ref.AnyQuery>(\n queryRef: QueryRef,\n ...args: Ref.OptionalArgs<QueryRef>\n ) => this.testConfectImplWithoutIdentity.query(queryRef, ...args);\n\n readonly mutation = <MutationRef extends Ref.AnyMutation>(\n mutationRef: MutationRef,\n ...args: Ref.OptionalArgs<MutationRef>\n ) => this.testConfectImplWithoutIdentity.mutation(mutationRef, ...args);\n\n readonly action = <ActionRef extends Ref.AnyAction>(\n actionRef: ActionRef,\n ...args: Ref.OptionalArgs<ActionRef>\n ) => this.testConfectImplWithoutIdentity.action(actionRef, ...args);\n\n readonly run: TestConfect<ConfectSchema>[\"run\"] = ((\n handler: any,\n returns?: any,\n ) =>\n this.testConfectImplWithoutIdentity.run(\n handler,\n returns,\n )) as TestConfect<ConfectSchema>[\"run\"];\n\n readonly fetch = <PathQueryFragment extends string>(\n pathQueryFragment: PathQueryFragment,\n init?: RequestInit,\n ) => this.testConfectImplWithoutIdentity.fetch(pathQueryFragment, init);\n\n readonly finishInProgressScheduledFunctions = () =>\n this.testConfectImplWithoutIdentity.finishInProgressScheduledFunctions();\n\n readonly finishAllScheduledFunctions = (advanceTimers: () => void) =>\n this.testConfectImplWithoutIdentity.finishAllScheduledFunctions(\n advanceTimers,\n );\n}\n\n/**\n * How a test registers one installed component: its own schema and modules, or\n * the `register(t, name)` a component package exports from `<package>/testing`\n * or `<package>/test`, which also registers the package's own children.\n */\nexport type ComponentKit =\n | {\n readonly schema: SchemaDefinition<GenericSchema, boolean>;\n readonly modules: Record<string, () => Promise<any>>;\n }\n | {\n register(\n t: { readonly registerComponent: RegisterComponent },\n name: string,\n ): unknown;\n };\n\nclass InvalidComponentKit extends Schema.TaggedError<InvalidComponentKit>()(\n \"InvalidComponentKit\",\n { componentPath: Schema.String, message: Schema.String },\n) {}\n\nconst registerKit = (\n registerComponent: RegisterComponent,\n name: string,\n kit: ComponentKit,\n) => {\n if (\"register\" in kit) {\n kit.register({ registerComponent }, name);\n } else if (\"schema\" in kit && \"modules\" in kit) {\n registerComponent(name, kit.schema, kit.modules);\n } else {\n // Codegen accepts a kit whose exports it cannot list, such as CommonJS.\n throw new InvalidComponentKit({\n componentPath: name,\n message: `The test kit for ${JSON.stringify(name)} must export register(t, name), or schema and modules.`,\n });\n }\n};\n\n/**\n * Codegen's test-only schema and module registry.\n */\nexport type Registry<DatabaseSchema_ extends DatabaseSchema.AnyWithProps> = {\n readonly schema: DatabaseSchema_;\n readonly convexSchema: SchemaDefinition<GenericSchema, true>;\n readonly modules: Record<string, () => Promise<any>>;\n readonly components: Readonly<Record<string, ComponentKit>>;\n /**\n * The secret policy codegen derives from the Confect specs, read by the\n * kernel target only.\n */\n readonly secrets?: SecretPolicy;\n};\n\n/**\n * The declared app's generated, test-only representation.\n */\nexport type DeclaredApp<DatabaseSchema_ extends DatabaseSchema.AnyWithProps> =\n Registry<DatabaseSchema_> & {\n readonly httpMounts: ReadonlyArray<HttpMount>;\n };\n\n/**\n * Build a fresh test backend from a declaration and its generated\n * `confect/_generated/testing` registry, without restating component mounts.\n * Pass `{ target: \"kernel\" }` to run it on Confect's test kernel instead of\n * convex-test.\n */\nexport function layer<DatabaseSchema_ extends DatabaseSchema.AnyWithProps>(\n app: DeclaredApp<DatabaseSchema_>,\n options?: TargetOptions,\n): Layer.Layer<TestConfect<DatabaseSchema_>>;\nexport function layer<\n A extends App.Any,\n DatabaseSchema_ extends DatabaseSchema.AnyWithProps,\n>(\n app: A,\n registry: Registry<DatabaseSchema_> & {\n readonly components: Readonly<\n Record<\n Mount.NameOf<NoInfer<A>[\"mounts\"][number]>,\n Registry<DatabaseSchema_>[\"components\"][string]\n >\n >;\n },\n options?: TargetOptions,\n): Layer.Layer<TestConfect<DatabaseSchema_>>;\nexport function layer<DatabaseSchema_ extends DatabaseSchema.AnyWithProps>(\n databaseSchema: DatabaseSchema_,\n convexSchemaDefinition: SchemaDefinition<GenericSchema, true>,\n modules: Record<string, () => Promise<any>>,\n options?: LayerOptions,\n): Layer.Layer<TestConfect<DatabaseSchema_>>;\nexport function layer<DatabaseSchema_ extends DatabaseSchema.AnyWithProps>(\n appOrSchema: App.Any | DeclaredApp<DatabaseSchema_> | DatabaseSchema_,\n second?:\n | Registry<DatabaseSchema_>\n | SchemaDefinition<GenericSchema, true>\n | TargetOptions,\n third?: Record<string, () => Promise<any>> | TargetOptions,\n options: LayerOptions = {},\n): Layer.Layer<TestConfect<DatabaseSchema_>> {\n if (App.isApp(appOrSchema)) {\n const registry = second as Registry<DatabaseSchema_>;\n const mounts = App.mounts(appOrSchema);\n return schemaLayer(\n registry.schema,\n registry.convexSchema,\n registry.modules,\n {\n ...targetOf(third as TargetOptions | undefined),\n ...secretsOf(registry),\n httpMounts: mounts.flatMap(({ name, httpPrefix }) =>\n httpPrefix === undefined ? [] : [{ componentPath: name, httpPrefix }],\n ),\n register: (registerComponent) => {\n for (const [name, component] of Object.entries(registry.components)) {\n if (\n mounts.some(\n (mount) =>\n name === mount.name || name.startsWith(`${mount.name}/`),\n )\n ) {\n registerKit(registerComponent, name, component);\n }\n }\n },\n },\n );\n }\n if (\"httpMounts\" in appOrSchema) {\n const app = appOrSchema as DeclaredApp<DatabaseSchema_>;\n return schemaLayer(app.schema, app.convexSchema, app.modules, {\n ...targetOf(second as TargetOptions | undefined),\n ...secretsOf(app),\n httpMounts: app.httpMounts,\n register: (registerComponent) => {\n for (const [name, component] of Object.entries(app.components)) {\n registerKit(registerComponent, name, component);\n }\n },\n });\n }\n return schemaLayer(\n appOrSchema as DatabaseSchema_,\n second as SchemaDefinition<GenericSchema, true>,\n third as Record<string, () => Promise<any>>,\n options,\n );\n}\n\nconst targetOf = (options: TargetOptions | undefined): TargetOptions =>\n options?.target === undefined ? {} : { target: options.target };\n\nconst secretsOf = (registry: {\n readonly secrets?: SecretPolicy;\n}): Pick<LayerOptions, \"secrets\"> =>\n registry.secrets === undefined ? {} : { secrets: registry.secrets };\n\nconst schemaLayer = <DatabaseSchema_ extends DatabaseSchema.AnyWithProps>(\n databaseSchema: DatabaseSchema_,\n convexSchemaDefinition: SchemaDefinition<GenericSchema, true>,\n modules: Record<string, () => Promise<any>>,\n options: LayerOptions = {},\n): Layer.Layer<TestConfect<DatabaseSchema_>> =>\n Layer.sync(TestConfect<DatabaseSchema_>(), () => {\n process.env.CONVEX_CLOUD_URL ??= \"https://some-deployment.convex.cloud\";\n process.env.CONVEX_SITE_URL ??= \"https://some.convex.site\";\n // On the kernel, a value under a secret node of the app's table schemas,\n // or of the policy's functions and component tables, reaches every\n // artifact as a marker.\n const testConvex =\n options.target === \"kernel\"\n ? kernelTest({\n schema: convexSchemaDefinition,\n modules,\n redaction: Redaction.policy(\n Redaction.merge(\n { tables: { \"\": Redaction.tablesOf(databaseSchema) } },\n options.secrets ?? {},\n ),\n ),\n })\n : convexTest(convexSchemaDefinition, modules);\n // convex-test takes three arguments and ignores the options. The kernel\n // reads `standing`.\n const registerComponent =\n testConvex.registerComponent as unknown as RegisterComponent;\n const mountedHttp = MountedHttp.make(options.httpMounts ?? [], (...args) =>\n registerComponent(...args),\n );\n options.register?.(mountedHttp.register);\n return new TestConfectImpl(databaseSchema, testConvex as any, mountedHttp);\n });\n"],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Attempt as AttemptNumber } from "./Invocation.js";
|
|
2
2
|
import * as Kernel from "./Kernel.js";
|
|
3
3
|
import type { DocumentId, StoredDocument } from "./KernelValues.js";
|
|
4
|
+
import * as Metering from "./Metering.js";
|
|
4
5
|
import type * as ReadSet from "./ReadSet.js";
|
|
5
6
|
/**
|
|
6
7
|
* One frame of an attempt at a query or mutation: the committed state the
|
|
@@ -28,12 +29,18 @@ export declare class KernelAttempt {
|
|
|
28
29
|
private readonly overlay;
|
|
29
30
|
private readonly life;
|
|
30
31
|
private readonly allReads;
|
|
32
|
+
/**
|
|
33
|
+
* The attempt's transaction-limit accounting. A nested mutation's frame
|
|
34
|
+
* meters into its own child, so its writes merge or drop with it while its
|
|
35
|
+
* reads stay.
|
|
36
|
+
*/
|
|
37
|
+
readonly meter: Metering.Meter;
|
|
31
38
|
/**
|
|
32
39
|
* Whether the attempt asked for its caller's identity, and the time it read.
|
|
33
40
|
* Every frame of the attempt shares them, as it shares the reads.
|
|
34
41
|
*/
|
|
35
42
|
private readonly observed;
|
|
36
|
-
constructor(snapshot: Kernel.State, number?: AttemptNumber, parent?: KernelAttempt | undefined);
|
|
43
|
+
constructor(snapshot: Kernel.State, number?: AttemptNumber, parent?: KernelAttempt | undefined, meter?: Metering.Meter);
|
|
37
44
|
get reads(): ReadonlyArray<ReadSet.Read>;
|
|
38
45
|
/**
|
|
39
46
|
* Whether the function asked for its caller's identity.
|
|
@@ -74,6 +81,12 @@ export declare class KernelAttempt {
|
|
|
74
81
|
*/
|
|
75
82
|
scan(componentPath: string, tableName: string): Array<StoredDocument>;
|
|
76
83
|
write(componentPath: string, id: DocumentId, doc: StoredDocument | null): void;
|
|
84
|
+
/**
|
|
85
|
+
* A query run on this attempt's snapshot rather than its pending writes. It
|
|
86
|
+
* reads and meters on its own, and its meter starts with this attempt's
|
|
87
|
+
* scheduling counters, as the binary's snapshot clone does.
|
|
88
|
+
*/
|
|
89
|
+
staleSnapshot(): KernelAttempt;
|
|
77
90
|
/**
|
|
78
91
|
* A nested mutation begins, in a frame of its own. Dropping a failed one is
|
|
79
92
|
* forgetting it.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Attempt.d.ts","sourceRoot":"","sources":["../../src/internal/Attempt.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEpE,OAAO,KAAK,KAAK,OAAO,MAAM,cAAc,CAAC;AAiB7C;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,aAAa;
|
|
1
|
+
{"version":3,"file":"Attempt.d.ts","sourceRoot":"","sources":["../../src/internal/Attempt.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEpE,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAC1C,OAAO,KAAK,KAAK,OAAO,MAAM,cAAc,CAAC;AAiB7C;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,aAAa;IAiBtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK;IAC/B,QAAQ,CAAC,MAAM,EAAE,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;IAlB1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsB;IAC9C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgD;IACrE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsB;IAC/C;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC;IAC/B;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA6C;IAEtE,YACW,QAAQ,EAAE,MAAM,CAAC,KAAK,EACtB,MAAM,GAAE,aAAiB,EACjB,MAAM,CAAC,EAAE,aAAa,YAAA,EACvC,KAAK,CAAC,EAAE,QAAQ,CAAC,KAAK,EAKvB;IAED,IAAI,KAAK,IAAI,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,CAEvC;IAED;;OAEG;IACH,IAAI,gBAAgB,IAAI,OAAO,CAE9B;IAED;;OAEG;IACH,IAAI,YAAY,IAAI,MAAM,GAAG,IAAI,CAEhC;IAED,eAAe,SAEd;IAED,WAAW,CAAC,EAAE,EAAE,MAAM,QAErB;IAED,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,YAAY,CAAC,aAAa,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,QAEjD;IAED;;;OAGG;IACH,YAAY,CACV,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,SAAS,CAAC,GAC1C,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,GAAG,KAAK,KAAK,IAAI,CAMxC;IAED;;OAEG;IACH,KAAK,IAAI,MAAM,IAAI,CAOlB;IAED;;;;OAIG;IACH,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAOvB;IAED,KAAK,SAEJ;IAED;;OAEG;IACH,OAAO,CAAC,QAAQ;IAMhB,GAAG,CAAC,aAAa,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,GAAG,cAAc,GAAG,IAAI,CAMhE;IAED;;;OAGG;IACH,IAAI,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,KAAK,CAAC,cAAc,CAAC,CAapE;IAED,KAAK,CAAC,aAAa,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,cAAc,GAAG,IAAI,QAItE;IAED;;;;OAIG;IACH,aAAa,IAAI,aAAa,CAO7B;IAED;;;OAGG;IACH,KAAK,IAAI,aAAa,CAErB;IAED;;;OAGG;IACH,KAAK,SAUJ;IAED;;OAEG;IACH,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAI5B;CACF"}
|
package/dist/internal/Attempt.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { tableNameFromId } from "./KernelValues.js";
|
|
2
2
|
import { get, rows } from "./Kernel.js";
|
|
3
|
+
import { Meter } from "./Metering.js";
|
|
3
4
|
import { setImmediate } from "node:timers/promises";
|
|
4
5
|
//#region src/internal/Attempt.ts
|
|
5
6
|
/**
|
|
@@ -33,15 +34,22 @@ var KernelAttempt = class KernelAttempt {
|
|
|
33
34
|
};
|
|
34
35
|
allReads;
|
|
35
36
|
/**
|
|
37
|
+
* The attempt's transaction-limit accounting. A nested mutation's frame
|
|
38
|
+
* meters into its own child, so its writes merge or drop with it while its
|
|
39
|
+
* reads stay.
|
|
40
|
+
*/
|
|
41
|
+
meter;
|
|
42
|
+
/**
|
|
36
43
|
* Whether the attempt asked for its caller's identity, and the time it read.
|
|
37
44
|
* Every frame of the attempt shares them, as it shares the reads.
|
|
38
45
|
*/
|
|
39
46
|
observed;
|
|
40
|
-
constructor(snapshot, number = 1, parent) {
|
|
47
|
+
constructor(snapshot, number = 1, parent, meter) {
|
|
41
48
|
this.snapshot = snapshot;
|
|
42
49
|
this.number = number;
|
|
43
50
|
this.parent = parent;
|
|
44
51
|
this.allReads = parent?.allReads ?? [];
|
|
52
|
+
this.meter = meter ?? parent?.meter.child() ?? new Meter();
|
|
45
53
|
this.observed = parent?.observed ?? {
|
|
46
54
|
identity: false,
|
|
47
55
|
time: null
|
|
@@ -149,6 +157,14 @@ var KernelAttempt = class KernelAttempt {
|
|
|
149
157
|
writes.set(id, doc);
|
|
150
158
|
}
|
|
151
159
|
/**
|
|
160
|
+
* A query run on this attempt's snapshot rather than its pending writes. It
|
|
161
|
+
* reads and meters on its own, and its meter starts with this attempt's
|
|
162
|
+
* scheduling counters, as the binary's snapshot clone does.
|
|
163
|
+
*/
|
|
164
|
+
staleSnapshot() {
|
|
165
|
+
return new KernelAttempt(this.snapshot, this.number, void 0, this.meter.forStaleSnapshot());
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
152
168
|
* A nested mutation begins, in a frame of its own. Dropping a failed one is
|
|
153
169
|
* forgetting it.
|
|
154
170
|
*/
|
|
@@ -163,6 +179,7 @@ var KernelAttempt = class KernelAttempt {
|
|
|
163
179
|
if (this.parent === void 0) throw new Error("The outermost frame of an attempt has no caller.");
|
|
164
180
|
if (this.life.open) throw new Error("A nested mutation's frame merges only once closed.");
|
|
165
181
|
for (const [componentPath, writes] of this.overlay) for (const [id, doc] of writes) this.parent.write(componentPath, id, doc);
|
|
182
|
+
this.meter.merge();
|
|
166
183
|
}
|
|
167
184
|
/**
|
|
168
185
|
* The outermost frame's writes, for `Kernel.apply`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Attempt.js","names":["Kernel.get","Kernel.rows"],"sources":["../../src/internal/Attempt.ts"],"sourcesContent":["// oxlint-disable-next-line effecttsgo/node-builtin-import, no-restricted-imports -- An attempt's drain waits one real turn of the event loop, which is no deadline. Fake timers in a test replace the global `setImmediate`, not this one.\nimport { setImmediate } from \"node:timers/promises\";\nimport type { Attempt as AttemptNumber } from \"./Invocation.js\";\nimport * as Kernel from \"./Kernel.js\";\nimport type { DocumentId, StoredDocument } from \"./KernelValues.js\";\nimport { tableNameFromId } from \"./KernelValues.js\";\nimport type * as ReadSet from \"./ReadSet.js\";\n\n/**\n * Pending writes, keyed by component path, then document ID. `null` deletes.\n */\ntype Overlay = Map<string, Map<DocumentId, StoredDocument | null>>;\n\n/**\n * How long one frame takes syscalls: those it has running, those it has\n * started, and whether it still takes them.\n */\ninterface Life {\n running: number;\n started: number;\n open: boolean;\n}\n\n/**\n * One frame of an attempt at a query or mutation: the committed state the\n * attempt started from, its caller's frame and its own pending writes. The\n * outermost frame belongs to the top-level function. Each nested mutation opens\n * a child frame, which merges into its caller's frame when it returns and is\n * dropped when it fails. Reads belong to the whole attempt and are never\n * dropped: a failed nested mutation's reads stay in the attempt.\n *\n * Each frame has its own lifetime. A frame takes reads and writes until it is\n * closed. A mutation's frame closes once its function has returned and no\n * syscall it started is still running, so a write a detached fiber makes after\n * the handler settled still lands in it, as on the binary. A nested mutation's\n * frame closes before it merges into its caller's, so no write reaches it after\n * its writes became its caller's.\n *\n * A frame belongs to one invocation, which alone writes to it, so a caller's\n * write made while its nested mutation is in flight stays the caller's.\n * `Kernel.apply` publishes the outermost frame's writes.\n */\nexport class KernelAttempt {\n private readonly overlay: Overlay = new Map();\n private readonly life: Life = { running: 0, started: 0, open: true };\n private readonly allReads: Array<ReadSet.Read>;\n /**\n * Whether the attempt asked for its caller's identity, and the time it read.\n * Every frame of the attempt shares them, as it shares the reads.\n */\n private readonly observed: { identity: boolean; time: number | null };\n\n constructor(\n readonly snapshot: Kernel.State,\n readonly number: AttemptNumber = 1,\n private readonly parent?: KernelAttempt,\n ) {\n this.allReads = parent?.allReads ?? [];\n this.observed = parent?.observed ?? { identity: false, time: null };\n }\n\n get reads(): ReadonlyArray<ReadSet.Read> {\n return this.allReads;\n }\n\n /**\n * Whether the function asked for its caller's identity.\n */\n get observedIdentity(): boolean {\n return this.observed.identity;\n }\n\n /**\n * The pinned time the function read, or `null` when it never read the time.\n */\n get observedTime(): number | null {\n return this.observed.time;\n }\n\n observeIdentity() {\n this.observed.identity = true;\n }\n\n observeTime(at: number) {\n this.observed.time = at;\n }\n\n get closed(): boolean {\n return !this.life.open;\n }\n\n readDocument(componentPath: string, id: DocumentId) {\n this.allReads.push({ kind: \"document\", componentPath, id });\n }\n\n /**\n * Record a read of an interval. The returned function advances how far the\n * query examined it.\n */\n readInterval(\n read: Omit<ReadSet.IntervalRead, \"through\">,\n ): (through: ReadSet.Key | \"end\") => void {\n const interval: ReadSet.IntervalRead = { ...read, through: null };\n this.allReads.push(interval);\n return (through) => {\n interval.through = through;\n };\n }\n\n /**\n * A syscall began. `end` runs when it settles.\n */\n begin(): () => void {\n const life = this.life;\n life.running++;\n life.started++;\n return () => {\n life.running--;\n };\n }\n\n /**\n * Resolves once a whole turn of the event loop passes with no syscall of this\n * frame running or started. A nested call is a syscall of its caller's frame\n * until it has drained.\n */\n drained(): Promise<void> {\n const before = this.life.started;\n return setImmediate().then(() =>\n this.life.running === 0 && this.life.started === before\n ? undefined\n : this.drained(),\n );\n }\n\n close() {\n this.life.open = false;\n }\n\n /**\n * The pending writes this frame sees, from the outermost frame to this one.\n */\n private overlays(): Array<Overlay> {\n return this.parent === undefined\n ? [this.overlay]\n : [...this.parent.overlays(), this.overlay];\n }\n\n get(componentPath: string, id: DocumentId): StoredDocument | null {\n for (const overlay of this.overlays().toReversed()) {\n const write = overlay.get(componentPath)?.get(id);\n if (write !== undefined) return write;\n }\n return Kernel.get(this.snapshot, componentPath, id)?.doc ?? null;\n }\n\n /**\n * The table as this frame sees it, committed rows under every pending write\n * from the outermost frame to this one.\n */\n scan(componentPath: string, tableName: string): Array<StoredDocument> {\n const ids = new Set<DocumentId>();\n for (const row of Kernel.rows(this.snapshot, componentPath, tableName))\n ids.add(row.doc._id);\n for (const overlay of this.overlays())\n for (const id of overlay.get(componentPath)?.keys() ?? [])\n if (tableNameFromId(id) === tableName) ids.add(id);\n const docs: Array<StoredDocument> = [];\n for (const id of ids) {\n const doc = this.get(componentPath, id);\n if (doc !== null) docs.push(doc);\n }\n return docs;\n }\n\n write(componentPath: string, id: DocumentId, doc: StoredDocument | null) {\n const writes = this.overlay.get(componentPath) ?? new Map();\n this.overlay.set(componentPath, writes);\n writes.set(id, doc);\n }\n\n /**\n * A nested mutation begins, in a frame of its own. Dropping a failed one is\n * forgetting it.\n */\n child(): KernelAttempt {\n return new KernelAttempt(this.snapshot, this.number, this);\n }\n\n /**\n * A nested mutation returned and its frame closed. Its writes become its\n * caller's.\n */\n merge() {\n if (this.parent === undefined) {\n throw new Error(\"The outermost frame of an attempt has no caller.\");\n }\n if (this.life.open) {\n throw new Error(\"A nested mutation's frame merges only once closed.\");\n }\n for (const [componentPath, writes] of this.overlay)\n for (const [id, doc] of writes) this.parent.write(componentPath, id, doc);\n }\n\n /**\n * The outermost frame's writes, for `Kernel.apply`.\n */\n writes(): Array<Kernel.Write> {\n return Array.from(this.overlay, ([componentPath, writes]) =>\n Array.from(writes, ([id, doc]) => ({ componentPath, id, doc })),\n ).flat();\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Attempt.js","names":["Metering.Meter","Kernel.get","Kernel.rows"],"sources":["../../src/internal/Attempt.ts"],"sourcesContent":["// oxlint-disable-next-line effecttsgo/node-builtin-import, no-restricted-imports -- An attempt's drain waits one real turn of the event loop, which is no deadline. Fake timers in a test replace the global `setImmediate`, not this one.\nimport { setImmediate } from \"node:timers/promises\";\nimport type { Attempt as AttemptNumber } from \"./Invocation.js\";\nimport * as Kernel from \"./Kernel.js\";\nimport type { DocumentId, StoredDocument } from \"./KernelValues.js\";\nimport { tableNameFromId } from \"./KernelValues.js\";\nimport * as Metering from \"./Metering.js\";\nimport type * as ReadSet from \"./ReadSet.js\";\n\n/**\n * Pending writes, keyed by component path, then document ID. `null` deletes.\n */\ntype Overlay = Map<string, Map<DocumentId, StoredDocument | null>>;\n\n/**\n * How long one frame takes syscalls: those it has running, those it has\n * started, and whether it still takes them.\n */\ninterface Life {\n running: number;\n started: number;\n open: boolean;\n}\n\n/**\n * One frame of an attempt at a query or mutation: the committed state the\n * attempt started from, its caller's frame and its own pending writes. The\n * outermost frame belongs to the top-level function. Each nested mutation opens\n * a child frame, which merges into its caller's frame when it returns and is\n * dropped when it fails. Reads belong to the whole attempt and are never\n * dropped: a failed nested mutation's reads stay in the attempt.\n *\n * Each frame has its own lifetime. A frame takes reads and writes until it is\n * closed. A mutation's frame closes once its function has returned and no\n * syscall it started is still running, so a write a detached fiber makes after\n * the handler settled still lands in it, as on the binary. A nested mutation's\n * frame closes before it merges into its caller's, so no write reaches it after\n * its writes became its caller's.\n *\n * A frame belongs to one invocation, which alone writes to it, so a caller's\n * write made while its nested mutation is in flight stays the caller's.\n * `Kernel.apply` publishes the outermost frame's writes.\n */\nexport class KernelAttempt {\n private readonly overlay: Overlay = new Map();\n private readonly life: Life = { running: 0, started: 0, open: true };\n private readonly allReads: Array<ReadSet.Read>;\n /**\n * The attempt's transaction-limit accounting. A nested mutation's frame\n * meters into its own child, so its writes merge or drop with it while its\n * reads stay.\n */\n readonly meter: Metering.Meter;\n /**\n * Whether the attempt asked for its caller's identity, and the time it read.\n * Every frame of the attempt shares them, as it shares the reads.\n */\n private readonly observed: { identity: boolean; time: number | null };\n\n constructor(\n readonly snapshot: Kernel.State,\n readonly number: AttemptNumber = 1,\n private readonly parent?: KernelAttempt,\n meter?: Metering.Meter,\n ) {\n this.allReads = parent?.allReads ?? [];\n this.meter = meter ?? parent?.meter.child() ?? new Metering.Meter();\n this.observed = parent?.observed ?? { identity: false, time: null };\n }\n\n get reads(): ReadonlyArray<ReadSet.Read> {\n return this.allReads;\n }\n\n /**\n * Whether the function asked for its caller's identity.\n */\n get observedIdentity(): boolean {\n return this.observed.identity;\n }\n\n /**\n * The pinned time the function read, or `null` when it never read the time.\n */\n get observedTime(): number | null {\n return this.observed.time;\n }\n\n observeIdentity() {\n this.observed.identity = true;\n }\n\n observeTime(at: number) {\n this.observed.time = at;\n }\n\n get closed(): boolean {\n return !this.life.open;\n }\n\n readDocument(componentPath: string, id: DocumentId) {\n this.allReads.push({ kind: \"document\", componentPath, id });\n }\n\n /**\n * Record a read of an interval. The returned function advances how far the\n * query examined it.\n */\n readInterval(\n read: Omit<ReadSet.IntervalRead, \"through\">,\n ): (through: ReadSet.Key | \"end\") => void {\n const interval: ReadSet.IntervalRead = { ...read, through: null };\n this.allReads.push(interval);\n return (through) => {\n interval.through = through;\n };\n }\n\n /**\n * A syscall began. `end` runs when it settles.\n */\n begin(): () => void {\n const life = this.life;\n life.running++;\n life.started++;\n return () => {\n life.running--;\n };\n }\n\n /**\n * Resolves once a whole turn of the event loop passes with no syscall of this\n * frame running or started. A nested call is a syscall of its caller's frame\n * until it has drained.\n */\n drained(): Promise<void> {\n const before = this.life.started;\n return setImmediate().then(() =>\n this.life.running === 0 && this.life.started === before\n ? undefined\n : this.drained(),\n );\n }\n\n close() {\n this.life.open = false;\n }\n\n /**\n * The pending writes this frame sees, from the outermost frame to this one.\n */\n private overlays(): Array<Overlay> {\n return this.parent === undefined\n ? [this.overlay]\n : [...this.parent.overlays(), this.overlay];\n }\n\n get(componentPath: string, id: DocumentId): StoredDocument | null {\n for (const overlay of this.overlays().toReversed()) {\n const write = overlay.get(componentPath)?.get(id);\n if (write !== undefined) return write;\n }\n return Kernel.get(this.snapshot, componentPath, id)?.doc ?? null;\n }\n\n /**\n * The table as this frame sees it, committed rows under every pending write\n * from the outermost frame to this one.\n */\n scan(componentPath: string, tableName: string): Array<StoredDocument> {\n const ids = new Set<DocumentId>();\n for (const row of Kernel.rows(this.snapshot, componentPath, tableName))\n ids.add(row.doc._id);\n for (const overlay of this.overlays())\n for (const id of overlay.get(componentPath)?.keys() ?? [])\n if (tableNameFromId(id) === tableName) ids.add(id);\n const docs: Array<StoredDocument> = [];\n for (const id of ids) {\n const doc = this.get(componentPath, id);\n if (doc !== null) docs.push(doc);\n }\n return docs;\n }\n\n write(componentPath: string, id: DocumentId, doc: StoredDocument | null) {\n const writes = this.overlay.get(componentPath) ?? new Map();\n this.overlay.set(componentPath, writes);\n writes.set(id, doc);\n }\n\n /**\n * A query run on this attempt's snapshot rather than its pending writes. It\n * reads and meters on its own, and its meter starts with this attempt's\n * scheduling counters, as the binary's snapshot clone does.\n */\n staleSnapshot(): KernelAttempt {\n return new KernelAttempt(\n this.snapshot,\n this.number,\n undefined,\n this.meter.forStaleSnapshot(),\n );\n }\n\n /**\n * A nested mutation begins, in a frame of its own. Dropping a failed one is\n * forgetting it.\n */\n child(): KernelAttempt {\n return new KernelAttempt(this.snapshot, this.number, this);\n }\n\n /**\n * A nested mutation returned and its frame closed. Its writes become its\n * caller's.\n */\n merge() {\n if (this.parent === undefined) {\n throw new Error(\"The outermost frame of an attempt has no caller.\");\n }\n if (this.life.open) {\n throw new Error(\"A nested mutation's frame merges only once closed.\");\n }\n for (const [componentPath, writes] of this.overlay)\n for (const [id, doc] of writes) this.parent.write(componentPath, id, doc);\n this.meter.merge();\n }\n\n /**\n * The outermost frame's writes, for `Kernel.apply`.\n */\n writes(): Array<Kernel.Write> {\n return Array.from(this.overlay, ([componentPath, writes]) =>\n Array.from(writes, ([id, doc]) => ({ componentPath, id, doc })),\n ).flat();\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { GenericSchema, SchemaDefinition, UserIdentity } from "convex/server";
|
|
2
2
|
import * as Execution from "./Execution.js";
|
|
3
|
+
import type * as Invocation from "./Invocation.js";
|
|
4
|
+
import type * as Redaction from "./Redaction.js";
|
|
3
5
|
import type * as Kernel from "./Kernel.js";
|
|
4
6
|
import * as Subscriptions from "./Subscriptions.js";
|
|
5
7
|
import type * as Scheduling from "./Scheduling.js";
|
|
@@ -52,6 +54,26 @@ export interface KernelControls {
|
|
|
52
54
|
* clock, so it never calls `advanceTimers`.
|
|
53
55
|
*/
|
|
54
56
|
readonly finishAllScheduledFunctions: (advanceTimers?: () => void, maxIterations?: number) => Promise<void>;
|
|
57
|
+
/**
|
|
58
|
+
* The committed state as snapshot bytes, bound to their SHA-256 digest. Two
|
|
59
|
+
* exports of the same state are the same bytes.
|
|
60
|
+
*/
|
|
61
|
+
readonly exportSnapshot: () => Uint8Array;
|
|
62
|
+
/**
|
|
63
|
+
* Replace a fresh backend's state with a snapshot's. Each job's world
|
|
64
|
+
* resolves by name among `worlds`. Tampered bytes refuse with
|
|
65
|
+
* `SnapshotDigestMismatch`.
|
|
66
|
+
*/
|
|
67
|
+
readonly restoreSnapshot: (bytes: Uint8Array, options?: {
|
|
68
|
+
readonly worlds?: ReadonlyArray<Invocation.World>;
|
|
69
|
+
readonly secrets?: Redaction.Secrets;
|
|
70
|
+
}) => Promise<void>;
|
|
71
|
+
/**
|
|
72
|
+
* A copy of the raw secrets the backend has seen under a secret schema node.
|
|
73
|
+
* A snapshot marks each one, and a restore given this copy puts them back. It
|
|
74
|
+
* lives in memory and is never written to an artifact.
|
|
75
|
+
*/
|
|
76
|
+
readonly secrets: () => Redaction.Secrets;
|
|
55
77
|
}
|
|
56
78
|
/**
|
|
57
79
|
* How a kit registers a component beyond its schema and modules.
|
|
@@ -75,13 +97,16 @@ export interface RegisterOptions {
|
|
|
75
97
|
* attempt 5. `runtime` supplies the clock and commit timestamps. Scheduled
|
|
76
98
|
* functions run on the kernel's clock, never on a host timer. A subscriber's
|
|
77
99
|
* subscriptions go stale when a commit changes what they read or the identity
|
|
78
|
-
* they read changes, and `refresh` reruns them.
|
|
100
|
+
* they read changes, and `refresh` reruns them. `redaction` names the secret
|
|
101
|
+
* schema nodes of tables and functions: a value under one reaches a snapshot, a
|
|
102
|
+
* failure report or a diff only as a marker.
|
|
79
103
|
*/
|
|
80
104
|
export declare function convexTest(schemaOrOptions?: SchemaDefinition<GenericSchema, boolean> | {
|
|
81
105
|
readonly schema?: SchemaDefinition<GenericSchema, boolean>;
|
|
82
106
|
readonly modules?: Modules;
|
|
83
107
|
readonly transactionLimits?: unknown;
|
|
84
108
|
readonly runtime?: Kernel.KernelRuntime;
|
|
109
|
+
readonly redaction?: Redaction.Policy;
|
|
85
110
|
}, modules?: Modules): any;
|
|
86
111
|
export {};
|
|
87
112
|
//# sourceMappingURL=ConvexTest.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConvexTest.d.ts","sourceRoot":"","sources":["../../src/internal/ConvexTest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,gBAAgB,EAChB,YAAY,EACb,MAAM,eAAe,CAAC;AAEvB,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAC;AAC5C,OAAO,KAAK,KAAK,MAAM,MAAM,aAAa,CAAC;AAE3C,OAAO,KAAK,aAAa,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,KAAK,UAAU,MAAM,iBAAiB,CAAC;AAEnD,KAAK,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;AAElD;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;IAC7D,QAAQ,CAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;IAChE,QAAQ,CAAC,MAAM,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;IAC9D,QAAQ,CAAC,OAAO,EAAE,CAChB,SAAS,EAAE,GAAG,EACd,IAAI,CAAC,EAAE,GAAG,KACP,OAAO,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAC/D,QAAQ,CAAC,IAAI,EAAE,MAAM,aAAa,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAC1D,QAAQ,CAAC,YAAY,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,YAAY,CAAC,KAAK,cAAc,CAAC;IAC3E,QAAQ,CAAC,mBAAmB,EAAE,CAAC,QAAQ,EAAE;QACvC,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KACpC,KAAK,cAAc,CAAC;IACrB;;OAEG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,aAAa,CAAC,UAAU,CAAC;IACpD;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC;IACzE;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC;IAC7E;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,aAAa,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IACnD;;OAEG;IACH,QAAQ,CAAC,kCAAkC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE;;;;OAIG;IACH,QAAQ,CAAC,2BAA2B,EAAE,CACpC,aAAa,CAAC,EAAE,MAAM,IAAI,EAC1B,aAAa,CAAC,EAAE,MAAM,KACnB,OAAO,CAAC,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"ConvexTest.d.ts","sourceRoot":"","sources":["../../src/internal/ConvexTest.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,31 +4,55 @@ import { Registry } from "./Subscriptions.js";
|
|
|
4
4
|
import { componentsGeneric } from "convex/server";
|
|
5
5
|
//#region src/internal/ConvexTest.ts
|
|
6
6
|
const isSchemaDefinition = (value) => value !== null && typeof value === "object" && "tables" in value && typeof value.tables === "object";
|
|
7
|
-
const accessor = (world, subscriptions, caller) =>
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
})
|
|
7
|
+
const accessor = (world, subscriptions, caller) => {
|
|
8
|
+
const reported = (run) => run().catch((error) => {
|
|
9
|
+
throw world.redactFailure(error);
|
|
10
|
+
});
|
|
11
|
+
const returnsOf = (subscription) => world.functionPathOf(subscriptions.referenceOf(subscription));
|
|
12
|
+
return {
|
|
13
|
+
query: (reference, args) => reported(() => world.query(caller, reference, args)),
|
|
14
|
+
mutation: (reference, args) => reported(() => world.mutation(caller, reference, args)),
|
|
15
|
+
action: (reference, args) => reported(() => world.action(caller, reference, args)),
|
|
16
|
+
prepare: (reference, args) => reported(() => world.prepare(caller, reference, args)).then((view) => world.projectHeld(view)),
|
|
17
|
+
apply: (id) => {
|
|
18
|
+
const functionPath = world.held().find((view) => view.id === id)?.functionPath;
|
|
19
|
+
return reported(() => world.apply(id)).then((applied) => world.projectApplied(applied, functionPath));
|
|
20
|
+
},
|
|
21
|
+
held: () => world.held().map((view) => world.projectHeld(view)),
|
|
22
|
+
subscriber: () => subscriptions.subscriber(caller),
|
|
23
|
+
refresh: () => reported(() => subscriptions.refresh()).then((transitions) => transitions.map((transition) => ({
|
|
24
|
+
...transition,
|
|
25
|
+
from: world.redactOutcome(transition.from, returnsOf(transition.subscription)),
|
|
26
|
+
to: world.redactOutcome(transition.to, returnsOf(transition.subscription)),
|
|
27
|
+
because: transition.because.kind === "commit" ? {
|
|
28
|
+
kind: "commit",
|
|
29
|
+
change: world.redactChange(transition.because.change)
|
|
30
|
+
} : transition.because
|
|
31
|
+
}))),
|
|
32
|
+
reference: () => reported(() => subscriptions.reference()).then((disagreements) => disagreements.map((disagreement) => ({
|
|
33
|
+
...disagreement,
|
|
34
|
+
incremental: world.redactOutcome(disagreement.incremental, returnsOf(disagreement.subscription)),
|
|
35
|
+
reference: world.redactOutcome(disagreement.reference, returnsOf(disagreement.subscription))
|
|
36
|
+
}))),
|
|
37
|
+
run: (handler) => reported(() => world.run(caller, "", handler)),
|
|
38
|
+
runInComponent: (componentPath, handler) => reported(() => world.run(caller, componentPath, handler)),
|
|
39
|
+
withIdentity: (identity) => accessor(world, subscriptions, withIdentity(caller, identity)),
|
|
40
|
+
withRequestMetadata: (metadata) => accessor(world, subscriptions, {
|
|
41
|
+
...caller,
|
|
42
|
+
ip: metadata.ip ?? null,
|
|
43
|
+
userAgent: metadata.userAgent ?? null
|
|
44
|
+
}),
|
|
45
|
+
fetch: () => Promise.reject(rowPending("HTTP routes", 6)),
|
|
46
|
+
jwks: () => Promise.reject(rowPending("JWT verification", 6)),
|
|
47
|
+
advance: (ms) => reported(() => world.advance(ms)),
|
|
48
|
+
jobs: () => world.jobs(),
|
|
49
|
+
finishInProgressScheduledFunctions: () => reported(() => world.advance(0)),
|
|
50
|
+
finishAllScheduledFunctions: (_advanceTimers, maxIterations) => reported(() => world.drain(maxIterations)),
|
|
51
|
+
exportSnapshot: () => world.exportSnapshot(),
|
|
52
|
+
restoreSnapshot: (bytes, options) => world.restoreSnapshot(bytes, options),
|
|
53
|
+
secrets: () => world.keptSecrets()
|
|
54
|
+
};
|
|
55
|
+
};
|
|
32
56
|
/**
|
|
33
57
|
* The test kernel under convex-test's `convexTest` signature. The fork's kernel
|
|
34
58
|
* lane aliases `convex-test` to this module, so every suite that calls
|
|
@@ -40,20 +64,24 @@ const accessor = (world, subscriptions, caller) => ({
|
|
|
40
64
|
* attempt 5. `runtime` supplies the clock and commit timestamps. Scheduled
|
|
41
65
|
* functions run on the kernel's clock, never on a host timer. A subscriber's
|
|
42
66
|
* subscriptions go stale when a commit changes what they read or the identity
|
|
43
|
-
* they read changes, and `refresh` reruns them.
|
|
67
|
+
* they read changes, and `refresh` reruns them. `redaction` names the secret
|
|
68
|
+
* schema nodes of tables and functions: a value under one reaches a snapshot, a
|
|
69
|
+
* failure report or a diff only as a marker.
|
|
44
70
|
*/
|
|
45
71
|
function convexTest(schemaOrOptions, modules) {
|
|
46
72
|
let schema;
|
|
47
73
|
let runtime;
|
|
74
|
+
let redaction;
|
|
48
75
|
if (isSchemaDefinition(schemaOrOptions)) schema = schemaOrOptions;
|
|
49
76
|
else if (schemaOrOptions !== void 0) {
|
|
50
77
|
if (schemaOrOptions.transactionLimits !== void 0) throw rowPending("transaction limits", 6);
|
|
51
78
|
schema = schemaOrOptions.schema;
|
|
52
79
|
modules = schemaOrOptions.modules;
|
|
53
80
|
runtime = schemaOrOptions.runtime;
|
|
81
|
+
redaction = schemaOrOptions.redaction;
|
|
54
82
|
}
|
|
55
83
|
if (modules === void 0) throw new Error("The test kernel needs the modules map: pass `import.meta.glob(...)` as the second argument.");
|
|
56
|
-
const world = new World(schema, modules, runtime);
|
|
84
|
+
const world = new World(schema, modules, runtime, redaction);
|
|
57
85
|
return {
|
|
58
86
|
...accessor(world, new Registry(world), anonymous),
|
|
59
87
|
registerComponent: (componentPath, componentSchema, componentModules, options) => {
|