fix(client): accept rc.115 schema metadata

This commit is contained in:
Kit Langton
2026-09-20 19:08:52 -07:00
parent 63e66ca3e6
commit 12e1821cc7
2 changed files with 24 additions and 3 deletions
+11 -3
View File
@@ -1600,7 +1600,15 @@ function assertPortable(schema: Schema.Top, path: string, portable: Map<SchemaAS
if (!annotationsPortable(ast.annotations)) return false
if (!checksPortable(ast.checks) || ("encodingChecks" in ast && !checksPortable(ast.encodingChecks))) return false
if (SchemaAST.isDeclaration(ast)) {
return typeof ast.annotations?.toCode === "function" && ast.typeParameters.every(visit)
const representation = ast.annotations?.representation
const supported =
typeof ast.annotations?.toCode === "function" ||
(typeof representation === "object" &&
representation !== null &&
"id" in representation &&
representation.id === "effect/schema/Json") ||
(ast.annotations?.["~constructor"] !== undefined && ast.typeParameters[0] !== undefined)
return supported && ast.typeParameters.every(visit)
}
if (ast.encoding !== undefined && ast.annotations?.toCode === undefined) return false
if (SchemaAST.isSuspend(ast)) return visit(ast.thunk())
@@ -1639,8 +1647,7 @@ function checksPortable(checks: SchemaAST.Checks | undefined): boolean {
check.annotations?.representation !== undefined &&
serializable(check.annotations.representation) &&
typeof check.annotations.arbitraryConstraint === "object" &&
check.annotations.arbitraryConstraint !== null &&
serializable(check.annotations.arbitraryConstraint)
check.annotations.arbitraryConstraint !== null
: checksPortable(check.checks),
)
}
@@ -1679,6 +1686,7 @@ function annotationsPortable(annotations: Schema.Annotations.Annotations | undef
"toCodec",
"toCodecJson",
"toCodecStringTree",
"toCodecArbitrary",
"toArbitrary",
"toFormatter",
"toEquivalence",
@@ -1473,6 +1473,19 @@ describe("HttpApiCodegen.generate", () => {
)
})
test("emits schema classes with native arbitrary constraints structurally", () => {
class Attempt extends Schema.Class<Attempt>("Attempt")({
count: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),
}) {}
const output = emitPromise(
compileContract(api(HttpApiEndpoint.get("get", "/session", { success: Attempt }))),
)
const types = output.files.find((file) => file.path === "types.ts")?.content
expect(types).toContain('export type Attempt = { readonly "count": number }')
expect(types).toContain("export type SessionGetOutput = Attempt")
})
test("rejects spoofed and aborted validation checks", () => {
const Spoofed = Schema.Number.check(
Schema.makeFilter(() => "always fails", { meta: { _tag: "isFinite" }, arbitrary: {} }),