diff --git a/apps/cli/scripts/publish.ts b/apps/cli/scripts/publish.ts index a40689739e..df201267da 100644 --- a/apps/cli/scripts/publish.ts +++ b/apps/cli/scripts/publish.ts @@ -50,7 +50,7 @@ const isAlreadyPublished = Effect.fnUntraced(function* ( name: string, version: string, ) { - const encodedName = name.replace("/", "%2F"); + const encodedName = name.replaceAll("/", "%2F"); const res = yield* HttpClient.get(`${registryUrl}/${encodedName}/${version}`); if (res.status === 200) return true; if (res.status === 404) return false; diff --git a/packages/api/scripts/generate.ts b/packages/api/scripts/generate.ts index 80c093368e..5bfd891fe6 100644 --- a/packages/api/scripts/generate.ts +++ b/packages/api/scripts/generate.ts @@ -235,6 +235,7 @@ const UUID_PATTERN = // Keys stripped from a schema node because they describe documentation/example // values, not the value's shape. const SCHEMA_METADATA_KEYS = new Set(["default", "example", "examples"]); +const CONTENT_ANNOTATION_KEYS = new Set(["contentEncoding", "contentMediaType"]); // `inPropertiesMap` tracks whether the current object is the value of a // `properties: {...}` map; there, keys are user-defined property names (which may @@ -271,6 +272,12 @@ export function sanitizeOpenApiSchema( continue; } + // The OpenAPI 3.0 converter rejects the annotation-only content keywords; `format` still + // carries the encoding. + if (!inPropertiesMap && CONTENT_ANNOTATION_KEYS.has(key)) { + continue; + } + // The OpenAPI 3.0 converter rejects `const`; a one-value `enum` is equivalent. if (!inPropertiesMap && key === "const") { Object.assign(sanitized, { enum: [rawValue] }); diff --git a/packages/api/scripts/generate.unit.test.ts b/packages/api/scripts/generate.unit.test.ts index 9fb33bef1d..a9fed3bd9b 100644 --- a/packages/api/scripts/generate.unit.test.ts +++ b/packages/api/scripts/generate.unit.test.ts @@ -145,6 +145,21 @@ describe("generate", () => { }); }); + test("drops content annotations from binary strings without touching a property named contentEncoding", () => { + expect( + renderOpenApiSchema({ + type: "object", + additionalProperties: false, + properties: { + eszip: { type: "string", format: "binary", contentEncoding: "binary" }, + contentEncoding: { type: "string", contentMediaType: "text/plain" }, + }, + }), + ).toBe( + 'Schema.Struct({ "eszip": Schema.optionalKey(Schema.String.annotate({ "format": "binary" })), "contentEncoding": Schema.optionalKey(Schema.String) })', + ); + }); + test("widens multi-value string enums and keeps single-value discriminators closed", () => { expect( openStringEnums({