From 9bbab8d415c95567b7cbca90dbbcffb4438904ea Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Fri, 4 Sep 2026 22:44:48 -0700 Subject: [PATCH 1/2] fix(effect): count Unicode code points for string length --- .../TypeScriptEffectSchemaRenderer.ts | 8 +++++-- test/fixtures.ts | 5 +++- ...-codepoint-length.1.fail.minmaxlength.json | 1 + .../unicode-codepoint-length.1.json | 1 + ...-codepoint-length.2.fail.minmaxlength.json | 1 + .../unicode-codepoint-length.2.json | 1 + ...-codepoint-length.3.fail.minmaxlength.json | 1 + ...-codepoint-length.4.fail.minmaxlength.json | 1 + ...icode-codepoint-length.5.fail.pattern.json | 1 + .../unicode-codepoint-length.schema | 24 +++++++++++++++++++ test/languages.ts | 4 ++++ 11 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 test/inputs/typescript-effect-schema/unicode-codepoint-length.1.fail.minmaxlength.json create mode 100644 test/inputs/typescript-effect-schema/unicode-codepoint-length.1.json create mode 100644 test/inputs/typescript-effect-schema/unicode-codepoint-length.2.fail.minmaxlength.json create mode 100644 test/inputs/typescript-effect-schema/unicode-codepoint-length.2.json create mode 100644 test/inputs/typescript-effect-schema/unicode-codepoint-length.3.fail.minmaxlength.json create mode 100644 test/inputs/typescript-effect-schema/unicode-codepoint-length.4.fail.minmaxlength.json create mode 100644 test/inputs/typescript-effect-schema/unicode-codepoint-length.5.fail.pattern.json create mode 100644 test/inputs/typescript-effect-schema/unicode-codepoint-length.schema diff --git a/packages/quicktype-core/src/language/TypeScriptEffectSchema/TypeScriptEffectSchemaRenderer.ts b/packages/quicktype-core/src/language/TypeScriptEffectSchema/TypeScriptEffectSchemaRenderer.ts index 2726f2f81b..f6b0cc2d92 100644 --- a/packages/quicktype-core/src/language/TypeScriptEffectSchema/TypeScriptEffectSchemaRenderer.ts +++ b/packages/quicktype-core/src/language/TypeScriptEffectSchema/TypeScriptEffectSchemaRenderer.ts @@ -210,9 +210,13 @@ export class TypeScriptEffectSchemaRenderer extends ConvenienceRenderer { const pattern = patternForType(t); const schema: Sourcelike[] = ["S.String"]; if (min !== undefined) - schema.push(".pipe(S.minLength(", min.toString(), "))"); + schema.push( + `.pipe(S.filter(value => Array.from(value).length >= ${min}))`, + ); if (max !== undefined) - schema.push(".pipe(S.maxLength(", max.toString(), "))"); + schema.push( + `.pipe(S.filter(value => Array.from(value).length <= ${max}))`, + ); if (pattern !== undefined) schema.push( `.pipe(S.pattern(new RegExp(${JSON.stringify(pattern)})))`, diff --git a/test/fixtures.ts b/test/fixtures.ts index 74693fc082..4ea5299475 100644 --- a/test/fixtures.ts +++ b/test/fixtures.ts @@ -809,7 +809,10 @@ class JSONSchemaFixture extends LanguageFixture { } getSamples(sources: string[]): { priority: Sample[]; others: Sample[] } { - const prioritySamples = testsInDir("test/inputs/schema/", "schema"); + const prioritySamples = testsInDir( + "test/inputs/schema/", + "schema", + ).concat(this.language.additionalSchemaFiles ?? []); const samples = samplesFromSources( sources, prioritySamples, diff --git a/test/inputs/typescript-effect-schema/unicode-codepoint-length.1.fail.minmaxlength.json b/test/inputs/typescript-effect-schema/unicode-codepoint-length.1.fail.minmaxlength.json new file mode 100644 index 0000000000..e225d1c57e --- /dev/null +++ b/test/inputs/typescript-effect-schema/unicode-codepoint-length.1.fail.minmaxlength.json @@ -0,0 +1 @@ +{"exact": "šŸ˜€", "minimum": "šŸ˜€a", "maximum": "šŸ˜€"} diff --git a/test/inputs/typescript-effect-schema/unicode-codepoint-length.1.json b/test/inputs/typescript-effect-schema/unicode-codepoint-length.1.json new file mode 100644 index 0000000000..5c07a588dd --- /dev/null +++ b/test/inputs/typescript-effect-schema/unicode-codepoint-length.1.json @@ -0,0 +1 @@ +{"exact": "šŸ˜€šŸ˜€", "minimum": "šŸ˜€a", "maximum": "šŸ˜€"} diff --git a/test/inputs/typescript-effect-schema/unicode-codepoint-length.2.fail.minmaxlength.json b/test/inputs/typescript-effect-schema/unicode-codepoint-length.2.fail.minmaxlength.json new file mode 100644 index 0000000000..c8c6591ef5 --- /dev/null +++ b/test/inputs/typescript-effect-schema/unicode-codepoint-length.2.fail.minmaxlength.json @@ -0,0 +1 @@ +{"exact": "šŸ˜€šŸ˜€šŸ˜€", "minimum": "šŸ˜€a", "maximum": "šŸ˜€"} diff --git a/test/inputs/typescript-effect-schema/unicode-codepoint-length.2.json b/test/inputs/typescript-effect-schema/unicode-codepoint-length.2.json new file mode 100644 index 0000000000..9a9dca1d26 --- /dev/null +++ b/test/inputs/typescript-effect-schema/unicode-codepoint-length.2.json @@ -0,0 +1 @@ +{"exact": "é", "minimum": "šŸ˜€a", "maximum": "šŸ˜€"} diff --git a/test/inputs/typescript-effect-schema/unicode-codepoint-length.3.fail.minmaxlength.json b/test/inputs/typescript-effect-schema/unicode-codepoint-length.3.fail.minmaxlength.json new file mode 100644 index 0000000000..8db7d970e7 --- /dev/null +++ b/test/inputs/typescript-effect-schema/unicode-codepoint-length.3.fail.minmaxlength.json @@ -0,0 +1 @@ +{"exact": "šŸ˜€šŸ˜€", "minimum": "šŸ˜€", "maximum": "šŸ˜€"} diff --git a/test/inputs/typescript-effect-schema/unicode-codepoint-length.4.fail.minmaxlength.json b/test/inputs/typescript-effect-schema/unicode-codepoint-length.4.fail.minmaxlength.json new file mode 100644 index 0000000000..8d6738c793 --- /dev/null +++ b/test/inputs/typescript-effect-schema/unicode-codepoint-length.4.fail.minmaxlength.json @@ -0,0 +1 @@ +{"exact": "šŸ˜€šŸ˜€", "minimum": "šŸ˜€a", "maximum": "šŸ˜€a"} diff --git a/test/inputs/typescript-effect-schema/unicode-codepoint-length.5.fail.pattern.json b/test/inputs/typescript-effect-schema/unicode-codepoint-length.5.fail.pattern.json new file mode 100644 index 0000000000..bc2f3d621a --- /dev/null +++ b/test/inputs/typescript-effect-schema/unicode-codepoint-length.5.fail.pattern.json @@ -0,0 +1 @@ +{"exact": "!!", "minimum": "šŸ˜€a", "maximum": "šŸ˜€"} diff --git a/test/inputs/typescript-effect-schema/unicode-codepoint-length.schema b/test/inputs/typescript-effect-schema/unicode-codepoint-length.schema new file mode 100644 index 0000000000..83c23969c4 --- /dev/null +++ b/test/inputs/typescript-effect-schema/unicode-codepoint-length.schema @@ -0,0 +1,24 @@ +{ + "type": "object", + "properties": { + "exact": { + "type": "string", + "minLength": 2, + "maxLength": 2, + "pattern": "^[^!]+$" + }, + "minimum": { + "type": "string", + "minLength": 2 + }, + "maximum": { + "type": "string", + "maxLength": 1 + } + }, + "required": [ + "exact", + "minimum", + "maximum" + ] +} diff --git a/test/languages.ts b/test/languages.ts index c26ce281c0..076348158c 100644 --- a/test/languages.ts +++ b/test/languages.ts @@ -70,6 +70,7 @@ export interface Language { includeJSON?: string[]; skipMiscJSON: boolean; skipSchema: string[]; + additionalSchemaFiles?: string[]; rendererOptions: RendererOptions; quickTestRendererOptions: (RendererOptions | [string, RendererOptions])[]; sourceFiles?: string[]; @@ -1736,6 +1737,9 @@ export const TypeScriptEffectSchemaLanguage: Language = { topLevel: "TopLevel", skipJSON: [], skipMiscJSON: false, + additionalSchemaFiles: [ + "test/inputs/typescript-effect-schema/unicode-codepoint-length.schema", + ], skipSchema: [], rendererOptions: {}, quickTestRendererOptions: [], From 74e51ca1d92f2be6d3519fe3c0301801a71c0462 Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Sat, 5 Sep 2026 09:58:53 -0700 Subject: [PATCH 2/2] test(effect): use shared Unicode length cases --- ...-codepoint-length.1.fail.minmaxlength.json | 1 - .../unicode-codepoint-length.1.json | 1 - ...-codepoint-length.2.fail.minmaxlength.json | 1 - .../unicode-codepoint-length.2.json | 1 - ...-codepoint-length.3.fail.minmaxlength.json | 1 - ...-codepoint-length.4.fail.minmaxlength.json | 1 - ...icode-codepoint-length.5.fail.pattern.json | 1 - .../unicode-codepoint-length.schema | 24 ------------------- test/languages.ts | 2 +- 9 files changed, 1 insertion(+), 32 deletions(-) delete mode 100644 test/inputs/typescript-effect-schema/unicode-codepoint-length.1.fail.minmaxlength.json delete mode 100644 test/inputs/typescript-effect-schema/unicode-codepoint-length.1.json delete mode 100644 test/inputs/typescript-effect-schema/unicode-codepoint-length.2.fail.minmaxlength.json delete mode 100644 test/inputs/typescript-effect-schema/unicode-codepoint-length.2.json delete mode 100644 test/inputs/typescript-effect-schema/unicode-codepoint-length.3.fail.minmaxlength.json delete mode 100644 test/inputs/typescript-effect-schema/unicode-codepoint-length.4.fail.minmaxlength.json delete mode 100644 test/inputs/typescript-effect-schema/unicode-codepoint-length.5.fail.pattern.json delete mode 100644 test/inputs/typescript-effect-schema/unicode-codepoint-length.schema diff --git a/test/inputs/typescript-effect-schema/unicode-codepoint-length.1.fail.minmaxlength.json b/test/inputs/typescript-effect-schema/unicode-codepoint-length.1.fail.minmaxlength.json deleted file mode 100644 index e225d1c57e..0000000000 --- a/test/inputs/typescript-effect-schema/unicode-codepoint-length.1.fail.minmaxlength.json +++ /dev/null @@ -1 +0,0 @@ -{"exact": "šŸ˜€", "minimum": "šŸ˜€a", "maximum": "šŸ˜€"} diff --git a/test/inputs/typescript-effect-schema/unicode-codepoint-length.1.json b/test/inputs/typescript-effect-schema/unicode-codepoint-length.1.json deleted file mode 100644 index 5c07a588dd..0000000000 --- a/test/inputs/typescript-effect-schema/unicode-codepoint-length.1.json +++ /dev/null @@ -1 +0,0 @@ -{"exact": "šŸ˜€šŸ˜€", "minimum": "šŸ˜€a", "maximum": "šŸ˜€"} diff --git a/test/inputs/typescript-effect-schema/unicode-codepoint-length.2.fail.minmaxlength.json b/test/inputs/typescript-effect-schema/unicode-codepoint-length.2.fail.minmaxlength.json deleted file mode 100644 index c8c6591ef5..0000000000 --- a/test/inputs/typescript-effect-schema/unicode-codepoint-length.2.fail.minmaxlength.json +++ /dev/null @@ -1 +0,0 @@ -{"exact": "šŸ˜€šŸ˜€šŸ˜€", "minimum": "šŸ˜€a", "maximum": "šŸ˜€"} diff --git a/test/inputs/typescript-effect-schema/unicode-codepoint-length.2.json b/test/inputs/typescript-effect-schema/unicode-codepoint-length.2.json deleted file mode 100644 index 9a9dca1d26..0000000000 --- a/test/inputs/typescript-effect-schema/unicode-codepoint-length.2.json +++ /dev/null @@ -1 +0,0 @@ -{"exact": "é", "minimum": "šŸ˜€a", "maximum": "šŸ˜€"} diff --git a/test/inputs/typescript-effect-schema/unicode-codepoint-length.3.fail.minmaxlength.json b/test/inputs/typescript-effect-schema/unicode-codepoint-length.3.fail.minmaxlength.json deleted file mode 100644 index 8db7d970e7..0000000000 --- a/test/inputs/typescript-effect-schema/unicode-codepoint-length.3.fail.minmaxlength.json +++ /dev/null @@ -1 +0,0 @@ -{"exact": "šŸ˜€šŸ˜€", "minimum": "šŸ˜€", "maximum": "šŸ˜€"} diff --git a/test/inputs/typescript-effect-schema/unicode-codepoint-length.4.fail.minmaxlength.json b/test/inputs/typescript-effect-schema/unicode-codepoint-length.4.fail.minmaxlength.json deleted file mode 100644 index 8d6738c793..0000000000 --- a/test/inputs/typescript-effect-schema/unicode-codepoint-length.4.fail.minmaxlength.json +++ /dev/null @@ -1 +0,0 @@ -{"exact": "šŸ˜€šŸ˜€", "minimum": "šŸ˜€a", "maximum": "šŸ˜€a"} diff --git a/test/inputs/typescript-effect-schema/unicode-codepoint-length.5.fail.pattern.json b/test/inputs/typescript-effect-schema/unicode-codepoint-length.5.fail.pattern.json deleted file mode 100644 index bc2f3d621a..0000000000 --- a/test/inputs/typescript-effect-schema/unicode-codepoint-length.5.fail.pattern.json +++ /dev/null @@ -1 +0,0 @@ -{"exact": "!!", "minimum": "šŸ˜€a", "maximum": "šŸ˜€"} diff --git a/test/inputs/typescript-effect-schema/unicode-codepoint-length.schema b/test/inputs/typescript-effect-schema/unicode-codepoint-length.schema deleted file mode 100644 index 83c23969c4..0000000000 --- a/test/inputs/typescript-effect-schema/unicode-codepoint-length.schema +++ /dev/null @@ -1,24 +0,0 @@ -{ - "type": "object", - "properties": { - "exact": { - "type": "string", - "minLength": 2, - "maxLength": 2, - "pattern": "^[^!]+$" - }, - "minimum": { - "type": "string", - "minLength": 2 - }, - "maximum": { - "type": "string", - "maxLength": 1 - } - }, - "required": [ - "exact", - "minimum", - "maximum" - ] -} diff --git a/test/languages.ts b/test/languages.ts index b858294b5f..0c8ad13f3a 100644 --- a/test/languages.ts +++ b/test/languages.ts @@ -1746,7 +1746,7 @@ export const TypeScriptEffectSchemaLanguage: Language = { skipJSON: [], skipMiscJSON: false, additionalSchemaFiles: [ - "test/inputs/typescript-effect-schema/unicode-codepoint-length.schema", + "test/inputs/regressions/unicode-codepoint-length.schema", ], skipSchema: [], rendererOptions: {},