@gaganref/confect-test 10.3.1-fork.92 → 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/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 +138 -1
- package/dist/internal/Execution.d.ts.map +1 -1
- package/dist/internal/Execution.js +595 -182
- package/dist/internal/Execution.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/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/ConvexTest.ts +135 -38
- package/src/internal/Execution.ts +886 -287
- package/src/internal/KernelRefusal.ts +160 -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,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) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConvexTest.js","names":["Execution.withIdentity","KernelRefusal.rowPending","Execution.World","Subscriptions.Registry","Execution.anonymous"],"sources":["../../src/internal/ConvexTest.ts"],"sourcesContent":["import type {\n GenericSchema,\n SchemaDefinition,\n UserIdentity,\n} from \"convex/server\";\nimport { componentsGeneric } from \"convex/server\";\nimport * as Execution from \"./Execution.js\";\nimport type * as Kernel from \"./Kernel.js\";\nimport * as KernelRefusal from \"./KernelRefusal.js\";\nimport * as Subscriptions from \"./Subscriptions.js\";\nimport type * as Scheduling from \"./Scheduling.js\";\n\ntype Modules = Record<string, () => Promise<any>>;\n\n/**\n * What the kernel adds to convex-test's surface, typed. The shim itself returns\n * `any`, as convex-test's callers expect.\n */\nexport interface KernelControls {\n readonly query: (reference: any, args?: any) => Promise<any>;\n readonly mutation: (reference: any, args?: any) => Promise<any>;\n readonly action: (reference: any, args?: any) => Promise<any>;\n readonly prepare: (\n reference: any,\n args?: any,\n ) => Promise<Execution.HeldAttempt>;\n readonly apply: (id: string) => Promise<Execution.KernelApply>;\n readonly held: () => ReadonlyArray<Execution.HeldAttempt>;\n readonly withIdentity: (identity: Partial<UserIdentity>) => KernelControls;\n readonly withRequestMetadata: (metadata: {\n readonly ip?: string | null;\n readonly userAgent?: string | null;\n }) => KernelControls;\n /**\n * A client's query set under this accessor's caller.\n */\n readonly subscriber: () => Subscriptions.Subscriber;\n /**\n * Rerun every stale subscription. Lists each one whose value changed.\n */\n readonly refresh: () => Promise<ReadonlyArray<Subscriptions.Transition>>;\n /**\n * Rerun every subscription from scratch. Lists each one whose value differs\n * from the full rerun.\n */\n readonly reference: () => Promise<ReadonlyArray<Subscriptions.Disagreement>>;\n /**\n * Move the kernel's clock forward, running each job due on the way at its\n * deadline.\n */\n readonly advance: (ms: number) => Promise<void>;\n /**\n * The pending jobs, earliest deadline first.\n */\n readonly jobs: () => ReadonlyArray<Scheduling.Job>;\n /**\n * Run the jobs due now. No future deadline is crossed.\n */\n readonly finishInProgressScheduledFunctions: () => Promise<void>;\n /**\n * Run jobs at their deadlines until only standing jobs remain, or fail with\n * `DrainBudgetExceeded` after `maxIterations` jobs. The kernel keeps its own\n * clock, so it never calls `advanceTimers`.\n */\n readonly finishAllScheduledFunctions: (\n advanceTimers?: () => void,\n maxIterations?: number,\n ) => Promise<void>;\n}\n\n/**\n * How a kit registers a component beyond its schema and modules.\n */\nexport interface 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`. A job that runs\n * one, or that one schedules, is never drain work.\n */\n readonly standing?: ReadonlyArray<string>;\n}\n\nconst isSchemaDefinition = (\n value: unknown,\n): value is SchemaDefinition<GenericSchema, boolean> =>\n value !== null &&\n typeof value === \"object\" &&\n \"tables\" in value &&\n typeof (value as { tables: unknown }).tables === \"object\";\n\nconst accessor = (\n world: Execution.World,\n subscriptions: Subscriptions.Registry,\n caller: Execution.Caller,\n): any => ({\n query: (reference: any, args?: any) => world.query(caller, reference, args),\n mutation: (reference: any, args?: any) =>\n world.mutation(caller, reference, args),\n action: (reference: any, args?: any) => world.action(caller, reference, args),\n prepare: (reference: any, args?: any) =>\n world.prepare(caller, reference, args),\n apply: (id: string) => world.apply(id),\n held: () => world.held(),\n subscriber: () => subscriptions.subscriber(caller),\n refresh: () => subscriptions.refresh(),\n reference: () => subscriptions.reference(),\n run: (handler: (ctx: any) => any) => world.run(caller, \"\", handler),\n runInComponent: (componentPath: string, handler: (ctx: any) => any) =>\n world.run(caller, componentPath, handler),\n withIdentity: (identity: Partial<UserIdentity>) =>\n accessor(world, subscriptions, Execution.withIdentity(caller, identity)),\n withRequestMetadata: (metadata: {\n readonly ip?: string | null;\n readonly userAgent?: string | null;\n }) =>\n accessor(world, subscriptions, {\n ...caller,\n ip: metadata.ip ?? null,\n userAgent: metadata.userAgent ?? null,\n }),\n fetch: () => Promise.reject(KernelRefusal.rowPending(\"HTTP routes\", 6)),\n jwks: () => Promise.reject(KernelRefusal.rowPending(\"JWT verification\", 6)),\n advance: (ms: number) => world.advance(ms),\n jobs: () => world.jobs(),\n finishInProgressScheduledFunctions: () => world.advance(0),\n finishAllScheduledFunctions: (\n _advanceTimers?: () => void,\n maxIterations?: number,\n ) => world.drain(maxIterations),\n});\n\n/**\n * The test kernel under convex-test's `convexTest` signature. The fork's kernel\n * lane aliases `convex-test` to this module, so every suite that calls\n * `convexTest` directly, and `TestConfect` itself, runs on the kernel.\n *\n * Beyond convex-test, `prepare` runs a mutation to its commit point and holds\n * it, and `apply` validates and publishes a held attempt. `mutation` applies\n * each attempt it prepares at once and prepares the next on a conflict, up to\n * attempt 5. `runtime` supplies the clock and commit timestamps. Scheduled\n * functions run on the kernel's clock, never on a host timer. A subscriber's\n * subscriptions go stale when a commit changes what they read or the identity\n * they read changes, and `refresh` reruns them.\n */\nexport function convexTest(\n schemaOrOptions?:\n | SchemaDefinition<GenericSchema, boolean>\n | {\n readonly schema?: SchemaDefinition<GenericSchema, boolean>;\n readonly modules?: Modules;\n readonly transactionLimits?: unknown;\n readonly runtime?: Kernel.KernelRuntime;\n },\n modules?: Modules,\n): any {\n let schema: SchemaDefinition<GenericSchema, boolean> | undefined;\n let runtime: Kernel.KernelRuntime | undefined;\n if (isSchemaDefinition(schemaOrOptions)) {\n schema = schemaOrOptions;\n } else if (schemaOrOptions !== undefined) {\n if (schemaOrOptions.transactionLimits !== undefined) {\n throw KernelRefusal.rowPending(\"transaction limits\", 6);\n }\n schema = schemaOrOptions.schema;\n modules = schemaOrOptions.modules;\n runtime = schemaOrOptions.runtime;\n }\n if (modules === undefined) {\n throw new Error(\n \"The test kernel needs the modules map: pass `import.meta.glob(...)` as the second argument.\",\n );\n }\n const world = new Execution.World(schema, modules, runtime);\n return {\n ...accessor(world, new Subscriptions.Registry(world), Execution.anonymous),\n registerComponent: (\n componentPath: string,\n componentSchema: SchemaDefinition<GenericSchema, boolean>,\n componentModules: Modules,\n options?: RegisterOptions,\n ) => {\n world.register(\n componentPath,\n componentSchema,\n componentModules,\n options?.standing,\n );\n return (componentsGeneric() as any)[componentPath];\n },\n };\n}\n"],"mappings":";;;;;AAkFA,MAAM,sBACJ,UAEA,UAAU,QACV,OAAO,UAAU,YACjB,YAAY,SACZ,OAAQ,MAA8B,WAAW;AAEnD,MAAM,YACJ,OACA,eACA,YACS;CACT,QAAQ,WAAgB,SAAe,MAAM,MAAM,QAAQ,WAAW,IAAI;CAC1E,WAAW,WAAgB,SACzB,MAAM,SAAS,QAAQ,WAAW,IAAI;CACxC,SAAS,WAAgB,SAAe,MAAM,OAAO,QAAQ,WAAW,IAAI;CAC5E,UAAU,WAAgB,SACxB,MAAM,QAAQ,QAAQ,WAAW,IAAI;CACvC,QAAQ,OAAe,MAAM,MAAM,EAAE;CACrC,YAAY,MAAM,KAAK;CACvB,kBAAkB,cAAc,WAAW,MAAM;CACjD,eAAe,cAAc,QAAQ;CACrC,iBAAiB,cAAc,UAAU;CACzC,MAAM,YAA+B,MAAM,IAAI,QAAQ,IAAI,OAAO;CAClE,iBAAiB,eAAuB,YACtC,MAAM,IAAI,QAAQ,eAAe,OAAO;CAC1C,eAAe,aACb,SAAS,OAAO,eAAeA,aAAuB,QAAQ,QAAQ,CAAC;CACzE,sBAAsB,aAIpB,SAAS,OAAO,eAAe;EAC7B,GAAG;EACH,IAAI,SAAS,MAAM;EACnB,WAAW,SAAS,aAAa;CACnC,CAAC;CACH,aAAa,QAAQ,OAAOC,WAAyB,eAAe,CAAC,CAAC;CACtE,YAAY,QAAQ,OAAOA,WAAyB,oBAAoB,CAAC,CAAC;CAC1E,UAAU,OAAe,MAAM,QAAQ,EAAE;CACzC,YAAY,MAAM,KAAK;CACvB,0CAA0C,MAAM,QAAQ,CAAC;CACzD,8BACE,gBACA,kBACG,MAAM,MAAM,aAAa;AAChC;;;;;;;;;;;;;;AAeA,SAAgB,WACd,iBAQA,SACK;CACL,IAAI;CACJ,IAAI;CACJ,IAAI,mBAAmB,eAAe,GACpC,SAAS;MACJ,IAAI,oBAAoB,KAAA,GAAW;EACxC,IAAI,gBAAgB,sBAAsB,KAAA,GACxC,MAAMA,WAAyB,sBAAsB,CAAC;EAExD,SAAS,gBAAgB;EACzB,UAAU,gBAAgB;EAC1B,UAAU,gBAAgB;CAC5B;CACA,IAAI,YAAY,KAAA,GACd,MAAM,IAAI,MACR,6FACF;CAEF,MAAM,QAAQ,IAAIC,MAAgB,QAAQ,SAAS,OAAO;CAC1D,OAAO;EACL,GAAG,SAAS,OAAO,IAAIC,SAAuB,KAAK,GAAGC,SAAmB;EACzE,oBACE,eACA,iBACA,kBACA,YACG;GACH,MAAM,SACJ,eACA,iBACA,kBACA,SAAS,QACX;GACA,OAAQ,kBAAkB,CAAC,CAAS;EACtC;CACF;AACF"}
|
|
1
|
+
{"version":3,"file":"ConvexTest.js","names":["Execution.withIdentity","KernelRefusal.rowPending","Execution.World","Subscriptions.Registry","Execution.anonymous"],"sources":["../../src/internal/ConvexTest.ts"],"sourcesContent":["import type {\n GenericSchema,\n SchemaDefinition,\n UserIdentity,\n} from \"convex/server\";\nimport { componentsGeneric } from \"convex/server\";\nimport * as Execution from \"./Execution.js\";\nimport type * as Invocation from \"./Invocation.js\";\nimport type * as Redaction from \"./Redaction.js\";\nimport type * as Kernel from \"./Kernel.js\";\nimport * as KernelRefusal from \"./KernelRefusal.js\";\nimport * as Subscriptions from \"./Subscriptions.js\";\nimport type * as Scheduling from \"./Scheduling.js\";\n\ntype Modules = Record<string, () => Promise<any>>;\n\n/**\n * What the kernel adds to convex-test's surface, typed. The shim itself returns\n * `any`, as convex-test's callers expect.\n */\nexport interface KernelControls {\n readonly query: (reference: any, args?: any) => Promise<any>;\n readonly mutation: (reference: any, args?: any) => Promise<any>;\n readonly action: (reference: any, args?: any) => Promise<any>;\n readonly prepare: (\n reference: any,\n args?: any,\n ) => Promise<Execution.HeldAttempt>;\n readonly apply: (id: string) => Promise<Execution.KernelApply>;\n readonly held: () => ReadonlyArray<Execution.HeldAttempt>;\n readonly withIdentity: (identity: Partial<UserIdentity>) => KernelControls;\n readonly withRequestMetadata: (metadata: {\n readonly ip?: string | null;\n readonly userAgent?: string | null;\n }) => KernelControls;\n /**\n * A client's query set under this accessor's caller.\n */\n readonly subscriber: () => Subscriptions.Subscriber;\n /**\n * Rerun every stale subscription. Lists each one whose value changed.\n */\n readonly refresh: () => Promise<ReadonlyArray<Subscriptions.Transition>>;\n /**\n * Rerun every subscription from scratch. Lists each one whose value differs\n * from the full rerun.\n */\n readonly reference: () => Promise<ReadonlyArray<Subscriptions.Disagreement>>;\n /**\n * Move the kernel's clock forward, running each job due on the way at its\n * deadline.\n */\n readonly advance: (ms: number) => Promise<void>;\n /**\n * The pending jobs, earliest deadline first.\n */\n readonly jobs: () => ReadonlyArray<Scheduling.Job>;\n /**\n * Run the jobs due now. No future deadline is crossed.\n */\n readonly finishInProgressScheduledFunctions: () => Promise<void>;\n /**\n * Run jobs at their deadlines until only standing jobs remain, or fail with\n * `DrainBudgetExceeded` after `maxIterations` jobs. The kernel keeps its own\n * clock, so it never calls `advanceTimers`.\n */\n readonly finishAllScheduledFunctions: (\n advanceTimers?: () => void,\n maxIterations?: number,\n ) => Promise<void>;\n /**\n * The committed state as snapshot bytes, bound to their SHA-256 digest. Two\n * exports of the same state are the same bytes.\n */\n readonly exportSnapshot: () => Uint8Array;\n /**\n * Replace a fresh backend's state with a snapshot's. Each job's world\n * resolves by name among `worlds`. Tampered bytes refuse with\n * `SnapshotDigestMismatch`.\n */\n readonly restoreSnapshot: (\n bytes: Uint8Array,\n options?: {\n readonly worlds?: ReadonlyArray<Invocation.World>;\n readonly secrets?: Redaction.Secrets;\n },\n ) => Promise<void>;\n /**\n * A copy of the raw secrets the backend has seen under a secret schema node.\n * A snapshot marks each one, and a restore given this copy puts them back. It\n * lives in memory and is never written to an artifact.\n */\n readonly secrets: () => Redaction.Secrets;\n}\n\n/**\n * How a kit registers a component beyond its schema and modules.\n */\nexport interface 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`. A job that runs\n * one, or that one schedules, is never drain work.\n */\n readonly standing?: ReadonlyArray<string>;\n}\n\nconst isSchemaDefinition = (\n value: unknown,\n): value is SchemaDefinition<GenericSchema, boolean> =>\n value !== null &&\n typeof value === \"object\" &&\n \"tables\" in value &&\n typeof (value as { tables: unknown }).tables === \"object\";\n\nconst accessor = (\n world: Execution.World,\n subscriptions: Subscriptions.Registry,\n caller: Execution.Caller,\n): any => {\n // Every failure the kernel hands back is a report a test runner prints, so\n // each leaves through the world's redaction.\n const reported = <A>(run: () => Promise<A>): Promise<A> =>\n run().catch((error: unknown) => {\n throw world.redactFailure(error);\n });\n // A diff names its subscription; its outcomes are marked by the shape of\n // what that subscription's query returns.\n const returnsOf = (subscription: string) =>\n world.functionPathOf(subscriptions.referenceOf(subscription));\n return {\n query: (reference: any, args?: any) =>\n reported(() => world.query(caller, reference, args)),\n mutation: (reference: any, args?: any) =>\n reported(() => world.mutation(caller, reference, args)),\n action: (reference: any, args?: any) =>\n reported(() => world.action(caller, reference, args)),\n prepare: (reference: any, args?: any) =>\n reported(() => world.prepare(caller, reference, args)).then((view) =>\n world.projectHeld(view),\n ),\n apply: (id: string) => {\n // The attempt leaves `held` once applied, so its function is read first.\n const functionPath = world\n .held()\n .find((view) => view.id === id)?.functionPath;\n return reported(() => world.apply(id)).then((applied) =>\n world.projectApplied(applied, functionPath),\n );\n },\n held: () => world.held().map((view) => world.projectHeld(view)),\n subscriber: () => subscriptions.subscriber(caller),\n refresh: () =>\n reported(() => subscriptions.refresh()).then((transitions) =>\n transitions.map((transition): Subscriptions.Transition => ({\n ...transition,\n from: world.redactOutcome(\n transition.from,\n returnsOf(transition.subscription),\n ),\n to: world.redactOutcome(\n transition.to,\n returnsOf(transition.subscription),\n ),\n because:\n transition.because.kind === \"commit\"\n ? {\n kind: \"commit\",\n change: world.redactChange(transition.because.change),\n }\n : transition.because,\n })),\n ),\n reference: () =>\n reported(() => subscriptions.reference()).then((disagreements) =>\n disagreements.map((disagreement): Subscriptions.Disagreement => ({\n ...disagreement,\n incremental: world.redactOutcome(\n disagreement.incremental,\n returnsOf(disagreement.subscription),\n ),\n reference: world.redactOutcome(\n disagreement.reference,\n returnsOf(disagreement.subscription),\n ),\n })),\n ),\n run: (handler: (ctx: any) => any) =>\n reported(() => world.run(caller, \"\", handler)),\n runInComponent: (componentPath: string, handler: (ctx: any) => any) =>\n reported(() => world.run(caller, componentPath, handler)),\n withIdentity: (identity: Partial<UserIdentity>) =>\n accessor(world, subscriptions, Execution.withIdentity(caller, identity)),\n withRequestMetadata: (metadata: {\n readonly ip?: string | null;\n readonly userAgent?: string | null;\n }) =>\n accessor(world, subscriptions, {\n ...caller,\n ip: metadata.ip ?? null,\n userAgent: metadata.userAgent ?? null,\n }),\n fetch: () => Promise.reject(KernelRefusal.rowPending(\"HTTP routes\", 6)),\n jwks: () => Promise.reject(KernelRefusal.rowPending(\"JWT verification\", 6)),\n advance: (ms: number) => reported(() => world.advance(ms)),\n jobs: () => world.jobs(),\n finishInProgressScheduledFunctions: () => reported(() => world.advance(0)),\n finishAllScheduledFunctions: (\n _advanceTimers?: () => void,\n maxIterations?: number,\n ) => reported(() => world.drain(maxIterations)),\n exportSnapshot: () => world.exportSnapshot(),\n restoreSnapshot: (\n bytes: Uint8Array,\n options?: {\n readonly worlds?: ReadonlyArray<Invocation.World>;\n readonly secrets?: Redaction.Secrets;\n },\n ) => world.restoreSnapshot(bytes, options),\n secrets: () => world.keptSecrets(),\n };\n};\n\n/**\n * The test kernel under convex-test's `convexTest` signature. The fork's kernel\n * lane aliases `convex-test` to this module, so every suite that calls\n * `convexTest` directly, and `TestConfect` itself, runs on the kernel.\n *\n * Beyond convex-test, `prepare` runs a mutation to its commit point and holds\n * it, and `apply` validates and publishes a held attempt. `mutation` applies\n * each attempt it prepares at once and prepares the next on a conflict, up to\n * attempt 5. `runtime` supplies the clock and commit timestamps. Scheduled\n * functions run on the kernel's clock, never on a host timer. A subscriber's\n * subscriptions go stale when a commit changes what they read or the identity\n * they read changes, and `refresh` reruns them. `redaction` names the secret\n * schema nodes of tables and functions: a value under one reaches a snapshot, a\n * failure report or a diff only as a marker.\n */\nexport function convexTest(\n schemaOrOptions?:\n | SchemaDefinition<GenericSchema, boolean>\n | {\n readonly schema?: SchemaDefinition<GenericSchema, boolean>;\n readonly modules?: Modules;\n readonly transactionLimits?: unknown;\n readonly runtime?: Kernel.KernelRuntime;\n readonly redaction?: Redaction.Policy;\n },\n modules?: Modules,\n): any {\n let schema: SchemaDefinition<GenericSchema, boolean> | undefined;\n let runtime: Kernel.KernelRuntime | undefined;\n let redaction: Redaction.Policy | undefined;\n if (isSchemaDefinition(schemaOrOptions)) {\n schema = schemaOrOptions;\n } else if (schemaOrOptions !== undefined) {\n if (schemaOrOptions.transactionLimits !== undefined) {\n throw KernelRefusal.rowPending(\"transaction limits\", 6);\n }\n schema = schemaOrOptions.schema;\n modules = schemaOrOptions.modules;\n runtime = schemaOrOptions.runtime;\n redaction = schemaOrOptions.redaction;\n }\n if (modules === undefined) {\n throw new Error(\n \"The test kernel needs the modules map: pass `import.meta.glob(...)` as the second argument.\",\n );\n }\n const world = new Execution.World(schema, modules, runtime, redaction);\n return {\n ...accessor(world, new Subscriptions.Registry(world), Execution.anonymous),\n registerComponent: (\n componentPath: string,\n componentSchema: SchemaDefinition<GenericSchema, boolean>,\n componentModules: Modules,\n options?: RegisterOptions,\n ) => {\n world.register(\n componentPath,\n componentSchema,\n componentModules,\n options?.standing,\n );\n return (componentsGeneric() as any)[componentPath];\n },\n };\n}\n"],"mappings":"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"}
|