@confect/core 10.0.0-next.23 → 10.0.0-next.25

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @confect/core
2
2
 
3
+ ## 10.0.0-next.25
4
+
5
+ ### Patch Changes
6
+
7
+ - f9958b9: Require `effect@^4.0.0-rc.118` and matching Effect platform packages. Upgrade Effect alongside Confect and replace `effect/unstable/*` imports with `effect/*`, using `effect/http-api` for HTTP API imports.
8
+
9
+ ## 10.0.0-next.24
10
+
11
+ ### Patch Changes
12
+
13
+ - 850a3c3: Require `effect@^4.0.0-rc.117` across `@confect/*` and `@effect/platform-node@^4.0.0-rc.117` for `@confect/server`'s optional Node integration. Upgrade these dependencies alongside Confect; existing Confect call sites are unchanged.
14
+
3
15
  ## 10.0.0-next.23
4
16
 
5
17
  ### Major Changes
@@ -1 +1 @@
1
- {"version":3,"file":"SystemFields.d.ts","sourceRoot":"","sources":["../src/SystemFields.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,IAAI,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAOhF,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAIxC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAGxC;;;GAGG;AACH,eAAO,MAAM,YAAY,GAAI,SAAS,SAAS,MAAM,aAAa,SAAS;;;EAIvE,CAAC;AAEL;;;GAGG;AACH,KAAK,eAAe,CAAC,SAAS,SAAS,MAAM,IAAI,UAAU,CACzD,OAAO,YAAY,CAAC,SAAS,CAAC,CAC/B,CAAC,QAAQ,CAAC,CAAC;AA4HZ;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,sBAAsB,GACjC,SAAS,SAAS,MAAM,EACxB,WAAW,SAAS,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,aAE/B,SAAS,UACZ,WAAW,KAClB,sBAAsB,CAAC,SAAS,EAAE,WAAW,CA0C/C,CAAC;AAEF;;;;GAIG;AACH,KAAK,iBAAiB,CAAC,SAAS,SAAS,MAAM,EAAE,CAAC,IAChD,CAAC,SAAS,MAAM,CAAC,MAAM,CAAC,MAAM,MAAM,SAAS,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,GAC9D,MAAM,CAAC,MAAM,CACX,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,SAAS,CAAC,CAAC,CAAC,CACnE,GACD,CAAC,SAAS,MAAM,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,MAAM,OAAO,CAAC,GAC/C,MAAM,CAAC,KAAK,CACV,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,EACjC,gBAAgB,CAAC,SAAS,EAAE,OAAO,CAAC,CACrC,GACD,KAAK,CAAC;AAEd;;;;;;;;;;GAUG;AACH,MAAM,MAAM,sBAAsB,CAChC,SAAS,SAAS,MAAM,EACxB,WAAW,SAAS,MAAM,CAAC,GAAG,IAE9B,WAAW,SAAS,MAAM,CAAC,KAAK,CAC9B,MAAM,OAAO,SAAS,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,CAChD,GACG,MAAM,CAAC,KAAK,CACV,MAAM,CAAC,QAAQ,CACb,QAAQ,CAAC;KACN,CAAC,IAAI,MAAM,OAAO,GAAG,sBAAsB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;CACpE,CAAC,CACH,CACF,GACD,iBAAiB,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;AAEhD;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,CAC1B,SAAS,SAAS,MAAM,EACxB,QAAQ,IACN,QAAQ,SAAS,OAAO,GACxB,OAAO,CAAC,SAAS,CAAC,GAAG,iBAAiB,GAAG,QAAQ,GACjD,KAAK,CAAC"}
1
+ {"version":3,"file":"SystemFields.d.ts","sourceRoot":"","sources":["../src/SystemFields.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,IAAI,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAOhF,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAIxC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAGxC;;;GAGG;AACH,eAAO,MAAM,YAAY,GAAI,SAAS,SAAS,MAAM,aAAa,SAAS;;;EAIvE,CAAC;AAEL;;;GAGG;AACH,KAAK,eAAe,CAAC,SAAS,SAAS,MAAM,IAAI,UAAU,CACzD,OAAO,YAAY,CAAC,SAAS,CAAC,CAC/B,CAAC,QAAQ,CAAC,CAAC;AA0HZ;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,sBAAsB,GACjC,SAAS,SAAS,MAAM,EACxB,WAAW,SAAS,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,aAE/B,SAAS,UACZ,WAAW,KAClB,sBAAsB,CAAC,SAAS,EAAE,WAAW,CA0C/C,CAAC;AAEF;;;;GAIG;AACH,KAAK,iBAAiB,CAAC,SAAS,SAAS,MAAM,EAAE,CAAC,IAChD,CAAC,SAAS,MAAM,CAAC,MAAM,CAAC,MAAM,MAAM,SAAS,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,GAC9D,MAAM,CAAC,MAAM,CACX,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,SAAS,CAAC,CAAC,CAAC,CACnE,GACD,CAAC,SAAS,MAAM,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,MAAM,OAAO,CAAC,GAC/C,MAAM,CAAC,KAAK,CACV,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,EACjC,gBAAgB,CAAC,SAAS,EAAE,OAAO,CAAC,CACrC,GACD,KAAK,CAAC;AAEd;;;;;;;;;;GAUG;AACH,MAAM,MAAM,sBAAsB,CAChC,SAAS,SAAS,MAAM,EACxB,WAAW,SAAS,MAAM,CAAC,GAAG,IAE9B,WAAW,SAAS,MAAM,CAAC,KAAK,CAC9B,MAAM,OAAO,SAAS,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,CAChD,GACG,MAAM,CAAC,KAAK,CACV,MAAM,CAAC,QAAQ,CACb,QAAQ,CAAC;KACN,CAAC,IAAI,MAAM,OAAO,GAAG,sBAAsB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;CACpE,CAAC,CACH,CACF,GACD,iBAAiB,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;AAEhD;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,CAC1B,SAAS,SAAS,MAAM,EACxB,QAAQ,IACN,QAAQ,SAAS,OAAO,GACxB,OAAO,CAAC,SAAS,CAAC,GAAG,iBAAiB,GAAG,QAAQ,GACjD,KAAK,CAAC"}
@@ -44,10 +44,10 @@ const splitSystemFields = (input) => {
44
44
  * output. Transformations construct fresh objects, so without this the system
45
45
  * fields would be dropped at every transformation step.
46
46
  */
47
- const wrapGetter = (getter) => new SchemaGetter.Getter((input, options) => {
48
- if (Option.isNone(input) || !Predicate.isObject(input.value)) return getter.run(input, options);
47
+ const wrapGetter = (getter) => SchemaGetter.transformOptionalEffect((input, options) => {
48
+ if (Option.isNone(input) || !Predicate.isObject(input.value)) return SchemaGetter.run(getter, input, options);
49
49
  const { system, rest } = splitSystemFields(input.value);
50
- return getter.run(Option.some(rest), options).pipe(Effect.map(Option.map((output) => Predicate.isObject(output) ? Struct.assign(output, system) : output)));
50
+ return SchemaGetter.run(getter, Option.some(rest), options).pipe(Effect.map(Option.map((output) => Predicate.isObject(output) ? Struct.assign(output, system) : output)));
51
51
  });
52
52
  const wrapTransformation = (transformation) => {
53
53
  if (!SchemaTransformation.isTransformation(transformation)) throw new Error("Cannot extend a table schema that uses decoding/encoding middleware with system fields");
@@ -1 +1 @@
1
- {"version":3,"file":"SystemFields.js","names":["GenericId.GenericId"],"sources":["../src/SystemFields.ts"],"sourcesContent":["import type { IdField, SystemFields as NonIdSystemFields } from \"convex/server\";\nimport { pipe } from \"effect/Function\";\nimport * as Array from \"effect/Array\";\nimport * as Effect from \"effect/Effect\";\nimport * as Option from \"effect/Option\";\nimport * as Predicate from \"effect/Predicate\";\nimport * as Record from \"effect/Record\";\nimport * as Schema from \"effect/Schema\";\nimport * as SchemaAST from \"effect/SchemaAST\";\nimport * as SchemaGetter from \"effect/SchemaGetter\";\nimport * as SchemaTransformation from \"effect/SchemaTransformation\";\nimport * as Struct from \"effect/Struct\";\nimport * as GenericId from \"./GenericId\";\n\n/**\n * Produces a schema for Convex system fields. In Confect, system fields include\n * `_id`.\n */\nexport const SystemFields = <TableName extends string>(tableName: TableName) =>\n Schema.Struct({\n _id: GenericId.GenericId(tableName),\n _creationTime: Schema.Finite,\n });\n\n/**\n * The field map added to a table schema, derived from {@link SystemFields} so it\n * stays in lockstep with the runtime schema.\n */\ntype SystemFieldsFor<TableName extends string> = ReturnType<\n typeof SystemFields<TableName>\n>[\"fields\"];\n\n/**\n * The system field names, derived from {@link SystemFields} so they stay in\n * lockstep with the schema.\n */\nconst systemFieldNames: ReadonlyArray<string> = Record.keys(\n SystemFields(\"\").fields,\n);\n\nconst isSystemFieldKey = (key: string | symbol): key is string =>\n Predicate.isString(key) && Array.contains(systemFieldNames, key);\n\nconst splitSystemFields = (input: { [key: PropertyKey]: unknown }) => {\n const keys = Reflect.ownKeys(input);\n const pick = (pickedKeys: ReadonlyArray<string | symbol>) =>\n Record.fromEntries(\n Array.map(pickedKeys, (key) => [key, input[key]] as const),\n );\n return {\n system: pick(Array.filter(keys, isSystemFieldKey)),\n rest: pick(Array.filter(keys, Predicate.not(isSystemFieldKey))),\n };\n};\n\n/**\n * Wraps a transformation getter so the system fields bypass it: they are split\n * off the input before the user-defined getter runs and merged back into its\n * output. Transformations construct fresh objects, so without this the system\n * fields would be dropped at every transformation step.\n */\nconst wrapGetter = <R>(\n getter: SchemaGetter.Getter<any, any, R>,\n): SchemaGetter.Getter<any, any, R> =>\n new SchemaGetter.Getter((input, options) => {\n if (Option.isNone(input) || !Predicate.isObject(input.value)) {\n return getter.run(input, options);\n }\n const { system, rest } = splitSystemFields(input.value);\n return getter\n .run(Option.some(rest), options)\n .pipe(\n Effect.map(\n Option.map((output) =>\n Predicate.isObject(output) ? Struct.assign(output, system) : output,\n ),\n ),\n );\n });\n\nconst wrapTransformation = (\n transformation: SchemaAST.Link[\"transformation\"],\n): SchemaTransformation.Transformation<any, any, any, any> => {\n if (!SchemaTransformation.isTransformation(transformation)) {\n throw new Error(\n \"Cannot extend a table schema that uses decoding/encoding middleware with system fields\",\n );\n }\n return new SchemaTransformation.Transformation(\n wrapGetter(transformation.decode),\n wrapGetter(transformation.encode),\n );\n};\n\n/**\n * Builds an AST walker that adds the given system-field property signatures to\n * every object node of a schema's AST—including each step of its encoding\n * chain—wrapping transformations so the fields survive them.\n */\nconst makeExtendAst = (\n systemPropertySignatures: ReadonlyArray<SchemaAST.PropertySignature>,\n) => {\n const extendEncoding = (encoding: SchemaAST.Encoding): SchemaAST.Encoding =>\n Array.map(\n encoding,\n (link) =>\n new SchemaAST.Link(\n extendAst(link.to),\n wrapTransformation(link.transformation),\n ),\n );\n\n const extendAst = (ast: SchemaAST.AST): SchemaAST.AST => {\n if (SchemaAST.isUnion(ast)) {\n return new SchemaAST.Union(\n Array.map(ast.types, extendAst),\n ast.options,\n ast.annotations,\n ast.checks,\n ast.encoding === undefined ? undefined : extendEncoding(ast.encoding),\n ast.context,\n ast.encodingChecks,\n );\n }\n if (SchemaAST.isSuspend(ast)) {\n return new SchemaAST.Suspend(\n () => extendAst(ast.thunk()),\n ast.annotations,\n undefined,\n ast.encoding === undefined ? undefined : extendEncoding(ast.encoding),\n ast.context,\n );\n }\n if (SchemaAST.isObjects(ast)) {\n return new SchemaAST.Objects(\n Array.appendAll(ast.propertySignatures, systemPropertySignatures),\n ast.indexSignatures,\n ast.annotations,\n ast.checks,\n ast.encoding === undefined ? undefined : extendEncoding(ast.encoding),\n ast.context,\n ast.encodingChecks,\n );\n }\n throw new Error(\n ast._tag === \"Declaration\"\n ? \"Cannot extend a `Declaration` schema (such as a `Schema.Class`) with system fields: its decoded values are constructed instances, which cannot gain extra fields. Use a plain `Schema.Struct`, or transform to one with `Schema.decodeTo`.\"\n : `Cannot extend a \\`${ast._tag}\\` schema node with system fields: a table schema must resolve to an object shape at every step of its encoding.`,\n );\n };\n\n return extendAst;\n};\n\n/**\n * Extend a table schema with Convex system fields.\n *\n * A plain `Struct` gains the fields via `Schema.fieldsAssign` and a `Union` has\n * them distributed across its members, preserving the schema's `Struct`/`Union`\n * structure. Any other object-shaped schema—one built with\n * `Schema.decodeTo`/`Schema.encodeKeys`, a branded struct, a suspended\n * schema—is extended at the AST level: every object node in its encoding chain\n * gains the system fields, and each transformation is wrapped so the fields\n * bypass the user-defined getters. Schemas that do not resolve to an object\n * shape at every step (such as `Schema.Class`, whose decoded values are class\n * instances) are rejected with a descriptive error.\n *\n * Note that struct-level checks on an extended schema observe the value with\n * the system fields attached, and encoding an extended schema emits the system\n * fields alongside the table fields.\n */\nexport const extendWithSystemFields = <\n TableName extends string,\n TableSchema extends Schema.Codec<any, any>,\n>(\n tableName: TableName,\n schema: TableSchema,\n): ExtendWithSystemFields<TableName, TableSchema> => {\n const system = SystemFields(tableName).fields;\n\n const extendAst = makeExtendAst(\n pipe(\n system,\n Record.toEntries,\n Array.map(\n ([name, field]) => new SchemaAST.PropertySignature(name, field.ast),\n ),\n ),\n );\n\n const extend = (s: Schema.Top): Schema.Top => {\n if (\n s.ast.encoding === undefined &&\n SchemaAST.isUnion(s.ast) &&\n Array.isArray((s as { readonly members?: unknown }).members)\n ) {\n return Schema.Union(\n Array.map(\n (s as Schema.Union<ReadonlyArray<Schema.Top>>).members,\n extend,\n ),\n );\n }\n if (\n s.ast.encoding === undefined &&\n SchemaAST.isObjects(s.ast) &&\n typeof (s as { readonly mapFields?: unknown }).mapFields === \"function\"\n ) {\n return Schema.fieldsAssign(system)(\n s as Schema.Struct<Schema.Struct.Fields>,\n );\n }\n return Schema.make(extendAst(s.ast));\n };\n\n return extend(schema) as unknown as ExtendWithSystemFields<\n TableName,\n TableSchema\n >;\n};\n\n/**\n * Applies the system fields to a single struct, mirroring\n * `Schema.fieldsAssign`. Any other (already-extended or opaque) schema falls\n * back to a `Codec` carrying the system-field document shape.\n */\ntype ApplySystemFields<TableName extends string, S> =\n S extends Schema.Struct<infer Fields extends Schema.Struct.Fields>\n ? Schema.Struct<\n Struct.Simplify<Struct.Assign<Fields, SystemFieldsFor<TableName>>>\n >\n : S extends Schema.Codec<infer Type, infer Encoded>\n ? Schema.Codec<\n WithSystemFields<TableName, Type>,\n WithSystemFields<TableName, Encoded>\n >\n : never;\n\n/**\n * Extend a table schema with Convex system fields at the type level.\n *\n * This mirrors the runtime {@link extendWithSystemFields}: a `Struct` gains the\n * system fields directly (matching `Schema.fieldsAssign`), and a `Union` has\n * them distributed across its members (matching\n * `union.mapMembers(Tuple.map(Schema.fieldsAssign(...)))`). The\n * `Struct`/`Union` structure is preserved rather than collapsed to a bare\n * `Codec`; any other schema falls back to a `Codec` carrying the system-field\n * document shape, matching the runtime's AST-level extension.\n */\nexport type ExtendWithSystemFields<\n TableName extends string,\n TableSchema extends Schema.Top,\n> =\n TableSchema extends Schema.Union<\n infer Members extends ReadonlyArray<Schema.Top>\n >\n ? Schema.Union<\n Struct.Simplify<\n Readonly<{\n [K in keyof Members]: ExtendWithSystemFields<TableName, Members[K]>;\n }>\n >\n >\n : ApplySystemFields<TableName, TableSchema>;\n\n/**\n * The decoded/encoded document shape: a table's fields plus Convex's system\n * fields. Deliberately a bare intersection (no `Expand`/`Simplify`)—flattening\n * it with a homomorphic mapped type collapses to `{ [x: string]: any }` when\n * `Document` is still an unresolved generic, which breaks structural\n * comparability in the database reader/writer plumbing.\n */\nexport type WithSystemFields<\n TableName extends string,\n Document,\n> = Document extends unknown\n ? IdField<TableName> & NonIdSystemFields & Document\n : never;\n"],"mappings":"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"}
1
+ {"version":3,"file":"SystemFields.js","names":["GenericId.GenericId"],"sources":["../src/SystemFields.ts"],"sourcesContent":["import type { IdField, SystemFields as NonIdSystemFields } from \"convex/server\";\nimport { pipe } from \"effect/Function\";\nimport * as Array from \"effect/Array\";\nimport * as Effect from \"effect/Effect\";\nimport * as Option from \"effect/Option\";\nimport * as Predicate from \"effect/Predicate\";\nimport * as Record from \"effect/Record\";\nimport * as Schema from \"effect/Schema\";\nimport * as SchemaAST from \"effect/SchemaAST\";\nimport * as SchemaGetter from \"effect/SchemaGetter\";\nimport * as SchemaTransformation from \"effect/SchemaTransformation\";\nimport * as Struct from \"effect/Struct\";\nimport * as GenericId from \"./GenericId\";\n\n/**\n * Produces a schema for Convex system fields. In Confect, system fields include\n * `_id`.\n */\nexport const SystemFields = <TableName extends string>(tableName: TableName) =>\n Schema.Struct({\n _id: GenericId.GenericId(tableName),\n _creationTime: Schema.Finite,\n });\n\n/**\n * The field map added to a table schema, derived from {@link SystemFields} so it\n * stays in lockstep with the runtime schema.\n */\ntype SystemFieldsFor<TableName extends string> = ReturnType<\n typeof SystemFields<TableName>\n>[\"fields\"];\n\n/**\n * The system field names, derived from {@link SystemFields} so they stay in\n * lockstep with the schema.\n */\nconst systemFieldNames: ReadonlyArray<string> = Record.keys(\n SystemFields(\"\").fields,\n);\n\nconst isSystemFieldKey = (key: string | symbol): key is string =>\n Predicate.isString(key) && Array.contains(systemFieldNames, key);\n\nconst splitSystemFields = (input: { [key: PropertyKey]: unknown }) => {\n const keys = Reflect.ownKeys(input);\n const pick = (pickedKeys: ReadonlyArray<string | symbol>) =>\n Record.fromEntries(\n Array.map(pickedKeys, (key) => [key, input[key]] as const),\n );\n return {\n system: pick(Array.filter(keys, isSystemFieldKey)),\n rest: pick(Array.filter(keys, Predicate.not(isSystemFieldKey))),\n };\n};\n\n/**\n * Wraps a transformation getter so the system fields bypass it: they are split\n * off the input before the user-defined getter runs and merged back into its\n * output. Transformations construct fresh objects, so without this the system\n * fields would be dropped at every transformation step.\n */\nconst wrapGetter = <R>(\n getter: SchemaGetter.Getter<any, any, R>,\n): SchemaGetter.Getter<any, any, R> =>\n SchemaGetter.transformOptionalEffect((input, options) => {\n if (Option.isNone(input) || !Predicate.isObject(input.value)) {\n return SchemaGetter.run(getter, input, options);\n }\n const { system, rest } = splitSystemFields(input.value);\n return SchemaGetter.run(getter, Option.some(rest), options).pipe(\n Effect.map(\n Option.map((output) =>\n Predicate.isObject(output) ? Struct.assign(output, system) : output,\n ),\n ),\n );\n });\n\nconst wrapTransformation = (\n transformation: SchemaAST.Link[\"transformation\"],\n): SchemaTransformation.Transformation<any, any, any, any> => {\n if (!SchemaTransformation.isTransformation(transformation)) {\n throw new Error(\n \"Cannot extend a table schema that uses decoding/encoding middleware with system fields\",\n );\n }\n return new SchemaTransformation.Transformation(\n wrapGetter(transformation.decode),\n wrapGetter(transformation.encode),\n );\n};\n\n/**\n * Builds an AST walker that adds the given system-field property signatures to\n * every object node of a schema's AST—including each step of its encoding\n * chain—wrapping transformations so the fields survive them.\n */\nconst makeExtendAst = (\n systemPropertySignatures: ReadonlyArray<SchemaAST.PropertySignature>,\n) => {\n const extendEncoding = (encoding: SchemaAST.Encoding): SchemaAST.Encoding =>\n Array.map(\n encoding,\n (link) =>\n new SchemaAST.Link(\n extendAst(link.to),\n wrapTransformation(link.transformation),\n ),\n );\n\n const extendAst = (ast: SchemaAST.AST): SchemaAST.AST => {\n if (SchemaAST.isUnion(ast)) {\n return new SchemaAST.Union(\n Array.map(ast.types, extendAst),\n ast.options,\n ast.annotations,\n ast.checks,\n ast.encoding === undefined ? undefined : extendEncoding(ast.encoding),\n ast.context,\n ast.encodingChecks,\n );\n }\n if (SchemaAST.isSuspend(ast)) {\n return new SchemaAST.Suspend(\n () => extendAst(ast.thunk()),\n ast.annotations,\n undefined,\n ast.encoding === undefined ? undefined : extendEncoding(ast.encoding),\n ast.context,\n );\n }\n if (SchemaAST.isObjects(ast)) {\n return new SchemaAST.Objects(\n Array.appendAll(ast.propertySignatures, systemPropertySignatures),\n ast.indexSignatures,\n ast.annotations,\n ast.checks,\n ast.encoding === undefined ? undefined : extendEncoding(ast.encoding),\n ast.context,\n ast.encodingChecks,\n );\n }\n throw new Error(\n ast._tag === \"Declaration\"\n ? \"Cannot extend a `Declaration` schema (such as a `Schema.Class`) with system fields: its decoded values are constructed instances, which cannot gain extra fields. Use a plain `Schema.Struct`, or transform to one with `Schema.decodeTo`.\"\n : `Cannot extend a \\`${ast._tag}\\` schema node with system fields: a table schema must resolve to an object shape at every step of its encoding.`,\n );\n };\n\n return extendAst;\n};\n\n/**\n * Extend a table schema with Convex system fields.\n *\n * A plain `Struct` gains the fields via `Schema.fieldsAssign` and a `Union` has\n * them distributed across its members, preserving the schema's `Struct`/`Union`\n * structure. Any other object-shaped schema—one built with\n * `Schema.decodeTo`/`Schema.encodeKeys`, a branded struct, a suspended\n * schema—is extended at the AST level: every object node in its encoding chain\n * gains the system fields, and each transformation is wrapped so the fields\n * bypass the user-defined getters. Schemas that do not resolve to an object\n * shape at every step (such as `Schema.Class`, whose decoded values are class\n * instances) are rejected with a descriptive error.\n *\n * Note that struct-level checks on an extended schema observe the value with\n * the system fields attached, and encoding an extended schema emits the system\n * fields alongside the table fields.\n */\nexport const extendWithSystemFields = <\n TableName extends string,\n TableSchema extends Schema.Codec<any, any>,\n>(\n tableName: TableName,\n schema: TableSchema,\n): ExtendWithSystemFields<TableName, TableSchema> => {\n const system = SystemFields(tableName).fields;\n\n const extendAst = makeExtendAst(\n pipe(\n system,\n Record.toEntries,\n Array.map(\n ([name, field]) => new SchemaAST.PropertySignature(name, field.ast),\n ),\n ),\n );\n\n const extend = (s: Schema.Top): Schema.Top => {\n if (\n s.ast.encoding === undefined &&\n SchemaAST.isUnion(s.ast) &&\n Array.isArray((s as { readonly members?: unknown }).members)\n ) {\n return Schema.Union(\n Array.map(\n (s as Schema.Union<ReadonlyArray<Schema.Top>>).members,\n extend,\n ),\n );\n }\n if (\n s.ast.encoding === undefined &&\n SchemaAST.isObjects(s.ast) &&\n typeof (s as { readonly mapFields?: unknown }).mapFields === \"function\"\n ) {\n return Schema.fieldsAssign(system)(\n s as Schema.Struct<Schema.Struct.Fields>,\n );\n }\n return Schema.make(extendAst(s.ast));\n };\n\n return extend(schema) as unknown as ExtendWithSystemFields<\n TableName,\n TableSchema\n >;\n};\n\n/**\n * Applies the system fields to a single struct, mirroring\n * `Schema.fieldsAssign`. Any other (already-extended or opaque) schema falls\n * back to a `Codec` carrying the system-field document shape.\n */\ntype ApplySystemFields<TableName extends string, S> =\n S extends Schema.Struct<infer Fields extends Schema.Struct.Fields>\n ? Schema.Struct<\n Struct.Simplify<Struct.Assign<Fields, SystemFieldsFor<TableName>>>\n >\n : S extends Schema.Codec<infer Type, infer Encoded>\n ? Schema.Codec<\n WithSystemFields<TableName, Type>,\n WithSystemFields<TableName, Encoded>\n >\n : never;\n\n/**\n * Extend a table schema with Convex system fields at the type level.\n *\n * This mirrors the runtime {@link extendWithSystemFields}: a `Struct` gains the\n * system fields directly (matching `Schema.fieldsAssign`), and a `Union` has\n * them distributed across its members (matching\n * `union.mapMembers(Tuple.map(Schema.fieldsAssign(...)))`). The\n * `Struct`/`Union` structure is preserved rather than collapsed to a bare\n * `Codec`; any other schema falls back to a `Codec` carrying the system-field\n * document shape, matching the runtime's AST-level extension.\n */\nexport type ExtendWithSystemFields<\n TableName extends string,\n TableSchema extends Schema.Top,\n> =\n TableSchema extends Schema.Union<\n infer Members extends ReadonlyArray<Schema.Top>\n >\n ? Schema.Union<\n Struct.Simplify<\n Readonly<{\n [K in keyof Members]: ExtendWithSystemFields<TableName, Members[K]>;\n }>\n >\n >\n : ApplySystemFields<TableName, TableSchema>;\n\n/**\n * The decoded/encoded document shape: a table's fields plus Convex's system\n * fields. Deliberately a bare intersection (no `Expand`/`Simplify`)—flattening\n * it with a homomorphic mapped type collapses to `{ [x: string]: any }` when\n * `Document` is still an unresolved generic, which breaks structural\n * comparability in the database reader/writer plumbing.\n */\nexport type WithSystemFields<\n TableName extends string,\n Document,\n> = Document extends unknown\n ? IdField<TableName> & NonIdSystemFields & Document\n : never;\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,21 +1,21 @@
1
1
  {
2
2
  "name": "@confect/core",
3
3
  "description": "Shared specs and schemas used by all Confect packages",
4
- "version": "10.0.0-next.23",
4
+ "version": "10.0.0-next.25",
5
5
  "author": "RJ Dellecese",
6
6
  "bugs": {
7
7
  "url": "https://github.com/rjdellecese/confect/issues"
8
8
  },
9
9
  "devDependencies": {
10
- "@effect/vitest": "4.0.0-rc.115",
10
+ "@effect/vitest": "4.0.0-rc.118",
11
11
  "@types/node": "24.13.3",
12
12
  "confect-bench-harness": "0.0.0",
13
- "effect": "4.0.0-rc.115",
13
+ "effect": "4.0.0-rc.118",
14
14
  "tsdown": "0.23.0",
15
- "tsx": "4.23.13",
15
+ "tsx": "4.23.15",
16
16
  "typescript": "7.0.2",
17
17
  "unrun": "0.3.1",
18
- "vitest": "5.0.0"
18
+ "vitest": "5.0.1"
19
19
  },
20
20
  "engines": {
21
21
  "node": ">=24"
@@ -51,7 +51,7 @@
51
51
  "module": "./dist/index.js",
52
52
  "peerDependencies": {
53
53
  "convex": "^1.32.0",
54
- "effect": "^4.0.0-rc.115"
54
+ "effect": "^4.0.0-rc.118"
55
55
  },
56
56
  "repository": {
57
57
  "type": "git",
@@ -62,20 +62,18 @@ const splitSystemFields = (input: { [key: PropertyKey]: unknown }) => {
62
62
  const wrapGetter = <R>(
63
63
  getter: SchemaGetter.Getter<any, any, R>,
64
64
  ): SchemaGetter.Getter<any, any, R> =>
65
- new SchemaGetter.Getter((input, options) => {
65
+ SchemaGetter.transformOptionalEffect((input, options) => {
66
66
  if (Option.isNone(input) || !Predicate.isObject(input.value)) {
67
- return getter.run(input, options);
67
+ return SchemaGetter.run(getter, input, options);
68
68
  }
69
69
  const { system, rest } = splitSystemFields(input.value);
70
- return getter
71
- .run(Option.some(rest), options)
72
- .pipe(
73
- Effect.map(
74
- Option.map((output) =>
75
- Predicate.isObject(output) ? Struct.assign(output, system) : output,
76
- ),
70
+ return SchemaGetter.run(getter, Option.some(rest), options).pipe(
71
+ Effect.map(
72
+ Option.map((output) =>
73
+ Predicate.isObject(output) ? Struct.assign(output, system) : output,
77
74
  ),
78
- );
75
+ ),
76
+ );
79
77
  });
80
78
 
81
79
  const wrapTransformation = (