diff --git a/.changeset/early-humans-argue.md b/.changeset/early-humans-argue.md new file mode 100644 index 0000000000..90668cf74f --- /dev/null +++ b/.changeset/early-humans-argue.md @@ -0,0 +1,5 @@ +--- +"@effect/schema": patch +--- + +Fix formatting for Class and brands AST. diff --git a/packages/schema/src/Schema.ts b/packages/schema/src/Schema.ts index 4c88414c7b..2eaef84da4 100644 --- a/packages/schema/src/Schema.ts +++ b/packages/schema/src/Schema.ts @@ -2275,15 +2275,12 @@ const makeBrandSchema = & brand_.Brand>) => { return makeBrandSchema(ast, annotations, brand) } - refined.toString = () => `${ast} & Brand<${formatPropertyKey(brand)}>` return refined } @@ -2340,6 +2337,8 @@ export const brand = ( onSome: (brands) => [...brands, brand] }) return makeBrandSchema(self.ast, { + // add a default title annotation containing the brand + title: String(self.ast) + ` & Brand<${util_.formatUnknown(brand)}>`, ...annotations, [AST.BrandAnnotationId]: brandAnnotation }, brand) @@ -6487,6 +6486,10 @@ const makeClass = ({ Base, annotations, fields, fromSchema, identifier, kind, ta const classSymbol = Symbol.for(`@effect/schema/${kind}/${identifier}`) const schema = fromSchema ?? Struct(fields) const validate = ParseResult.validateSync(schema) + const from = option_.match(AST.getTitleAnnotation(schema.ast), { + onNone: () => schema.annotations({ title: `${identifier} (Encoded side)` }), + onSome: () => schema + }) return class extends Base { constructor( @@ -6508,10 +6511,6 @@ const makeClass = ({ Base, annotations, fields, fromSchema, identifier, kind, ta return classSymbol } - toString() { - return toStringOverride !== undefined ? toStringOverride(this) : pretty_.make(this.constructor as any)(this) - } - static pipe() { return pipeArguments(this, arguments) } @@ -6520,6 +6519,14 @@ const makeClass = ({ Base, annotations, fields, fromSchema, identifier, kind, ta return make(this.ast).annotations(annotations) } + static toString() { + return `(${String(from)} <-> ${identifier})` + } + + toString() { + return toStringOverride !== undefined ? toStringOverride(this) : pretty_.make(this.constructor as any)(this) + } + static fields = { ...fields } static identifier = identifier @@ -6558,10 +6565,6 @@ const makeClass = ({ Base, annotations, fields, fromSchema, identifier, kind, ta ...annotations } ) - const from = option_.match(AST.getTitleAnnotation(schema.ast), { - onNone: () => schema.annotations({ title: `${identifier} (Encoded side)` }), - onSome: () => schema - }) const transformation = transform( from, declaration, diff --git a/packages/schema/test/Schema/Class/Class.test.ts b/packages/schema/test/Schema/Class/Class.test.ts index 6d97906ddf..663a89a3e9 100644 --- a/packages/schema/test/Schema/Class/Class.test.ts +++ b/packages/schema/test/Schema/Class/Class.test.ts @@ -129,6 +129,8 @@ describe("Class APIs", () => { it("should be a Schema", () => { class A extends S.Class("A")({ a: S.String }) {} expect(S.isSchema(A)).toEqual(true) + expect(String(A)).toBe("(A (Encoded side) <-> A)") + expect(S.format(A)).toBe("(A (Encoded side) <-> A)") }) it("should expose the fields", () => { diff --git a/packages/schema/test/Schema/brand.test.ts b/packages/schema/test/Schema/brand.test.ts index 3cf3469e10..28bec536fb 100644 --- a/packages/schema/test/Schema/brand.test.ts +++ b/packages/schema/test/Schema/brand.test.ts @@ -13,6 +13,12 @@ const isBrandConstructor = (u: unknown): u is Brand.Brand.Constructor => describe("brand", () => { describe("annotations", () => { + it("toString / format", () => { + const schema = S.Number.pipe(S.brand("A")) + expect(String(schema)).toBe(`number & Brand<"A">`) + expect(S.format(schema)).toBe(`number & Brand<"A">`) + }) + it("using .annotations() twice", () => { const schema = S.Number.pipe(S.brand("A")) const annotatedSchema = schema.annotations({ @@ -48,7 +54,7 @@ describe("brand", () => { expect(schema.ast.annotations).toEqual({ [AST.TypeAnnotationId]: S.IntTypeId, [AST.BrandAnnotationId]: ["A"], - [AST.TitleAnnotationId]: "integer", + [AST.TitleAnnotationId]: `integer & Brand<"A">`, [AST.DescriptionAnnotationId]: "an A brand", [AST.JSONSchemaAnnotationId]: { type: "integer" } }) @@ -67,7 +73,7 @@ describe("brand", () => { expect(schema.ast.annotations).toEqual({ [AST.TypeAnnotationId]: S.IntTypeId, [AST.BrandAnnotationId]: ["A", "B"], - [AST.TitleAnnotationId]: "integer", + [AST.TitleAnnotationId]: `integer & Brand<"A"> & Brand<"B">`, [AST.DescriptionAnnotationId]: "a B brand", [AST.JSONSchemaAnnotationId]: { type: "integer" } }) @@ -87,7 +93,7 @@ describe("brand", () => { expect(schema.ast.annotations).toEqual({ [AST.TypeAnnotationId]: S.IntTypeId, [AST.BrandAnnotationId]: [A, B], - [AST.TitleAnnotationId]: "integer", + [AST.TitleAnnotationId]: "integer & Brand & Brand", [AST.DescriptionAnnotationId]: "a B brand", [AST.JSONSchemaAnnotationId]: { type: "integer" } }) @@ -131,7 +137,7 @@ describe("brand", () => { it("either", () => { const Int = S.NumberFromString.pipe(S.int(), S.brand("Int")) expect(Int.either(1)).toEqual(Either.right(1)) - expect(Either.mapLeft(Int.either(1.2), (errors) => errors[0].message)).toEqual(Either.left(`integer + expect(Either.mapLeft(Int.either(1.2), (errors) => errors[0].message)).toEqual(Either.left(`integer & Brand<"Int"> └─ Predicate refinement failure └─ Expected an integer, actual 1.2`)) })